@shepai/cli 1.137.0 → 1.138.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 (252) hide show
  1. package/apis/json-schema/Feature.yaml +3 -0
  2. package/apis/json-schema/SdlcLifecycle.yaml +1 -0
  3. package/dist/packages/core/src/application/ports/output/repositories/feature-repository.interface.d.ts +2 -0
  4. package/dist/packages/core/src/application/ports/output/repositories/feature-repository.interface.d.ts.map +1 -1
  5. package/dist/packages/core/src/application/use-cases/features/archive-feature.use-case.d.ts +20 -0
  6. package/dist/packages/core/src/application/use-cases/features/archive-feature.use-case.d.ts.map +1 -0
  7. package/dist/packages/core/src/application/use-cases/features/archive-feature.use-case.js +73 -0
  8. package/dist/packages/core/src/application/use-cases/features/unarchive-feature.use-case.d.ts +20 -0
  9. package/dist/packages/core/src/application/use-cases/features/unarchive-feature.use-case.d.ts.map +1 -0
  10. package/dist/packages/core/src/application/use-cases/features/unarchive-feature.use-case.js +65 -0
  11. package/dist/packages/core/src/domain/generated/output.d.ts +6 -1
  12. package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
  13. package/dist/packages/core/src/domain/generated/output.js +1 -0
  14. package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
  15. package/dist/packages/core/src/infrastructure/di/container.js +10 -0
  16. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.d.ts +1 -0
  17. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.d.ts.map +1 -1
  18. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.js +6 -0
  19. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/044-add-previous-lifecycle.d.ts +12 -0
  20. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/044-add-previous-lifecycle.d.ts.map +1 -0
  21. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/044-add-previous-lifecycle.js +16 -0
  22. package/dist/packages/core/src/infrastructure/repositories/sqlite-feature.repository.d.ts.map +1 -1
  23. package/dist/packages/core/src/infrastructure/repositories/sqlite-feature.repository.js +7 -2
  24. package/dist/src/presentation/cli/commands/feat/archive.command.d.ts +18 -0
  25. package/dist/src/presentation/cli/commands/feat/archive.command.d.ts.map +1 -0
  26. package/dist/src/presentation/cli/commands/feat/archive.command.js +54 -0
  27. package/dist/src/presentation/cli/commands/feat/index.d.ts.map +1 -1
  28. package/dist/src/presentation/cli/commands/feat/index.js +5 -1
  29. package/dist/src/presentation/cli/commands/feat/ls.command.d.ts.map +1 -1
  30. package/dist/src/presentation/cli/commands/feat/ls.command.js +5 -0
  31. package/dist/src/presentation/cli/commands/feat/unarchive.command.d.ts +17 -0
  32. package/dist/src/presentation/cli/commands/feat/unarchive.command.d.ts.map +1 -0
  33. package/dist/src/presentation/cli/commands/feat/unarchive.command.js +42 -0
  34. package/dist/src/presentation/web/app/(dashboard)/get-graph-data.d.ts.map +1 -1
  35. package/dist/src/presentation/web/app/(dashboard)/get-graph-data.js +6 -1
  36. package/dist/src/presentation/web/app/actions/archive-feature.d.ts +6 -0
  37. package/dist/src/presentation/web/app/actions/archive-feature.d.ts.map +1 -0
  38. package/dist/src/presentation/web/app/actions/archive-feature.js +16 -0
  39. package/dist/src/presentation/web/app/actions/unarchive-feature.d.ts +6 -0
  40. package/dist/src/presentation/web/app/actions/unarchive-feature.d.ts.map +1 -0
  41. package/dist/src/presentation/web/app/actions/unarchive-feature.js +16 -0
  42. package/dist/src/presentation/web/app/api/agent-events/route.d.ts.map +1 -1
  43. package/dist/src/presentation/web/app/api/agent-events/route.js +1 -0
  44. package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.d.ts.map +1 -1
  45. package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.js +6 -0
  46. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts +3 -1
  47. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts.map +1 -1
  48. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.js +11 -1
  49. package/dist/src/presentation/web/components/common/feature-node/feature-node.d.ts.map +1 -1
  50. package/dist/src/presentation/web/components/common/feature-node/feature-node.js +25 -8
  51. package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts +5 -0
  52. package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts.map +1 -1
  53. package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.js +75 -1
  54. package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
  55. package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +13 -4
  56. package/dist/src/presentation/web/components/features/control-center/control-center.stories.d.ts +6 -0
  57. package/dist/src/presentation/web/components/features/control-center/control-center.stories.d.ts.map +1 -1
  58. package/dist/src/presentation/web/components/features/control-center/control-center.stories.js +70 -0
  59. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts +6 -0
  60. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
  61. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +50 -2
  62. package/dist/src/presentation/web/components/layouts/app-shell/app-shell.d.ts.map +1 -1
  63. package/dist/src/presentation/web/components/layouts/app-shell/app-shell.js +1 -3
  64. package/dist/src/presentation/web/components/layouts/app-sidebar/app-sidebar.d.ts.map +1 -1
  65. package/dist/src/presentation/web/components/layouts/app-sidebar/app-sidebar.js +45 -5
  66. package/dist/src/presentation/web/hooks/sidebar-features-context.d.ts.map +1 -1
  67. package/dist/src/presentation/web/hooks/sidebar-features-context.js +1 -0
  68. package/dist/src/presentation/web/hooks/use-graph-state.d.ts +1 -1
  69. package/dist/src/presentation/web/hooks/use-graph-state.d.ts.map +1 -1
  70. package/dist/src/presentation/web/hooks/use-graph-state.js +17 -2
  71. package/dist/src/presentation/web/hooks/use-sound-action.d.ts +4 -4
  72. package/dist/src/presentation/web/hooks/use-sound-action.js +2 -2
  73. package/dist/src/presentation/web/lib/derive-graph.d.ts +4 -0
  74. package/dist/src/presentation/web/lib/derive-graph.d.ts.map +1 -1
  75. package/dist/src/presentation/web/lib/derive-graph.js +11 -0
  76. package/dist/tsconfig.build.tsbuildinfo +1 -1
  77. package/package.json +1 -1
  78. package/web/.next/BUILD_ID +1 -1
  79. package/web/.next/build-manifest.json +2 -2
  80. package/web/.next/fallback-build-manifest.json +2 -2
  81. package/web/.next/prerender-manifest.json +3 -3
  82. package/web/.next/required-server-files.js +2 -2
  83. package/web/.next/required-server-files.json +2 -2
  84. package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +82 -52
  85. package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js +1 -1
  86. package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
  87. package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
  88. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +82 -52
  89. package/web/.next/server/app/(dashboard)/@drawer/create/page.js +1 -1
  90. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  91. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  92. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +98 -68
  93. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js +1 -1
  94. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  95. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  96. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +98 -68
  97. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +1 -1
  98. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  99. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  100. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +78 -48
  101. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js +1 -1
  102. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  103. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  104. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +82 -52
  105. package/web/.next/server/app/(dashboard)/create/page.js +1 -1
  106. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  107. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  108. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +98 -68
  109. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js +1 -1
  110. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  111. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  112. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +98 -68
  113. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +1 -1
  114. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  115. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  116. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +78 -48
  117. package/web/.next/server/app/(dashboard)/page.js +1 -1
  118. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  119. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  120. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +78 -48
  121. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js +1 -1
  122. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  123. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  124. package/web/.next/server/app/_global-error.html +2 -2
  125. package/web/.next/server/app/_global-error.rsc +1 -1
  126. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  127. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  128. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  129. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  130. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  131. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +3 -3
  132. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  133. package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
  134. package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
  135. package/web/.next/server/app/api/graph-data/route.js.nft.json +1 -1
  136. package/web/.next/server/app/settings/page/server-reference-manifest.json +8 -8
  137. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  138. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  139. package/web/.next/server/app/skills/page/server-reference-manifest.json +8 -8
  140. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  141. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  142. package/web/.next/server/app/tools/page/server-reference-manifest.json +8 -8
  143. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  144. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  145. package/web/.next/server/app/version/page/server-reference-manifest.json +3 -3
  146. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  147. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js +1 -1
  148. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js.map +1 -1
  149. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js +2 -2
  150. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js.map +1 -1
  151. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  152. package/web/.next/server/chunks/[root-of-the-server]__c6e32a23._.js +1 -1
  153. package/web/.next/server/chunks/[root-of-the-server]__c6e32a23._.js.map +1 -1
  154. package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js +1 -1
  155. package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js.map +1 -1
  156. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  157. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  158. package/web/.next/server/chunks/ssr/{[root-of-the-server]__90fdc0ee._.js → [root-of-the-server]__2c703b78._.js} +2 -2
  159. package/web/.next/server/chunks/ssr/{[root-of-the-server]__90fdc0ee._.js.map → [root-of-the-server]__2c703b78._.js.map} +1 -1
  160. package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
  161. package/web/.next/server/chunks/ssr/[root-of-the-server]__3ef34e4c._.js +1 -1
  162. package/web/.next/server/chunks/ssr/[root-of-the-server]__43f51aa6._.js +1 -1
  163. package/web/.next/server/chunks/ssr/[root-of-the-server]__43f51aa6._.js.map +1 -1
  164. package/web/.next/server/chunks/ssr/{[root-of-the-server]__1626f5d7._.js → [root-of-the-server]__59a3897b._.js} +2 -2
  165. package/web/.next/server/chunks/ssr/{[root-of-the-server]__1626f5d7._.js.map → [root-of-the-server]__59a3897b._.js.map} +1 -1
  166. package/web/.next/server/chunks/ssr/[root-of-the-server]__6ec59045._.js +1 -1
  167. package/web/.next/server/chunks/ssr/[root-of-the-server]__6ec59045._.js.map +1 -1
  168. package/web/.next/server/chunks/ssr/{[root-of-the-server]__49557873._.js → [root-of-the-server]__78aecdd5._.js} +2 -2
  169. package/web/.next/server/chunks/ssr/{[root-of-the-server]__a7259d16._.js.map → [root-of-the-server]__78aecdd5._.js.map} +1 -1
  170. package/web/.next/server/chunks/ssr/[root-of-the-server]__815546bd._.js +1 -1
  171. package/web/.next/server/chunks/ssr/[root-of-the-server]__815546bd._.js.map +1 -1
  172. package/web/.next/server/chunks/ssr/[root-of-the-server]__a5f9c6e5._.js +2 -2
  173. package/web/.next/server/chunks/ssr/[root-of-the-server]__a5f9c6e5._.js.map +1 -1
  174. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +2 -2
  175. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
  176. package/web/.next/server/chunks/ssr/[root-of-the-server]__d48c5b11._.js +1 -1
  177. package/web/.next/server/chunks/ssr/[root-of-the-server]__d48c5b11._.js.map +1 -1
  178. package/web/.next/server/chunks/ssr/{[root-of-the-server]__a7259d16._.js → [root-of-the-server]__f222995d._.js} +2 -2
  179. package/web/.next/server/chunks/ssr/{[root-of-the-server]__49557873._.js.map → [root-of-the-server]__f222995d._.js.map} +1 -1
  180. package/web/.next/server/chunks/ssr/_0020fddd._.js +1 -1
  181. package/web/.next/server/chunks/ssr/_0020fddd._.js.map +1 -1
  182. package/web/.next/server/chunks/ssr/_02ec1aea._.js +1 -1
  183. package/web/.next/server/chunks/ssr/_02ec1aea._.js.map +1 -1
  184. package/web/.next/server/chunks/ssr/{_48a8ee28._.js → _0c5f56e3._.js} +3 -3
  185. package/web/.next/server/chunks/ssr/{_6e8c85b1._.js.map → _0c5f56e3._.js.map} +1 -1
  186. package/web/.next/server/chunks/ssr/{_1a09002f._.js → _1b719e7f._.js} +2 -2
  187. package/web/.next/server/chunks/ssr/{_939287c5._.js.map → _1b719e7f._.js.map} +1 -1
  188. package/web/.next/server/chunks/ssr/_1c296899._.js +4 -0
  189. package/web/.next/server/chunks/ssr/_1c296899._.js.map +1 -0
  190. package/web/.next/server/chunks/ssr/_2119691d._.js +3 -0
  191. package/web/.next/server/chunks/ssr/{_037421b9._.js.map → _2119691d._.js.map} +1 -1
  192. package/web/.next/server/chunks/ssr/{_939287c5._.js → _37e8548b._.js} +2 -2
  193. package/web/.next/server/chunks/ssr/{_149f6559._.js.map → _37e8548b._.js.map} +1 -1
  194. package/web/.next/server/chunks/ssr/{_149f6559._.js → _55d763e2._.js} +2 -2
  195. package/web/.next/server/chunks/ssr/{_1a09002f._.js.map → _55d763e2._.js.map} +1 -1
  196. package/web/.next/server/chunks/ssr/{_6e8c85b1._.js → _64bdfc6f._.js} +3 -3
  197. package/web/.next/server/chunks/ssr/{_48a8ee28._.js.map → _64bdfc6f._.js.map} +1 -1
  198. package/web/.next/server/chunks/ssr/_7dca1882._.js +1 -1
  199. package/web/.next/server/chunks/ssr/_7dca1882._.js.map +1 -1
  200. package/web/.next/server/chunks/ssr/_a9f57758._.js +1 -1
  201. package/web/.next/server/chunks/ssr/_a9f57758._.js.map +1 -1
  202. package/web/.next/server/chunks/ssr/{_83220ba0._.js → _b71645b4._.js} +2 -2
  203. package/web/.next/server/chunks/ssr/{_83220ba0._.js.map → _b71645b4._.js.map} +1 -1
  204. package/web/.next/server/chunks/ssr/_d4b20e29._.js.map +1 -1
  205. package/web/.next/server/chunks/ssr/_d8575088._.js +1 -1
  206. package/web/.next/server/chunks/ssr/_d8575088._.js.map +1 -1
  207. package/web/.next/server/chunks/ssr/_f39a1adb._.js +1 -1
  208. package/web/.next/server/chunks/ssr/_f39a1adb._.js.map +1 -1
  209. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  210. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  211. package/web/.next/server/chunks/ssr/{src_presentation_web_951640a3._.js → src_presentation_web_844c9657._.js} +2 -2
  212. package/web/.next/server/chunks/ssr/{src_presentation_web_951640a3._.js.map → src_presentation_web_844c9657._.js.map} +1 -1
  213. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1b176e3c.js +1 -1
  214. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1b176e3c.js.map +1 -1
  215. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_bd9f0dda.js +1 -1
  216. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_bd9f0dda.js.map +1 -1
  217. package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js +1 -1
  218. package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js.map +1 -1
  219. package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js +1 -1
  220. package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js.map +1 -1
  221. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
  222. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
  223. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  224. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  225. package/web/.next/server/pages/500.html +2 -2
  226. package/web/.next/server/server-reference-manifest.js +1 -1
  227. package/web/.next/server/server-reference-manifest.json +484 -328
  228. package/web/.next/static/chunks/0e9ca746aadf6c8d.js +1 -0
  229. package/web/.next/static/chunks/{92d66288f6e5f235.js → 2e9491b73bcb5948.js} +1 -1
  230. package/web/.next/static/chunks/{5fe8c723c668f1ef.js → 3722a9f53d9069d1.js} +2 -2
  231. package/web/.next/static/chunks/47ae402c9d3ad1ca.js +1 -0
  232. package/web/.next/static/chunks/4c760047d0972f96.js +2 -0
  233. package/web/.next/static/chunks/{f3e37f559952d6a1.js → 6c097d096a289e07.js} +1 -1
  234. package/web/.next/static/chunks/{f070c67389a686ff.js → 7e7537ab107a5ed5.js} +1 -1
  235. package/web/.next/static/chunks/{e4024647334fa56f.js → a2a9cfdc7ff45d62.js} +1 -1
  236. package/web/.next/static/chunks/{0bd451437bb30264.js → ad74ee85368e7d04.js} +1 -1
  237. package/web/.next/static/chunks/{5aa808c7bec008f3.js → c581e1010c5c217e.js} +1 -1
  238. package/web/.next/static/chunks/{29fe67f664ff2dc6.js → ce8197531c98b4ea.js} +1 -1
  239. package/web/.next/static/chunks/eb35e98c31806836.css +1 -0
  240. package/web/.next/static/chunks/{d73ad54d54cd7e1d.js → ec01c627aae92366.js} +1 -1
  241. package/web/.next/static/chunks/f15f1f16948e7263.js +1 -0
  242. package/web/.next/server/chunks/ssr/_037421b9._.js +0 -3
  243. package/web/.next/server/chunks/ssr/_9cb5f6e3._.js +0 -4
  244. package/web/.next/server/chunks/ssr/_9cb5f6e3._.js.map +0 -1
  245. package/web/.next/static/chunks/ab3afb0b942c1eb2.css +0 -1
  246. package/web/.next/static/chunks/c17f8118fc760923.js +0 -1
  247. package/web/.next/static/chunks/c473e2924fbd8fd1.js +0 -1
  248. package/web/.next/static/chunks/db80bb0df7318fac.js +0 -2
  249. package/web/.next/static/chunks/fa89e48e0d67e4dc.js +0 -1
  250. /package/web/.next/static/{i847vZGPwgKFPH7P5kTBl → 0zlf5ntHpnR5YfkgEsA-1}/_buildManifest.js +0 -0
  251. /package/web/.next/static/{i847vZGPwgKFPH7P5kTBl → 0zlf5ntHpnR5YfkgEsA-1}/_clientMiddlewareManifest.json +0 -0
  252. /package/web/.next/static/{i847vZGPwgKFPH7P5kTBl → 0zlf5ntHpnR5YfkgEsA-1}/_ssgManifest.js +0 -0
