@shepai/cli 1.73.1-pr225.4fad6ad → 1.73.1-pr226.fdb5c39

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 (192) hide show
  1. package/dist/src/presentation/web/app/actions/create-feature.d.ts +2 -1
  2. package/dist/src/presentation/web/app/actions/create-feature.d.ts.map +1 -1
  3. package/dist/src/presentation/web/app/actions/create-feature.js +10 -6
  4. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts +2 -1
  5. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts.map +1 -1
  6. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.js +9 -4
  7. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.d.ts +8 -7
  8. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.d.ts.map +1 -1
  9. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.js +15 -12
  10. package/dist/src/presentation/web/hooks/use-viewport-persistence.d.ts +14 -0
  11. package/dist/src/presentation/web/hooks/use-viewport-persistence.d.ts.map +1 -0
  12. package/dist/src/presentation/web/hooks/use-viewport-persistence.js +55 -0
  13. package/dist/tsconfig.build.tsbuildinfo +1 -1
  14. package/package.json +1 -1
  15. package/web/.next/BUILD_ID +1 -1
  16. package/web/.next/build-manifest.json +2 -2
  17. package/web/.next/cache/.previewinfo +1 -1
  18. package/web/.next/cache/.rscinfo +1 -1
  19. package/web/.next/cache/.tsbuildinfo +1 -1
  20. package/web/.next/cache/config.json +3 -3
  21. package/web/.next/fallback-build-manifest.json +2 -2
  22. package/web/.next/prerender-manifest.json +3 -3
  23. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +16 -16
  24. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  25. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  26. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +19 -19
  27. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  28. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  29. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +14 -14
  30. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  31. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  32. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +16 -16
  33. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  34. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  35. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +19 -19
  36. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  37. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  38. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +14 -14
  39. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  40. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  41. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +14 -14
  42. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  43. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  44. package/web/.next/server/app/_global-error.html +2 -2
  45. package/web/.next/server/app/_global-error.rsc +1 -1
  46. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  47. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  48. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  49. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  50. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  51. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  52. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  53. package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  54. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  55. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  56. package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  57. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  58. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  59. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  60. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  61. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  62. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  63. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_da7eef33.js +1 -1
  64. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_da7eef33.js.map +1 -1
  65. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_0a9251aa.js +1 -1
  66. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_0a9251aa.js.map +1 -1
  67. package/web/.next/server/chunks/ssr/[root-of-the-server]__17a611f0._.js +2 -2
  68. package/web/.next/server/chunks/ssr/[root-of-the-server]__17a611f0._.js.map +1 -1
  69. package/web/.next/server/chunks/ssr/[root-of-the-server]__45dbf93d._.js +2 -2
  70. package/web/.next/server/chunks/ssr/[root-of-the-server]__45dbf93d._.js.map +1 -1
  71. package/web/.next/server/chunks/ssr/[root-of-the-server]__6258349c._.js +1 -1
  72. package/web/.next/server/chunks/ssr/[root-of-the-server]__6258349c._.js.map +1 -1
  73. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  74. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +1 -1
  75. package/web/.next/server/chunks/ssr/[root-of-the-server]__6cbc1149._.js +2 -2
  76. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  77. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +1 -1
  78. package/web/.next/server/chunks/ssr/[root-of-the-server]__94a6d275._.js +1 -1
  79. package/web/.next/server/chunks/ssr/[root-of-the-server]__94a6d275._.js.map +1 -1
  80. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +1 -1
  81. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
  82. package/web/.next/server/chunks/ssr/_0e9d6bf7._.js +1 -1
  83. package/web/.next/server/chunks/ssr/_0e9d6bf7._.js.map +1 -1
  84. package/web/.next/server/chunks/ssr/_61351ed3._.js +1 -1
  85. package/web/.next/server/chunks/ssr/_61351ed3._.js.map +1 -1
  86. package/web/.next/server/chunks/ssr/_8400c8bb._.js +1 -1
  87. package/web/.next/server/chunks/ssr/_8400c8bb._.js.map +1 -1
  88. package/web/.next/server/chunks/ssr/_9f940437._.js +1 -1
  89. package/web/.next/server/chunks/ssr/_9f940437._.js.map +1 -1
  90. package/web/.next/server/chunks/ssr/{_49f6575f._.js → _f2375f32._.js} +2 -2
  91. package/web/.next/server/chunks/ssr/{_49f6575f._.js.map → _f2375f32._.js.map} +1 -1
  92. package/web/.next/server/chunks/ssr/src_presentation_web_163038ba._.js +4 -2
  93. package/web/.next/server/chunks/ssr/src_presentation_web_163038ba._.js.map +1 -1
  94. package/web/.next/server/chunks/ssr/src_presentation_web_30d7eeda._.js +1 -1
  95. package/web/.next/server/chunks/ssr/src_presentation_web_30d7eeda._.js.map +1 -1
  96. package/web/.next/server/chunks/ssr/src_presentation_web_459cb687._.js +4 -2
  97. package/web/.next/server/chunks/ssr/src_presentation_web_459cb687._.js.map +1 -1
  98. package/web/.next/server/chunks/ssr/src_presentation_web_565a14f8._.js +1 -1
  99. package/web/.next/server/chunks/ssr/src_presentation_web_565a14f8._.js.map +1 -1
  100. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_021a05f2.js +1 -1
  101. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_021a05f2.js.map +1 -1
  102. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  103. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  104. package/web/.next/server/pages/500.html +2 -2
  105. package/web/.next/server/server-reference-manifest.js +1 -1
  106. package/web/.next/server/server-reference-manifest.json +22 -22
  107. package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
  108. package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +2 -2
  109. package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
  110. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +16 -16
  111. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  112. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  113. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +19 -19
  114. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  115. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  116. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +14 -14
  117. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  118. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  119. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +16 -16
  120. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  121. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  122. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +19 -19
  123. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  124. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  125. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +14 -14
  126. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  127. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  128. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +14 -14
  129. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  130. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  131. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
  132. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
  133. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  134. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  135. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  136. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  137. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  138. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  139. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  140. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  141. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page.js.nft.json +1 -1
  142. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  143. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  144. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page.js.nft.json +1 -1
  145. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  146. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  147. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  148. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  149. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_da7eef33.js +1 -1
  150. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_0a9251aa.js +1 -1
  151. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__17a611f0._.js +2 -2
  152. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__45dbf93d._.js +2 -2
  153. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6258349c._.js +1 -1
  154. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  155. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6cbc1149._.js +2 -2
  156. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  157. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__94a6d275._.js +1 -1
  158. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +1 -1
  159. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_0e9d6bf7._.js +1 -1
  160. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_61351ed3._.js +1 -1
  161. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_8400c8bb._.js +1 -1
  162. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_9f940437._.js +1 -1
  163. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/{_49f6575f._.js → _f2375f32._.js} +2 -2
  164. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_163038ba._.js +4 -2
  165. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_30d7eeda._.js +1 -1
  166. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_459cb687._.js +4 -2
  167. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_565a14f8._.js +1 -1
  168. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_021a05f2.js +1 -1
  169. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  170. package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
  171. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
  172. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +22 -22
  173. package/web/.next/standalone/src/presentation/web/app/actions/create-feature.ts +18 -7
  174. package/web/.next/standalone/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.tsx +15 -16
  175. package/web/.next/standalone/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.tsx +31 -12
  176. package/web/.next/standalone/src/presentation/web/hooks/use-viewport-persistence.ts +74 -0
  177. package/web/.next/static/chunks/{ed768e1443066c95.js → 12ad44030ef749c5.js} +1 -1
  178. package/web/.next/static/chunks/{0c8d4bdd95ae45e7.js → 21b006fceeb06d75.js} +1 -1
  179. package/web/.next/static/chunks/{b2084d9c2260b140.js → 23b5d335f35b805d.js} +1 -1
  180. package/web/.next/static/chunks/{40baf05ad602fee7.js → 541a0b97db170e4d.js} +1 -1
  181. package/web/.next/static/chunks/{a539a922a7ba0851.js → 6a8972e2848a1399.js} +1 -1
  182. package/web/.next/static/chunks/{0a91a62af4813cbe.js → 6b2409eea058f725.js} +1 -1
  183. package/web/.next/static/chunks/e2025942e9d6dabf.js +1 -0
  184. package/web/.next/static/chunks/{37c95269aa36cf41.js → f84505146fbade38.js} +1 -1
  185. package/web/.next/static/chunks/f976ce94071808c2.js +1 -0
  186. package/web/.next/trace +1 -1
  187. package/web/.next/trace-build +1 -1
  188. package/web/.next/static/chunks/4fbd01af2bfc46a0.js +0 -1
  189. package/web/.next/static/chunks/b47db04e0dd7ff83.js +0 -1
  190. /package/web/.next/static/{Xj_ABhg1MoIBpmI-Qeezj → 5C6PZRGib8ndD_M_0Vs0w}/_buildManifest.js +0 -0
  191. /package/web/.next/static/{Xj_ABhg1MoIBpmI-Qeezj → 5C6PZRGib8ndD_M_0Vs0w}/_clientMiddlewareManifest.json +0 -0
  192. /package/web/.next/static/{Xj_ABhg1MoIBpmI-Qeezj → 5C6PZRGib8ndD_M_0Vs0w}/_ssgManifest.js +0 -0
