@shepai/cli 1.72.9 → 1.73.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 (440) hide show
  1. package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts +20 -1
  2. package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts.map +1 -1
  3. package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.js +68 -41
  4. package/dist/packages/core/src/application/use-cases/features/create/types.d.ts +10 -0
  5. package/dist/packages/core/src/application/use-cases/features/create/types.d.ts.map +1 -1
  6. package/dist/packages/core/src/infrastructure/services/notifications/notification.service.d.ts.map +1 -1
  7. package/dist/packages/core/src/infrastructure/services/notifications/notification.service.js +2 -4
  8. package/dist/src/presentation/web/app/actions/create-feature.d.ts.map +1 -1
  9. package/dist/src/presentation/web/app/actions/create-feature.js +20 -2
  10. package/dist/src/presentation/web/app/actions/get-feature-metadata.d.ts +10 -0
  11. package/dist/src/presentation/web/app/actions/get-feature-metadata.d.ts.map +1 -0
  12. package/dist/src/presentation/web/app/actions/get-feature-metadata.js +14 -0
  13. package/dist/src/presentation/web/app/api/agent-events/route.d.ts.map +1 -1
  14. package/dist/src/presentation/web/app/api/agent-events/route.js +15 -0
  15. package/dist/src/presentation/web/app/build-feature-node-data.d.ts.map +1 -1
  16. package/dist/src/presentation/web/app/build-feature-node-data.js +2 -26
  17. package/dist/src/presentation/web/app/build-graph-nodes.d.ts.map +1 -1
  18. package/dist/src/presentation/web/app/build-graph-nodes.js +2 -26
  19. package/dist/src/presentation/web/app/layout.js +1 -1
  20. package/dist/src/presentation/web/components/common/add-repository-button/add-repository-button.d.ts.map +1 -0
  21. package/dist/src/presentation/web/components/common/add-repository-button/index.d.ts +2 -0
  22. package/dist/src/presentation/web/components/common/add-repository-button/index.d.ts.map +1 -0
  23. package/dist/src/presentation/web/components/common/{add-repository-node → add-repository-button}/index.js +0 -1
  24. package/dist/src/presentation/web/components/common/add-repository-button/pick-folder.d.ts.map +1 -0
  25. package/dist/src/presentation/web/components/common/control-center-drawer/create-drawer-client.d.ts.map +1 -1
  26. package/dist/src/presentation/web/components/common/control-center-drawer/create-drawer-client.js +13 -18
  27. package/dist/src/presentation/web/components/common/control-center-drawer/drawer-view.d.ts +2 -0
  28. package/dist/src/presentation/web/components/common/control-center-drawer/drawer-view.d.ts.map +1 -1
  29. package/dist/src/presentation/web/components/common/control-center-drawer/drawer-view.js +11 -11
  30. package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.d.ts.map +1 -1
  31. package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.js +74 -144
  32. package/dist/src/presentation/web/components/common/control-center-drawer/index.d.ts +0 -1
  33. package/dist/src/presentation/web/components/common/control-center-drawer/index.d.ts.map +1 -1
  34. package/dist/src/presentation/web/components/common/control-center-drawer/index.js +0 -1
  35. package/dist/src/presentation/web/components/common/control-center-drawer/use-artifact-fetch.d.ts +13 -0
  36. package/dist/src/presentation/web/components/common/control-center-drawer/use-artifact-fetch.d.ts.map +1 -0
  37. package/dist/src/presentation/web/components/common/control-center-drawer/use-artifact-fetch.js +46 -0
  38. package/dist/src/presentation/web/components/common/feature-drawer/use-feature-actions.d.ts.map +1 -1
  39. package/dist/src/presentation/web/components/common/feature-drawer/use-feature-actions.js +7 -10
  40. package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.d.ts +25 -0
  41. package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.d.ts.map +1 -1
  42. package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.js +45 -2
  43. package/dist/src/presentation/web/components/common/index.d.ts +2 -3
  44. package/dist/src/presentation/web/components/common/index.d.ts.map +1 -1
  45. package/dist/src/presentation/web/components/common/index.js +2 -3
  46. package/dist/src/presentation/web/components/common/repository-node/repository-node.js +1 -1
  47. package/dist/src/presentation/web/components/common/repository-node/use-repository-actions.d.ts.map +1 -1
  48. package/dist/src/presentation/web/components/common/repository-node/use-repository-actions.js +14 -39
  49. package/dist/src/presentation/web/components/common/sidebar-section-header/sidebar-section-header.d.ts +1 -3
  50. package/dist/src/presentation/web/components/common/sidebar-section-header/sidebar-section-header.d.ts.map +1 -1
  51. package/dist/src/presentation/web/components/common/sidebar-section-header/sidebar-section-header.js +3 -7
  52. package/dist/src/presentation/web/components/common/sidebar-section-header/sidebar-section-header.stories.d.ts +0 -1
  53. package/dist/src/presentation/web/components/common/sidebar-section-header/sidebar-section-header.stories.d.ts.map +1 -1
  54. package/dist/src/presentation/web/components/common/sidebar-section-header/sidebar-section-header.stories.js +0 -11
  55. package/dist/src/presentation/web/components/features/control-center/control-center-empty-state.js +1 -1
  56. package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
  57. package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +31 -14
  58. package/dist/src/presentation/web/components/features/control-center/control-center.stories.d.ts +0 -11
  59. package/dist/src/presentation/web/components/features/control-center/control-center.stories.d.ts.map +1 -1
  60. package/dist/src/presentation/web/components/features/control-center/control-center.stories.js +2 -37
  61. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts +8 -0
  62. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
  63. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +160 -354
  64. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts +2 -10
  65. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts.map +1 -1
  66. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.js +11 -54
  67. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.stories.d.ts.map +1 -1
  68. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.stories.js +0 -46
  69. package/dist/src/presentation/web/components/layouts/app-shell/app-shell.js +1 -1
  70. package/dist/src/presentation/web/components/layouts/app-sidebar/app-sidebar.d.ts +1 -3
  71. package/dist/src/presentation/web/components/layouts/app-sidebar/app-sidebar.d.ts.map +1 -1
  72. package/dist/src/presentation/web/components/layouts/app-sidebar/app-sidebar.js +2 -2
  73. package/dist/src/presentation/web/components/ui/alert-dialog.d.ts.map +1 -1
  74. package/dist/src/presentation/web/components/ui/alert-dialog.js +2 -2
  75. package/dist/src/presentation/web/components/ui/dialog.d.ts.map +1 -1
  76. package/dist/src/presentation/web/components/ui/dialog.js +2 -2
  77. package/dist/src/presentation/web/components/ui/scroll-area.js +1 -1
  78. package/dist/src/presentation/web/hooks/agent-events-provider.d.ts.map +1 -1
  79. package/dist/src/presentation/web/hooks/agent-events-provider.js +3 -2
  80. package/dist/src/presentation/web/hooks/use-agent-events.d.ts.map +1 -1
  81. package/dist/src/presentation/web/hooks/use-agent-events.js +18 -5
  82. package/dist/src/presentation/web/hooks/use-deploy-action.d.ts.map +1 -1
  83. package/dist/src/presentation/web/hooks/use-deploy-action.js +8 -3
  84. package/dist/src/presentation/web/hooks/use-graph-state.d.ts +42 -0
  85. package/dist/src/presentation/web/hooks/use-graph-state.d.ts.map +1 -0
  86. package/dist/src/presentation/web/hooks/use-graph-state.js +257 -0
  87. package/dist/src/presentation/web/hooks/use-notifications.d.ts +1 -5
  88. package/dist/src/presentation/web/hooks/use-notifications.d.ts.map +1 -1
  89. package/dist/src/presentation/web/hooks/use-notifications.js +1 -26
  90. package/dist/src/presentation/web/hooks/use-notifications.stories.d.ts.map +1 -1
  91. package/dist/src/presentation/web/hooks/use-notifications.stories.js +28 -38
  92. package/dist/src/presentation/web/lib/derive-graph.d.ts +52 -0
  93. package/dist/src/presentation/web/lib/derive-graph.d.ts.map +1 -0
  94. package/dist/src/presentation/web/lib/derive-graph.js +126 -0
  95. package/dist/src/presentation/web/lib/layout-with-dagre.d.ts.map +1 -1
  96. package/dist/src/presentation/web/lib/layout-with-dagre.js +1 -2
  97. package/dist/src/presentation/web/lib/logger.d.ts +7 -0
  98. package/dist/src/presentation/web/lib/logger.d.ts.map +1 -0
  99. package/dist/src/presentation/web/lib/logger.js +11 -0
  100. package/dist/tsconfig.build.tsbuildinfo +1 -1
  101. package/package.json +1 -1
  102. package/web/.next/BUILD_ID +1 -1
  103. package/web/.next/build-manifest.json +2 -2
  104. package/web/.next/cache/.previewinfo +1 -1
  105. package/web/.next/cache/.rscinfo +1 -1
  106. package/web/.next/cache/.tsbuildinfo +1 -1
  107. package/web/.next/cache/config.json +3 -3
  108. package/web/.next/fallback-build-manifest.json +2 -2
  109. package/web/.next/prerender-manifest.json +3 -3
  110. package/web/.next/required-server-files.js +1 -1
  111. package/web/.next/required-server-files.json +1 -1
  112. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +34 -34
  113. package/web/.next/server/app/(dashboard)/@drawer/create/page.js +3 -3
  114. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  115. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  116. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +40 -40
  117. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +3 -3
  118. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  119. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  120. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +30 -30
  121. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js +3 -3
  122. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  123. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  124. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +34 -34
  125. package/web/.next/server/app/(dashboard)/create/page.js +3 -3
  126. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  127. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  128. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +40 -40
  129. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +3 -3
  130. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  131. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  132. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +30 -30
  133. package/web/.next/server/app/(dashboard)/page.js +3 -3
  134. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  135. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  136. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +30 -30
  137. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js +3 -3
  138. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  139. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  140. package/web/.next/server/app/_global-error.html +2 -2
  141. package/web/.next/server/app/_global-error.rsc +1 -1
  142. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  143. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  144. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  145. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  146. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  147. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  148. package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  149. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  150. package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  151. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  152. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  153. package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  154. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  155. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  156. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  157. package/web/.next/server/app/version/page.js.nft.json +1 -1
  158. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  159. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js +2 -2
  160. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js.map +1 -1
  161. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  162. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  163. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_816618e2.js +3 -0
  164. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_816618e2.js.map +1 -0
  165. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_ba2e050f.js +3 -0
  166. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_ba2e050f.js.map +1 -0
  167. package/web/.next/server/chunks/ssr/[root-of-the-server]__17a611f0._.js +2 -2
  168. package/web/.next/server/chunks/ssr/[root-of-the-server]__17a611f0._.js.map +1 -1
  169. package/web/.next/server/chunks/ssr/[root-of-the-server]__2018e25f._.js +1 -1
  170. package/web/.next/server/chunks/ssr/[root-of-the-server]__2018e25f._.js.map +1 -1
  171. package/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
  172. package/web/.next/server/chunks/ssr/[root-of-the-server]__45dbf93d._.js +2 -2
  173. package/web/.next/server/chunks/ssr/[root-of-the-server]__45dbf93d._.js.map +1 -1
  174. package/web/.next/server/chunks/ssr/{[root-of-the-server]__cbae9863._.js → [root-of-the-server]__6258349c._.js} +2 -2
  175. package/web/.next/server/chunks/ssr/[root-of-the-server]__6258349c._.js.map +1 -0
  176. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  177. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +1 -1
  178. package/web/.next/server/chunks/ssr/[root-of-the-server]__6cbc1149._.js +2 -2
  179. package/web/.next/server/chunks/ssr/[root-of-the-server]__6cbc1149._.js.map +1 -1
  180. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  181. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +1 -1
  182. package/web/.next/server/chunks/ssr/{[root-of-the-server]__e5e09f72._.js → [root-of-the-server]__94a6d275._.js} +2 -2
  183. package/web/.next/server/chunks/ssr/[root-of-the-server]__94a6d275._.js.map +1 -0
  184. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +1 -1
  185. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
  186. package/web/.next/server/chunks/ssr/_07c2a32a._.js +1 -1
  187. package/web/.next/server/chunks/ssr/_07c2a32a._.js.map +1 -1
  188. package/web/.next/server/chunks/ssr/_0e9d6bf7._.js +1 -1
  189. package/web/.next/server/chunks/ssr/_0e9d6bf7._.js.map +1 -1
  190. package/web/.next/server/chunks/ssr/_250a63ae._.js +3 -0
  191. package/web/.next/server/chunks/ssr/_250a63ae._.js.map +1 -0
  192. package/web/.next/server/chunks/ssr/_61351ed3._.js +1 -1
  193. package/web/.next/server/chunks/ssr/_61351ed3._.js.map +1 -1
  194. package/web/.next/server/chunks/ssr/_8400c8bb._.js +1 -1
  195. package/web/.next/server/chunks/ssr/_8400c8bb._.js.map +1 -1
  196. package/web/.next/server/chunks/ssr/_9f940437._.js +1 -1
  197. package/web/.next/server/chunks/ssr/_9f940437._.js.map +1 -1
  198. package/web/.next/server/chunks/ssr/_dee726e3._.js +6 -0
  199. package/web/.next/server/chunks/ssr/_dee726e3._.js.map +1 -0
  200. package/web/.next/{standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_5ea689db._.js → server/chunks/ssr/src_presentation_web_2b91e4ec._.js} +2 -2
  201. package/web/.next/server/chunks/ssr/{src_presentation_web_7188a290._.js.map → src_presentation_web_2b91e4ec._.js.map} +1 -1
  202. package/web/.next/server/chunks/ssr/{src_presentation_web_5ea689db._.js → src_presentation_web_5bcc1537._.js} +2 -2
  203. package/web/.next/server/chunks/ssr/{src_presentation_web_5ea689db._.js.map → src_presentation_web_5bcc1537._.js.map} +1 -1
  204. package/web/.next/server/chunks/ssr/src_presentation_web_67178b88._.js +1 -1
  205. package/web/.next/server/chunks/ssr/src_presentation_web_67178b88._.js.map +1 -1
  206. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_5955c012.js +3 -0
  207. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_5955c012.js.map +1 -0
  208. package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js +3 -0
  209. package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js.map +1 -0
  210. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
  211. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
  212. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  213. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  214. package/web/.next/server/chunks/ssr/src_presentation_web_d5b0cb86._.js +8 -0
  215. package/web/.next/server/chunks/ssr/src_presentation_web_d5b0cb86._.js.map +1 -0
  216. package/web/.next/server/chunks/ssr/src_presentation_web_e626b63c._.js +8 -0
  217. package/web/.next/server/chunks/ssr/src_presentation_web_e626b63c._.js.map +1 -0
  218. package/web/.next/server/pages/500.html +2 -2
  219. package/web/.next/server/server-reference-manifest.js +1 -1
  220. package/web/.next/server/server-reference-manifest.json +142 -142
  221. package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
  222. package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +2 -2
  223. package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
  224. package/web/.next/standalone/src/presentation/web/.next/required-server-files.json +1 -1
  225. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +34 -34
  226. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page.js +3 -3
  227. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  228. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  229. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +40 -40
  230. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +3 -3
  231. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  232. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  233. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +30 -30
  234. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js +3 -3
  235. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  236. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  237. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +34 -34
  238. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page.js +3 -3
  239. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  240. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  241. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +40 -40
  242. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +3 -3
  243. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  244. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  245. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +30 -30
  246. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page.js +3 -3
  247. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  248. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  249. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +30 -30
  250. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js +3 -3
  251. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  252. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  253. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
  254. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
  255. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  256. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  257. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  258. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  259. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  260. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  261. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  262. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  263. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  264. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page.js.nft.json +1 -1
  265. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  266. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  267. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page.js.nft.json +1 -1
  268. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  269. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  270. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page.js.nft.json +1 -1
  271. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  272. package/web/.next/standalone/src/presentation/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js +2 -2
  273. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  274. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_816618e2.js +3 -0
  275. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_ba2e050f.js +3 -0
  276. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__17a611f0._.js +2 -2
  277. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__2018e25f._.js +1 -1
  278. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
  279. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__45dbf93d._.js +2 -2
  280. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/{[root-of-the-server]__cbae9863._.js → [root-of-the-server]__6258349c._.js} +2 -2
  281. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  282. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6cbc1149._.js +2 -2
  283. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  284. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/{[root-of-the-server]__e5e09f72._.js → [root-of-the-server]__94a6d275._.js} +2 -2
  285. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +1 -1
  286. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_07c2a32a._.js +1 -1
  287. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_0e9d6bf7._.js +1 -1
  288. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_250a63ae._.js +3 -0
  289. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_61351ed3._.js +1 -1
  290. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_8400c8bb._.js +1 -1
  291. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_9f940437._.js +1 -1
  292. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_dee726e3._.js +6 -0
  293. package/web/.next/{server/chunks/ssr/src_presentation_web_7188a290._.js → standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_2b91e4ec._.js} +2 -2
  294. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/{src_presentation_web_7188a290._.js → src_presentation_web_5bcc1537._.js} +2 -2
  295. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_67178b88._.js +1 -1
  296. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_5955c012.js +3 -0
  297. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js +3 -0
  298. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
  299. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  300. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_d5b0cb86._.js +8 -0
  301. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_e626b63c._.js +8 -0
  302. package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
  303. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
  304. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +142 -142
  305. package/web/.next/standalone/src/presentation/web/CLAUDE.md +77 -33
  306. package/web/.next/standalone/src/presentation/web/app/actions/create-feature.ts +27 -2
  307. package/web/.next/standalone/src/presentation/web/app/actions/get-feature-metadata.ts +18 -0
  308. package/web/.next/standalone/src/presentation/web/app/api/agent-events/route.ts +17 -0
  309. package/web/.next/standalone/src/presentation/web/app/build-feature-node-data.ts +3 -30
  310. package/web/.next/standalone/src/presentation/web/app/build-graph-nodes.ts +3 -30
  311. package/web/.next/standalone/src/presentation/web/app/layout.tsx +1 -1
  312. package/web/.next/standalone/src/presentation/web/components/common/add-repository-button/index.ts +1 -0
  313. package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/create-drawer-client.tsx +15 -21
  314. package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/drawer-view.ts +12 -13
  315. package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.tsx +105 -141
  316. package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/index.ts +0 -1
  317. package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/use-artifact-fetch.ts +56 -0
  318. package/web/.next/standalone/src/presentation/web/components/common/feature-drawer/use-feature-actions.ts +6 -7
  319. package/web/.next/standalone/src/presentation/web/components/common/feature-node/derive-feature-state.ts +63 -2
  320. package/web/.next/standalone/src/presentation/web/components/common/index.ts +2 -12
  321. package/web/.next/standalone/src/presentation/web/components/common/repository-node/repository-node.tsx +2 -2
  322. package/web/.next/standalone/src/presentation/web/components/common/repository-node/use-repository-actions.ts +29 -54
  323. package/web/.next/standalone/src/presentation/web/components/common/sidebar-section-header/sidebar-section-header.stories.tsx +0 -13
  324. package/web/.next/standalone/src/presentation/web/components/common/sidebar-section-header/sidebar-section-header.tsx +1 -45
  325. package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center-empty-state.tsx +1 -1
  326. package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center-inner.tsx +43 -36
  327. package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center.stories.tsx +2 -41
  328. package/web/.next/standalone/src/presentation/web/components/features/control-center/use-control-center-state.ts +203 -440
  329. package/web/.next/standalone/src/presentation/web/components/features/features-canvas/features-canvas.stories.tsx +0 -48
  330. package/web/.next/standalone/src/presentation/web/components/features/features-canvas/features-canvas.tsx +13 -76
  331. package/web/.next/standalone/src/presentation/web/components/layouts/app-shell/app-shell.tsx +1 -1
  332. package/web/.next/standalone/src/presentation/web/components/layouts/app-sidebar/app-sidebar.tsx +2 -14
  333. package/web/.next/standalone/src/presentation/web/components/ui/alert-dialog.tsx +2 -5
  334. package/web/.next/standalone/src/presentation/web/components/ui/dialog.tsx +2 -5
  335. package/web/.next/standalone/src/presentation/web/components/ui/scroll-area.tsx +1 -1
  336. package/web/.next/standalone/src/presentation/web/hooks/agent-events-provider.tsx +7 -2
  337. package/web/.next/standalone/src/presentation/web/hooks/use-agent-events.ts +19 -5
  338. package/web/.next/standalone/src/presentation/web/hooks/use-deploy-action.ts +11 -3
  339. package/web/.next/standalone/src/presentation/web/hooks/use-graph-state.ts +376 -0
  340. package/web/.next/standalone/src/presentation/web/hooks/use-notifications.stories.tsx +2 -30
  341. package/web/.next/standalone/src/presentation/web/hooks/use-notifications.ts +2 -36
  342. package/web/.next/standalone/src/presentation/web/lib/derive-graph.ts +178 -0
  343. package/web/.next/standalone/src/presentation/web/lib/layout-with-dagre.ts +1 -2
  344. package/web/.next/standalone/src/presentation/web/lib/logger.ts +12 -0
  345. package/web/.next/standalone/src/presentation/web/server.js +1 -1
  346. package/web/.next/static/chunks/0ffccd7be73305c8.css +2 -0
  347. package/web/.next/static/chunks/15ceb197ec725da2.js +1 -0
  348. package/web/.next/static/chunks/3f205fd6adbfd20a.js +7 -0
  349. package/web/.next/static/chunks/{d4492cd12fdf0891.js → 6691ad02dc1efd1f.js} +1 -1
  350. package/web/.next/static/chunks/{64850cf4081a2950.js → 7bff5fbcbf157df5.js} +1 -1
  351. package/web/.next/static/chunks/8959112899679e25.js +1 -0
  352. package/web/.next/static/chunks/{c83897e9213881bf.js → 8f508ef906cbf0fa.js} +1 -1
  353. package/web/.next/static/chunks/9cbb42a6bd516d3b.js +1 -0
  354. package/web/.next/static/chunks/c5603ed8a95d460d.js +1 -0
  355. package/web/.next/static/chunks/cb41849bcfaa304e.js +1 -0
  356. package/web/.next/static/chunks/d7e0cd32364a8d76.js +1 -0
  357. package/web/.next/static/chunks/e69d79bd3f19dec8.js +4 -0
  358. package/web/.next/trace +1 -1
  359. package/web/.next/trace-build +1 -1
  360. package/dist/src/presentation/web/components/common/add-repository-node/add-repository-button.d.ts.map +0 -1
  361. package/dist/src/presentation/web/components/common/add-repository-node/add-repository-node-config.d.ts +0 -7
  362. package/dist/src/presentation/web/components/common/add-repository-node/add-repository-node-config.d.ts.map +0 -1
  363. package/dist/src/presentation/web/components/common/add-repository-node/add-repository-node-config.js +0 -1
  364. package/dist/src/presentation/web/components/common/add-repository-node/add-repository-node.d.ts +0 -6
  365. package/dist/src/presentation/web/components/common/add-repository-node/add-repository-node.d.ts.map +0 -1
  366. package/dist/src/presentation/web/components/common/add-repository-node/add-repository-node.js +0 -23
  367. package/dist/src/presentation/web/components/common/add-repository-node/add-repository-node.stories.d.ts +0 -10
  368. package/dist/src/presentation/web/components/common/add-repository-node/add-repository-node.stories.d.ts.map +0 -1
  369. package/dist/src/presentation/web/components/common/add-repository-node/add-repository-node.stories.js +0 -33
  370. package/dist/src/presentation/web/components/common/add-repository-node/index.d.ts +0 -4
  371. package/dist/src/presentation/web/components/common/add-repository-node/index.d.ts.map +0 -1
  372. package/dist/src/presentation/web/components/common/add-repository-node/pick-folder.d.ts.map +0 -1
  373. package/dist/src/presentation/web/components/common/control-center-drawer/control-center-drawer.d.ts +0 -12
  374. package/dist/src/presentation/web/components/common/control-center-drawer/control-center-drawer.d.ts.map +0 -1
  375. package/dist/src/presentation/web/components/common/control-center-drawer/control-center-drawer.js +0 -337
  376. package/dist/src/presentation/web/components/common/control-center-drawer/control-center-drawer.stories.d.ts +0 -33
  377. package/dist/src/presentation/web/components/common/control-center-drawer/control-center-drawer.stories.d.ts.map +0 -1
  378. package/dist/src/presentation/web/components/common/control-center-drawer/control-center-drawer.stories.js +0 -214
  379. package/dist/src/presentation/web/components/common/notification-permission-banner/index.d.ts +0 -2
  380. package/dist/src/presentation/web/components/common/notification-permission-banner/index.d.ts.map +0 -1
  381. package/dist/src/presentation/web/components/common/notification-permission-banner/index.js +0 -1
  382. package/dist/src/presentation/web/components/common/notification-permission-banner/notification-permission-banner.d.ts +0 -2
  383. package/dist/src/presentation/web/components/common/notification-permission-banner/notification-permission-banner.d.ts.map +0 -1
  384. package/dist/src/presentation/web/components/common/notification-permission-banner/notification-permission-banner.js +0 -33
  385. package/dist/src/presentation/web/components/common/notification-permission-banner/notification-permission-banner.stories.d.ts +0 -6
  386. package/dist/src/presentation/web/components/common/notification-permission-banner/notification-permission-banner.stories.d.ts.map +0 -1
  387. package/dist/src/presentation/web/components/common/notification-permission-banner/notification-permission-banner.stories.js +0 -24
  388. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_3a02d8a5.js +0 -3
  389. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_3a02d8a5.js.map +0 -1
  390. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_a3044852.js +0 -3
  391. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_a3044852.js.map +0 -1
  392. package/web/.next/server/chunks/ssr/[root-of-the-server]__cbae9863._.js.map +0 -1
  393. package/web/.next/server/chunks/ssr/[root-of-the-server]__e5e09f72._.js.map +0 -1
  394. package/web/.next/server/chunks/ssr/_38d24563._.js +0 -6
  395. package/web/.next/server/chunks/ssr/_38d24563._.js.map +0 -1
  396. package/web/.next/server/chunks/ssr/_6e08ce21._.js +0 -3
  397. package/web/.next/server/chunks/ssr/_6e08ce21._.js.map +0 -1
  398. package/web/.next/server/chunks/ssr/src_presentation_web_0a49d9ee._.js +0 -8
  399. package/web/.next/server/chunks/ssr/src_presentation_web_0a49d9ee._.js.map +0 -1
  400. package/web/.next/server/chunks/ssr/src_presentation_web_79b0305a._.js +0 -8
  401. package/web/.next/server/chunks/ssr/src_presentation_web_79b0305a._.js.map +0 -1
  402. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_cc16bd01.js +0 -3
  403. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_cc16bd01.js.map +0 -1
  404. package/web/.next/server/chunks/ssr/src_presentation_web_app_(dashboard)_get-graph-data_ts_b018483e._.js +0 -3
  405. package/web/.next/server/chunks/ssr/src_presentation_web_app_(dashboard)_get-graph-data_ts_b018483e._.js.map +0 -1
  406. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_3a02d8a5.js +0 -3
  407. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_a3044852.js +0 -3
  408. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_38d24563._.js +0 -6
  409. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_6e08ce21._.js +0 -3
  410. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_0a49d9ee._.js +0 -8
  411. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_79b0305a._.js +0 -8
  412. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_cc16bd01.js +0 -3
  413. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_app_(dashboard)_get-graph-data_ts_b018483e._.js +0 -3
  414. package/web/.next/standalone/src/presentation/web/components/common/add-repository-node/add-repository-node-config.ts +0 -8
  415. package/web/.next/standalone/src/presentation/web/components/common/add-repository-node/add-repository-node.stories.tsx +0 -70
  416. package/web/.next/standalone/src/presentation/web/components/common/add-repository-node/add-repository-node.tsx +0 -49
  417. package/web/.next/standalone/src/presentation/web/components/common/add-repository-node/index.ts +0 -3
  418. package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/control-center-drawer.stories.tsx +0 -293
  419. package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/control-center-drawer.tsx +0 -745
  420. package/web/.next/standalone/src/presentation/web/components/common/notification-permission-banner/index.ts +0 -1
  421. package/web/.next/standalone/src/presentation/web/components/common/notification-permission-banner/notification-permission-banner.stories.tsx +0 -52
  422. package/web/.next/standalone/src/presentation/web/components/common/notification-permission-banner/notification-permission-banner.tsx +0 -55
  423. package/web/.next/static/chunks/0c54314c8c9c9739.js +0 -7
  424. package/web/.next/static/chunks/10cd08dae8c210ff.js +0 -1
  425. package/web/.next/static/chunks/15bf7ee1da91eb46.js +0 -4
  426. package/web/.next/static/chunks/3c79bca4d3f18f66.js +0 -1
  427. package/web/.next/static/chunks/67f2a7a5e8dc358a.css +0 -2
  428. package/web/.next/static/chunks/6cc840197626843b.js +0 -1
  429. package/web/.next/static/chunks/e3239b6c18cf8b96.js +0 -1
  430. package/web/.next/static/chunks/e9cc53ce8a7bdea6.js +0 -1
  431. package/web/.next/static/chunks/ef916db8c537211a.js +0 -1
  432. /package/dist/src/presentation/web/components/common/{add-repository-node → add-repository-button}/add-repository-button.d.ts +0 -0
  433. /package/dist/src/presentation/web/components/common/{add-repository-node → add-repository-button}/add-repository-button.js +0 -0
  434. /package/dist/src/presentation/web/components/common/{add-repository-node → add-repository-button}/pick-folder.d.ts +0 -0
  435. /package/dist/src/presentation/web/components/common/{add-repository-node → add-repository-button}/pick-folder.js +0 -0
  436. /package/web/.next/standalone/src/presentation/web/components/common/{add-repository-node → add-repository-button}/add-repository-button.tsx +0 -0
  437. /package/web/.next/standalone/src/presentation/web/components/common/{add-repository-node → add-repository-button}/pick-folder.ts +0 -0
  438. /package/web/.next/static/{Atrl1oUfRQej2kgJ972uS → 1AvkeBASQdtzZt9cm9UYg}/_buildManifest.js +0 -0
  439. /package/web/.next/static/{Atrl1oUfRQej2kgJ972uS → 1AvkeBASQdtzZt9cm9UYg}/_clientMiddlewareManifest.json +0 -0
  440. /package/web/.next/static/{Atrl1oUfRQej2kgJ972uS → 1AvkeBASQdtzZt9cm9UYg}/_ssgManifest.js +0 -0