@@ -21,6 +21,8 @@ import { createApproveCommand } from './approve.command.js';
21
21
  import { createRejectCommand } from './reject.command.js';
22
22
  import { createLogsCommand } from './logs.command.js';
23
23
  import { createAdoptCommand } from './adopt.command.js';
24
+ import { createArchiveCommand } from './archive.command.js';
25
+ import { createUnarchiveCommand } from './unarchive.command.js';
24
26
  /**
25
27
  * Create the feat command group
26
28
  */
@@ -37,5 +39,7 @@ export function createFeatCommand() {
37
39
  .addCommand(createApproveCommand())
38
40
  .addCommand(createRejectCommand())
39
41
  .addCommand(createLogsCommand())
40
- .addCommand(createAdoptCommand());
42
+ .addCommand(createAdoptCommand())
43
+ .addCommand(createArchiveCommand())
44
+ .addCommand(createUnarchiveCommand());
41
45
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ls.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/ls.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6KpC,wBAAgB,eAAe,IAAI,OAAO,CAsGzC"}
1
+ {"version":3,"file":"ls.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/ls.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkLpC,wBAAgB,eAAe,IAAI,OAAO,CAwGzC"}
@@ -48,6 +48,9 @@ const STATUS_PRIORITY = {
48
48
  */
49
49
  function formatStatus(feature, run) {
50
50
  // Blocked features show "Waiting" — the parent relationship is conveyed by tree indentation
51
+ if (feature.lifecycle === 'Archived') {
52
+ return `${colors.muted(symbols.dotEmpty)} ${colors.muted('Archived')}`;
53
+ }
51
54
  if (feature.lifecycle === 'Deleting') {
52
55
  return `${colors.muted(symbols.spinner[0])} ${colors.muted('Deleting')}`;
53
56
  }
@@ -168,6 +171,7 @@ export function createLsCommand() {
168
171
  .description('List features')
169
172
  .option('-r, --repo <path>', 'Filter by repository path')
170
173
  .option('--include-deleted', 'Include soft-deleted features')
174
+ .option('--show-archived', 'Include archived features')
171
175
  .action(async (options) => {
172
176
  try {
173
177
  const useCase = container.resolve(ListFeaturesUseCase);
@@ -176,6 +180,7 @@ export function createLsCommand() {
176
180
  const filters = {
177
181
  ...(options.repo && { repositoryPath: options.repo }),
178
182
  ...(options.includeDeleted && { includeDeleted: true }),
183
+ ...(options.showArchived && { includeArchived: true }),
179
184
  };
180
185
  const features = await useCase.execute(Object.keys(filters).length > 0 ? filters : undefined);
181
186
  // Load agent runs and phase timings for all features in parallel
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Feature Unarchive Command
3
+ *
4
+ * Restores an archived feature to its previous lifecycle state.
5
+ * No confirmation needed — unarchive is always safe and non-destructive.
6
+ *
7
+ * Usage: shep feat unarchive <id>
8
+ *
9
+ * @example
10
+ * $ shep feat unarchive feat-123
11
+ */
12
+ import { Command } from 'commander';
13
+ /**
14
+ * Create the feat unarchive command
15
+ */
16
+ export declare function createUnarchiveCommand(): Command;
17
+ //# sourceMappingURL=unarchive.command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unarchive.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/unarchive.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAuBhD"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Feature Unarchive Command
3
+ *
4
+ * Restores an archived feature to its previous lifecycle state.
5
+ * No confirmation needed — unarchive is always safe and non-destructive.
6
+ *
7
+ * Usage: shep feat unarchive <id>
8
+ *
9
+ * @example
10
+ * $ shep feat unarchive feat-123
11
+ */
12
+ import { Command } from 'commander';
13
+ import { container } from '../../../../../packages/core/src/infrastructure/di/container.js';
14
+ import { ShowFeatureUseCase } from '../../../../../packages/core/src/application/use-cases/features/show-feature.use-case.js';
15
+ import { UnarchiveFeatureUseCase } from '../../../../../packages/core/src/application/use-cases/features/unarchive-feature.use-case.js';
16
+ import { colors, messages } from '../../ui/index.js';
17
+ /**
18
+ * Create the feat unarchive command
19
+ */
20
+ export function createUnarchiveCommand() {
21
+ return new Command('unarchive')
22
+ .description('Restore an archived feature to its previous state')
23
+ .argument('<id>', 'Feature ID or prefix')
24
+ .action(async (featureId) => {
25
+ try {
26
+ const showUseCase = container.resolve(ShowFeatureUseCase);
27
+ const feature = await showUseCase.execute(featureId);
28
+ const unarchiveUseCase = container.resolve(UnarchiveFeatureUseCase);
29
+ const restored = await unarchiveUseCase.execute(feature.id);
30
+ messages.newline();
31
+ messages.success('Feature unarchived');
32
+ console.log(` ${colors.muted('Name:')} ${feature.name}`);
33
+ console.log(` ${colors.muted('Restored:')} ${restored.lifecycle}`);
34
+ messages.newline();
35
+ }
36
+ catch (error) {
37
+ const err = error instanceof Error ? error : new Error(String(error));
38
+ messages.error('Failed to unarchive feature', err);
39
+ process.exitCode = 1;
40
+ }
41
+ });
42
+ }
@@ -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;AAiFD,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"}
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;AAiFD,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,CAkExF"}
@@ -101,7 +101,12 @@ export async function getGraphData() {
101
101
  const listFeatures = resolve('ListFeaturesUseCase');
102
102
  const listRepos = resolve('ListRepositoriesUseCase');
103
103
  const agentRunRepo = resolve('IAgentRunRepository');
104
- const [features, repositories] = await Promise.all([listFeatures.execute(), listRepos.execute()]);
104
+ // Always include archived features so the client has full data for instant
105
+ // show/hide toggle without a server round-trip (NFR-3).
106
+ const [features, repositories] = await Promise.all([
107
+ listFeatures.execute({ includeArchived: true }),
108
+ listRepos.execute(),
109
+ ]);
105
110
  // Read git info from cache (zero git calls). Stale entries trigger
106
111
  // a fire-and-forget background refresh for the next poll cycle.
107
112
  const repoGitInfoMap = new Map();
@@ -0,0 +1,6 @@
1
+ import type { Feature } from '../../../../../packages/core/src/domain/generated/output.js';
2
+ export declare function archiveFeature(featureId: string): Promise<{
3
+ feature?: Feature;
4
+ error?: string;
5
+ }>;
6
+ //# sourceMappingURL=archive-feature.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive-feature.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/archive-feature.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AAEpE,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAahD"}
@@ -0,0 +1,16 @@
1
+ 'use server';
2
+ import { resolve } from '../../lib/server-container.js';
3
+ export async function archiveFeature(featureId) {
4
+ if (!featureId?.trim()) {
5
+ return { error: 'id is required' };
6
+ }
7
+ try {
8
+ const archiveFeatureUseCase = resolve('ArchiveFeatureUseCase');
9
+ const feature = await archiveFeatureUseCase.execute(featureId);
10
+ return { feature };
11
+ }
12
+ catch (error) {
13
+ const message = error instanceof Error ? error.message : 'Failed to archive feature';
14
+ return { error: message };
15
+ }
16
+ }
@@ -0,0 +1,6 @@
1
+ import type { Feature } from '../../../../../packages/core/src/domain/generated/output.js';
2
+ export declare function unarchiveFeature(featureId: string): Promise<{
3
+ feature?: Feature;
4
+ error?: string;
5
+ }>;
6
+ //# sourceMappingURL=unarchive-feature.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unarchive-feature.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/unarchive-feature.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AAEpE,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAahD"}
@@ -0,0 +1,16 @@
1
+ 'use server';
2
+ import { resolve } from '../../lib/server-container.js';
3
+ export async function unarchiveFeature(featureId) {
4
+ if (!featureId?.trim()) {
5
+ return { error: 'id is required' };
6
+ }
7
+ try {
8
+ const unarchiveFeatureUseCase = resolve('UnarchiveFeatureUseCase');
9
+ const feature = await unarchiveFeatureUseCase.execute(featureId);
10
+ return { feature };
11
+ }
12
+ catch (error) {
13
+ const message = error instanceof Error ? error.message : 'Failed to unarchive feature';
14
+ return { error: message };
15
+ }
16
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/app/api/agent-events/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAiBH,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAsEvC,wBAAgB,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CA4R9C"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/app/api/agent-events/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAiBH,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAuEvC,wBAAgB,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CA4R9C"}
@@ -36,6 +36,7 @@ const LIFECYCLE_TO_NODE = {
36
36
  [SdlcLifecycle.Blocked]: 'blocked',
37
37
  [SdlcLifecycle.Pending]: 'pending',
38
38
  [SdlcLifecycle.Deleting]: 'blocked',
39
+ [SdlcLifecycle.Archived]: 'archived',
39
40
  };
40
41
  const STATUS_TO_EVENT = {
41
42
  [AgentRunStatus.running]: {
@@ -1 +1 @@
1
- {"version":3,"file":"derive-feature-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/derive-feature-state.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAIL,qBAAqB,EACtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAE3F;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,OAAO,EAChB,QAAQ,CAAC,EAAE,QAAQ,GAAG,IAAI,EAC1B,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACjC,gBAAgB,CA4DlB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAYvD;AAED,oGAAoG;AACpG,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,qBAAqB,GAAG,gBAAgB,CAsBtF;AAED,wEAAwE;AACxE,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAQlE,CAAC;AAeF;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI,GAAG,qBAAqB,CAQ7F;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACpC,SAAS,EAAE,qBAAqB,GAAG,SAAS,CAAC;IAC7C,SAAS,EAAE,qBAAqB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,SAAS;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,qBAAqB,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,GAC7F,cAAc,EAAE,CAmBlB;AAED,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,qBAAqB,GAAG,SAAS,CAGnC"}
1
+ {"version":3,"file":"derive-feature-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/derive-feature-state.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAIL,qBAAqB,EACtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAE3F;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,OAAO,EAChB,QAAQ,CAAC,EAAE,QAAQ,GAAG,IAAI,EAC1B,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACjC,gBAAgB,CAiElB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAYvD;AAED,oGAAoG;AACpG,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,qBAAqB,GAAG,gBAAgB,CAsBtF;AAED,wEAAwE;AACxE,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CASlE,CAAC;AAgBF;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI,GAAG,qBAAqB,CAQ7F;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACpC,SAAS,EAAE,qBAAqB,GAAG,SAAS,CAAC;IAC7C,SAAS,EAAE,qBAAqB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,SAAS;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,qBAAqB,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,GAC7F,cAAc,EAAE,CAmBlB;AAED,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,qBAAqB,GAAG,SAAS,CAGnC"}
@@ -21,6 +21,10 @@ export function deriveNodeState(feature, agentRun, options) {
21
21
  if (feature.lifecycle === SdlcLifecycle.Deleting) {
22
22
  return 'deleting';
23
23
  }
24
+ // Archived lifecycle — feature is hidden/dormant, takes priority over agent run
25
+ if (feature.lifecycle === SdlcLifecycle.Archived) {
26
+ return 'archived';
27
+ }
24
28
  // Pending lifecycle — user-deferred, agent not yet spawned
25
29
  if (feature.lifecycle === SdlcLifecycle.Pending) {
26
30
  return 'pending';
@@ -120,6 +124,7 @@ export const sdlcLifecycleMap = {
120
124
  'Deploy & QA': 'deploy',
121
125
  Maintain: 'maintain',
122
126
  Pending: 'pending',
127
+ Archived: 'maintain',
123
128
  };
124
129
  /** Map agent graph node names (from agent_run.result or SSE phaseName) to UI lifecycle phases. */
125
130
  const phaseNameToLifecycle = {
@@ -132,6 +137,7 @@ const phaseNameToLifecycle = {
132
137
  maintain: 'maintain',
133
138
  blocked: 'requirements',
134
139
  pending: 'pending',
140
+ archived: 'maintain',
135
141
  };
136
142
  /**
137
143
  * Derives the UI lifecycle phase from a Feature + AgentRun.
@@ -2,7 +2,7 @@ import { type LucideIcon } from 'lucide-react';
2
2
  import type { Node } from '@xyflow/react';
3
3
  import type { PrStatus, CiStatus, DeploymentState } from '../../../../../../packages/core/src/domain/generated/output.js';
4
4
  import type { AgentTypeValue } from './agent-type-icons.js';
5
- export type FeatureNodeState = 'creating' | 'running' | 'action-required' | 'done' | 'blocked' | 'pending' | 'error' | 'deleting';
5
+ export type FeatureNodeState = 'creating' | 'running' | 'action-required' | 'done' | 'blocked' | 'pending' | 'error' | 'deleting' | 'archived';
6
6
  export type FeatureLifecyclePhase = 'pending' | 'requirements' | 'research' | 'implementation' | 'review' | 'deploy' | 'maintain';
7
7
  /** Human-readable display labels for lifecycle phases. */
8
8
  export declare const lifecycleDisplayLabels: Record<FeatureLifecyclePhase, string>;
@@ -112,6 +112,8 @@ export interface FeatureNodeData {
112
112
  onRetry?: (featureId: string) => void;
113
113
  onStart?: (featureId: string) => void;
114
114
  onStop?: (featureId: string) => void;
115
+ onArchive?: (featureId: string) => void;
116
+ onUnarchive?: (featureId: string) => void;
115
117
  showHandles?: boolean;
116
118
  }
117
119
  export type FeatureNodeType = Node<FeatureNodeData, 'featureNode'>;
@@ -1 +1 @@
1
- {"version":3,"file":"feature-node-state-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node-state-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"feature-node-state-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node-state-config.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { Loader2, CircleAlert, CircleCheck, Ban, CircleX, Trash2, Clock, } from 'lucide-react';
1
+ import { Loader2, CircleAlert, CircleCheck, Ban, CircleX, Trash2, Clock, Archive, } from 'lucide-react';
2
2
  /** Human-readable display labels for lifecycle phases. */
3
3
  export const lifecycleDisplayLabels = {
4
4
  pending: 'PENDING',
@@ -191,4 +191,14 @@ export const featureNodeStateConfig = {
191
191
  label: 'Deleting...',
192
192
  showProgressBar: false,
193
193
  },
194
+ archived: {
195
+ icon: Archive,
196
+ borderClass: 'border-l-gray-500',
197
+ labelClass: 'text-gray-500',
198
+ progressClass: 'bg-gray-500',
199
+ badgeClass: 'text-gray-600',
200
+ badgeBgClass: 'bg-gray-100',
201
+ label: 'Archived',
202
+ showProgressBar: false,
203
+ },
194
204
  };
@@ -1 +1 @@
1
- {"version":3,"file":"feature-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AA4CnE,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,2CA6WA"}
1
+ {"version":3,"file":"feature-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node.tsx"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AA4CnE,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,2CA+bA"}
@@ -2,9 +2,10 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { useState } from 'react';
4
4
  import { Handle, Position } from '@xyflow/react';
5
- import { Plus, Trash2, Zap, Loader2, Globe, RotateCcw, Play, Eye, } from 'lucide-react';
5
+ import { Plus, Trash2, Zap, Loader2, Globe, RotateCcw, Play, Eye, Archive, ArchiveRestore, } from 'lucide-react';
6
6
  import { cn } from '../../../lib/utils.js';
7
7
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../ui/tooltip.js';
8
+ import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '../../ui/alert-dialog.js';
8
9
  import { DeleteFeatureDialog } from '../../common/delete-feature-dialog/index.js';
9
10
  import { featureNodeStateConfig, lifecycleRunningVerbs, lifecyclePhaseBadge, } from './feature-node-state-config.js';
10
11
  import { getAgentTypeIcon } from './agent-type-icons.js';
@@ -52,13 +53,29 @@ export function FeatureNode({ data, selected, }) {
52
53
  const config = featureNodeStateConfig[data.state];
53
54
  const Icon = config.icon;
54
55
  const [confirmOpen, setConfirmOpen] = useState(false);
55
- return (_jsxs("div", { className: "animate-in fade-in group relative duration-300", children: [data.showHandles ? (_jsx(Handle, { type: "target", position: Position.Left, isConnectable: false, className: "opacity-0!", style: { top: 70 } })) : null, data.onDelete && data.featureId && data.state !== 'deleting' ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "absolute top-1/2 -left-10 -translate-y-1/2 opacity-0 transition-opacity group-hover:opacity-100", onPointerDown: (e) => e.stopPropagation(), children: _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { "aria-label": "Delete feature", "data-testid": "feature-node-delete-button", onClick: (e) => {
56
- e.stopPropagation();
57
- setConfirmOpen(true);
58
- }, className: "bg-card text-muted-foreground hover:border-destructive hover:text-destructive flex h-7 w-7 cursor-pointer items-center justify-center rounded-full border shadow-sm transition-colors", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "Delete feature" })] }) }) }), _jsx(DeleteFeatureDialog, { open: confirmOpen, onOpenChange: setConfirmOpen, onConfirm: (cleanup, cascadeDelete, closePr) => {
59
- setConfirmOpen(false);
60
- data.onDelete?.(data.featureId, cleanup, cascadeDelete, closePr);
61
- }, isDeleting: false, featureName: data.name ?? 'this feature', featureId: data.featureId, hasChildren: data.hasChildren, hasOpenPr: !!data.pr && data.pr.status === 'Open' })] })) : null, _jsxs("div", { "data-testid": "feature-node-card", "aria-busy": data.state === 'creating' || data.state === 'deleting' ? 'true' : undefined, className: cn('bg-card flex min-h-35 w-97 cursor-pointer flex-col rounded-lg border p-3 shadow-sm dark:bg-neutral-800/80', data.state === 'action-required' && 'border-amber-300/60 dark:border-amber-700/40', selected && 'ring-primary ring-2', data.state === 'deleting' && 'opacity-60'), children: [data.state !== 'creating' ? (_jsx("div", { className: "absolute top-3 right-4", children: _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("span", { "data-testid": "feature-node-phase-badge", className: "flex items-center gap-1.5", children: [_jsx("span", { className: "text-muted-foreground text-[10px]", children: lifecyclePhaseBadge[data.lifecycle].tooltip }), _jsx("span", { className: cn('h-1.5 w-1.5 -translate-y-px rounded-full', lifecyclePhaseBadge[data.lifecycle].dot) })] }) }), _jsxs(TooltipContent, { side: "bottom", className: "max-w-56 bg-white text-neutral-900 shadow-lg dark:bg-neutral-100 dark:text-neutral-900", children: [_jsx("p", { className: "font-semibold", children: lifecyclePhaseBadge[data.lifecycle].tooltip }), _jsx("p", { className: "mt-1 text-xs leading-relaxed text-neutral-500", children: lifecyclePhaseBadge[data.lifecycle].description })] })] }) }) })) : null, _jsxs("div", { className: "flex items-center gap-1.5", children: [data.agentType ? (_jsx(AgentIcon, { agentType: data.agentType, className: "h-4 w-4 shrink-0" })) : null, _jsx("h3", { className: "min-w-0 truncate text-sm font-bold", children: data.name })] }), data.description ? (_jsx("p", { "data-testid": "feature-node-description", className: "text-muted-foreground mt-1 line-clamp-2 text-xs", children: data.description })) : null, _jsxs("div", { className: "mt-auto pt-2", children: [config.showProgressBar ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-muted-foreground flex items-center justify-end text-[10px]", children: _jsxs("span", { children: [data.progress, "%"] }) }), _jsx("div", { "data-testid": "feature-node-progress-bar", className: "bg-muted mt-1.5 h-1 w-full overflow-hidden rounded-full", children: _jsx("div", { className: cn('h-full rounded-full transition-all', config.progressClass), style: { width: `${data.progress}%` } }) })] })) : null, !config.showProgressBar &&
56
+ const [archiveConfirmOpen, setArchiveConfirmOpen] = useState(false);
57
+ return (_jsxs("div", { className: "animate-in fade-in group relative duration-300", children: [data.showHandles ? (_jsx(Handle, { type: "target", position: Position.Left, isConnectable: false, className: "opacity-0!", style: { top: 70 } })) : null, _jsxs("div", { className: "absolute top-1/2 -left-10 flex -translate-y-1/2 flex-col items-center gap-2 opacity-0 transition-opacity group-hover:opacity-100", onPointerDown: (e) => e.stopPropagation(), children: [data.onArchive &&
58
+ data.featureId &&
59
+ data.state !== 'deleting' &&
60
+ data.state !== 'archived' ? (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { "aria-label": "Archive feature", "data-testid": "feature-node-archive-button", onClick: (e) => {
61
+ e.stopPropagation();
62
+ setArchiveConfirmOpen(true);
63
+ }, className: "bg-card text-muted-foreground flex h-7 w-7 cursor-pointer items-center justify-center rounded-full border shadow-sm transition-colors hover:border-gray-500 hover:text-gray-600", children: _jsx(Archive, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "Archive feature" })] }) })) : null, data.onDelete && data.featureId && data.state !== 'deleting' ? (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { "aria-label": "Delete feature", "data-testid": "feature-node-delete-button", onClick: (e) => {
64
+ e.stopPropagation();
65
+ setConfirmOpen(true);
66
+ }, className: "bg-card text-muted-foreground hover:border-destructive hover:text-destructive flex h-7 w-7 cursor-pointer items-center justify-center rounded-full border shadow-sm transition-colors", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "Delete feature" })] }) })) : null, data.onUnarchive && data.featureId && data.state === 'archived' ? (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { "aria-label": "Unarchive feature", "data-testid": "feature-node-unarchive-button", onClick: (e) => {
67
+ e.stopPropagation();
68
+ data.onUnarchive?.(data.featureId);
69
+ }, className: "bg-card text-muted-foreground hover:border-primary hover:text-primary flex h-7 w-7 cursor-pointer items-center justify-center rounded-full border shadow-sm transition-colors", children: _jsx(ArchiveRestore, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "Unarchive feature" })] }) })) : null] }), data.onDelete && data.featureId && data.state !== 'deleting' ? (_jsx(DeleteFeatureDialog, { open: confirmOpen, onOpenChange: setConfirmOpen, onConfirm: (cleanup, cascadeDelete, closePr) => {
70
+ setConfirmOpen(false);
71
+ data.onDelete?.(data.featureId, cleanup, cascadeDelete, closePr);
72
+ }, isDeleting: false, featureName: data.name ?? 'this feature', featureId: data.featureId, hasChildren: data.hasChildren, hasOpenPr: !!data.pr && data.pr.status === 'Open' })) : null, data.onArchive &&
73
+ data.featureId &&
74
+ data.state !== 'deleting' &&
75
+ data.state !== 'archived' ? (_jsx(AlertDialog, { open: archiveConfirmOpen, onOpenChange: setArchiveConfirmOpen, children: _jsxs(AlertDialogContent, { onCloseAutoFocus: (e) => e.preventDefault(), children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Archive feature?" }), _jsxs(AlertDialogDescription, { children: [_jsx("strong", { children: data.name }), " will be hidden from the canvas. You can unarchive it later to restore it."] })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { onClick: () => setArchiveConfirmOpen(false), children: "Cancel" }), _jsx(AlertDialogAction, { onClick: () => {
76
+ setArchiveConfirmOpen(false);
77
+ data.onArchive?.(data.featureId);
78
+ }, children: "Archive" })] })] }) })) : null, _jsxs("div", { "data-testid": "feature-node-card", "aria-busy": data.state === 'creating' || data.state === 'deleting' ? 'true' : undefined, className: cn('bg-card flex min-h-35 w-97 cursor-pointer flex-col rounded-lg border p-3 shadow-sm dark:bg-neutral-800/80', data.state === 'action-required' && 'border-amber-300/60 dark:border-amber-700/40', selected && 'ring-primary ring-2', data.state === 'deleting' && 'opacity-60', data.state === 'archived' && 'opacity-50'), children: [data.state !== 'creating' ? (_jsx("div", { className: "absolute top-3 right-4", children: _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("span", { "data-testid": "feature-node-phase-badge", className: "flex items-center gap-1.5", children: [_jsx("span", { className: "text-muted-foreground text-[10px]", children: lifecyclePhaseBadge[data.lifecycle].tooltip }), _jsx("span", { className: cn('h-1.5 w-1.5 -translate-y-px rounded-full', lifecyclePhaseBadge[data.lifecycle].dot) })] }) }), _jsxs(TooltipContent, { side: "bottom", className: "max-w-56 bg-white text-neutral-900 shadow-lg dark:bg-neutral-100 dark:text-neutral-900", children: [_jsx("p", { className: "font-semibold", children: lifecyclePhaseBadge[data.lifecycle].tooltip }), _jsx("p", { className: "mt-1 text-xs leading-relaxed text-neutral-500", children: lifecyclePhaseBadge[data.lifecycle].description })] })] }) }) })) : null, _jsxs("div", { className: "flex items-center gap-1.5", children: [data.agentType ? (_jsx(AgentIcon, { agentType: data.agentType, className: "h-4 w-4 shrink-0" })) : null, _jsx("h3", { className: "min-w-0 truncate text-sm font-bold", children: data.name })] }), data.description ? (_jsx("p", { "data-testid": "feature-node-description", className: "text-muted-foreground mt-1 line-clamp-2 text-xs", children: data.description })) : null, _jsxs("div", { className: "mt-auto pt-2", children: [config.showProgressBar ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-muted-foreground flex items-center justify-end text-[10px]", children: _jsxs("span", { children: [data.progress, "%"] }) }), _jsx("div", { "data-testid": "feature-node-progress-bar", className: "bg-muted mt-1.5 h-1 w-full overflow-hidden rounded-full", children: _jsx("div", { className: cn('h-full rounded-full transition-all', config.progressClass), style: { width: `${data.progress}%` } }) })] })) : null, !config.showProgressBar &&
62
79
  ![
63
80
  'deleting',
64
81
  'creating',
@@ -26,4 +26,9 @@ export declare const DeploymentWithFastModeAndAgent: Story;
26
26
  export declare const Interactive: Story;
27
27
  export declare const Pending: Story;
28
28
  export declare const PendingWithStart: Story;
29
+ export declare const Archived: Story;
30
+ export declare const ArchivedWithUnarchive: Story;
31
+ export declare const DoneWithArchive: Story;
32
+ /** Shows the archive confirmation dialog in its open state. */
33
+ export declare const ArchiveConfirmationDialog: Story;
29
34
  //# sourceMappingURL=feature-node.stories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"feature-node.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAMvD,OAAO,KAAK,EACV,eAAe,EAIhB,MAAM,6BAA6B,CAAC;AAoCrC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,eAAe,CAqB/B,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,eAAe,CAAC,CAAC;AAEvC,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAqLF,eAAO,MAAM,SAAS,EAAE,KAQvB,CAAC;AAYF,eAAO,MAAM,aAAa,EAAE,KAqB3B,CAAC;AA2EF,eAAO,MAAM,aAAa,EAAE,KAQ3B,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAMxB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAOzB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAW7B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAW9B,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAUtB,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,KAUvC,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAUtB,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAW9B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAY5B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAW9B,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAatB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAc1B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,KAY/B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAa7B,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,KAYlC,CAAC;AAEF,eAAO,MAAM,8BAA8B,EAAE,KAe5C,CAAC;AA4EF,eAAO,MAAM,WAAW,EAAE,KAOzB,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,KAUrB,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAW9B,CAAC"}
1
+ {"version":3,"file":"feature-node.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAMvD,OAAO,KAAK,EACV,eAAe,EAIhB,MAAM,6BAA6B,CAAC;AAoCrC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,eAAe,CAqB/B,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,eAAe,CAAC,CAAC;AAEvC,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AA+LF,eAAO,MAAM,SAAS,EAAE,KAQvB,CAAC;AAYF,eAAO,MAAM,aAAa,EAAE,KAqB3B,CAAC;AA2EF,eAAO,MAAM,aAAa,EAAE,KAQ3B,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAMxB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAOzB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAW7B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAW9B,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAUtB,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,KAUvC,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAUtB,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAW9B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAY5B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAW9B,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAatB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAc1B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,KAY/B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAa7B,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,KAYlC,CAAC;AAEF,eAAO,MAAM,8BAA8B,EAAE,KAe5C,CAAC;AA4EF,eAAO,MAAM,WAAW,EAAE,KAOzB,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,KAUrB,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAW9B,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAUtB,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,KAWnC,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAa7B,CAAC;AAEF,+DAA+D;AAC/D,eAAO,MAAM,yBAAyB,EAAE,KAyBvC,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useMemo } from 'react';
3
- import { expect, fn, waitFor } from '@storybook/test';
3
+ import { expect, fn, userEvent, waitFor, within } from '@storybook/test';
4
4
  import { ReactFlowProvider, ReactFlow, useNodesState } from '@xyflow/react';
5
5
  import { DeploymentState, PrStatus, CiStatus } from '../../../../../../packages/core/src/domain/generated/output.js';
6
6
  import { FeatureNode } from './feature-node.js';
@@ -213,6 +213,16 @@ const allStatesData = [
213
213
  agentType: 'claude-code',
214
214
  hasAgentRun: true,
215
215
  },
216
+ {
217
+ name: 'Old Dashboard',
218
+ description: 'Previous iteration of the admin dashboard',
219
+ featureId: '#f8',
220
+ lifecycle: 'maintain',
221
+ state: 'archived',
222
+ progress: 100,
223
+ repositoryPath: '/home/user/my-repo',
224
+ branch: 'feat/old-dashboard',
225
+ },
216
226
  ];
217
227
  export const AllStates = {
218
228
  render: () => (_jsx("div", { className: "flex flex-wrap gap-6", children: allStatesData.map((data) => (_jsx(FeatureNodeCanvas, { style: { width: 500, height: 350 }, data: data }, data.featureId))) })),
@@ -594,3 +604,67 @@ export const PendingWithStart = {
594
604
  },
595
605
  render: (args) => _jsx(FeatureNodeCanvas, { data: args }),
596
606
  };
607
+ export const Archived = {
608
+ args: {
609
+ name: 'Old Dashboard',
610
+ description: 'Previous iteration of the admin dashboard',
611
+ featureId: '#a1',
612
+ lifecycle: 'maintain',
613
+ state: 'archived',
614
+ progress: 100,
615
+ },
616
+ render: (args) => _jsx(FeatureNodeCanvas, { data: args }),
617
+ };
618
+ export const ArchivedWithUnarchive = {
619
+ args: {
620
+ name: 'Old Dashboard',
621
+ description: 'Previous iteration of the admin dashboard',
622
+ featureId: '#a2',
623
+ lifecycle: 'maintain',
624
+ state: 'archived',
625
+ progress: 100,
626
+ onUnarchive: fn(),
627
+ },
628
+ render: (args) => _jsx(FeatureNodeCanvas, { data: args }),
629
+ };
630
+ export const DoneWithArchive = {
631
+ args: {
632
+ name: 'Completed Feature',
633
+ description: 'A feature ready to be archived',
634
+ featureId: '#ar1',
635
+ lifecycle: 'maintain',
636
+ state: 'done',
637
+ progress: 100,
638
+ runtime: '2h 30m',
639
+ onArchive: fn(),
640
+ onDelete: fn(),
641
+ },
642
+ render: (args) => _jsx(FeatureNodeCanvas, { data: args }),
643
+ };
644
+ /** Shows the archive confirmation dialog in its open state. */
645
+ export const ArchiveConfirmationDialog = {
646
+ args: {
647
+ name: 'Payment Gateway',
648
+ description: 'Stripe integration for subscriptions',
649
+ featureId: '#cd1',
650
+ lifecycle: 'maintain',
651
+ state: 'done',
652
+ progress: 100,
653
+ runtime: '1h 42m',
654
+ onArchive: fn(),
655
+ },
656
+ render: (args) => _jsx(FeatureNodeCanvas, { data: args, style: { width: 600, height: 500 } }),
657
+ play: async ({ canvasElement }) => {
658
+ const canvas = within(canvasElement);
659
+ // Hover over the node to reveal the archive button
660
+ const card = await waitFor(() => canvas.getByTestId('feature-node-card'));
661
+ await userEvent.hover(card);
662
+ // Click the archive button to open the confirmation dialog
663
+ const archiveButton = await waitFor(() => canvas.getByTestId('feature-node-archive-button'));
664
+ await userEvent.click(archiveButton);
665
+ // Verify the dialog is open
666
+ await waitFor(() => {
667
+ expect(document.querySelector('[role="alertdialog"]')).toBeTruthy();
668
+ });
669
+ },
670
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AAGpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAuB5E,UAAU,uBAAuB;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,uBAAuB,2CAuWzF"}
1
+ {"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AAKpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAuB5E,UAAU,uBAAuB;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,uBAAuB,2CAoYzF"}
@@ -1,8 +1,10 @@
1
1
  'use client';
2
- import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
4
4
  import { useRouter, usePathname } from 'next/navigation';
5
- import { useReactFlow } from '@xyflow/react';
5
+ import { Panel, useReactFlow } from '@xyflow/react';
6
+ import { Eye, EyeOff } from 'lucide-react';
7
+ import { cn } from '../../../lib/utils.js';
6
8
  import { FeaturesCanvas } from '../../features/features-canvas/index.js';
7
9
  import { useSidebarFeaturesContext, mapNodeStateToSidebarStatus, } from '../../../hooks/sidebar-features-context.js';
8
10
  import { useSelectedFeatureId } from '../../../hooks/use-selected-feature-id.js';
@@ -26,7 +28,7 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
26
28
  const { fitView } = useReactFlow();
27
29
  const drawerTimerRef = useRef(null);
28
30
  const { defaultViewport, onMoveEnd: handleViewportChange, resetViewport, } = useViewportPersistence();
29
- const { nodes, edges, onNodesChange, handleConnect, handleAddRepository, handleDeleteFeature, handleRetryFeature, handleStartFeature, handleStopFeature, handleDeleteRepository, createFeatureNode, setCallbacks, } = useControlCenterState(initialNodes, initialEdges);
31
+ const { nodes, edges, onNodesChange, handleConnect, handleAddRepository, handleArchiveFeature, handleDeleteFeature, handleRetryFeature, handleStartFeature, handleStopFeature, handleUnarchiveFeature, handleDeleteRepository, createFeatureNode, showArchived, setShowArchived, setCallbacks, } = useControlCenterState(initialNodes, initialEdges);
30
32
  // Publish sidebar features + repo state to context
31
33
  const { setFeatures: setSidebarFeatures, setHasRepositories: setSidebarHasRepos } = useSidebarFeaturesContext();
32
34
  const featureNodes = useMemo(() => nodes.filter((n) => n.type === 'featureNode'), [nodes]);
@@ -201,6 +203,8 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
201
203
  onRetryFeature: handleRetryFeature,
202
204
  onStartFeature: handleStartFeature,
203
205
  onStopFeature: handleStopFeature,
206
+ onArchiveFeature: handleArchiveFeature,
207
+ onUnarchiveFeature: handleUnarchiveFeature,
204
208
  onRepositoryAdd: handleAddFeatureToRepo,
205
209
  onRepositoryClick: handleRepositoryClick,
206
210
  onRepositoryDelete: handleDeleteRepository,
@@ -208,10 +212,12 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
208
212
  }, [
209
213
  setCallbacks,
210
214
  handleAddFeatureToFeature,
215
+ handleArchiveFeature,
211
216
  handleDeleteFeature,
212
217
  handleRetryFeature,
213
218
  handleStartFeature,
214
219
  handleStopFeature,
220
+ handleUnarchiveFeature,
215
221
  handleAddFeatureToRepo,
216
222
  handleRepositoryClick,
217
223
  handleDeleteRepository,
@@ -263,5 +269,8 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
263
269
  return nodes;
264
270
  return nodes.map((n) => n.type === 'repositoryNode' ? { ...n, data: { ...n.data, pulseAdd: true } } : n);
265
271
  }, [nodes, isCreateDrawerOpen]);
266
- return (_jsx(FeaturesCanvas, { nodes: showCanvas ? displayNodes : [], edges: showCanvas ? edges : [], selectedFeatureId: selectedFeatureId, defaultViewport: defaultViewport, onNodesChange: onNodesChange, onConnect: handleConnect, onAddFeature: handleAddFeature, onNodeClick: handleNodeClick, onPaneClick: handleClearDrawers, onMoveEnd: handleMoveEnd, onResetViewport: resetViewport, emptyState: _jsx(ControlCenterEmptyState, { onRepositorySelect: addRepoAndFocus }) }));
272
+ const archiveToggle = (_jsx(Panel, { position: "top-right", children: _jsxs("button", { type: "button", "aria-label": showArchived ? 'Hide archived features' : 'Show archived features', "data-testid": "archive-toggle-button", onClick: () => setShowArchived(!showArchived), className: cn('bg-card flex items-center gap-1.5 rounded-md border px-2.5 py-1.5 text-xs font-medium shadow-sm transition-colors', showArchived
273
+ ? 'border-primary/30 text-primary'
274
+ : 'text-muted-foreground hover:text-foreground'), children: [showArchived ? _jsx(Eye, { className: "h-3.5 w-3.5" }) : _jsx(EyeOff, { className: "h-3.5 w-3.5" }), showArchived ? 'Archived visible' : 'Show archived'] }) }));
275
+ return (_jsx(FeaturesCanvas, { nodes: showCanvas ? displayNodes : [], edges: showCanvas ? edges : [], selectedFeatureId: selectedFeatureId, defaultViewport: defaultViewport, onNodesChange: onNodesChange, onConnect: handleConnect, onAddFeature: handleAddFeature, onNodeClick: handleNodeClick, onPaneClick: handleClearDrawers, onMoveEnd: handleMoveEnd, onResetViewport: resetViewport, toolbar: archiveToggle, emptyState: _jsx(ControlCenterEmptyState, { onRepositorySelect: addRepoAndFocus }) }));
267
276
  }
@@ -15,4 +15,10 @@ export declare const WithNodeActions: Story;
15
15
  * "Horizontal" to switch back.
16
16
  */
17
17
  export declare const DagreLayout: Story;
18
+ /**
19
+ * Canvas with active and archived features.
20
+ * The archive toggle button appears in the top-right corner ("Show archived").
21
+ * Click the toggle to reveal the dimmed archived feature node.
22
+ */
23
+ export declare const WithArchivedFeatures: Story;
18
24
  //# sourceMappingURL=control-center.stories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"control-center.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAQjD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,aAAa,CAkBpC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AA0EnC,eAAO,MAAM,KAAK,EAAE,KAKnB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAQ1B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAKzB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAS7B,CAAC;AAiIF;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,EAAE,KAKzB,CAAC"}
1
+ {"version":3,"file":"control-center.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAQjD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,aAAa,CAkBpC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AA0EnC,eAAO,MAAM,KAAK,EAAE,KAKnB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAQ1B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAKzB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAS7B,CAAC;AAiIF;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,EAAE,KAKzB,CAAC;AA4DF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,KASlC,CAAC"}