@@ -4,7 +4,8 @@ interface Attachment {
4
4
  name: string;
5
5
  }
6
6
  interface CreateFeatureInput {
7
- description: string;
7
+ name: string;
8
+ description?: string;
8
9
  repositoryPath: string;
9
10
  attachments?: Attachment[];
10
11
  approvalGates?: {
@@ -1 +1 @@
1
- {"version":3,"file":"create-feature.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/create-feature.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AAEpE,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAQD,UAAU,kBAAkB;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,aAAa,CAAC,EAAE;QACd,QAAQ,EAAE,OAAO,CAAC;QAClB,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC;IACF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAaD,wBAAsB,aAAa,CACjC,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAyDhD"}
1
+ {"version":3,"file":"create-feature.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/create-feature.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AAEpE,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAQD,UAAU,kBAAkB;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,aAAa,CAAC,EAAE;QACd,QAAQ,EAAE,OAAO,CAAC;QAClB,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC;IACF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAqBD,wBAAsB,aAAa,CACjC,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA2DhD"}
@@ -1,7 +1,10 @@
1
1
  'use server';
2
2
  import { resolve } from '../../lib/server-container.js';
3
- function composeUserInput(description, attachments) {
4
- let userInput = description;
3
+ function composeUserInput(name, description, attachments) {
4
+ let userInput = `Feature: ${name}`;
5
+ if (description) {
6
+ userInput += `\n\n${description}`;
7
+ }
5
8
  if (attachments && attachments.length > 0) {
6
9
  const paths = attachments.map((a) => `- ${a.path}`).join('\n');
7
10
  userInput += `\n\nAttached files:\n${paths}`;
@@ -9,14 +12,14 @@ function composeUserInput(description, attachments) {
9
12
  return userInput;
10
13
  }
11
14
  export async function createFeature(input) {
12
- const { description, repositoryPath, attachments, approvalGates, push, openPr, parentId } = input;
13
- if (!description?.trim()) {
14
- return { error: 'description is required' };
15
+ const { name, description, repositoryPath, attachments, approvalGates, push, openPr, parentId } = input;
16
+ if (!name?.trim()) {
17
+ return { error: 'name is required' };
15
18
  }
16
19
  if (!repositoryPath?.trim()) {
17
20
  return { error: 'repositoryPath is required' };
18
21
  }
19
- const userInput = composeUserInput(description, attachments);
22
+ const userInput = composeUserInput(name, description, attachments);
20
23
  const gates = {
21
24
  allowPrd: approvalGates?.allowPrd ?? false,
22
25
  allowPlan: approvalGates?.allowPlan ?? false,
@@ -32,6 +35,7 @@ export async function createFeature(input) {
32
35
  push: push ?? false,
33
36
  openPr: openPr ?? false,
34
37
  ...(parentId ? { parentId } : {}),
38
+ name,
35
39
  description,
36
40
  });
37
41
  // Phase 2 (background): metadata generation, worktree, spec, agent spawn
@@ -7,7 +7,8 @@ export interface ParentFeatureOption {
7
7
  name: string;
8
8
  }
9
9
  export interface FeatureCreatePayload {
10
- description: string;
10
+ name: string;
11
+ description?: string;
11
12
  attachments: FileAttachment[];
12
13
  repositoryPath: string;
13
14
  approvalGates: {
@@ -1 +1 @@
1
- {"version":3,"file":"feature-create-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.tsx"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0DAA0D,CAAC;AAC/F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAG5E,YAAY,EAAE,cAAc,EAAE,MAAM,0DAA0D,CAAC;AAE/F,0DAA0D;AAC1D,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE;QACb,QAAQ,EAAE,OAAO,CAAC;QAClB,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC;IACF,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAcD,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC/C,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,qEAAqE;IACrE,QAAQ,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACjC,kGAAkG;IAClG,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,cAAc,EACd,YAAoB,EACpB,gBAAgB,EAChB,QAAQ,EACR,eAAe,GAChB,EAAE,wBAAwB,2CA4P1B"}
1
+ {"version":3,"file":"feature-create-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.tsx"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0DAA0D,CAAC;AAC/F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAG5E,YAAY,EAAE,cAAc,EAAE,MAAM,0DAA0D,CAAC;AAE/F,0DAA0D;AAC1D,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE;QACb,QAAQ,EAAE,OAAO,CAAC;QAClB,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC;IACF,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAcD,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC/C,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,qEAAqE;IACrE,QAAQ,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACjC,kGAAkG;IAClG,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,cAAc,EACd,YAAoB,EACpB,gBAAgB,EAChB,QAAQ,EACR,eAAe,GAChB,EAAE,wBAAwB,2CA8Q1B"}
@@ -31,6 +31,7 @@ export function FeatureCreateDrawer({ open, onClose, onSubmit, repositoryPath, i
31
31
  const defaultGates = workflowDefaults?.approvalGates ?? EMPTY_GATES;
32
32
  const defaultPush = workflowDefaults?.push ?? false;
33
33
  const defaultOpenPr = workflowDefaults?.openPr ?? false;
34
+ const [name, setName] = useState('');
34
35
  const [description, setDescription] = useState('');
35
36
  const [attachments, setAttachments] = useState([]);
36
37
  const [approvalGates, setApprovalGates] = useState({ ...defaultGates });
@@ -52,6 +53,7 @@ export function FeatureCreateDrawer({ open, onClose, onSubmit, repositoryPath, i
52
53
  }
53
54
  }, [open, initialParentId]);
54
55
  const resetForm = useCallback(() => {
56
+ setName('');
55
57
  setDescription('');
56
58
  setAttachments([]);
57
59
  setApprovalGates({ ...defaultGates });
@@ -60,16 +62,18 @@ export function FeatureCreateDrawer({ open, onClose, onSubmit, repositoryPath, i
60
62
  setParentId(undefined);
61
63
  }, [defaultGates, defaultPush, defaultOpenPr]);
62
64
  // Track whether the form has unsaved data
63
- const isDirty = description.trim() !== '' || attachments.length > 0;
65
+ const isDirty = name.trim() !== '' || description.trim() !== '' || attachments.length > 0;
64
66
  // Shared close guard — shows confirmation when dirty, prevents navigation
65
67
  const { attemptClose } = useGuardedDrawerClose({ open, isDirty, onClose, onReset: resetForm });
66
68
  const handleSubmit = useCallback((e) => {
67
69
  e.preventDefault();
68
- if (!description.trim())
70
+ if (!name.trim())
69
71
  return;
70
72
  createSound.play();
73
+ const trimmedDescription = description.trim() || undefined;
71
74
  onSubmit({
72
- description: description.trim(),
75
+ name: name.trim(),
76
+ description: trimmedDescription,
73
77
  attachments,
74
78
  repositoryPath,
75
79
  approvalGates: {
@@ -83,6 +87,7 @@ export function FeatureCreateDrawer({ open, onClose, onSubmit, repositoryPath, i
83
87
  });
84
88
  resetForm();
85
89
  }, [
90
+ name,
86
91
  description,
87
92
  attachments,
88
93
  approvalGates,
@@ -109,7 +114,7 @@ export function FeatureCreateDrawer({ open, onClose, onSubmit, repositoryPath, i
109
114
  setAttachments((prev) => prev.filter((f) => f.path !== path));
110
115
  }, []);
111
116
  const hasFeatures = features && features.length > 0;
112
- return (_jsx(BaseDrawer, { open: open, onClose: attemptClose, size: "md", modal: false, dismissOnOutsideClick: true, "data-testid": "feature-create-drawer", header: _jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "h-2.5 w-2.5 shrink-0 rounded-full bg-blue-500" }), _jsx(DrawerTitle, { children: "NEW FEATURE" })] }), isSubmitting ? (_jsx(DrawerDescription, { asChild: true, children: _jsx("div", { children: _jsx(Badge, { variant: "secondary", children: "Creating..." }) }) })) : null] }), footer: _jsxs("div", { className: "flex flex-row justify-end gap-2", children: [_jsx(Button, { variant: "outline", onClick: attemptClose, disabled: isSubmitting, children: "Cancel" }), _jsx(Button, { type: "submit", form: "create-feature-form", disabled: !description.trim() || isSubmitting, children: isSubmitting ? 'Creating...' : '+ Create Feature' })] }), children: _jsx("div", { className: "overflow-y-auto p-4", children: _jsxs("form", { id: "create-feature-form", onSubmit: handleSubmit, className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "feature-description", className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "DESCRIBE YOUR FEATURE" }), _jsx(Textarea, { id: "feature-description", placeholder: "e.g. Add GitHub OAuth login with callback handling and token refresh...", value: description, onChange: (e) => setDescription(e.target.value), rows: 4, required: true, disabled: isSubmitting })] }), hasFeatures ? (_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "parent-feature", className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "PARENT FEATURE" }), _jsx(ParentFeatureCombobox, { features: features, value: parentId, onChange: setParentId, disabled: isSubmitting })] })) : null, _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "APPROVE" }), _jsx(CheckboxGroup, { label: "Autonomous Mode", description: "YOLO!", parentAriaLabel: "Auto approve all", options: AUTO_APPROVE_OPTIONS, value: approvalGates, onValueChange: setApprovalGates, disabled: isSubmitting })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "GIT" }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(CheckboxGroupItem, { id: "push", label: "Push", description: "Push branch to remote after implementation.", checked: push || openPr, onCheckedChange: setPush, disabled: openPr || isSubmitting }), _jsx(CheckboxGroupItem, { id: "open-pr", label: "Create PR", description: "Open a pull request after pushing.", checked: openPr, onCheckedChange: setOpenPr, disabled: isSubmitting })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs(Label, { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: ["ATTACHMENTS", attachments.length > 0 && (_jsxs("span", { className: "text-muted-foreground/60 ml-1.5", children: ["(", attachments.length, ")"] }))] }), _jsxs(Button, { type: "button", variant: "outline", size: "xs", onClick: handleAddFiles, disabled: isSubmitting, children: [_jsx(PlusIcon, { className: "size-3" }), "Add Files"] })] }), attachments.length > 0 && (_jsx("div", { className: "flex flex-col gap-2", children: attachments.map((file) => (_jsx(AttachmentCard, { file: file, onRemove: () => handleRemoveFile(file.path), disabled: isSubmitting }, file.path))) }))] })] }) }) }));
117
+ return (_jsx(BaseDrawer, { open: open, onClose: attemptClose, size: "md", modal: false, dismissOnOutsideClick: true, "data-testid": "feature-create-drawer", header: _jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "h-2.5 w-2.5 shrink-0 rounded-full bg-blue-500" }), _jsx(DrawerTitle, { children: "NEW FEATURE" })] }), isSubmitting ? (_jsx(DrawerDescription, { asChild: true, children: _jsx("div", { children: _jsx(Badge, { variant: "secondary", children: "Creating..." }) }) })) : null] }), footer: _jsxs("div", { className: "flex flex-row justify-end gap-2", children: [_jsx(Button, { variant: "outline", onClick: attemptClose, disabled: isSubmitting, children: "Cancel" }), _jsx(Button, { type: "submit", form: "create-feature-form", disabled: !name.trim() || isSubmitting, children: isSubmitting ? 'Creating...' : '+ Create Feature' })] }), children: _jsx("div", { className: "overflow-y-auto p-4", children: _jsxs("form", { id: "create-feature-form", onSubmit: handleSubmit, className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "feature-name", className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "FEATURE NAME" }), _jsx(Input, { id: "feature-name", placeholder: "e.g. GitHub OAuth Login", value: name, onChange: (e) => setName(e.target.value), required: true, disabled: isSubmitting })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "feature-description", className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "DESCRIPTION" }), _jsx(Textarea, { id: "feature-description", placeholder: "Describe what this feature does...", value: description, onChange: (e) => setDescription(e.target.value), rows: 4, disabled: isSubmitting })] }), hasFeatures ? (_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "parent-feature", className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "PARENT FEATURE" }), _jsx(ParentFeatureCombobox, { features: features, value: parentId, onChange: setParentId, disabled: isSubmitting })] })) : null, _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "APPROVE" }), _jsx(CheckboxGroup, { label: "Autonomous Mode", description: "YOLO!", parentAriaLabel: "Auto approve all", options: AUTO_APPROVE_OPTIONS, value: approvalGates, onValueChange: setApprovalGates, disabled: isSubmitting })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "GIT" }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(CheckboxGroupItem, { id: "push", label: "Push", description: "Push branch to remote after implementation.", checked: push || openPr, onCheckedChange: setPush, disabled: openPr || isSubmitting }), _jsx(CheckboxGroupItem, { id: "open-pr", label: "Create PR", description: "Open a pull request after pushing.", checked: openPr, onCheckedChange: setOpenPr, disabled: isSubmitting })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs(Label, { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: ["ATTACHMENTS", attachments.length > 0 && (_jsxs("span", { className: "text-muted-foreground/60 ml-1.5", children: ["(", attachments.length, ")"] }))] }), _jsxs(Button, { type: "button", variant: "outline", size: "xs", onClick: handleAddFiles, disabled: isSubmitting, children: [_jsx(PlusIcon, { className: "size-3" }), "Add Files"] })] }), attachments.length > 0 && (_jsx("div", { className: "flex flex-col gap-2", children: attachments.map((file) => (_jsx(AttachmentCard, { file: file, onRemove: () => handleRemoveFile(file.path), disabled: isSubmitting }, file.path))) }))] })] }) }) }));
113
118
  }
