@shepai/cli 1.58.0 → 1.60.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 (298) hide show
  1. package/dist/src/presentation/web/app/page.d.ts.map +1 -1
  2. package/dist/src/presentation/web/app/page.js +9 -0
  3. package/dist/src/presentation/web/app/skills/page.d.ts +2 -0
  4. package/dist/src/presentation/web/app/skills/page.d.ts.map +1 -0
  5. package/dist/src/presentation/web/app/skills/page.js +11 -0
  6. package/dist/src/presentation/web/components/common/ci-status-badge/ci-status-badge.d.ts +5 -0
  7. package/dist/src/presentation/web/components/common/ci-status-badge/ci-status-badge.d.ts.map +1 -0
  8. package/dist/src/presentation/web/components/common/ci-status-badge/ci-status-badge.js +14 -0
  9. package/dist/src/presentation/web/components/common/ci-status-badge/ci-status-badge.stories.d.ts +12 -0
  10. package/dist/src/presentation/web/components/common/ci-status-badge/ci-status-badge.stories.d.ts.map +1 -0
  11. package/dist/src/presentation/web/components/common/ci-status-badge/ci-status-badge.stories.js +20 -0
  12. package/dist/src/presentation/web/components/common/ci-status-badge/index.d.ts +2 -0
  13. package/dist/src/presentation/web/components/common/ci-status-badge/index.d.ts.map +1 -0
  14. package/dist/src/presentation/web/components/common/ci-status-badge/index.js +1 -0
  15. package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.d.ts.map +1 -1
  16. package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.js +13 -2
  17. package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.stories.d.ts +8 -0
  18. package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.stories.d.ts.map +1 -1
  19. package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.stories.js +41 -0
  20. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts +9 -0
  21. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts.map +1 -1
  22. package/dist/src/presentation/web/components/common/merge-review/merge-review.d.ts.map +1 -1
  23. package/dist/src/presentation/web/components/common/merge-review/merge-review.js +2 -12
  24. package/dist/src/presentation/web/components/features/skills/category-filter.d.ts +8 -0
  25. package/dist/src/presentation/web/components/features/skills/category-filter.d.ts.map +1 -0
  26. package/dist/src/presentation/web/components/features/skills/category-filter.js +12 -0
  27. package/dist/src/presentation/web/components/features/skills/category-filter.stories.d.ts +9 -0
  28. package/dist/src/presentation/web/components/features/skills/category-filter.stories.d.ts.map +1 -0
  29. package/dist/src/presentation/web/components/features/skills/category-filter.stories.js +36 -0
  30. package/dist/src/presentation/web/components/features/skills/index.d.ts +6 -0
  31. package/dist/src/presentation/web/components/features/skills/index.d.ts.map +1 -0
  32. package/dist/src/presentation/web/components/features/skills/index.js +5 -0
  33. package/dist/src/presentation/web/components/features/skills/skill-card.d.ts +7 -0
  34. package/dist/src/presentation/web/components/features/skills/skill-card.d.ts.map +1 -0
  35. package/dist/src/presentation/web/components/features/skills/skill-card.js +12 -0
  36. package/dist/src/presentation/web/components/features/skills/skill-card.stories.d.ts +11 -0
  37. package/dist/src/presentation/web/components/features/skills/skill-card.stories.d.ts.map +1 -0
  38. package/dist/src/presentation/web/components/features/skills/skill-card.stories.js +88 -0
  39. package/dist/src/presentation/web/components/features/skills/skill-detail-drawer.d.ts +7 -0
  40. package/dist/src/presentation/web/components/features/skills/skill-detail-drawer.d.ts.map +1 -0
  41. package/dist/src/presentation/web/components/features/skills/skill-detail-drawer.js +13 -0
  42. package/dist/src/presentation/web/components/features/skills/skill-detail-drawer.stories.d.ts +10 -0
  43. package/dist/src/presentation/web/components/features/skills/skill-detail-drawer.stories.d.ts.map +1 -0
  44. package/dist/src/presentation/web/components/features/skills/skill-detail-drawer.stories.js +71 -0
  45. package/dist/src/presentation/web/components/features/skills/skill-list.d.ts +7 -0
  46. package/dist/src/presentation/web/components/features/skills/skill-list.d.ts.map +1 -0
  47. package/dist/src/presentation/web/components/features/skills/skill-list.js +21 -0
  48. package/dist/src/presentation/web/components/features/skills/skill-list.stories.d.ts +9 -0
  49. package/dist/src/presentation/web/components/features/skills/skill-list.stories.d.ts.map +1 -0
  50. package/dist/src/presentation/web/components/features/skills/skill-list.stories.js +124 -0
  51. package/dist/src/presentation/web/components/features/skills/skills-page-client.d.ts +6 -0
  52. package/dist/src/presentation/web/components/features/skills/skills-page-client.d.ts.map +1 -0
  53. package/dist/src/presentation/web/components/features/skills/skills-page-client.js +52 -0
  54. package/dist/src/presentation/web/components/features/skills/skills-page-client.stories.d.ts +16 -0
  55. package/dist/src/presentation/web/components/features/skills/skills-page-client.stories.d.ts.map +1 -0
  56. package/dist/src/presentation/web/components/features/skills/skills-page-client.stories.js +186 -0
  57. package/dist/src/presentation/web/components/layouts/app-sidebar/app-sidebar.d.ts.map +1 -1
  58. package/dist/src/presentation/web/components/layouts/app-sidebar/app-sidebar.js +3 -2
  59. package/dist/src/presentation/web/lib/feature-flags.d.ts +10 -0
  60. package/dist/src/presentation/web/lib/feature-flags.d.ts.map +1 -0
  61. package/dist/src/presentation/web/lib/feature-flags.js +12 -0
  62. package/dist/src/presentation/web/lib/skills.d.ts +30 -0
  63. package/dist/src/presentation/web/lib/skills.d.ts.map +1 -0
  64. package/dist/src/presentation/web/lib/skills.js +137 -0
  65. package/dist/tsconfig.build.tsbuildinfo +1 -1
  66. package/package.json +1 -1
  67. package/web/.next/BUILD_ID +1 -1
  68. package/web/.next/app-path-routes-manifest.json +1 -0
  69. package/web/.next/build-manifest.json +4 -4
  70. package/web/.next/cache/.previewinfo +1 -1
  71. package/web/.next/cache/.rscinfo +1 -1
  72. package/web/.next/cache/.tsbuildinfo +1 -1
  73. package/web/.next/cache/config.json +3 -3
  74. package/web/.next/fallback-build-manifest.json +2 -2
  75. package/web/.next/prerender-manifest.json +3 -3
  76. package/web/.next/required-server-files.js +1 -1
  77. package/web/.next/required-server-files.json +1 -1
  78. package/web/.next/routes-manifest.json +6 -0
  79. package/web/.next/server/app/_global-error/page/build-manifest.json +2 -2
  80. package/web/.next/server/app/_global-error.html +2 -2
  81. package/web/.next/server/app/_global-error.rsc +1 -1
  82. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  83. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  84. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  85. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  86. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  87. package/web/.next/server/app/_not-found/page/build-manifest.json +2 -2
  88. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  89. package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  90. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  91. package/web/.next/server/app/api/tools/[id]/install/route.js +1 -1
  92. package/web/.next/server/app/api/tools/[id]/install/route.js.nft.json +1 -1
  93. package/web/.next/server/app/page/build-manifest.json +2 -2
  94. package/web/.next/server/app/page/server-reference-manifest.json +14 -14
  95. package/web/.next/server/app/page.js +1 -1
  96. package/web/.next/server/app/page.js.nft.json +1 -1
  97. package/web/.next/server/app/page_client-reference-manifest.js +1 -1
  98. package/web/.next/server/app/skills/page/app-paths-manifest.json +3 -0
  99. package/web/.next/server/app/skills/page/build-manifest.json +17 -0
  100. package/web/.next/server/app/skills/page/next-font-manifest.json +6 -0
  101. package/web/.next/server/app/skills/page/react-loadable-manifest.json +1 -0
  102. package/web/.next/server/app/skills/page/server-reference-manifest.json +20 -0
  103. package/web/.next/server/app/skills/page.js +16 -0
  104. package/web/.next/server/app/skills/page.js.map +5 -0
  105. package/web/.next/server/app/skills/page.js.nft.json +1 -0
  106. package/web/.next/server/app/skills/page_client-reference-manifest.js +2 -0
  107. package/web/.next/server/app/tools/page/build-manifest.json +2 -2
  108. package/web/.next/server/app/tools/page/server-reference-manifest.json +1 -1
  109. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  110. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  111. package/web/.next/server/app/version/page/build-manifest.json +2 -2
  112. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  113. package/web/.next/server/app/version/page.js.nft.json +1 -1
  114. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  115. package/web/.next/server/app-paths-manifest.json +1 -0
  116. package/web/.next/server/chunks/{[root-of-the-server]__bb619083._.js → [root-of-the-server]__e926de65._.js} +2 -2
  117. package/web/.next/server/chunks/ssr/[root-of-the-server]__08ba9bd3._.js +1 -1
  118. package/web/.next/server/chunks/ssr/[root-of-the-server]__08ba9bd3._.js.map +1 -1
  119. package/web/.next/server/chunks/ssr/[root-of-the-server]__2395adc6._.js +3 -0
  120. package/web/.next/server/chunks/ssr/[root-of-the-server]__2395adc6._.js.map +1 -0
  121. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  122. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +1 -1
  123. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  124. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +1 -1
  125. package/web/.next/server/chunks/ssr/[root-of-the-server]__87fda958._.js +3 -0
  126. package/web/.next/server/chunks/ssr/[root-of-the-server]__87fda958._.js.map +1 -0
  127. package/web/.next/server/chunks/ssr/[root-of-the-server]__9add7c3a._.js +2 -2
  128. package/web/.next/server/chunks/ssr/[root-of-the-server]__9add7c3a._.js.map +1 -1
  129. package/web/.next/server/chunks/ssr/{[root-of-the-server]__86c7bba5._.js → [root-of-the-server]__b6839c3f._.js} +3 -3
  130. package/web/.next/server/chunks/ssr/{[root-of-the-server]__86c7bba5._.js.map → [root-of-the-server]__b6839c3f._.js.map} +1 -1
  131. package/web/.next/server/chunks/ssr/[root-of-the-server]__da0ade1f._.js +4 -0
  132. package/web/.next/server/chunks/ssr/[root-of-the-server]__da0ade1f._.js.map +1 -0
  133. package/web/.next/server/chunks/ssr/[root-of-the-server]__edca9510._.js +3 -0
  134. package/web/.next/server/chunks/ssr/[root-of-the-server]__edca9510._.js.map +1 -0
  135. package/web/.next/server/chunks/ssr/[root-of-the-server]__ee7cffe1._.js +3 -0
  136. package/web/.next/server/chunks/ssr/[root-of-the-server]__ee7cffe1._.js.map +1 -0
  137. package/web/.next/server/chunks/ssr/[root-of-the-server]__fbc89707._.js +1 -1
  138. package/web/.next/server/chunks/ssr/_34627374._.js +6 -0
  139. package/web/.next/server/chunks/ssr/_34627374._.js.map +1 -0
  140. package/web/.next/server/chunks/ssr/_380c6567._.js +6 -0
  141. package/web/.next/server/chunks/ssr/_380c6567._.js.map +1 -0
  142. package/web/.next/server/chunks/ssr/_44cce4e0._.js +4 -0
  143. package/web/.next/server/chunks/ssr/_44cce4e0._.js.map +1 -0
  144. package/web/.next/server/chunks/ssr/_9915d2a7._.js +3 -0
  145. package/web/.next/server/chunks/ssr/_9915d2a7._.js.map +1 -0
  146. package/web/.next/server/chunks/ssr/_a64b7b24._.js +3 -0
  147. package/web/.next/server/chunks/ssr/{_e242b954._.js.map → _a64b7b24._.js.map} +1 -1
  148. package/web/.next/server/chunks/ssr/_e7a4b0e4._.js +3 -0
  149. package/web/.next/server/chunks/ssr/_e7a4b0e4._.js.map +1 -0
  150. package/web/.next/{standalone/src/presentation/web/.next/server/chunks/ssr/node_modules__pnpm_d26a7485._.js → server/chunks/ssr/node_modules__pnpm_fe355030._.js} +2 -2
  151. package/web/.next/server/chunks/ssr/node_modules__pnpm_fe355030._.js.map +1 -0
  152. package/web/.next/server/chunks/ssr/src_presentation_web_components_0286756b._.js +3 -0
  153. package/web/.next/server/chunks/ssr/src_presentation_web_components_0286756b._.js.map +1 -0
  154. package/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.js +1 -1
  155. package/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.js.map +1 -1
  156. package/web/.next/server/middleware-build-manifest.js +2 -2
  157. package/web/.next/server/pages/500.html +2 -2
  158. package/web/.next/server/server-reference-manifest.js +1 -1
  159. package/web/.next/server/server-reference-manifest.json +22 -15
  160. package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
  161. package/web/.next/standalone/src/presentation/web/.next/app-path-routes-manifest.json +1 -0
  162. package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +4 -4
  163. package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
  164. package/web/.next/standalone/src/presentation/web/.next/required-server-files.json +1 -1
  165. package/web/.next/standalone/src/presentation/web/.next/routes-manifest.json +6 -0
  166. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error/page/build-manifest.json +2 -2
  167. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
  168. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
  169. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  170. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  171. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  172. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  173. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  174. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page/build-manifest.json +2 -2
  175. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  176. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  177. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  178. package/web/.next/standalone/src/presentation/web/.next/server/app/api/tools/[id]/install/route.js +1 -1
  179. package/web/.next/standalone/src/presentation/web/.next/server/app/api/tools/[id]/install/route.js.nft.json +1 -1
  180. package/web/.next/standalone/src/presentation/web/.next/server/app/page/build-manifest.json +2 -2
  181. package/web/.next/standalone/src/presentation/web/.next/server/app/page/server-reference-manifest.json +14 -14
  182. package/web/.next/standalone/src/presentation/web/.next/server/app/page.js +1 -1
  183. package/web/.next/standalone/src/presentation/web/.next/server/app/page.js.nft.json +1 -1
  184. package/web/.next/standalone/src/presentation/web/.next/server/app/page_client-reference-manifest.js +1 -1
  185. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page/app-paths-manifest.json +3 -0
  186. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page/build-manifest.json +17 -0
  187. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page/next-font-manifest.json +6 -0
  188. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page/react-loadable-manifest.json +1 -0
  189. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page/server-reference-manifest.json +20 -0
  190. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page.js +16 -0
  191. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page.js.map +5 -0
  192. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page.js.nft.json +1 -0
  193. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page_client-reference-manifest.js +2 -0
  194. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page/build-manifest.json +2 -2
  195. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page/server-reference-manifest.json +1 -1
  196. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page.js.nft.json +1 -1
  197. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  198. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page/build-manifest.json +2 -2
  199. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  200. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page.js.nft.json +1 -1
  201. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  202. package/web/.next/standalone/src/presentation/web/.next/server/app-paths-manifest.json +1 -0
  203. package/web/.next/standalone/src/presentation/web/.next/server/chunks/{[root-of-the-server]__bb619083._.js → [root-of-the-server]__e926de65._.js} +2 -2
  204. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__08ba9bd3._.js +1 -1
  205. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__2395adc6._.js +3 -0
  206. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  207. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  208. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__87fda958._.js +3 -0
  209. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__9add7c3a._.js +2 -2
  210. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/{[root-of-the-server]__86c7bba5._.js → [root-of-the-server]__b6839c3f._.js} +3 -3
  211. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__da0ade1f._.js +4 -0
  212. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__edca9510._.js +3 -0
  213. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__ee7cffe1._.js +3 -0
  214. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__fbc89707._.js +1 -1
  215. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_34627374._.js +6 -0
  216. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_380c6567._.js +6 -0
  217. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_44cce4e0._.js +4 -0
  218. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_9915d2a7._.js +3 -0
  219. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_a64b7b24._.js +3 -0
  220. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_e7a4b0e4._.js +3 -0
  221. package/web/.next/{server/chunks/ssr/node_modules__pnpm_d26a7485._.js → standalone/src/presentation/web/.next/server/chunks/ssr/node_modules__pnpm_fe355030._.js} +2 -2
  222. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_0286756b._.js +3 -0
  223. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.js +1 -1
  224. package/web/.next/standalone/src/presentation/web/.next/server/middleware-build-manifest.js +2 -2
  225. package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
  226. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
  227. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +22 -15
  228. package/web/.next/standalone/src/presentation/web/app/page.tsx +9 -0
  229. package/web/.next/standalone/src/presentation/web/app/skills/page.tsx +12 -0
  230. package/web/.next/standalone/src/presentation/web/components/common/ci-status-badge/ci-status-badge.stories.tsx +27 -0
  231. package/web/.next/standalone/src/presentation/web/components/common/ci-status-badge/ci-status-badge.tsx +29 -0
  232. package/web/.next/standalone/src/presentation/web/components/common/ci-status-badge/index.ts +1 -0
  233. package/web/.next/standalone/src/presentation/web/components/common/feature-drawer/feature-drawer.stories.tsx +53 -0
  234. package/web/.next/standalone/src/presentation/web/components/common/feature-drawer/feature-drawer.tsx +61 -1
  235. package/web/.next/standalone/src/presentation/web/components/common/feature-node/feature-node-state-config.ts +9 -0
  236. package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review.tsx +1 -29
  237. package/web/.next/standalone/src/presentation/web/components/features/skills/category-filter.stories.tsx +57 -0
  238. package/web/.next/standalone/src/presentation/web/components/features/skills/category-filter.tsx +36 -0
  239. package/web/.next/standalone/src/presentation/web/components/features/skills/index.ts +5 -0
  240. package/web/.next/standalone/src/presentation/web/components/features/skills/skill-card.stories.tsx +105 -0
  241. package/web/.next/standalone/src/presentation/web/components/features/skills/skill-card.tsx +48 -0
  242. package/web/.next/standalone/src/presentation/web/components/features/skills/skill-detail-drawer.stories.tsx +96 -0
  243. package/web/.next/standalone/src/presentation/web/components/features/skills/skill-detail-drawer.tsx +100 -0
  244. package/web/.next/standalone/src/presentation/web/components/features/skills/skill-list.stories.tsx +139 -0
  245. package/web/.next/standalone/src/presentation/web/components/features/skills/skill-list.tsx +48 -0
  246. package/web/.next/standalone/src/presentation/web/components/features/skills/skills-page-client.stories.tsx +199 -0
  247. package/web/.next/standalone/src/presentation/web/components/features/skills/skills-page-client.tsx +112 -0
  248. package/web/.next/standalone/src/presentation/web/components/layouts/app-sidebar/app-sidebar.tsx +10 -1
  249. package/web/.next/standalone/src/presentation/web/lib/feature-flags.ts +14 -0
  250. package/web/.next/standalone/src/presentation/web/lib/skills.ts +188 -0
  251. package/web/.next/standalone/src/presentation/web/package.json +2 -0
  252. package/web/.next/standalone/src/presentation/web/server.js +1 -1
  253. package/web/.next/static/chunks/09d898be63c54f20.js +1 -0
  254. package/web/.next/static/chunks/{eb0e60434c992fc1.js → 1fe24572a810eafa.js} +5 -5
  255. package/web/.next/static/chunks/25f42652257ff43d.js +1 -0
  256. package/web/.next/static/chunks/2934854f0378f815.js +1 -0
  257. package/web/.next/static/chunks/7d3c5ae8f47e74cd.js +1 -0
  258. package/web/.next/static/chunks/8b2879f911a05b55.css +2 -0
  259. package/web/.next/static/chunks/acdb8af5a21f1ae9.js +1 -0
  260. package/web/.next/static/chunks/bac5122e95f5c7eb.js +1 -0
  261. package/web/.next/static/chunks/{3d4dcf0be654a331.js → cb1b27e4a21415d3.js} +2 -2
  262. package/web/.next/static/chunks/d4379644a6145352.js +1 -0
  263. package/web/.next/static/chunks/{turbopack-6a11f2f1634ff6e0.js → turbopack-eb24b869babb34b4.js} +2 -2
  264. package/web/.next/trace +1 -1
  265. package/web/.next/trace-build +1 -1
  266. package/web/.next/types/link.d.ts +1 -0
  267. package/web/.next/types/routes.d.ts +2 -1
  268. package/web/.next/types/validator.ts +9 -0
  269. package/web/package.json +2 -0
  270. package/web/.next/server/chunks/ssr/[root-of-the-server]__847521e6._.js +0 -3
  271. package/web/.next/server/chunks/ssr/[root-of-the-server]__847521e6._.js.map +0 -1
  272. package/web/.next/server/chunks/ssr/[root-of-the-server]__d21f0894._.js +0 -3
  273. package/web/.next/server/chunks/ssr/[root-of-the-server]__d21f0894._.js.map +0 -1
  274. package/web/.next/server/chunks/ssr/_027596cf._.js +0 -6
  275. package/web/.next/server/chunks/ssr/_027596cf._.js.map +0 -1
  276. package/web/.next/server/chunks/ssr/_e242b954._.js +0 -3
  277. package/web/.next/server/chunks/ssr/node_modules__pnpm_d26a7485._.js.map +0 -1
  278. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +0 -3
  279. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +0 -1
  280. package/web/.next/server/chunks/ssr/src_presentation_web_components_ec3b0a65._.js +0 -3
  281. package/web/.next/server/chunks/ssr/src_presentation_web_components_ec3b0a65._.js.map +0 -1
  282. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__847521e6._.js +0 -3
  283. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__d21f0894._.js +0 -3
  284. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_027596cf._.js +0 -6
  285. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_e242b954._.js +0 -3
  286. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +0 -3
  287. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_ec3b0a65._.js +0 -3
  288. package/web/.next/static/chunks/0cd7c513169faee3.js +0 -1
  289. package/web/.next/static/chunks/3f5de337d3fc604f.js +0 -1
  290. package/web/.next/static/chunks/60bbbe7ff679eb4c.css +0 -2
  291. package/web/.next/static/chunks/67459433cc866344.js +0 -1
  292. package/web/.next/static/chunks/7138c478667158d0.js +0 -1
  293. package/web/.next/static/chunks/a9c2b889c8749a94.js +0 -1
  294. package/web/.next/static/chunks/cda11a2491d519fc.js +0 -1
  295. /package/web/.next/server/chunks/{[root-of-the-server]__bb619083._.js.map → [root-of-the-server]__e926de65._.js.map} +0 -0
  296. /package/web/.next/static/{e7Q45G0MI6cgci9Gn2J-i → enyZhg62FqP6oInxg1T3h}/_buildManifest.js +0 -0
  297. /package/web/.next/static/{e7Q45G0MI6cgci9Gn2J-i → enyZhg62FqP6oInxg1T3h}/_clientMiddlewareManifest.json +0 -0
  298. /package/web/.next/static/{e7Q45G0MI6cgci9Gn2J-i → enyZhg62FqP6oInxg1T3h}/_ssgManifest.js +0 -0