@@ -37,6 +37,66 @@ pnpm dev:cli ui
37
37
  | WebSocket upgrades | Forwarded (HMR works) | NOT forwarded in `WebServerService` |
38
38
  | Next.js mode | Always dev | dev when run from source, prod when installed |
39
39
 
40
+ ## Graph State Architecture (Domain-Model-Driven)
41
+
42
+ All canvas node/edge state is managed through **domain Maps as the single source of truth**.
43
+
44
+ ```
45
+ Server (layout.tsx) Client (useGraphState)
46
+ ┌──────────────────┐ ┌─────────────────────────────┐
47
+ │ initialNodes[] │──parseMaps──→ │ Domain Maps (source of truth)│
48
+ │ initialEdges[] │ │ featureMap: Map<id, Entry> │
49
+ └──────────────────┘ │ repoMap: Map<id, Entry> │
50
+ │ pendingMap: Map<id, Entry> │
51
+ SSE Events │ │
52
+ ┌──────────────────┐ └──────────┬──────────────────┘
53
+ │ NotificationEvent│──updateFeature──→ │
54
+ └──────────────────┘ │ deriveGraph() + layoutWithDagre()
55
+
56
+ Optimistic UI ┌─────────────────────────────┐
57
+ ┌──────────────────┐ │ Derived (read-only) │
58
+ │ shep:feature- │──addPending───→ │ nodes: CanvasNodeType[] │
59
+ │ created event │ │ edges: Edge[] │
60
+ └──────────────────┘ │ (callbacks + layout applied)│
61
+ └─────────────────────────────┘
62
+ ```
63
+
64
+ ### Key Files
65
+
66
+ | File | Purpose |
67
+ | ---------------------------------------------------------------- | -------------------------------------------------------------------- |
68
+ | `lib/derive-graph.ts` | Pure function: domain Maps → nodes + edges (with callbacks injected) |
69
+ | `hooks/use-graph-state.ts` | Hook: domain Maps state + reconciliation + derivation + layout |
70
+ | `components/features/control-center/use-control-center-state.ts` | Wraps useGraphState, handles server actions + SSE events |
71
+ | `components/features/control-center/control-center-inner.tsx` | Wires callbacks via `setCallbacks()`, passes nodes/edges to canvas |
72
+ | `components/features/features-canvas/features-canvas.tsx` | Renders React Flow; only adds `selectedFeatureId` highlighting |
73
+
74
+ ### Design Principles
75
+
76
+ 1. **Domain Maps are the source of truth** — all mutations go through Maps (featureMap, repoMap, pendingMap)
77
+ 2. **Edges are derived, never stored** — repo→feature edges from `repositoryPath` matching, dep edges from `parentNodeId`
78
+ 3. **Callbacks via ref** — `callbacksRef` + stable `useMemo([])` wrapper prevents circular re-renders
79
+ 4. **Layout in derivation** — `layoutWithDagre` runs inside `useMemo` after `deriveGraph()`
80
+ 5. **`onNodesChange` is a no-op** — since `nodesDraggable=false`, we ignore all React Flow changes
81
+
82
+ ### Mutation Paths
83
+
84
+ | Operation | Flow |
85
+ | ----------------- | ------------------------------------------------------------------------------------------------------- |
86
+ | SSE event | `useAgentEventsContext` → `updateFeature(nodeId, {state, lifecycle})` |
87
+ | Server prop sync | `useEffect` watches `initialNodeKey` → `reconcile(newNodes, newEdges)` |
88
+ | Optimistic create | `shep:feature-created` event → `createFeatureNode()` → `addPendingFeature()` |
89
+ | Delete feature | `handleDeleteFeature()` → `removeFeature()` → server action → `restoreFeature()` on error |
90
+ | Add repository | `handleAddRepository()` → `addRepository(tempId)` → server action → `replaceRepository(tempId, realId)` |
91
+
92
+ ### Reconciliation
93
+
94
+ `reconcile(newNodes, newEdges)` merges server data into domain Maps:
95
+
96
+ - Replaces featureMap and repoMap with fresh server data
97
+ - Preserves pending (creating) features in featureMap unless matched by `name + repositoryPath`
98
+ - Cleans pendingMap entries that now have a real counterpart in server data
99
+
40
100
  ## SSE / Real-Time Update Architecture
