@shepai/cli 1.128.0 → 1.129.0-pr410.71f3ab6

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 (193) hide show
  1. package/dist/packages/core/src/application/use-cases/features/delete-feature.use-case.d.ts +1 -0
  2. package/dist/packages/core/src/application/use-cases/features/delete-feature.use-case.d.ts.map +1 -1
  3. package/dist/packages/core/src/application/use-cases/features/delete-feature.use-case.js +46 -15
  4. package/dist/packages/core/src/application/use-cases/repositories/add-repository.use-case.d.ts.map +1 -1
  5. package/dist/packages/core/src/application/use-cases/repositories/add-repository.use-case.js +5 -2
  6. package/dist/packages/core/src/infrastructure/repositories/sqlite-repository.repository.js +2 -2
  7. package/dist/src/presentation/cli/commands/feat/del.command.d.ts +2 -1
  8. package/dist/src/presentation/cli/commands/feat/del.command.d.ts.map +1 -1
  9. package/dist/src/presentation/cli/commands/feat/del.command.js +28 -2
  10. package/dist/src/presentation/web/app/(dashboard)/get-graph-data.d.ts +8 -0
  11. package/dist/src/presentation/web/app/(dashboard)/get-graph-data.d.ts.map +1 -1
  12. package/dist/src/presentation/web/app/(dashboard)/get-graph-data.js +75 -22
  13. package/dist/src/presentation/web/app/actions/delete-feature.d.ts +1 -1
  14. package/dist/src/presentation/web/app/actions/delete-feature.d.ts.map +1 -1
  15. package/dist/src/presentation/web/app/actions/delete-feature.js +3 -1
  16. package/dist/src/presentation/web/app/build-graph-nodes.d.ts +2 -0
  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 -0
  19. package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.d.ts.map +1 -1
  20. package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.js +3 -3
  21. package/dist/src/presentation/web/components/common/delete-feature-dialog/delete-feature-dialog-config.d.ts +2 -1
  22. package/dist/src/presentation/web/components/common/delete-feature-dialog/delete-feature-dialog-config.d.ts.map +1 -1
  23. package/dist/src/presentation/web/components/common/delete-feature-dialog/delete-feature-dialog.d.ts +1 -1
  24. package/dist/src/presentation/web/components/common/delete-feature-dialog/delete-feature-dialog.d.ts.map +1 -1
  25. package/dist/src/presentation/web/components/common/delete-feature-dialog/delete-feature-dialog.js +12 -2
  26. package/dist/src/presentation/web/components/common/delete-feature-dialog/delete-feature-dialog.stories.d.ts +3 -0
  27. package/dist/src/presentation/web/components/common/delete-feature-dialog/delete-feature-dialog.stories.d.ts.map +1 -1
  28. package/dist/src/presentation/web/components/common/delete-feature-dialog/delete-feature-dialog.stories.js +17 -0
  29. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts +1 -1
  30. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts.map +1 -1
  31. package/dist/src/presentation/web/components/common/feature-node/feature-node.d.ts.map +1 -1
  32. package/dist/src/presentation/web/components/common/feature-node/feature-node.js +6 -6
  33. package/dist/src/presentation/web/components/common/repository-node/repository-node-config.d.ts +2 -0
  34. package/dist/src/presentation/web/components/common/repository-node/repository-node-config.d.ts.map +1 -1
  35. package/dist/src/presentation/web/components/common/repository-node/repository-node.d.ts.map +1 -1
  36. package/dist/src/presentation/web/components/common/repository-node/repository-node.js +7 -3
  37. package/dist/src/presentation/web/components/common/repository-node/repository-node.stories.d.ts +2 -0
  38. package/dist/src/presentation/web/components/common/repository-node/repository-node.stories.d.ts.map +1 -1
  39. package/dist/src/presentation/web/components/common/repository-node/repository-node.stories.js +14 -0
  40. package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
  41. package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +2 -2
  42. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts +1 -1
  43. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
  44. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +3 -2
  45. package/dist/src/presentation/web/hooks/use-graph-state.d.ts.map +1 -1
  46. package/dist/src/presentation/web/hooks/use-graph-state.js +1 -1
  47. package/dist/src/presentation/web/lib/derive-graph.d.ts +1 -1
  48. package/dist/src/presentation/web/lib/derive-graph.d.ts.map +1 -1
  49. package/dist/src/presentation/web/lib/derive-graph.js +5 -2
  50. package/dist/src/presentation/web/lib/layout-with-dagre.js +2 -2
  51. package/dist/tsconfig.build.tsbuildinfo +1 -1
  52. package/package.json +1 -1
  53. package/web/.next/BUILD_ID +1 -1
  54. package/web/.next/build-manifest.json +2 -2
  55. package/web/.next/fallback-build-manifest.json +2 -2
  56. package/web/.next/prerender-manifest.json +3 -3
  57. package/web/.next/required-server-files.js +3 -3
  58. package/web/.next/required-server-files.json +3 -3
  59. package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +24 -24
  60. package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
  61. package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
  62. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +24 -24
  63. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  64. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  65. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +30 -30
  66. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  67. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  68. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +30 -30
  69. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  70. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  71. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +22 -22
  72. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  73. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  74. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +24 -24
  75. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  76. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  77. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +30 -30
  78. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  79. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  80. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +30 -30
  81. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  82. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  83. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +22 -22
  84. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  85. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  86. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +22 -22
  87. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  88. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  89. package/web/.next/server/app/_global-error.html +2 -2
  90. package/web/.next/server/app/_global-error.rsc +1 -1
  91. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  92. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  93. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  94. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  95. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  96. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +3 -3
  97. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  98. package/web/.next/server/app/settings/page/server-reference-manifest.json +8 -8
  99. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  100. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  101. package/web/.next/server/app/skills/page/server-reference-manifest.json +8 -8
  102. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  103. package/web/.next/server/app/tools/page/server-reference-manifest.json +8 -8
  104. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  105. package/web/.next/server/app/version/page/server-reference-manifest.json +3 -3
  106. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  107. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js +1 -1
  108. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js.map +1 -1
  109. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  110. package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_adopt_page_actions_4e741df2.js +1 -1
  111. package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_adopt_page_actions_4e741df2.js.map +1 -1
  112. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  113. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  114. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_026fdffa.js +1 -1
  115. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_026fdffa.js.map +1 -1
  116. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_8b91e197.js +1 -1
  117. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_8b91e197.js.map +1 -1
  118. package/web/.next/server/chunks/ssr/[root-of-the-server]__0e842eba._.js +1 -1
  119. package/web/.next/server/chunks/ssr/[root-of-the-server]__0e842eba._.js.map +1 -1
  120. package/web/.next/server/chunks/ssr/[root-of-the-server]__2f886f77._.js +2 -2
  121. package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
  122. package/web/.next/server/chunks/ssr/[root-of-the-server]__43f51aa6._.js +1 -1
  123. package/web/.next/server/chunks/ssr/[root-of-the-server]__43f51aa6._.js.map +1 -1
  124. package/web/.next/server/chunks/ssr/[root-of-the-server]__60684242._.js +2 -2
  125. package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js +2 -2
  126. package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js.map +1 -1
  127. package/web/.next/server/chunks/ssr/[root-of-the-server]__755cfe02._.js +1 -1
  128. package/web/.next/server/chunks/ssr/[root-of-the-server]__755cfe02._.js.map +1 -1
  129. package/web/.next/server/chunks/ssr/[root-of-the-server]__815546bd._.js +1 -1
  130. package/web/.next/server/chunks/ssr/[root-of-the-server]__815546bd._.js.map +1 -1
  131. package/web/.next/server/chunks/ssr/[root-of-the-server]__a628fb91._.js +1 -1
  132. package/web/.next/server/chunks/ssr/[root-of-the-server]__a628fb91._.js.map +1 -1
  133. package/web/.next/server/chunks/ssr/[root-of-the-server]__bfba58e6._.js +1 -1
  134. package/web/.next/server/chunks/ssr/[root-of-the-server]__bfba58e6._.js.map +1 -1
  135. package/web/.next/server/chunks/ssr/[root-of-the-server]__c3ab8422._.js +1 -1
  136. package/web/.next/server/chunks/ssr/[root-of-the-server]__c3ab8422._.js.map +1 -1
  137. package/web/.next/server/chunks/ssr/[root-of-the-server]__f4a463ee._.js +2 -2
  138. package/web/.next/server/chunks/ssr/[root-of-the-server]__f4a463ee._.js.map +1 -1
  139. package/web/.next/server/chunks/ssr/_02ec1aea._.js +1 -1
  140. package/web/.next/server/chunks/ssr/_02ec1aea._.js.map +1 -1
  141. package/web/.next/server/chunks/ssr/{_087a3e78._.js → _64a3c7d3._.js} +2 -2
  142. package/web/.next/server/chunks/ssr/{_087a3e78._.js.map → _64a3c7d3._.js.map} +1 -1
  143. package/web/.next/server/chunks/ssr/_7dca1882._.js +1 -1
  144. package/web/.next/server/chunks/ssr/_7dca1882._.js.map +1 -1
  145. package/web/.next/server/chunks/ssr/_a9f57758._.js +1 -1
  146. package/web/.next/server/chunks/ssr/_a9f57758._.js.map +1 -1
  147. package/web/.next/server/chunks/ssr/_d8575088._.js +1 -1
  148. package/web/.next/server/chunks/ssr/_d8575088._.js.map +1 -1
  149. package/web/.next/server/chunks/ssr/{_c2314ba5._.js → _db4aa3f2._.js} +2 -2
  150. package/web/.next/server/chunks/ssr/{_c2314ba5._.js.map → _db4aa3f2._.js.map} +1 -1
  151. package/web/.next/server/chunks/ssr/_f39a1adb._.js +1 -1
  152. package/web/.next/server/chunks/ssr/_f39a1adb._.js.map +1 -1
  153. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  154. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  155. package/web/.next/server/chunks/ssr/src_presentation_web_8e7fe0d1._.js +2 -2
  156. package/web/.next/server/chunks/ssr/src_presentation_web_8e7fe0d1._.js.map +1 -1
  157. package/web/.next/server/chunks/ssr/src_presentation_web_9cb12e3b._.js +3 -0
  158. package/web/.next/server/chunks/ssr/{src_presentation_web_39dc6c69._.js.map → src_presentation_web_9cb12e3b._.js.map} +1 -1
  159. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_ca051134.js +1 -1
  160. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_ca051134.js.map +1 -1
  161. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1b176e3c.js +1 -1
  162. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1b176e3c.js.map +1 -1
  163. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_bd9f0dda.js +1 -1
  164. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_bd9f0dda.js.map +1 -1
  165. package/web/.next/server/chunks/ssr/src_presentation_web_b9023017._.js +2 -2
  166. package/web/.next/server/chunks/ssr/src_presentation_web_b9023017._.js.map +1 -1
  167. package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js +1 -1
  168. package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js.map +1 -1
  169. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
  170. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
  171. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  172. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  173. package/web/.next/server/pages/500.html +2 -2
  174. package/web/.next/server/server-reference-manifest.js +1 -1
  175. package/web/.next/server/server-reference-manifest.json +38 -38
  176. package/web/.next/static/chunks/{eea5d09deb8afd9a.js → 3c86788cf5aaca4e.js} +1 -1
  177. package/web/.next/static/chunks/{d534a122561e6231.js → 43562d612da226a2.js} +1 -1
  178. package/web/.next/static/chunks/{e22192217a4fc0d4.js → 49ff89ae6f890930.js} +1 -1
  179. package/web/.next/static/chunks/{6d8be29584ad0fdd.js → 5057f2ba8229ec5d.js} +1 -1
  180. package/web/.next/static/chunks/{c1537a58c2e5625b.js → 7940be1ed516ea85.js} +2 -2
  181. package/web/.next/static/chunks/{1ccaceb64fe9084f.js → 8a1096cfc6611914.js} +1 -1
  182. package/web/.next/static/chunks/{822ed01254f97121.js → a1f8e12c7af6f4a4.js} +1 -1
  183. package/web/.next/static/chunks/{776e7f0d6b402430.js → a5f028af12ff0cbe.js} +2 -2
  184. package/web/.next/static/chunks/{4b9ea85ea5fbc162.js → b330ae68d9c239e8.js} +1 -1
  185. package/web/.next/static/chunks/{3d5d625e02456fab.js → bcbe1e3b28395d31.js} +1 -1
  186. package/web/.next/static/chunks/{8f979abfe5512674.js → de479f171ac13ada.js} +1 -1
  187. package/web/.next/static/chunks/{3c0cef220743905a.js → e7cd6b1e7b9f3ad1.js} +1 -1
  188. package/web/.next/static/chunks/f569a6dc0496430f.css +1 -0
  189. package/web/.next/server/chunks/ssr/src_presentation_web_39dc6c69._.js +0 -3
  190. package/web/.next/static/chunks/98dfbecc5ee30ce1.css +0 -1
  191. /package/web/.next/static/{aZANFTRivKlrY7NZ-ovtr → Jwu7miNxo1h4OaodlLCXb}/_buildManifest.js +0 -0
  192. /package/web/.next/static/{aZANFTRivKlrY7NZ-ovtr → Jwu7miNxo1h4OaodlLCXb}/_clientMiddlewareManifest.json +0 -0
  193. /package/web/.next/static/{aZANFTRivKlrY7NZ-ovtr → Jwu7miNxo1h4OaodlLCXb}/_ssgManifest.js +0 -0