114
119
  function ParentFeatureCombobox({ features, value, onChange, disabled, }) {
115
120
  const [open, setOpen] = useState(false);
@@ -5,7 +5,8 @@ import { FeatureCreateDrawer } from './feature-create-drawer.js';
5
5
  * create a new feature in the Control Center.
6
6
  *
7
7
  * ### Form sections
8
- * - **Description** (required) — multi-line textarea, submit is disabled when empty
8
+ * - **Feature Name** (required) — text input, submit is disabled when empty
9
+ * - **Description** (optional) — multi-line textarea
9
10
  * - **Auto Approve** — Tri-state parent checkbox with 3 child checkboxes (PRD, Plan, Merge).
10
11
  * Parent shows indeterminate when some children are selected, checks/unchecks all on click.
11
12
  * - **Attachments** (optional) — native OS file picker with extension-based icon system:
@@ -17,12 +18,12 @@ import { FeatureCreateDrawer } from './feature-create-drawer.js';
17
18
  * |------|------|-------------|
18
19
  * | `open` | `boolean` | Controls drawer visibility |
19
20
  * | `onClose` | `() => void` | Called on dismiss (close button, cancel, or backdrop) |
20
- * | `onSubmit` | `(data: FeatureCreatePayload) => void` | Called with `{ description, attachments, repositoryPath, approvalGates }` |
21
+ * | `onSubmit` | `(data: FeatureCreatePayload) => void` | Called with `{ name, description, attachments, repositoryPath, approvalGates }` |
21
22
  * | `repositoryPath` | `string` | Repository path (mandatory) included in the submitted data |
22
23
  *
23
24
  * ### Behavior
24
- * - Form resets (description, attachments, checkboxes) when the drawer closes
25
- * - Submit button is disabled when description is empty
25
+ * - Form resets (name, description, attachments, checkboxes) when the drawer closes
26
+ * - Submit button is disabled when name is empty
26
27
  * - `approvalGates` always included: `{ allowPrd, allowPlan, allowMerge }` (all false by default)
27
28
  * - Non-modal (`modal={false}`) — canvas stays interactive behind the drawer
28
29
  * - Fixed width: 448px (`w-xl`) — matches review drawers (PRD, Plan, Merge)
@@ -35,13 +36,13 @@ type Story = StoryObj<typeof FeatureCreateDrawer>;
35
36
  /** Default empty form — click the trigger button to open the create feature drawer. */
36
37
  export declare const Default: Story;
37
38
  /**
38
- * Pre-filled form — click to open, then description is typed in.
39
+ * Pre-filled form — click to open, then name and description are typed in.
39
40
  * Demonstrates the form in a "ready to submit" state.
40
41
  */
41
42
  export declare const PreFilled: Story;
42
43
  /**
43
- * Validation state — open the drawer with an empty description field.
44
- * The "+ Create Feature" button is disabled because description validation fails.
44
+ * Validation state — open the drawer with an empty name field.
45
+ * The "+ Create Feature" button is disabled because name validation fails.
45
46
  */
46
47
  export declare const ValidationDisabled: Story;
47
48
  /** Click to open the drawer for quick visual inspection. */
@@ -1 +1 @@
1
- {"version":3,"file":"feature-create-drawer.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAU9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,mBAAmB,CAgC1C,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAiDlD,uFAAuF;AACvF,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,KAiBvB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,KAMhC,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,SAAS,EAAE,KAMvB,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,KAM1B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,KAUxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,OAAO,EAAE,KAUrB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,KAUvB,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,KAUtB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,SAAS,EAAE,KAUvB,CAAC;AAYF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,KAWlC,CAAC;AAgDF,+EAA+E;AAC/E,eAAO,MAAM,QAAQ,EAAE,KAEtB,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAgBjC,CAAC;AAMF,eAAO,MAAM,WAAW,EAAE,KAsCzB,CAAC"}
1
+ {"version":3,"file":"feature-create-drawer.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAU9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,mBAAmB,CAgC1C,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAiDlD,uFAAuF;AACvF,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,KAiBvB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,KAMhC,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,SAAS,EAAE,KAMvB,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,KAM1B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,KAUxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,OAAO,EAAE,KAUrB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,KAUvB,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,KAUtB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,SAAS,EAAE,KAUvB,CAAC;AAYF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,KAWlC,CAAC;AAgDF,+EAA+E;AAC/E,eAAO,MAAM,QAAQ,EAAE,KAEtB,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAcjC,CAAC;AAMF,eAAO,MAAM,WAAW,EAAE,KAsCzB,CAAC"}
@@ -12,7 +12,8 @@ import { DrawerCloseGuardProvider } from '../../../hooks/drawer-close-guard.js';
12
12
  * create a new feature in the Control Center.
13
13
  *
14
14
  * ### Form sections
15
- * - **Description** (required) — multi-line textarea, submit is disabled when empty
15
+ * - **Feature Name** (required) — text input, submit is disabled when empty
16
+ * - **Description** (optional) — multi-line textarea
16
17
  * - **Auto Approve** — Tri-state parent checkbox with 3 child checkboxes (PRD, Plan, Merge).
17
18
  * Parent shows indeterminate when some children are selected, checks/unchecks all on click.
18
19
  * - **Attachments** (optional) — native OS file picker with extension-based icon system:
@@ -24,12 +25,12 @@ import { DrawerCloseGuardProvider } from '../../../hooks/drawer-close-guard.js';
24
25
  * |------|------|-------------|
25
26
  * | `open` | `boolean` | Controls drawer visibility |
26
27
  * | `onClose` | `() => void` | Called on dismiss (close button, cancel, or backdrop) |
27
- * | `onSubmit` | `(data: FeatureCreatePayload) => void` | Called with `{ description, attachments, repositoryPath, approvalGates }` |
28
+ * | `onSubmit` | `(data: FeatureCreatePayload) => void` | Called with `{ name, description, attachments, repositoryPath, approvalGates }` |
28
29
  * | `repositoryPath` | `string` | Repository path (mandatory) included in the submitted data |
29
30
  *
30
31
  * ### Behavior
31
- * - Form resets (description, attachments, checkboxes) when the drawer closes
32
- * - Submit button is disabled when description is empty
32
+ * - Form resets (name, description, attachments, checkboxes) when the drawer closes
33
+ * - Submit button is disabled when name is empty
33
34
  * - `approvalGates` always included: `{ allowPrd, allowPlan, allowMerge }` (all false by default)
34
35
  * - Non-modal (`modal={false}`) — canvas stays interactive behind the drawer
35
36
  * - Fixed width: 448px (`w-xl`) — matches review drawers (PRD, Plan, Merge)
@@ -55,7 +56,7 @@ const meta = {
55
56
  description: 'Callback fired when the drawer is dismissed (close button, cancel, or backdrop click).',
56
57
  },
57
58
  onSubmit: {
58
- description: 'Callback fired with `FeatureCreatePayload` when the form is submitted. Receives `{ description, attachments, repositoryPath, approvalGates }`.',
59
+ description: 'Callback fired with `FeatureCreatePayload` when the form is submitted. Receives `{ name, description, attachments, repositoryPath, approvalGates }`.',
59
60
  },
60
61
  repositoryPath: {
61
62
  control: 'text',
@@ -91,7 +92,7 @@ export const Default = {
91
92
  render: () => _jsx(CreateDrawerTrigger, {}),
92
93
  };
93
94
  /**
94
- * Pre-filled form — click to open, then description is typed in.
95
+ * Pre-filled form — click to open, then name and description are typed in.
95
96
  * Demonstrates the form in a "ready to submit" state.
96
97
  */
97
98
  export const PreFilled = {
@@ -101,13 +102,15 @@ export const PreFilled = {
101
102
  await userEvent.click(canvas.getByRole('button', { name: 'Open Pre-Filled' }));
102
103
  // Drawer renders in a portal — query from document body
103
104
  const body = within(canvasElement.ownerDocument.body);
104
- const descInput = await body.findByPlaceholderText('e.g. Add GitHub OAuth login with callback handling and token refresh...');
105
+ const nameInput = await body.findByPlaceholderText('e.g. GitHub OAuth Login');
106
+ const descInput = body.getByPlaceholderText('Describe what this feature does...');
107
+ await userEvent.type(nameInput, 'GitHub OAuth Login');
105
108
  await userEvent.type(descInput, 'Implement OAuth2 authentication with GitHub as the identity provider. Includes login, callback handling, and token refresh.');
106
109
  },
107
110
  };
108
111
  /**
109
- * Validation state — open the drawer with an empty description field.
110
- * The "+ Create Feature" button is disabled because description validation fails.
112
+ * Validation state — open the drawer with an empty name field.
113
+ * The "+ Create Feature" button is disabled because name validation fails.
111
114
  */
112
115
  export const ValidationDisabled = {
113
116
  render: () => _jsx(CreateDrawerTrigger, { label: "Open Validation Demo" }),
@@ -240,7 +243,7 @@ export const WithWorkflowDefaults = {
240
243
  * and click "Add Files" to attach files via the native OS file picker.
241
244
  *
242
245
  * **Submitted data** is displayed in a styled panel showing `FeatureCreatePayload`
243
- * with `{ description, attachments, repositoryPath, approvalGates }`.
246
+ * with `{ name, description, attachments, repositoryPath, approvalGates }`.
244
247
  *
245
248
  * In Storybook, the native picker won't work (no backend), but submitted data
246
249
  * would show the paths if files were attached programmatically.
@@ -275,8 +278,8 @@ export const DiscardConfirmation = {
275
278
  const canvas = within(canvasElement);
276
279
  await userEvent.click(canvas.getByRole('button', { name: 'Open (Discard Confirmation)' }));
277
280
  const body = within(canvasElement.ownerDocument.body);
278
- const descInput = await body.findByPlaceholderText('e.g. Add GitHub OAuth login with callback handling and token refresh...');
279
- await userEvent.type(descInput, 'My Feature');
281
+ const nameInput = await body.findByPlaceholderText('e.g. GitHub OAuth Login');
282
+ await userEvent.type(nameInput, 'My Feature');
280
283
  // Click Cancel — should show the discard confirmation dialog
281
284
  const cancelButton = body.getByRole('button', { name: 'Cancel' });
282
285
  await userEvent.click(cancelButton);
@@ -0,0 +1,14 @@
1
+ export declare const STORAGE_KEY = "shep-canvas-viewport";
2
+ export declare const DEBOUNCE_MS = 500;
3
+ export interface Viewport {
4
+ x: number;
5
+ y: number;
6
+ zoom: number;
7
+ }
8
+ export declare const DEFAULT_VIEWPORT: Viewport;
9
+ export interface UseViewportPersistenceResult {
10
+ defaultViewport: Viewport;
11
+ onMoveEnd: (viewport: Viewport) => void;
12
+ }
13
+ export declare function useViewportPersistence(): UseViewportPersistenceResult;
14
+ //# sourceMappingURL=use-viewport-persistence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-viewport-persistence.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/hooks/use-viewport-persistence.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,yBAAyB,CAAC;AAClD,eAAO,MAAM,WAAW,MAAM,CAAC;AAE/B,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,gBAAgB,EAAE,QAAuC,CAAC;AAEvE,MAAM,WAAW,4BAA4B;IAC3C,eAAe,EAAE,QAAQ,CAAC;IAC1B,SAAS,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;CACzC;AA6BD,wBAAgB,sBAAsB,IAAI,4BAA4B,CA0BrE"}
@@ -0,0 +1,55 @@
1
+ 'use client';
2
+ import { useCallback, useEffect, useRef } from 'react';
3
+ export const STORAGE_KEY = 'shep-canvas-viewport';
4
+ export const DEBOUNCE_MS = 500;
5
+ export const DEFAULT_VIEWPORT = { x: 30, y: 30, zoom: 0.85 };
6
+ function isValidViewport(value) {
7
+ if (value == null || typeof value !== 'object' || Array.isArray(value)) {
8
+ return false;
9
+ }
10
+ const v = value;
11
+ return (typeof v.x === 'number' &&
12
+ typeof v.y === 'number' &&
13
+ typeof v.zoom === 'number' &&
14
+ Number.isFinite(v.x) &&
15
+ Number.isFinite(v.y) &&
16
+ Number.isFinite(v.zoom) &&
17
+ v.zoom > 0);
18
+ }
19
+ function readViewport() {
20
+ try {
21
+ const raw = localStorage.getItem(STORAGE_KEY);
22
+ if (raw == null)
23
+ return DEFAULT_VIEWPORT;
24
+ const parsed = JSON.parse(raw);
25
+ return isValidViewport(parsed) ? parsed : DEFAULT_VIEWPORT;
26
+ }
27
+ catch {
28
+ return DEFAULT_VIEWPORT;
29
+ }
30
+ }
31
+ export function useViewportPersistence() {
32
+ const defaultViewport = useRef(readViewport()).current;
33
+ const timerRef = useRef(null);
34
+ useEffect(() => {
35
+ return () => {
36
+ if (timerRef.current != null) {
37
+ clearTimeout(timerRef.current);
38
+ }
39
+ };
40
+ }, []);
41
+ const onMoveEnd = useCallback((viewport) => {
42
+ if (timerRef.current != null) {
43
+ clearTimeout(timerRef.current);
44
+ }
45
+ timerRef.current = setTimeout(() => {
46
+ try {
47
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(viewport));
48
+ }
49
+ catch {
50
+ // Silently ignore localStorage errors (quota exceeded, private browsing, etc.)
51
+ }
52
+ }, DEBOUNCE_MS);
53
+ }, []);
54
+ return { defaultViewport, onMoveEnd };
55
+ }