41
101
 
42
102
  ```
@@ -45,8 +105,8 @@ DB polling (500ms) -> /api/agent-events (SSE route)
45
105
  -> postMessage to all browser tabs
46
106
  -> useAgentEvents hook (hooks/use-agent-events.ts)
47
107
  -> AgentEventsProvider context (hooks/agent-events-provider.tsx)
48
- -> useControlCenterState (optimistic node updates via setNodes)
49
- -> React state updates -> sidebar + React Flow canvas
108
+ -> useControlCenterState (SSE effect calls updateFeature)
109
+ -> domain Maps update -> derivation -> React Flow canvas
50
110
  ```
51
111
 
52
112
  ### SSE Key Files
@@ -58,18 +118,9 @@ DB polling (500ms) -> /api/agent-events (SSE route)
58
118
  | `public/agent-events-sw.js` | Service Worker: multiplexes single SSE to all tabs |
59
119
  | `hooks/use-agent-events.ts` | Client hook: registers with SW, receives events |
60
120
  | `hooks/agent-events-provider.tsx` | React context wrapping `useAgentEvents` |
61
- | `components/features/control-center/use-control-center-state.ts` | Processes SSE events into React Flow node updates |
121
+ | `components/features/control-center/use-control-center-state.ts` | SSE effect calls `updateFeature()` on domain Maps |
62
122
  | `components/common/feature-node/derive-feature-state.ts` | Maps event types/phases to UI state/lifecycle |