@@ -21,6 +21,7 @@ import type { IGitPrService } from '../../ports/output/services/git-pr-service.i
21
21
  export interface DeleteFeatureOptions {
22
22
  cleanup?: boolean;
23
23
  cascadeDelete?: boolean;
24
+ closePr?: boolean;
24
25
  }
25
26
  export declare class DeleteFeatureUseCase {
26
27
  private readonly featureRepo;
@@ -1 +1 @@
1
- {"version":3,"file":"delete-feature.use-case.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/application/use-cases/features/delete-feature.use-case.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qCAAqC,CAAC;AAEnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iEAAiE,CAAC;AAC1G,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2DAA2D,CAAC;AAClG,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,8DAA8D,CAAC;AAChH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6DAA6D,CAAC;AACvG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yDAAyD,CAAC;AAE7F,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,qBACa,oBAAoB;IAEC,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC9B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAE5D,OAAO,CAAC,QAAQ,CAAC,cAAc;IACA,OAAO,CAAC,QAAQ,CAAC,OAAO;IAC9B,OAAO,CAAC,QAAQ,CAAC,YAAY;gBALP,WAAW,EAAE,kBAAkB,EACjC,eAAe,EAAE,gBAAgB,EAE7D,cAAc,EAAE,2BAA2B,EACZ,OAAO,EAAE,mBAAmB,EAClC,YAAY,EAAE,aAAa;IAGjE,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC;IA8BlF,oGAAoG;YACtF,gBAAgB;IAW9B,0DAA0D;YAC5C,iBAAiB;IAQ/B,6DAA6D;YAC/C,yBAAyB;IAWvC,sDAAsD;YACxC,sBAAsB;IAYpC,6EAA6E;YAC/D,oBAAoB;CAsDnC"}
1
+ {"version":3,"file":"delete-feature.use-case.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/application/use-cases/features/delete-feature.use-case.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qCAAqC,CAAC;AAEnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iEAAiE,CAAC;AAC1G,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2DAA2D,CAAC;AAClG,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,8DAA8D,CAAC;AAChH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6DAA6D,CAAC;AACvG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yDAAyD,CAAC;AAE7F,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,qBACa,oBAAoB;IAEC,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC9B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAE5D,OAAO,CAAC,QAAQ,CAAC,cAAc;IACA,OAAO,CAAC,QAAQ,CAAC,OAAO;IAC9B,OAAO,CAAC,QAAQ,CAAC,YAAY;gBALP,WAAW,EAAE,kBAAkB,EACjC,eAAe,EAAE,gBAAgB,EAE7D,cAAc,EAAE,2BAA2B,EACZ,OAAO,EAAE,mBAAmB,EAClC,YAAY,EAAE,aAAa;IAGjE,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC;IA8BlF,oGAAoG;YACtF,gBAAgB;IAW9B,0DAA0D;YAC5C,iBAAiB;IAQ/B,6DAA6D;YAC/C,yBAAyB;IAevC,sDAAsD;YACxC,sBAAsB;IAYpC,6EAA6E;YAC/D,oBAAoB;CA+EnC"}
@@ -25,7 +25,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
25
25
  return function (target, key) { decorator(target, key, paramIndex); }
26
26
  };