@@ -0,0 +1,29 @@
1
+ import { CheckCircle2, Loader2, XCircle } from 'lucide-react';
2
+ import { CiStatus } from '@shepai/core/domain/generated/output';
3
+ import { Badge } from '@/components/ui/badge';
4
+
5
+ export function CiStatusBadge({ status }: { status: CiStatus }) {
6
+ switch (status) {
7
+ case CiStatus.Success:
8
+ return (
9
+ <Badge className="border-transparent bg-green-50 text-green-700 hover:bg-green-50">
10
+ <CheckCircle2 className="mr-1 h-3.5 w-3.5" />
11
+ Passing
12
+ </Badge>
13
+ );
14
+ case CiStatus.Pending:
15
+ return (
16
+ <Badge className="border-transparent bg-yellow-50 text-yellow-700 hover:bg-yellow-50">
17
+ <Loader2 className="mr-1 h-3.5 w-3.5 animate-spin" />
18
+ Pending
19
+ </Badge>
20
+ );
21
+ case CiStatus.Failure:
22
+ return (
23
+ <Badge className="border-transparent bg-red-50 text-red-700 hover:bg-red-50">
24
+ <XCircle className="mr-1 h-3.5 w-3.5" />
25
+ Failing
26
+ </Badge>
27
+ );
28
+ }
29
+ }
@@ -0,0 +1 @@
1
+ export { CiStatusBadge } from './ci-status-badge';
@@ -1,5 +1,6 @@
1
1
  import { useState } from 'react';