63
123
 
64
- ### SSE Event Flow Details
65
-
66
- 1. **SSE route** seeds a per-connection cache on first poll (no events emitted for initial state)
67
- 2. Subsequent polls compare DB state against cache, emit only deltas
68
- 3. **Service Worker** connects to `/api/agent-events` via EventSource on first subscriber
69
- 4. SW broadcasts `{ type: 'notification', data }` to all tabs via `clients.matchAll()`
70
- 5. **useControlCenterState** effect processes new events, calls `setNodes()` to update node state/lifecycle
71
- 6. **Polling fallback** (5s interval) fetches via `fetchGraphData()` server action for active features
72
-
73
124
  ### SSE Lifecycle Mappings
74
125
 
75
126
  The SSE route maps `SdlcLifecycle` enum -> agent graph node names -> client `FeatureLifecyclePhase`:
@@ -94,21 +145,17 @@ React Flow v12 (`@xyflow/react` ^12.10.0) has specific behaviors that affect rea
94
145
  - **Internal Zustand store**: React Flow syncs props to an internal `nodeLookup` Map via `StoreUpdater`
95
146
  - **Memoized NodeWrapper**: Each node is wrapped in `memo(NodeWrapper)` which subscribes to store via `useStore(selector, shallow)`
96
147
  - **NodeWrapper gets node from store**, NOT from props directly. It does `s.nodeLookup.get(id)` with `shallow` comparison