27
27
  import { injectable, inject } from 'tsyringe';
28
- import { AgentRunStatus, SdlcLifecycle } from '../../../domain/generated/output.js';
28
+ import { AgentRunStatus, PrStatus, SdlcLifecycle } from '../../../domain/generated/output.js';
29
29
  let DeleteFeatureUseCase = class DeleteFeatureUseCase {
30
30
  featureRepo;
31
31
  worktreeService;
@@ -93,6 +93,10 @@ let DeleteFeatureUseCase = class DeleteFeatureUseCase {
93
93
  });
94
94
  // Soft-delete: sets deletedAt, hiding from normal queries
95
95
  await this.featureRepo.softDelete(feature.id);
96
+ // Sync the in-memory feature object so subsequent update() calls
97
+ // (e.g. PR status update in cleanup) don't overwrite deleted_at back to null.
98
+ feature.lifecycle = SdlcLifecycle.Deleting;
99
+ feature.deletedAt = new Date();
96
100
  }
97
101
  /** Recursively cleanup all children (depth-first). */
98
102
  async cascadeCleanupChildren(parentId, options) {
@@ -133,22 +137,49 @@ let DeleteFeatureUseCase = class DeleteFeatureUseCase {
133
137
  }
134
138
  const cleanup = options?.cleanup !== false;
135
139
  if (cleanup) {
136
- // Delete local feature branch
137
- try {
138
- await this.gitPrService.deleteBranch(feature.repositoryPath, feature.branch);
139
- }
140
- catch {
141
- // Branch might not exist
142
- }
143
- // Delete remote feature branch if it exists
144
- try {
145
- const remoteExists = await this.worktreeService.remoteBranchExists(feature.repositoryPath, feature.branch);
146
- if (remoteExists) {
147
- await this.gitPrService.deleteBranch(feature.repositoryPath, feature.branch, true);
140
+ const shouldDeleteRemote = options?.closePr !== false;
141
+ // Delete local branch, and also remote if closePr is enabled.
142
+ // deleteBranch(cwd, branch, true) deletes local then remote in one call,
143
+ // so we must NOT delete local separately when also deleting remote.
144
+ if (shouldDeleteRemote) {
145
+ let remoteDeleted = false;
146
+ try {
147
+ const remoteExists = await this.worktreeService.remoteBranchExists(feature.repositoryPath, feature.branch);
148
+ if (remoteExists) {
149
+ // Delete local + remote in one call (deleteBranch does local first, then remote)
150
+ await this.gitPrService.deleteBranch(feature.repositoryPath, feature.branch, true);
151
+ remoteDeleted = true;
152
+ }
153
+ else {
154
+ // No remote branch — just delete local
155
+ await this.gitPrService.deleteBranch(feature.repositoryPath, feature.branch);
156
+ }
157
+ }
158
+ catch {
159
+ // Branch cleanup is best-effort
160
+ }
161
+ // Update pr.status to Closed after remote branch deletion (GitHub auto-closes the PR)
162
+ if (remoteDeleted && feature.pr?.status === PrStatus.Open) {
163
+ try {
164
+ await this.featureRepo.update({
165
+ ...feature,
166
+ pr: { ...feature.pr, status: PrStatus.Closed },
167
+ updatedAt: new Date(),
168
+ });
169
+ }
170
+ catch {
171
+ // PR status update is best-effort
172
+ }
148
173
  }
149
174
  }
150
- catch {
151
- // Remote branch cleanup is best-effort
175
+ else {
176
+ // closePr is false — only delete local branch, preserve remote (and the PR)
177
+ try {
178
+ await this.gitPrService.deleteBranch(feature.repositoryPath, feature.branch);
179
+ }
180
+ catch {
181
+ // Branch might not exist
182
+ }
152
183
  }
153
184
  }
154
185
  }
@@ -1 +1 @@
1
- {"version":3,"file":"add-repository.use-case.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/application/use-cases/repositories/add-repository.use-case.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oEAAoE,CAAC;AAEhH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAcD,qBACa,oBAAoB;IAG7B,OAAO,CAAC,QAAQ,CAAC,cAAc;gBAAd,cAAc,EAAE,qBAAqB;IAGlD,OAAO,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC;CA8B9D"}
1
+ {"version":3,"file":"add-repository.use-case.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/application/use-cases/repositories/add-repository.use-case.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oEAAoE,CAAC;AAEhH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAcD,qBACa,oBAAoB;IAG7B,OAAO,CAAC,QAAQ,CAAC,cAAc;gBAAd,cAAc,EAAE,qBAAqB;IAGlD,OAAO,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC;CAiC9D"}
@@ -41,11 +41,14 @@ let AddRepositoryUseCase = class AddRepositoryUseCase {
41
41
  if (existing) {
42
42
  return existing;
43
43
  }
44
- // Check for soft-deleted repository — restore it instead of creating a duplicate
44
+ // Check for soft-deleted repository — restore it instead of creating a duplicate.
45
+ // Reset createdAt so the restored repo sorts as "newest" on the canvas
46
+ // (otherwise the old createdAt would place it above repos added later).
45
47
  const deleted = await this.repositoryRepo.findByPathIncludingDeleted(normalizedPath);
46
48
  if (deleted) {
49
+ const now = new Date();
47
50
  await this.repositoryRepo.restore(deleted.id);
48
- return { ...deleted, deletedAt: undefined, updatedAt: new Date() };
51
+ return { ...deleted, deletedAt: undefined, createdAt: now, updatedAt: now };
49
52
  }
50
53
  const now = new Date();
51
54
  const name = input.name ?? normalizedPath.split('/').pop() ?? normalizedPath;
@@ -94,8 +94,8 @@ let SQLiteRepositoryRepository = SQLiteRepositoryRepository_1 = class SQLiteRepo
94
94
  }
95
95
  async restore(id) {
96
96
  const now = Date.now();
97
- const stmt = this.db.prepare('UPDATE repositories SET deleted_at = NULL, updated_at = ? WHERE id = ?');
98
- stmt.run(now, id);
97
+ const stmt = this.db.prepare('UPDATE repositories SET deleted_at = NULL, created_at = ?, updated_at = ? WHERE id = ?');
98
+ stmt.run(now, now, id);
99
99
  }
100
100
  static normalizeRemoteUrl(url) {
101
101
  return url.replace(/\.git$/, '').toLowerCase();
@@ -4,12 +4,13 @@
4
4
  * Deletes a feature, its worktree, and cancels any running agent.
5
5
  * Optionally cleans up worktree and branches (local + remote).
6
6
  *
7
- * Usage: shep feat del <id> [--force] [--no-cleanup]
7
+ * Usage: shep feat del <id> [--force] [--no-cleanup] [--no-close-pr]
8
8
  *
9
9
  * @example
10
10
  * $ shep feat del feat-123
11
11
  * $ shep feat del feat-123 --force
12
12
  * $ shep feat del feat-123 --force --no-cleanup
13
+ * $ shep feat del feat-123 --force --no-close-pr
13
14
  */
14
15
  import { Command } from 'commander';
15
16
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"del.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/del.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAmD1C"}
1
+ {"version":3,"file":"del.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/del.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CA2E1C"}
@@ -4,12 +4,13 @@
4
4
  * Deletes a feature, its worktree, and cancels any running agent.
5
5
  * Optionally cleans up worktree and branches (local + remote).
6
6
  *
7
- * Usage: shep feat del <id> [--force] [--no-cleanup]
7
+ * Usage: shep feat del <id> [--force] [--no-cleanup] [--no-close-pr]
8
8
  *
9
9
  * @example
10
10
  * $ shep feat del feat-123
11
11
  * $ shep feat del feat-123 --force
12
12
  * $ shep feat del feat-123 --force --no-cleanup
13
+ * $ shep feat del feat-123 --force --no-close-pr
13
14
  */
14
15
  import { Command } from 'commander';
15
16
  import { container } from '../../../../../packages/core/src/infrastructure/di/container.js';
@@ -26,6 +27,7 @@ export function createDelCommand() {
26
27
  .argument('<id>', 'Feature ID or prefix')
27
28
  .option('-f, --force', 'Skip confirmation prompt')
28
29
  .option('--no-cleanup', 'Skip worktree and branch cleanup')
30
+ .option('--no-close-pr', 'Keep the pull request open')
29
31
  .action(async (featureId, options) => {
30
32
  try {
31
33
  // First show what we're about to delete
@@ -52,8 +54,29 @@ export function createDelCommand() {
52
54
  default: true,
53
55
  });
54
56
  }
57
+ // Determine close-PR preference
58
+ const hasOpenPr = feature.pr?.status === 'Open';
59
+ let closePr;
60
+ if (options.closePr === false) {
61
+ closePr = false;
62
+ }
63
+ else if (hasOpenPr && cleanup) {
64
+ if (options.force) {
65
+ closePr = true;
66
+ }
67
+ else {
68
+ closePr = await confirm({
69
+ message: `Also close the pull request? (PR #${feature.pr.number})`,
70
+ default: true,
71
+ });
72
+ }
73
+ }
55
74
  const deleteUseCase = container.resolve(DeleteFeatureUseCase);
56
- await deleteUseCase.execute(feature.id, { cleanup });
75
+ const executeOptions = { cleanup };
76
+ if (closePr !== undefined) {
77
+ executeOptions.closePr = closePr;
78
+ }
79
+ await deleteUseCase.execute(feature.id, executeOptions);
57
80
  messages.newline();
58
81
  messages.success('Feature deleted');
59
82
  console.log(` ${colors.muted('Name:')} ${feature.name}`);
@@ -61,6 +84,9 @@ export function createDelCommand() {
61
84
  if (cleanup) {
62
85
  console.log(` ${colors.muted('Cleanup:')} worktree, local branch, remote branch`);
63
86
  }
87
+ if (closePr && hasOpenPr) {
88
+ console.log(` ${colors.muted('PR:')} #${feature.pr.number} closed`);
89
+ }
64
90
  messages.newline();
65
91
  }
66
92
  catch (error) {
@@ -6,6 +6,14 @@ export interface RepoGitInfo {
6
6
  committer: string;
7
7
  behindCount: number | null;
8
8
  }
9
+ export type GitInfoResult = {
10
+ status: 'loading';
11
+ } | {
12
+ status: 'ready';
13
+ data: RepoGitInfo;
14
+ } | {
15
+ status: 'not-a-repo';
16
+ };
9
17
  export declare function getGraphData(): Promise<{
10
18
  nodes: CanvasNodeType[];
11
19
  edges: Edge[];
@@ -1 +1 @@
1
- {"version":3,"file":"get-graph-data.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/(dashboard)/get-graph-data.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAE5E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAI1C,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAqDD,wBAAsB,YAAY,IAAI,OAAO,CAAC;IAAE,KAAK,EAAE,cAAc,EAAE,CAAC;IAAC,KAAK,EAAE,IAAI,EAAE,CAAA;CAAE,CAAC,CAyDxF"}
1
+ {"version":3,"file":"get-graph-data.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/(dashboard)/get-graph-data.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAE5E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAI1C,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAwFD,MAAM,MAAM,aAAa,GACrB;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,GACtC;IAAE,MAAM,EAAE,YAAY,CAAA;CAAE,CAAC;AA6B7B,wBAAsB,YAAY,IAAI,OAAO,CAAC;IAAE,KAAK,EAAE,cAAc,EAAE,CAAC;IAAC,KAAK,EAAE,IAAI,EAAE,CAAA;CAAE,CAAC,CA6DxF"}
@@ -6,6 +6,11 @@ import { getSettings } from '../../../../../packages/core/src/infrastructure/ser
6
6
  import { layoutWithDagre, CANVAS_LAYOUT_DEFAULTS } from '../../lib/layout-with-dagre.js';
7
7
  import { buildGraphNodes } from '../build-graph-nodes.js';
8
8
  const execFileAsync = promisify(execFileCb);
9
+ // Cache git info per repo — refreshed every GIT_INFO_TTL_MS via background-style check.
10
+ // getGraphData() always reads from cache (zero git calls), and only spawns git
11
+ // processes when the cache entry is older than the TTL.
12
+ const GIT_INFO_TTL_MS = 30_000;
13
+ const gitInfoCache = new Map();
9
14
  async function gitCommand(cwd, args) {
10
15
  try {
11
16
  const opts = IS_WINDOWS ? { cwd, windowsHide: true } : { cwd };
@@ -16,22 +21,38 @@ async function gitCommand(cwd, args) {
16
21
  return null;
17
22
  }
18
23
  }
19
- async function fetchRepoGitInfo(repo) {
24
+ const FIELD_SEP = '\x1f'; // ASCII Unit Separator — safe in git output and child_process
25
+ /** Refresh git info for a single repo (spawns git processes). */
26
+ async function refreshRepoGitInfo(repo) {
20
27
  try {
21
- const [currentBranch, commitMessage, committer] = await Promise.all([
28
+ const headSha = await gitCommand(repo.path, ['rev-parse', 'HEAD']);
29
+ if (!headSha) {
30
+ // Not a git repo (or bare/broken) — cache this so the UI can show it
31
+ gitInfoCache.set(repo.path, { kind: 'not-a-repo', checkedAt: Date.now() });
32
+ return;
33
+ }
34
+ const cached = gitInfoCache.get(repo.path);
35
+ if (cached?.kind === 'repo' && cached.sha === headSha) {
36
+ // HEAD unchanged — just bump checkedAt
37
+ cached.checkedAt = Date.now();
38
+ return;
39
+ }
40
+ // HEAD changed — fetch branch + subject & author in parallel
41
+ const [currentBranch, logLine] = await Promise.all([
22
42
  gitCommand(repo.path, ['symbolic-ref', '--short', 'HEAD']),
23
- gitCommand(repo.path, ['log', '-1', '--format=%s']),
24
- gitCommand(repo.path, ['log', '-1', '--format=%an']),
43
+ gitCommand(repo.path, ['log', '-1', `--format=%s${FIELD_SEP}%an`]),
25
44
  ]);
26
45
  if (!currentBranch)
27
- return null;
28
- // Try to determine the default branch to compute behind count
46
+ return;
47
+ const [commitMessage, committer] = (logLine ?? '').split(FIELD_SEP);
48
+ // Behind count
29
49
  let behindCount = null;
30
- const defaultBranch = await gitCommand(repo.path, [
50
+ const defaultBranchRef = await gitCommand(repo.path, [
31
51
  'symbolic-ref',
32
52
  '--short',
33
53
  'refs/remotes/origin/HEAD',
34
- ]).then((ref) => ref?.replace('origin/', '') ?? null);
54
+ ]);
55
+ const defaultBranch = defaultBranchRef?.replace('origin/', '') ?? null;
35
56
  if (defaultBranch && currentBranch !== defaultBranch) {
36
57
  const behind = await gitCommand(repo.path, [
37
58
  'rev-list',
@@ -42,32 +63,63 @@ async function fetchRepoGitInfo(repo) {
42
63
  if (isNaN(behindCount))
43
64
  behindCount = null;
44
65
  }
45
- else if (!defaultBranch || currentBranch === defaultBranch) {
66
+ else {
46
67
  behindCount = 0;
47
68
  }
48
- return {
49
- branch: currentBranch,
50
- commitMessage: commitMessage ?? 'unknown',
51
- committer: committer ?? 'unknown',
52
- behindCount,
53
- };
69
+ gitInfoCache.set(repo.path, {
70
+ kind: 'repo',
71
+ sha: headSha,
72
+ checkedAt: Date.now(),
73
+ data: {
74
+ branch: currentBranch,
75
+ commitMessage: commitMessage ?? 'unknown',
76
+ committer: committer ?? 'unknown',
77
+ behindCount,
78
+ },
79
+ });
54
80
  }
55
81
  catch {
56
- return null;
82
+ // ignore — stale cache is better than no data
57
83
  }
58
84
  }
85
+ /**
86
+ * Return cached git info for a repo. If the cache is stale (> TTL),
87
+ * kick off a fire-and-forget refresh so the NEXT call gets fresh data.
88
+ * Never blocks getGraphData() with git subprocess calls.
89
+ */
90
+ function getRepoGitInfo(repo) {
91
+ const cached = gitInfoCache.get(repo.path);
92
+ const now = Date.now();
93
+ if (!cached) {
94
+ // First time — trigger async refresh, return loading for this call
95
+ void refreshRepoGitInfo(repo);
96
+ return { status: 'loading' };
97
+ }
98
+ if (now - cached.checkedAt >= GIT_INFO_TTL_MS) {
99
+ // Stale — trigger async refresh, return current data immediately
100
+ void refreshRepoGitInfo(repo);
101
+ }
102
+ if (cached.kind === 'not-a-repo') {
103
+ return { status: 'not-a-repo' };
104
+ }
105
+ return { status: 'ready', data: cached.data };
106
+ }
59
107
  export async function getGraphData() {
60
108
  const listFeatures = resolve('ListFeaturesUseCase');
61
109
  const listRepos = resolve('ListRepositoriesUseCase');
62
110
  const agentRunRepo = resolve('IAgentRunRepository');
63
111
  const [features, repositories] = await Promise.all([listFeatures.execute(), listRepos.execute()]);
64
- // Fetch git info (branch, commit, behind count) for each repository
112
+ // Read git info from cache (zero git calls). Stale entries trigger
113
+ // a fire-and-forget background refresh for the next poll cycle.
65
114
  const repoGitInfoMap = new Map();
66
- await Promise.all(repositories.map(async (repo) => {
67
- const info = await fetchRepoGitInfo(repo);
68
- if (info)
69
- repoGitInfoMap.set(repo.path, info);
70
- }));
115
+ const repoGitStatusMap = new Map();
116
+ for (const repo of repositories) {
117
+ const result = getRepoGitInfo(repo);
118
+ repoGitStatusMap.set(repo.path, result.status);
119
+ if (result.status === 'ready') {
120
+ repoGitInfoMap.set(repo.path, result.data);
121
+ }
122
+ }
71
123
  // PR/CI status is kept fresh by PrSyncWatcher (30s background poll).
72
124
  // No live GitHub calls here — use cached DB values for fast response.
73
125
  const featuresWithRuns = await Promise.all(features.map(async (feature) => {
@@ -80,6 +132,7 @@ export async function getGraphData() {
80
132
  commitEvidence: workflow.commitEvidence,
81
133
  ciWatchEnabled: workflow.ciWatchEnabled,
82
134
  repoGitInfo: repoGitInfoMap,
135
+ repoGitStatus: repoGitStatusMap,
83
136
  });
84
137
  // Enrich feature nodes with deployment status
85
138
  let deploymentService = null;
@@ -1,5 +1,5 @@
1
1
  import type { Feature } from '../../../../../packages/core/src/domain/generated/output.js';
2
- export declare function deleteFeature(featureId: string, cleanup?: boolean, cascadeDelete?: boolean): Promise<{
2
+ export declare function deleteFeature(featureId: string, cleanup?: boolean, cascadeDelete?: boolean, closePr?: boolean): Promise<{
3
3
  feature?: Feature;
4
4
  error?: string;
5
5
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"delete-feature.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/delete-feature.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AAEpE,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,EACjB,aAAa,CAAC,EAAE,OAAO,GACtB,OAAO,CAAC;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAmBhD"}
1
+ {"version":3,"file":"delete-feature.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/delete-feature.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AAEpE,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,EACjB,aAAa,CAAC,EAAE,OAAO,EACvB,OAAO,CAAC,EAAE,OAAO,GAChB,OAAO,CAAC;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAoBhD"}
@@ -1,6 +1,6 @@
1
1
  'use server';
2
2
  import { resolve } from '../../lib/server-container.js';
3
- export async function deleteFeature(featureId, cleanup, cascadeDelete) {
3
+ export async function deleteFeature(featureId, cleanup, cascadeDelete, closePr) {
4
4
  if (!featureId?.trim()) {
5
5
  return { error: 'id is required' };
6
6
  }
@@ -11,6 +11,8 @@ export async function deleteFeature(featureId, cleanup, cascadeDelete) {
11
11
  options.cleanup = cleanup;
12
12
  if (cascadeDelete !== undefined)
13
13
  options.cascadeDelete = cascadeDelete;
14
+ if (closePr !== undefined)
15
+ options.closePr = closePr;
14
16
  const feature = Object.keys(options).length > 0
15
17
  ? await deleteFeatureUseCase.execute(featureId, options)
16
18
  : await deleteFeatureUseCase.execute(featureId);
@@ -27,6 +27,8 @@ export interface BuildGraphNodesOptions {
27
27
  committer: string;
28
28
  behindCount: number | null;
29
29
  }>;
30
+ /** Git info resolution status keyed by repository path */
31
+ repoGitStatus?: Map<string, 'loading' | 'ready' | 'not-a-repo'>;
30
32
  }
31
33
  export declare function buildGraphNodes(repositories: Repository[], featuresWithRuns: FeatureWithRun[], options?: BuildGraphNodesOptions): {
32
34
  nodes: CanvasNodeType[];
@@ -1 +1 @@
1
- {"version":3,"file":"build-graph-nodes.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/app/build-graph-nodes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,sCAAsC,CAAC;AAS1F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAU1C,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,QAAQ,GAAG,IAAI,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,sBAAsB;IACrC,uEAAuE;IACvE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,6EAA6E;IAC7E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,qEAAqE;IACrE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,0FAA0F;IAC1F,WAAW,CAAC,EAAE,GAAG,CACf,MAAM,EACN;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CACzF,CAAC;CACH;AAED,wBAAgB,eAAe,CAC7B,YAAY,EAAE,UAAU,EAAE,EAC1B,gBAAgB,EAAE,cAAc,EAAE,EAClC,OAAO,CAAC,EAAE,sBAAsB,GAC/B;IAAE,KAAK,EAAE,cAAc,EAAE,CAAC;IAAC,KAAK,EAAE,IAAI,EAAE,CAAA;CAAE,CAkG5C"}
1
+ {"version":3,"file":"build-graph-nodes.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/app/build-graph-nodes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,sCAAsC,CAAC;AAS1F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAU1C,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,QAAQ,GAAG,IAAI,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,sBAAsB;IACrC,uEAAuE;IACvE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,6EAA6E;IAC7E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,qEAAqE;IACrE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,0FAA0F;IAC1F,WAAW,CAAC,EAAE,GAAG,CACf,MAAM,EACN;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CACzF,CAAC;IACF,0DAA0D;IAC1D,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,YAAY,CAAC,CAAC;CACjE;AAED,wBAAgB,eAAe,CAC7B,YAAY,EAAE,UAAU,EAAE,EAC1B,gBAAgB,EAAE,cAAc,EAAE,EAClC,OAAO,CAAC,EAAE,sBAAsB,GAC/B;IAAE,KAAK,EAAE,cAAc,EAAE,CAAC;IAAC,KAAK,EAAE,IAAI,EAAE,CAAA;CAAE,CAoG5C"}
@@ -32,6 +32,7 @@ export function buildGraphNodes(repositories, featuresWithRuns, options) {
32
32
  coveredPaths.add(normalizedRepoPath);
33
33
  const repoNodeId = `repo-${repo.id}`;
34
34
  const gitInfo = options?.repoGitInfo?.get(repo.path);
35
+ const gitInfoStatus = options?.repoGitStatus?.get(repo.path) ?? 'loading';
35
36
  nodes.push({
36
37
  id: repoNodeId,
37
38
  type: 'repositoryNode',
@@ -41,6 +42,7 @@ export function buildGraphNodes(repositories, featuresWithRuns, options) {
41
42
  repositoryPath: normalizedRepoPath,
42
43
  id: repo.id,
43
44
  createdAt: repo.createdAt instanceof Date ? repo.createdAt.getTime() : Number(repo.createdAt),
45
+ gitInfoStatus,
44
46
  ...(gitInfo && {
45
47
  branch: gitInfo.branch,
46
48
  commitMessage: gitInfo.commitMessage,
@@ -1 +1 @@
1
- {"version":3,"file":"feature-drawer-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/control-center-drawer/feature-drawer-client.tsx"],"names":[],"mappings":"AAuCA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAI/D,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,UAAU,CAAC;IACjB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,wBAAwB,2CAqkB1F"}
1
+ {"version":3,"file":"feature-drawer-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/control-center-drawer/feature-drawer-client.tsx"],"names":[],"mappings":"AAuCA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAI/D,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,UAAU,CAAC;IACjB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,wBAAwB,2CAskB1F"}
@@ -256,7 +256,7 @@ export function FeatureDrawerClient({ view: initialView, urlTab }) {
256
256
  }, [view, featureNode, prdData, prdSelections, onClose]);
257
257
  const handleTechApprove = useCallback(() => handleSimpleApprove('Plan'), [handleSimpleApprove]);
258
258
  const handleMergeApprove = useCallback(() => handleSimpleApprove('Merge'), [handleSimpleApprove]);
259
- const handleDelete = useCallback(async (featureId, cleanup, cascadeDelete) => {
259
+ const handleDelete = useCallback(async (featureId, cleanup, cascadeDelete, closePr) => {
260
260
  setIsDeleting(true);
261
261
  // Close the delete dialog and drawer before the server action so the
262
262
  // user sees immediate feedback. We dispatch a DOM event so the canvas
@@ -264,7 +264,7 @@ export function FeatureDrawerClient({ view: initialView, urlTab }) {
264
264
  // mutation guard, node removal) in parallel.
265
265
  setDeleteDialogOpen(false);
266
266
  window.dispatchEvent(new CustomEvent('shep:feature-delete-requested', {
267
- detail: { featureId, cleanup, cascadeDelete },
267
+ detail: { featureId, cleanup, cascadeDelete, closePr },
268
268
  }));
269
269
  router.push('/');
270
270
  }, [router]);
@@ -336,7 +336,7 @@ export function FeatureDrawerClient({ view: initialView, urlTab }) {
336
336
  const repoName = featureNode.repositoryName ??
337
337
  featureNode.repositoryPath.split('/').filter(Boolean).at(-1) ??
338
338
  '';
339
- header = (_jsxs(_Fragment, { children: [_jsxs("div", { "data-testid": "feature-drawer-header", children: [_jsx(DrawerTitle, { children: featureNode.name }), repoName ? (_jsxs("div", { className: "flex items-center gap-1.5 pt-0.5", children: [_jsx(Code2, { className: "text-muted-foreground size-3.5 shrink-0" }), featureNode.remoteUrl ? (_jsxs("a", { href: featureNode.remoteUrl, target: "_blank", rel: "noopener noreferrer", className: "text-muted-foreground hover:text-foreground inline-flex items-center gap-1 text-xs transition-colors", "data-testid": "feature-drawer-repo-link", children: [repoName, _jsx(ExternalLink, { className: "size-3" })] })) : (_jsx("span", { className: "text-muted-foreground text-xs", children: repoName }))] })) : null, _jsx(DrawerDescription, { className: "sr-only", children: featureNode.name })] }), featureActionsInput ? (_jsxs("div", { className: "flex items-center gap-2 pt-2", "data-testid": "feature-drawer-actions", 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, _jsxs("div", { className: "ml-auto flex items-center gap-1.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.featureId ? (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Delete feature", disabled: isDeleting, className: "text-muted-foreground hover:text-destructive", "data-testid": "feature-drawer-delete", onClick: () => setDeleteDialogOpen(true), children: isDeleting ? (_jsx(Loader2, { className: "size-4 animate-spin" })) : (_jsx(Trash2, { className: "size-4" })) }), _jsx(DeleteFeatureDialog, { open: deleteDialogOpen, onOpenChange: setDeleteDialogOpen, onConfirm: (cleanup, cascadeDelete) => handleDelete(featureNode.featureId, cleanup, cascadeDelete), isDeleting: isDeleting, featureName: featureNode.name, featureId: featureNode.featureId, hasChildren: featureNode.hasChildren })] })) : null] })) : null] }));
339
+ header = (_jsxs(_Fragment, { children: [_jsxs("div", { "data-testid": "feature-drawer-header", children: [_jsx(DrawerTitle, { children: featureNode.name }), repoName ? (_jsxs("div", { className: "flex items-center gap-1.5 pt-0.5", children: [_jsx(Code2, { className: "text-muted-foreground size-3.5 shrink-0" }), featureNode.remoteUrl ? (_jsxs("a", { href: featureNode.remoteUrl, target: "_blank", rel: "noopener noreferrer", className: "text-muted-foreground hover:text-foreground inline-flex items-center gap-1 text-xs transition-colors", "data-testid": "feature-drawer-repo-link", children: [repoName, _jsx(ExternalLink, { className: "size-3" })] })) : (_jsx("span", { className: "text-muted-foreground text-xs", children: repoName }))] })) : null, _jsx(DrawerDescription, { className: "sr-only", children: featureNode.name })] }), featureActionsInput ? (_jsxs("div", { className: "flex items-center gap-2 pt-2", "data-testid": "feature-drawer-actions", 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, _jsxs("div", { className: "ml-auto flex items-center gap-1.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.featureId ? (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Delete feature", disabled: isDeleting, className: "text-muted-foreground hover:text-destructive", "data-testid": "feature-drawer-delete", onClick: () => setDeleteDialogOpen(true), children: isDeleting ? (_jsx(Loader2, { className: "size-4 animate-spin" })) : (_jsx(Trash2, { className: "size-4" })) }), _jsx(DeleteFeatureDialog, { open: deleteDialogOpen, onOpenChange: setDeleteDialogOpen, onConfirm: (cleanup, cascadeDelete, closePr) => handleDelete(featureNode.featureId, cleanup, cascadeDelete, closePr), isDeleting: isDeleting, featureName: featureNode.name, featureId: featureNode.featureId, hasChildren: featureNode.hasChildren, hasOpenPr: !!featureNode.pr && featureNode.pr.status === 'Open' })] })) : null] })) : null] }));
340
340
  }
341
341
  // ── Body ──────────────────────────────────────────────────────────────
342
342
  let body = null;
@@ -1,10 +1,11 @@
1
1
  export interface DeleteFeatureDialogProps {
2
2
  open: boolean;
3
3
  onOpenChange: (open: boolean) => void;
4
- onConfirm: (cleanup: boolean, cascadeDelete: boolean) => void;
4
+ onConfirm: (cleanup: boolean, cascadeDelete: boolean, closePr: boolean) => void;
5
5
  isDeleting: boolean;
6
6
  featureName: string;
7
7
  featureId: string;
8
8
  hasChildren?: boolean;
9
+ hasOpenPr?: boolean;
9
10
  }
10
11
  //# sourceMappingURL=delete-feature-dialog-config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"delete-feature-dialog-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/delete-feature-dialog/delete-feature-dialog-config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9D,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB"}
1
+ {"version":3,"file":"delete-feature-dialog-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/delete-feature-dialog/delete-feature-dialog-config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAChF,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB"}
@@ -1,3 +1,3 @@
1
1
  import type { DeleteFeatureDialogProps } from './delete-feature-dialog-config.js';
2
- export declare function DeleteFeatureDialog({ open, onOpenChange, onConfirm, isDeleting, featureName, featureId, hasChildren, }: DeleteFeatureDialogProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function DeleteFeatureDialog({ open, onOpenChange, onConfirm, isDeleting, featureName, featureId, hasChildren, hasOpenPr, }: DeleteFeatureDialogProps): import("react/jsx-runtime").JSX.Element;
3
3
  //# sourceMappingURL=delete-feature-dialog.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"delete-feature-dialog.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/delete-feature-dialog/delete-feature-dialog.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAE/E,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,UAAU,EACV,WAAW,EACX,SAAS,EACT,WAAW,GACZ,EAAE,wBAAwB,2CAuE1B"}
1
+ {"version":3,"file":"delete-feature-dialog.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/delete-feature-dialog/delete-feature-dialog.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAE/E,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,UAAU,EACV,WAAW,EACX,SAAS,EACT,WAAW,EACX,SAAS,GACV,EAAE,wBAAwB,2CA+F1B"}
@@ -5,14 +5,24 @@ import { Loader2 } from 'lucide-react';
5
5
  import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '../../ui/alert-dialog.js';
6
6
  import { Checkbox } from '../../ui/checkbox.js';
7
7
  import { Label } from '../../ui/label.js';
8
- export function DeleteFeatureDialog({ open, onOpenChange, onConfirm, isDeleting, featureName, featureId, hasChildren, }) {
8
+ export function DeleteFeatureDialog({ open, onOpenChange, onConfirm, isDeleting, featureName, featureId, hasChildren, hasOpenPr, }) {
9
9
  const [cleanup, setCleanup] = useState(true);
10
10
  const [cascadeDelete, setCascadeDelete] = useState(false);
11
+ const [closePr, setClosePr] = useState(true);
11
12
  useEffect(() => {
12
13
  if (open) {
13
14
  setCleanup(true);
14
15
  setCascadeDelete(false);
16
+ setClosePr(true);
15
17
  }
16
18
  }, [open]);
17
- return (_jsx(AlertDialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(AlertDialogContent, { onCloseAutoFocus: (e) => e.preventDefault(), children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Delete feature?" }), _jsxs(AlertDialogDescription, { children: ["This will permanently delete ", _jsx("strong", { children: featureName }), " (", featureId, "). This action cannot be undone."] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Checkbox, { id: "cleanup-checkbox", checked: cleanup, onCheckedChange: (checked) => setCleanup(checked === true), disabled: isDeleting, "aria-label": "Clean up worktree and branches" }), _jsx(Label, { htmlFor: "cleanup-checkbox", className: "cursor-pointer text-sm", children: "Clean up worktree and branches" })] }), hasChildren ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Checkbox, { id: "cascade-delete-checkbox", checked: cascadeDelete, onCheckedChange: (checked) => setCascadeDelete(checked === true), disabled: isDeleting, "aria-label": "Delete sub-features" }), _jsx(Label, { htmlFor: "cascade-delete-checkbox", className: "cursor-pointer text-sm", children: "Delete sub-features" })] })) : null] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: isDeleting, onClick: () => onOpenChange(false), children: "Cancel" }), _jsx(AlertDialogAction, { variant: "destructive", disabled: isDeleting, onClick: () => onConfirm(cleanup, cascadeDelete), children: isDeleting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Deleting\u2026"] })) : ('Delete') })] })] }) }));
19
+ useEffect(() => {
20
+ if (cleanup) {
21
+ setClosePr(true);
22
+ }
23
+ else {
24
+ setClosePr(false);
25
+ }
26
+ }, [cleanup]);
27
+ return (_jsx(AlertDialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(AlertDialogContent, { onCloseAutoFocus: (e) => e.preventDefault(), children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Delete feature?" }), _jsxs(AlertDialogDescription, { children: ["This will permanently delete ", _jsx("strong", { children: featureName }), " (", featureId, "). This action cannot be undone."] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Checkbox, { id: "cleanup-checkbox", checked: cleanup, onCheckedChange: (checked) => setCleanup(checked === true), disabled: isDeleting, "aria-label": "Clean up worktree and branches" }), _jsx(Label, { htmlFor: "cleanup-checkbox", className: "cursor-pointer text-sm", children: "Clean up worktree and branches" })] }), hasChildren ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Checkbox, { id: "cascade-delete-checkbox", checked: cascadeDelete, onCheckedChange: (checked) => setCascadeDelete(checked === true), disabled: isDeleting, "aria-label": "Delete sub-features" }), _jsx(Label, { htmlFor: "cascade-delete-checkbox", className: "cursor-pointer text-sm", children: "Delete sub-features" })] })) : null, hasOpenPr ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Checkbox, { id: "close-pr-checkbox", checked: closePr, onCheckedChange: (checked) => setClosePr(checked === true), disabled: isDeleting || !cleanup, "aria-label": "Close pull request" }), _jsx(Label, { htmlFor: "close-pr-checkbox", className: "cursor-pointer text-sm", children: "Close pull request" })] })) : null] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: isDeleting, onClick: () => onOpenChange(false), children: "Cancel" }), _jsx(AlertDialogAction, { variant: "destructive", disabled: isDeleting, onClick: () => onConfirm(cleanup, cascadeDelete, hasOpenPr ? closePr : false), children: isDeleting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Deleting\u2026"] })) : ('Delete') })] })] }) }));
18
28
  }