2
2
  import type { Meta, StoryObj } from '@storybook/react';
3
+ import { PrStatus, CiStatus } from '@shepai/core/domain/generated/output';
3
4
  import { FeatureDrawer } from './feature-drawer';
4
5
  import type { FeatureNodeData } from '@/components/common/feature-node';
5
6
  import type { FeatureLifecyclePhase, FeatureNodeState } from '@/components/common/feature-node';
@@ -353,3 +354,55 @@ export const DeletingState: Story = {
353
354
  export const DeleteRunningAgent: Story = {
354
355
  render: () => <DrawerTriggerWithDelete data={runningData} label="Open Running Agent Delete" />,
355
356
  };
357
+
358
+ /* ---------------------------------------------------------------------------
359
+ * PR info stories
360
+ * ------------------------------------------------------------------------- */
361
+
362
+ const doneWithPrData: FeatureNodeData = {
363
+ ...doneData,
364
+ pr: {
365
+ url: 'https://github.com/org/repo/pull/42',
366
+ number: 42,
367
+ status: PrStatus.Merged,
368
+ ciStatus: CiStatus.Success,
369
+ commitHash: 'abc1234567890def',
370
+ },
371
+ };
372
+
373
+ const doneWithPartialPrData: FeatureNodeData = {
374
+ ...doneData,
375
+ pr: {
376
+ url: 'https://github.com/org/repo/pull/99',
377
+ number: 99,
378
+ status: PrStatus.Merged,
379
+ },
380
+ };
381
+
382
+ /** Done feature with full PR card — number, status, CI, commit hash. */
383
+ export const DoneWithPr: Story = {
384
+ render: () => <DrawerTrigger data={doneWithPrData} label="Open Done + PR" />,
385
+ };
386
+
387
+ /** Done feature with partial PR data — no CI status, no commit hash. */
388
+ export const DoneWithPartialPr: Story = {
389
+ render: () => <DrawerTrigger data={doneWithPartialPrData} label="Open Done + Partial PR" />,
390
+ };
391
+
392
+ /** PR with Open status — blue badge. */
393
+ export const PrStatusOpen: Story = {
394
+ render: () => (
395
+ <DrawerTrigger
396
+ data={{
397
+ ...doneWithPrData,
398
+ pr: { ...doneWithPrData.pr!, status: PrStatus.Open, ciStatus: CiStatus.Pending },
399
+ }}
400
+ label="Open PR Status: Open"
401
+ />
402
+ ),
403
+ };
404
+
405
+ /** PR with Merged status — purple badge. */
406
+ export const PrStatusMerged: Story = {
407
+ render: () => <DrawerTrigger data={doneWithPrData} label="Open PR Status: Merged" />,
408
+ };
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
 
3
- import { XIcon, Loader2, Trash2 } from 'lucide-react';
3
+ import { XIcon, Loader2, Trash2, ExternalLink, GitCommitHorizontal } from 'lucide-react';
4
+ import { PrStatus } from '@shepai/core/domain/generated/output';
4
5
  import { cn } from '@/lib/utils';
5
6
  import { OpenActionMenu } from '@/components/common/open-action-menu';
6
7
  import {
@@ -11,6 +12,7 @@ import {
11
12
  DrawerDescription,
12
13
  } from '@/components/ui/drawer';
13
14
  import { Button } from '@/components/ui/button';
15
+ import { Badge } from '@/components/ui/badge';
14
16
  import { Separator } from '@/components/ui/separator';
15
17
  import { CometSpinner } from '@/components/ui/comet-spinner';
16
18
  import {
@@ -24,6 +26,7 @@ import {
24
26
  AlertDialogTitle,
25
27
  AlertDialogTrigger,
26
28
  } from '@/components/ui/alert-dialog';
29
+ import { CiStatusBadge } from '@/components/common/ci-status-badge';
27
30
  import { featureNodeStateConfig, lifecycleDisplayLabels } from '@/components/common/feature-node';
28
31
  import type { FeatureNodeData } from '@/components/common/feature-node';
29
32
  import { useFeatureActions } from './use-feature-actions';
@@ -108,6 +111,14 @@ export function FeatureDrawer({
108
111
  ) : null}
109
112
  </div>
110
113
 
114
+ {/* PR info */}
115
+ {selectedNode.pr ? (
116
+ <>
117
+ <Separator />
118
+ <PrInfoSection pr={selectedNode.pr} />
119
+ </>
120
+ ) : null}
121
+
111
122
  <Separator />
112
123
 
113
124
  {/* Details */}
@@ -213,6 +224,55 @@ function DetailRow({ label, value }: { label: string; value: string }) {
213
224
  );
214
225
  }
215
226
 
227
+ const prStatusStyles: Record<PrStatus, string> = {
228
+ [PrStatus.Open]: 'border-transparent bg-blue-50 text-blue-700 hover:bg-blue-50',
229
+ [PrStatus.Merged]: 'border-transparent bg-purple-50 text-purple-700 hover:bg-purple-50',
230
+ [PrStatus.Closed]: 'border-transparent bg-red-50 text-red-700 hover:bg-red-50',
231
+ };
232
+
233
+ function PrInfoSection({ pr }: { pr: NonNullable<FeatureNodeData['pr']> }) {
234
+ return (
235
+ <div data-testid="feature-drawer-pr" className="border-border mx-4 rounded-lg border">
236
+ <div className="space-y-3 px-4 py-3">
237
+ {/* PR number + link */}
238
+ <div className="flex items-center justify-between">
239
+ <a
240
+ href={pr.url}
241
+ target="_blank"
242
+ rel="noopener noreferrer"
243
+ className="text-primary flex items-center gap-1.5 text-sm font-semibold underline underline-offset-2"
244
+ >
245
+ PR #{pr.number}
246
+ <ExternalLink className="h-3.5 w-3.5" />
247
+ </a>
248
+ <Badge className={prStatusStyles[pr.status]}>{pr.status}</Badge>
249
+ </div>
250
+
251
+ {/* CI status */}
252
+ {pr.ciStatus ? (
253
+ <div className="flex items-center justify-between">
254
+ <span className="text-muted-foreground text-xs font-medium">CI Status</span>
255
+ <CiStatusBadge status={pr.ciStatus} />
256
+ </div>
257
+ ) : null}
258
+
259
+ {/* Commit hash */}
260
+ {pr.commitHash ? (
261
+ <div className="flex items-center justify-between">
262
+ <span className="text-muted-foreground text-xs font-medium">Commit</span>
263
+ <div className="flex items-center gap-1.5">
264
+ <GitCommitHorizontal className="text-muted-foreground h-3.5 w-3.5" />
265
+ <code className="bg-muted text-foreground rounded-md px-1.5 py-0.5 font-mono text-[11px]">
266
+ {pr.commitHash.slice(0, 7)}
267
+ </code>
268
+ </div>
269
+ </div>
270
+ ) : null}
271
+ </div>
272
+ </div>
273
+ );
274
+ }
275
+
216
276
  function DrawerActions({
217
277
  repositoryPath,
218
278
  branch,
@@ -1,5 +1,6 @@
1
1
  import { Loader2, CircleAlert, CircleCheck, Ban, CircleX, type LucideIcon } from 'lucide-react';
2
2
  import type { Node } from '@xyflow/react';
3
+ import type { PrStatus, CiStatus } from '@shepai/core/domain/generated/output';
3
4
  import type { AgentTypeValue } from './agent-type-icons';
4
5
 
5
6
  export type FeatureNodeState =
@@ -60,6 +61,14 @@ export interface FeatureNodeData {
60
61
  errorMessage?: string;
61
62
  /** Agent executor type (e.g. "claude-code", "cursor"). */
62
63
  agentType?: AgentTypeValue;
64
+ /** PR metadata for features with an associated pull request */
65
+ pr?: {
66
+ url: string;
67
+ number: number;
68
+ status: PrStatus;
69
+ ciStatus?: CiStatus;
70
+ commitHash?: string;
71
+ };
63
72
  onAction?: () => void;
64
73
  onSettings?: () => void;
65
74
  showHandles?: boolean;
@@ -1,11 +1,9 @@
1
1
  'use client';
2
2
 
3
3
  import {
4
- CheckCircle2,
5
4
  ExternalLink,
6
5
  GitMerge,
7
6
  Loader2,
8
- XCircle,
9
7
  AlertTriangle,
10
8
  FileDiff,
11
9
  GitCommitHorizontal,
@@ -13,37 +11,11 @@ import {
13
11
  ArrowRight,
14
12
  Layers,
15
13
  } from 'lucide-react';
16
- import { CiStatus } from '@shepai/core/domain/generated/output';
17
14
  import { Badge } from '@/components/ui/badge';
15
+ import { CiStatusBadge } from '@/components/common/ci-status-badge';
18
16
  import { DrawerActionBar } from '@/components/common/drawer-action-bar';
19
17
  import type { MergeReviewProps, MergeReviewPhase } from './merge-review-config';
20
18
 
21
- function CiStatusBadge({ status }: { status: CiStatus }) {
22
- switch (status) {
23
- case CiStatus.Success:
24
- return (
25
- <Badge className="border-transparent bg-green-50 text-green-700 hover:bg-green-50">
26
- <CheckCircle2 className="mr-1 h-3.5 w-3.5" />
27
- Passing
28
- </Badge>
29
- );
30
- case CiStatus.Pending:
31
- return (
32
- <Badge className="border-transparent bg-yellow-50 text-yellow-700 hover:bg-yellow-50">
33
- <Loader2 className="mr-1 h-3.5 w-3.5 animate-spin" />
34
- Pending
35
- </Badge>
36
- );
37
- case CiStatus.Failure:
38
- return (
39
- <Badge className="border-transparent bg-red-50 text-red-700 hover:bg-red-50">
40
- <XCircle className="mr-1 h-3.5 w-3.5" />
41
- Failing
42
- </Badge>
43
- );
44
- }
45
- }
46
-
47
19
  function PhaseList({ phases }: { phases: MergeReviewPhase[] }) {
48
20
  return (
49
21
  <div className="border-border rounded-lg border">
@@ -0,0 +1,57 @@
1
+ import { useState } from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import { CategoryFilter } from './category-filter';
4
+ import type { SkillCategory } from '@/lib/skills';
5
+
6
+ const meta: Meta<typeof CategoryFilter> = {
7
+ title: 'Features/CategoryFilter',
8
+ component: CategoryFilter,
9
+ tags: ['autodocs'],
10
+ parameters: {
11
+ layout: 'padded',
12
+ },
13
+ };
14
+
15
+ export default meta;
16
+ type Story = StoryObj<typeof CategoryFilter>;
17
+
18
+ /* ---------------------------------------------------------------------------
19
+ * Interactive wrapper — manages activeCategory state
20
+ * ------------------------------------------------------------------------- */
21
+
22
+ function InteractiveCategoryFilter({
23
+ initial,
24
+ counts,
25
+ }: {
26
+ initial: SkillCategory | null;
27
+ counts?: Record<SkillCategory, number>;
28
+ }) {
29
+ const [active, setActive] = useState<SkillCategory | null>(initial);
30
+ return <CategoryFilter activeCategory={active} onCategoryChange={setActive} counts={counts} />;
31
+ }
32
+
33
+ /* ---------------------------------------------------------------------------
34
+ * Stories
35
+ * ------------------------------------------------------------------------- */
36
+
37
+ export const AllSelected: Story = {
38
+ render: () => <InteractiveCategoryFilter initial={null} />,
39
+ };
40
+
41
+ export const WorkflowSelected: Story = {
42
+ render: () => <InteractiveCategoryFilter initial="Workflow" />,
43
+ };
44
+
45
+ export const WithCounts: Story = {
46
+ render: () => (
47
+ <InteractiveCategoryFilter
48
+ initial={null}
49
+ counts={{
50
+ Workflow: 8,
51
+ 'Code Generation': 1,
52
+ Analysis: 2,
53
+ Reference: 7,
54
+ }}
55
+ />
56
+ ),
57
+ };
@@ -0,0 +1,36 @@
1
+ import { Button } from '@/components/ui/button';
2
+ import type { SkillCategory } from '@/lib/skills';
3
+
4
+ const CATEGORIES: { label: string; value: SkillCategory | null }[] = [
5
+ { label: 'All', value: null },
6
+ { label: 'Workflow', value: 'Workflow' },
7
+ { label: 'Code Generation', value: 'Code Generation' },
8
+ { label: 'Analysis', value: 'Analysis' },
9
+ { label: 'Reference', value: 'Reference' },
10
+ ];
11
+
12
+ export interface CategoryFilterProps {
13
+ activeCategory: SkillCategory | null;
14
+ onCategoryChange: (category: SkillCategory | null) => void;
15
+ counts?: Record<SkillCategory, number>;
16
+ }
17
+
18
+ export function CategoryFilter({ activeCategory, onCategoryChange, counts }: CategoryFilterProps) {
19
+ return (
20
+ <div className="flex flex-wrap gap-2" role="group" aria-label="Filter by category">
21
+ {CATEGORIES.map(({ label, value }) => (
22
+ <Button
23
+ key={label}
24
+ variant={activeCategory === value ? 'default' : 'outline'}
25
+ size="sm"
26
+ onClick={() => onCategoryChange(value)}
27
+ >
28
+ {label}
29
+ {counts && value ? (
30
+ <span className="ml-1 text-xs opacity-70">({counts[value]})</span>
31
+ ) : null}
32
+ </Button>
33
+ ))}
34
+ </div>
35
+ );
36
+ }
@@ -0,0 +1,5 @@
1
+ export { SkillsPageClient, type SkillsPageClientProps } from './skills-page-client';
2
+ export { SkillCard, type SkillCardProps } from './skill-card';
3
+ export { CategoryFilter, type CategoryFilterProps } from './category-filter';
4
+ export { SkillList, type SkillListProps } from './skill-list';
5
+ export { SkillDetailDrawer, type SkillDetailDrawerProps } from './skill-detail-drawer';
@@ -0,0 +1,105 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { fn } from '@storybook/test';
3
+ import { SkillCard } from './skill-card';
4
+ import type { SkillData } from '@/lib/skills';
5
+
6
+ const meta: Meta<typeof SkillCard> = {
7
+ title: 'Features/SkillCard',
8
+ component: SkillCard,
9
+ tags: ['autodocs'],
10
+ parameters: {
11
+ layout: 'centered',
12
+ },
13
+ args: {
14
+ onSelect: fn(),
15
+ },
16
+ };
17
+
18
+ export default meta;
19
+ type Story = StoryObj<typeof meta>;
20
+
21
+ /* ---------------------------------------------------------------------------
22
+ * Data fixtures
23
+ * ------------------------------------------------------------------------- */
24
+
25
+ const baseSkill: SkillData = {
26
+ name: 'shep-kit:implement',
27
+ displayName: 'implement',
28
+ description: 'Validate specs and autonomously execute implementation tasks with status tracking.',
29
+ category: 'Workflow',
30
+ source: 'project',
31
+ body: '## Usage\n\nRun /shep-kit:implement after planning is complete.',
32
+ resources: [],
33
+ };
34
+
35
+ const skillWithAllBadges: SkillData = {
36
+ name: 'shep:ui-component',
37
+ displayName: 'ui-component',
38
+ description:
39
+ 'Use when creating, modifying, or reviewing web UI components. Triggers include "new component", "add component", "create UI".',
40
+ context: 'fork',
41
+ allowedTools: 'Read, Write, Bash, Edit, Glob',
42
+ category: 'Code Generation',
43
+ source: 'project',
44
+ body: '## Overview\n\nScaffolds UI components following the four-tier hierarchy.',
45
+ resources: [
46
+ { name: 'references', fileCount: 7 },
47
+ { name: 'templates', fileCount: 3 },
48
+ { name: 'rules', fileCount: 2 },
49
+ ],
50
+ };
51
+
52
+ const globalSkill: SkillData = {
53
+ name: 'vercel-react-best-practices',
54
+ displayName: 'vercel-react-best-practices',
55
+ description: 'React and Next.js performance optimization guidelines from Vercel Engineering.',
56
+ category: 'Reference',
57
+ source: 'global',
58
+ body: 'Performance patterns for React and Next.js applications.',
59
+ resources: [{ name: 'references', fileCount: 4 }],
60
+ };
61
+
62
+ const skillWithContext: SkillData = {
63
+ name: 'architecture-reviewer',
64
+ displayName: 'architecture-reviewer',
65
+ description: 'Use when making architectural decisions, planning features, or reviewing PRs.',
66
+ context: 'fork',
67
+ category: 'Analysis',
68
+ source: 'project',
69
+ body: '',
70
+ resources: [],
71
+ };
72
+
73
+ /* ---------------------------------------------------------------------------
74
+ * Stories
75
+ * ------------------------------------------------------------------------- */
76
+
77
+ export const Default: Story = {
78
+ args: {
79
+ skill: baseSkill,
80
+ },
81
+ };
82
+
83
+ export const WithContext: Story = {
84
+ args: {
85
+ skill: skillWithContext,
86
+ },
87
+ };
88
+
89
+ export const WithAllBadges: Story = {
90
+ args: {
91
+ skill: skillWithAllBadges,
92
+ },
93
+ };
94
+
95
+ export const ProjectSource: Story = {
96
+ args: {
97
+ skill: baseSkill,
98
+ },
99
+ };
100
+
101
+ export const GlobalSource: Story = {
102
+ args: {
103
+ skill: globalSkill,
104
+ },
105
+ };
@@ -0,0 +1,48 @@
1
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
2
+ import { Badge } from '@/components/ui/badge';
3
+ import type { SkillData } from '@/lib/skills';
4
+ import { FolderOpen } from 'lucide-react';
5
+
6
+ export interface SkillCardProps {
7
+ skill: SkillData;
8
+ onSelect: (skill: SkillData) => void;
9
+ }
10
+
11
+ export function SkillCard({ skill, onSelect }: SkillCardProps) {
12
+ return (
13
+ <Card
14
+ className="hover:border-primary/50 cursor-pointer transition-colors"
15
+ role="button"
16
+ tabIndex={0}
17
+ onClick={() => onSelect(skill)}
18
+ onKeyDown={(e) => {
19
+ if (e.key === 'Enter' || e.key === ' ') {
20
+ e.preventDefault();
21
+ onSelect(skill);
22
+ }
23
+ }}
24
+ data-testid={`skill-card-${skill.name}`}
25
+ >
26
+ <CardHeader className="pb-3">
27
+ <CardTitle className="text-base">{skill.displayName}</CardTitle>
28
+ <p className="text-muted-foreground font-mono text-xs">{skill.name}</p>
29
+ </CardHeader>
30
+ <CardContent className="space-y-3">
31
+ <p className="text-muted-foreground line-clamp-2 text-sm">{skill.description}</p>
32
+ <div className="flex flex-wrap items-center gap-1.5">
33
+ <Badge variant={skill.source === 'project' ? 'secondary' : 'outline'}>
34
+ {skill.source === 'project' ? 'Project' : 'Global'}
35
+ </Badge>
36
+ {skill.context ? <Badge variant="outline">{skill.context}</Badge> : null}
37
+ {skill.allowedTools ? <Badge variant="outline">Tools</Badge> : null}
38
+ {skill.resources.length > 0 ? (
39
+ <span className="text-muted-foreground inline-flex items-center gap-1 text-xs">
40
+ <FolderOpen className="size-3" />
41
+ {skill.resources.length} {skill.resources.length === 1 ? 'resource' : 'resources'}
42
+ </span>
43
+ ) : null}
44
+ </div>
45
+ </CardContent>
46
+ </Card>
47
+ );
48
+ }
@@ -0,0 +1,96 @@
1
+ import { useState } from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import { SkillDetailDrawer } from './skill-detail-drawer';
4
+ import { Button } from '@/components/ui/button';
5
+ import type { SkillData } from '@/lib/skills';
6
+
7
+ const meta: Meta<typeof SkillDetailDrawer> = {
8
+ title: 'Features/SkillDetailDrawer',
9
+ component: SkillDetailDrawer,
10
+ tags: ['autodocs'],
11
+ parameters: {
12
+ layout: 'fullscreen',
13
+ },
14
+ };
15
+
16
+ export default meta;
17
+ type Story = StoryObj<typeof SkillDetailDrawer>;
18
+
19
+ /* ---------------------------------------------------------------------------
20
+ * Data fixtures
21
+ * ------------------------------------------------------------------------- */
22
+
23
+ const skillWithResources: SkillData = {
24
+ name: 'shep:ui-component',
25
+ displayName: 'ui-component',
26
+ description:
27
+ 'Use when creating, modifying, or reviewing web UI components. Triggers include "new component", "add component", "create UI", "build a widget".',
28
+ context: 'fork',
29
+ allowedTools: 'Read, Write, Bash, Edit, Glob, Grep',
30
+ category: 'Code Generation',
31
+ source: 'project',
32
+ body: '## Overview\n\nScaffolds UI components following the four-tier hierarchy.\n\n## Usage\n\nRun /shep:ui-component when you need to create or modify components.',
33
+ resources: [
34
+ { name: 'references', fileCount: 7 },
35
+ { name: 'templates', fileCount: 3 },
36
+ { name: 'rules', fileCount: 2 },
37
+ ],
38
+ };
39
+
40
+ const skillWithoutResources: SkillData = {
41
+ name: 'shep-kit:implement',
42
+ displayName: 'implement',
43
+ description:
44
+ 'Validate specs and autonomously execute implementation tasks with status tracking. Use after /shep-kit:plan when ready to start implementation.',
45
+ category: 'Workflow',
46
+ source: 'project',
47
+ body: '## Usage\n\nRun /shep-kit:implement after planning is complete to start autonomous implementation.\n\n## What it does\n\n1. Pre-Implementation Validation Gate\n2. Autonomous Execution\n3. Status Tracking',
48
+ resources: [],
49
+ };
50
+
51
+ const minimalSkill: SkillData = {
52
+ name: 'find-skills',
53
+ displayName: 'find-skills',
54
+ description: 'Helps users discover and install agent skills.',
55
+ category: 'Reference',
56
+ source: 'global',
57
+ body: '',
58
+ resources: [],
59
+ };
60
+
61
+ /* ---------------------------------------------------------------------------
62
+ * Trigger wrapper — starts closed, click to open
63
+ * ------------------------------------------------------------------------- */
64
+
65
+ function DrawerTrigger({ skill, label }: { skill: SkillData; label: string }) {
66
+ const [selected, setSelected] = useState<SkillData | null>(null);
67
+
68
+ return (
69
+ <div className="flex h-screen items-start p-4">
70
+ <Button variant="outline" onClick={() => setSelected(skill)}>
71
+ {label}
72
+ </Button>
73
+ <SkillDetailDrawer skill={selected} onClose={() => setSelected(null)} />
74
+ </div>
75
+ );
76
+ }
77
+
78
+ /* ---------------------------------------------------------------------------
79
+ * Stories
80
+ * ------------------------------------------------------------------------- */
81
+
82
+ export const Open: Story = {
83
+ render: () => <DrawerTrigger skill={skillWithResources} label="Open Skill Detail" />,
84
+ };
85
+
86
+ export const WithResources: Story = {
87
+ render: () => <DrawerTrigger skill={skillWithResources} label="Open With Resources" />,
88
+ };
89
+
90
+ export const WithoutResources: Story = {
91
+ render: () => <DrawerTrigger skill={skillWithoutResources} label="Open Without Resources" />,
92
+ };
93
+
94
+ export const MinimalSkill: Story = {
95
+ render: () => <DrawerTrigger skill={minimalSkill} label="Open Minimal Skill" />,
96
+ };