97
- - **Single ReactFlowProvider**: There must be exactly ONE `ReactFlowProvider` ancestor. Multiple nested providers create separate stores, causing the outer one's `StoreUpdater` to sync nodes to a store that the inner components don't read from
148
+ - **Single ReactFlowProvider**: There must be exactly ONE `ReactFlowProvider` ancestor. Multiple nested providers create separate stores
98
149
 
99
- ### Circular Update Loop (FIXED — do not reintroduce)
150
+ ### Circular Update Loop Prevention
100
151
 
101
- In controlled mode, `enrichedNodes` (useMemo in FeaturesCanvas) creates new node objects every render
102
- (adding callbacks to `data`). StoreUpdater sees different references and emits `replace` changes via
103
- `onNodesChange`. If `onNodesChange` applies these 'replace' changes back to state via `applyNodeChanges`,
104
- it overwrites SSE-driven state updates with stale data from the previous render, AND triggers another
105
- `enrichedNodes` recalculation → infinite loop (110+ renders on page load).
152
+ With the domain-model-driven architecture, the circular update loop is prevented by design:
106
153
 
107
- **Fix**: `onNodesChange` in `use-control-center-state.ts` filters out `replace` changes. Only `dimensions`,
108
- `position`, `select`, etc. are applied. StoreUpdater still syncs props to its internal store regardless
109
- our state remains the source of truth.
154
+ 1. **Callbacks are stable** — injected via `callbacksRef` + stable `useMemo([])` wrapper, so node objects don't change when callbacks change
155
+ 2. **`onNodesChange` is a no-op** — domain Maps are the source of truth, React Flow's internal changes are ignored
156
+ 3. **`enrichedNodes` only adds `selectedFeatureId`** no callback injection in FeaturesCanvas
110
157
 