@@ -7,4 +7,7 @@ export declare const Default: Story;
7
7
  export declare const WithChildren: Story;
8
8
  export declare const Deleting: Story;
9
9
  export declare const DeletingWithChildren: Story;
10
+ export declare const WithOpenPr: Story;
11
+ export declare const WithOpenPrAndChildren: Story;
12
+ export declare const DeletingWithOpenPr: Story;
10
13
  //# sourceMappingURL=delete-feature-dialog.stories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"delete-feature-dialog.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/delete-feature-dialog/delete-feature-dialog.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE9D,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,mBAAmB,CAe1C,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAElD,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC,eAAO,MAAM,YAAY,EAAE,KAI1B,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAItB,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,KAKlC,CAAC"}
1
+ {"version":3,"file":"delete-feature-dialog.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/delete-feature-dialog/delete-feature-dialog.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE9D,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,mBAAmB,CAe1C,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAElD,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC,eAAO,MAAM,YAAY,EAAE,KAI1B,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAItB,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,KAKlC,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAIxB,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,KAKnC,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAKhC,CAAC"}
@@ -34,3 +34,20 @@ export const DeletingWithChildren = {
34
34
  hasChildren: true,
35
35
  },
36
36
  };
37
+ export const WithOpenPr = {
38
+ args: {
39
+ hasOpenPr: true,
40
+ },
41
+ };
42
+ export const WithOpenPrAndChildren = {
43
+ args: {
44
+ hasOpenPr: true,
45
+ hasChildren: true,
46
+ },
47
+ };
48
+ export const DeletingWithOpenPr = {
49
+ args: {
50
+ isDeleting: true,
51
+ hasOpenPr: true,
52
+ },
53
+ };
@@ -89,7 +89,7 @@ export interface FeatureNodeData {
89
89
  onAction?: () => void;
90
90
  onSettings?: () => void;
91
91
  hasChildren?: boolean;
92
- onDelete?: (featureId: string, cleanup?: boolean, cascadeDelete?: boolean) => void;
92
+ onDelete?: (featureId: string, cleanup?: boolean, cascadeDelete?: boolean, closePr?: boolean) => void;
93
93
  onRetry?: (featureId: string) => void;
94
94
  onStart?: (featureId: string) => void;
95
95
  onStop?: (featureId: string) => void;