111
- **NEVER** remove the `c.type !== 'replace'` filter from `onNodesChange`.
158
+ **NEVER** make `onNodesChange` apply `replace` changes back to state.
112
159
 
113
160
  ## Testing Real-Time Updates
114
161
 
@@ -124,24 +171,21 @@ our state remains the source of truth.
124
171
 
125
172
  When a user creates a feature, the UI uses optimistic updates:
126
173
 
127
- 1. **Create drawer** dispatches `shep:feature-created` → canvas adds a temp node (`feature-<ts>` ID, state `creating`)
174
+ 1. **Create drawer** dispatches `shep:feature-created` → `createFeatureNode()` → `addPendingFeature()` adds temp node to pendingMap
128
175
  2. Drawer closes immediately via `router.push('/')`
129
176
  3. Server action `createFeature` runs in background → agent starts
130
- 4. SSE events arrive with real feature ID (`feat-<uuid>`) — **these won't match the temp node**
131
- 5. **Polling fallback** (5s) detects new server nodereplaces temp `creating` node in-place
177
+ 4. SSE events arrive with real feature ID (`feat-<uuid>`) — these update featureMap via `updateFeature()`
178
+ 5. **Server prop sync** (rerender with new initialNodes) → `reconcile()` detects matching real featureremoves pending from both featureMap and pendingMap
132
179
 
133
180
  ### Key constraints
134
181
 
135
- - **Temp node IDs don't match SSE events**: Optimistic nodes use `feature-<ts>` IDs, server uses `feat-<uuid>`.
136
- SSE-driven `setNodes()` can't find the temp node. The polling fallback handles the swap.
137
- - **Create drawer `isSubmitting`**: Must NOT reset until pathname leaves `/create`. Resetting in `.finally()`
138
- causes the drawer to flash open because `router.push('/')` is async and pathname hasn't changed yet.
139
- - **Parallel routes preserve state**: The `CreateDrawerClient` component is NOT unmounted on navigation.
140
- `isOpen` is derived from pathname, not mount/unmount lifecycle.
182
+ - **Temp node IDs don't match SSE events**: Optimistic nodes use `feature-<ts>` IDs, server uses `feat-<uuid>`. SSE events call `updateFeature('feat-<uuid>', ...)` which doesn't match the temp ID. The reconcile on next server prop update handles the swap.
183
+ - **Create drawer `isSubmitting`**: Must NOT reset until pathname leaves `/create`. Resetting in `.finally()` causes the drawer to flash open because `router.push('/')` is async and pathname hasn't changed yet.
184
+ - **Parallel routes preserve state**: The `CreateDrawerClient` component is NOT unmounted on navigation. `isOpen` is derived from pathname, not mount/unmount lifecycle.
141
185
 
142
186
  ## Common Pitfalls
143
187
 
144
188
  - **No events when nothing changes**: SSE only emits deltas. If no feature state changes, no events are sent. This is correct behavior.
145
- - **Polling fallback dependency**: The 5s polling `useEffect` depends on a derived `hasActiveFeature` boolean (not `nodes` directly). Using `[nodes]` as a dependency would reset the interval on every node change, potentially preventing it from ever firing.
146
189
  - **Storybook mocks**: New server actions need mocks in `.storybook/mocks/app/actions/` or Storybook build breaks.
147
190
  - **`output: 'standalone'`** in next.config.ts: Production builds use standalone mode. Route handlers are bundled differently.
191
+ - **Map insertion order affects dagre layout**: After remove+restore of a feature, the Map insertion order may change, causing slightly different dagre positions. This is expected behavior — don't write tests asserting exact position preservation across remove/restore cycles.
@@ -72,15 +72,40 @@ export async function createFeature(
72
72
 
73
73
  try {
74
74
  const createFeatureUseCase = resolve<CreateFeatureUseCase>('CreateFeatureUseCase');
75
- const result = await createFeatureUseCase.execute({
75
+
76
+ // Phase 1 (fast): create DB record with real UUID — returns immediately
77
+ const { feature, shouldSpawn } = await createFeatureUseCase.createRecord({
76
78
  userInput,
77
79
  repositoryPath,
78
80
  approvalGates: gates,
79
81
  push: push ?? false,
80
82
  openPr: openPr ?? false,
81
83
  ...(parentId ? { parentId } : {}),
84
+ name,
85
+ description,
82
86
  });
83
- return { feature: result.feature };
87
+
88
+ // Phase 2 (background): metadata generation, worktree, spec, agent spawn
89
+ // Fire-and-forget — the UI gets the real feature ID immediately
90
+ createFeatureUseCase
91
+ .initializeAndSpawn(
92
+ feature,
93
+ {
94
+ userInput,
95
+ repositoryPath,
96
+ approvalGates: gates,
97
+ push: push ?? false,
98
+ openPr: openPr ?? false,
99
+ ...(parentId ? { parentId } : {}),
100
+ },
101
+ shouldSpawn
102
+ )
103
+ .catch((err: unknown) => {
104
+ // eslint-disable-next-line no-console
105
+ console.error('[createFeature] initializeAndSpawn failed:', err);
106
+ });
107
+
108
+ return { feature };
84
109
  } catch (error: unknown) {
85
110
  const message = error instanceof Error ? error.message : 'Failed to create feature';
86
111
  return { error: message };
@@ -0,0 +1,18 @@
1
+ 'use server';
2
+
3
+ import { resolve } from '@/lib/server-container';
4
+ import type { IFeatureRepository } from '@shepai/core/application/ports/output/repositories/feature-repository.interface';
5
+
6
+ /**
7
+ * Lightweight server action to fetch a single feature's name and description.
8
+ * Used by the SSE effect to update node metadata after AI metadata generation
9
+ * without a full graph reconcile (which can overwrite SSE-driven state).
10
+ */
11
+ export async function getFeatureMetadata(
12
+ featureId: string
13
+ ): Promise<{ name: string; description: string } | null> {
14
+ const featureRepo = resolve<IFeatureRepository>('IFeatureRepository');
15
+ const feature = await featureRepo.findById(featureId);
16
+ if (!feature) return null;
17
+ return { name: feature.name, description: feature.description };
18
+ }
@@ -191,6 +191,23 @@ export function GET(request: Request): Response {
191
191
  }
192
192
  }
193
193
 
194
+ // Check for feature name change (AI metadata generation updates name)
195
+ if (prev.featureName !== feature.name) {
196
+ prev.featureName = feature.name;
197
+ const nodeName =
198
+ LIFECYCLE_TO_NODE[feature.lifecycle as SdlcLifecycle] ?? 'requirements';
199
+ emitEvent({
200
+ eventType: NotificationEventType.PhaseCompleted,
201
+ agentRunId: run.id,
202
+ featureId: feature.id,
203
+ featureName: feature.name,
204
+ phaseName: nodeName,
205
+ message: `Feature metadata updated`,
206
+ severity: NotificationSeverity.Info,
207
+ timestamp: new Date().toISOString(),
208
+ });
209
+ }
210
+
194
211
  // Check for lifecycle change (agent stays "running" but moves through phases)
195
212
  if (prev.lifecycle !== feature.lifecycle) {
196
213
  prev.lifecycle = feature.lifecycle;
@@ -2,47 +2,20 @@ import type { Feature, AgentRun } from '@shepai/core/domain/generated/output';
2
2
  import {
3
3
  deriveNodeState,
4
4
  deriveProgress,
5
+ deriveLifecycle,
5
6
  } from '@/components/common/feature-node/derive-feature-state';
6
- import type { FeatureNodeData, FeatureLifecyclePhase } from '@/components/common/feature-node';
7
-
8
- /** Map domain SdlcLifecycle enum values to UI FeatureLifecyclePhase (1:1). */
9
- const lifecycleMap: Record<string, FeatureLifecyclePhase> = {
10
- Requirements: 'requirements',
11
- Research: 'research',
12
- Implementation: 'implementation',
13
- Review: 'review',
14
- 'Deploy & QA': 'deploy',
15
- Maintain: 'maintain',
16
- };
17
-
18
- /** Map agent graph node names (from agent_run.result) to UI lifecycle phases. */
19
- const nodeToLifecyclePhase: Record<string, FeatureLifecyclePhase> = {
20
- analyze: 'requirements',
21
- requirements: 'requirements',
22
- research: 'research',
23
- plan: 'implementation',
24
- implement: 'implementation',
25
- merge: 'review',
26
- };
7
+ import type { FeatureNodeData } from '@/components/common/feature-node';
27
8
 
28
9
  /**
29
10
  * Builds a FeatureNodeData object from a Feature entity and optional AgentRun.
30
11
  * This is the single-feature version of the logic in `buildGraphNodes`.
31
12
  */
32
13
  export function buildFeatureNodeData(feature: Feature, run: AgentRun | null): FeatureNodeData {
33
- const agentNode = run?.result?.startsWith('node:') ? run.result.slice(5) : undefined;
34
- const lifecycle: FeatureLifecyclePhase =
35
- run?.status === 'completed'
36
- ? 'maintain'
37
- : ((agentNode ? nodeToLifecyclePhase[agentNode] : undefined) ??
38
- lifecycleMap[feature.lifecycle] ??
39
- 'requirements');
40
-
41
14
  return {
42
15
  name: feature.name,
43
16
  description: feature.description ?? feature.slug,
44
17
  featureId: feature.id,
45
- lifecycle,
18
+ lifecycle: deriveLifecycle(feature, run),
46
19
  repositoryPath: feature.repositoryPath,
47
20
  branch: feature.branch,
48
21
  specPath: feature.specPath,
@@ -2,30 +2,11 @@ import type { Feature, Repository, AgentRun } from '@shepai/core/domain/generate
2
2
  import {
3
3
  deriveNodeState,
4
4
  deriveProgress,
5
+ deriveLifecycle,
5
6
  } from '@/components/common/feature-node/derive-feature-state';
6
7
  import type { CanvasNodeType } from '@/components/features/features-canvas';
7
8
  import type { Edge } from '@xyflow/react';
8
- import type { FeatureNodeData, FeatureLifecyclePhase } from '@/components/common/feature-node';
9
-
10
- /** Map domain SdlcLifecycle enum values to UI FeatureLifecyclePhase (1:1). */
11
- const lifecycleMap: Record<string, FeatureLifecyclePhase> = {
12
- Requirements: 'requirements',
13
- Research: 'research',
14
- Implementation: 'implementation',
15
- Review: 'review',
16
- 'Deploy & QA': 'deploy',
17
- Maintain: 'maintain',
18
- };
19
-
20
- /** Map agent graph node names (from agent_run.result) to UI lifecycle phases. */
21
- const nodeToLifecyclePhase: Record<string, FeatureLifecyclePhase> = {
22
- analyze: 'requirements',
23
- requirements: 'requirements',
24
- research: 'research',
25
- plan: 'implementation',
26
- implement: 'implementation',
27
- merge: 'review',
28
- };
9
+ import type { FeatureNodeData } from '@/components/common/feature-node';
29
10
 
30
11
  export interface FeatureWithRun {
31
12
  feature: Feature;
@@ -131,14 +112,6 @@ function appendFeatureNodes(
131
112
  });
132
113
 
133
114
  sorted.forEach(({ feature, run }) => {
134
- const agentNode = run?.result?.startsWith('node:') ? run.result.slice(5) : undefined;
135
- const lifecycle: FeatureLifecyclePhase =
136
- run?.status === 'completed'
137
- ? 'maintain'
138
- : ((agentNode ? nodeToLifecyclePhase[agentNode] : undefined) ??
139
- lifecycleMap[feature.lifecycle] ??
140
- 'requirements');
141
-
142
115
  // Resolve blockedBy display name from parent feature
143
116
  let blockedBy: string | undefined;
144
117
  if (feature.parentId && feature.lifecycle === 'Blocked') {
@@ -152,7 +125,7 @@ function appendFeatureNodes(
152
125
  name: feature.name,
153
126
  description: feature.description ?? feature.slug,
154
127
  featureId: feature.id,
155
- lifecycle,
128
+ lifecycle: deriveLifecycle(feature, run),
156
129
  repositoryPath: feature.repositoryPath,
157
130
  branch: feature.branch,
158
131
  specPath: feature.specPath,
@@ -53,7 +53,7 @@ export default function RootLayout({
53
53
  </head>
54
54
  <body className="min-h-screen antialiased">
55
55
  <AppShell>{children}</AppShell>
56
- <Toaster />
56
+ <Toaster position="bottom-center" />
57
57
  </body>
58
58
  </html>
59
59
  );
@@ -0,0 +1 @@
1
+ export { AddRepositoryButton } from './add-repository-button';
@@ -8,7 +8,6 @@ import { FeatureCreateDrawer } from '@/components/common/feature-create-drawer';
8
8
  import type { FeatureCreatePayload } from '@/components/common/feature-create-drawer';
9
9
  import type { ParentFeatureOption } from '@/components/common/feature-create-drawer/feature-create-drawer';
10
10
  import type { WorkflowDefaults } from '@/app/actions/get-workflow-defaults';
11
- import { useSoundAction } from '@/hooks/use-sound-action';
12
11
 
13
12
  export interface CreateDrawerClientProps {
14
13
  repositoryPath: string;
@@ -24,7 +23,6 @@ export function CreateDrawerClient({
24
23
  workflowDefaults,
25
24
  }: CreateDrawerClientProps) {
26
25
  const router = useRouter();
27
- const createSound = useSoundAction('create');
28
26
  const [isSubmitting, setIsSubmitting] = useState(false);
29
27
 
30
28
  // Derive open state from the URL. Next.js parallel routes preserve slot
@@ -54,40 +52,36 @@ export function CreateDrawerClient({
54
52
  (data: FeatureCreatePayload) => {
55
53
  setIsSubmitting(true);
56
54
 
57
- // Dispatch event for optimistic canvas update before navigating
58
- window.dispatchEvent(
59
- new CustomEvent('shep:feature-created', {
60
- detail: {
61
- name: data.name,
62
- description: data.description,
63
- repositoryPath: data.repositoryPath,
64
- parentId: data.parentId,
65
- },
66
- })
67
- );
68
-
69
55
  // Close the drawer immediately for responsive UI
70
56
  router.push('/');
71
57
 
72
- // Fire server action in the background
58
+ // Server action Phase 1 returns fast with real feature ID (DB record created)
59
+ // Phase 2 (metadata, worktree, agent) runs in background on server
73
60
  createFeature(data)
74
61
  .then((result) => {
75
62
  if (result.error) {
76
63
  toast.error(result.error);
77
- // Dispatch rollback event
78
- window.dispatchEvent(new CustomEvent('shep:feature-create-failed'));
79
64
  return;
80
65
  }
81
- createSound.play();
66
+ // Dispatch event with real feature ID so control center adds it to featureMap
67
+ window.dispatchEvent(
68
+ new CustomEvent('shep:feature-created', {
69
+ detail: {
70
+ featureId: result.feature!.id,
71
+ name: result.feature!.name,
72
+ description: result.feature!.description,
73
+ repositoryPath: result.feature!.repositoryPath,
74
+ parentId: data.parentId,
75
+ },
76
+ })
77
+ );
82
78
  })
83
79
  .catch(() => {
84
80
  toast.error('Failed to create feature');
85
- window.dispatchEvent(new CustomEvent('shep:feature-create-failed'));
86
- // Reset on error so the user can retry without navigating away
87
81
  setIsSubmitting(false);
88
82
  });
89
83
  },
90
- [router, createSound]
84
+ [router]
91
85
  );
92
86
 
93
87
  return (
@@ -27,6 +27,17 @@ export type DrawerView =
27
27
  /** Repository node actions */
28
28
  | { type: 'repository'; data: RepositoryNodeData };
29
29
 
30
+ /** Derives the feature-specific view type from node lifecycle + state. */
31
+ export function deriveFeatureViewType(
32
+ node: FeatureNodeData
33
+ ): 'feature' | 'prd-review' | 'tech-review' | 'merge-review' {
34
+ if (node.lifecycle === 'requirements' && node.state === 'action-required') return 'prd-review';
35
+ if (node.lifecycle === 'implementation' && node.state === 'action-required') return 'tech-review';
36
+ if (node.lifecycle === 'review' && (node.state === 'action-required' || node.state === 'error'))
37
+ return 'merge-review';
38
+ return 'feature';
39
+ }
40
+
30
41
  /**
31
42
  * Derives the active DrawerView from control-center state.
32
43
  * Priority: feature-create > selected-node (prd/tech/merge/feature) > repository
@@ -59,19 +70,7 @@ export function computeDrawerView({
59
70
  }
60
71
 
61
72
  if (selectedNode) {
62
- if (selectedNode.lifecycle === 'requirements' && selectedNode.state === 'action-required') {
63
- return { type: 'prd-review', node: selectedNode };
64
- }
65
- if (selectedNode.lifecycle === 'implementation' && selectedNode.state === 'action-required') {
66
- return { type: 'tech-review', node: selectedNode };
67
- }
68
- if (
69
- selectedNode.lifecycle === 'review' &&
70
- (selectedNode.state === 'action-required' || selectedNode.state === 'error')
71
- ) {
72
- return { type: 'merge-review', node: selectedNode };
73
- }
74
- return { type: 'feature', node: selectedNode };
73
+ return { type: deriveFeatureViewType(selectedNode), node: selectedNode };
75
74
  }
76
75
 
77
76
  if (selectedRepoNode) {