@shepai/cli 1.74.0 → 1.75.0-pr237.5e7fa4f

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 (255) hide show
  1. package/dist/packages/core/src/application/ports/output/agents/feature-agent-process.interface.d.ts +1 -0
  2. package/dist/packages/core/src/application/ports/output/agents/feature-agent-process.interface.d.ts.map +1 -1
  3. package/dist/packages/core/src/application/ports/output/services/spec-initializer.interface.d.ts +4 -1
  4. package/dist/packages/core/src/application/ports/output/services/spec-initializer.interface.d.ts.map +1 -1
  5. package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts.map +1 -1
  6. package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.js +5 -2
  7. package/dist/packages/core/src/application/use-cases/features/create/types.d.ts +2 -0
  8. package/dist/packages/core/src/application/use-cases/features/create/types.d.ts.map +1 -1
  9. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/fast-feature-agent-graph.d.ts +220 -0
  10. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/fast-feature-agent-graph.d.ts.map +1 -0
  11. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/fast-feature-agent-graph.js +66 -0
  12. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts +1 -0
  13. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts.map +1 -1
  14. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.js +3 -0
  15. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts +1 -0
  16. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts.map +1 -1
  17. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js +10 -1
  18. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/lifecycle-context.d.ts.map +1 -1
  19. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/lifecycle-context.js +1 -0
  20. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/fast-implement.node.d.ts +21 -0
  21. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/fast-implement.node.d.ts.map +1 -0
  22. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/fast-implement.node.js +60 -0
  23. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/fast-implement.prompt.d.ts +25 -0
  24. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/fast-implement.prompt.d.ts.map +1 -0
  25. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/fast-implement.prompt.js +176 -0
  26. package/dist/packages/core/src/infrastructure/services/spec/spec-initializer.service.d.ts +1 -1
  27. package/dist/packages/core/src/infrastructure/services/spec/spec-initializer.service.d.ts.map +1 -1
  28. package/dist/packages/core/src/infrastructure/services/spec/spec-initializer.service.js +8 -3
  29. package/dist/src/presentation/cli/commands/feat/new.command.d.ts.map +1 -1
  30. package/dist/src/presentation/cli/commands/feat/new.command.js +2 -0
  31. package/dist/src/presentation/web/app/actions/create-feature.d.ts +2 -0
  32. package/dist/src/presentation/web/app/actions/create-feature.d.ts.map +1 -1
  33. package/dist/src/presentation/web/app/actions/create-feature.js +3 -1
  34. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts +2 -0
  35. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts.map +1 -1
  36. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.js +5 -1
  37. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.d.ts +18 -0
  38. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.d.ts.map +1 -1
  39. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.js +49 -0
  40. package/dist/src/presentation/web/components/common/theme-toggle/theme-toggle.d.ts.map +1 -1
  41. package/dist/src/presentation/web/components/common/theme-toggle/theme-toggle.js +21 -10
  42. package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
  43. package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +31 -5
  44. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts +4 -1
  45. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
  46. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +4 -2
  47. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts +4 -1
  48. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts.map +1 -1
  49. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.js +3 -2
  50. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.stories.d.ts +3 -0
  51. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.stories.d.ts.map +1 -1
  52. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.stories.js +89 -0
  53. package/dist/src/presentation/web/hooks/use-graph-state.d.ts +2 -0
  54. package/dist/src/presentation/web/hooks/use-graph-state.d.ts.map +1 -1
  55. package/dist/src/presentation/web/hooks/use-graph-state.js +4 -0
  56. package/dist/src/presentation/web/hooks/use-viewport-persistence.d.ts +15 -0
  57. package/dist/src/presentation/web/hooks/use-viewport-persistence.d.ts.map +1 -0
  58. package/dist/src/presentation/web/hooks/use-viewport-persistence.js +17 -0
  59. package/dist/tsconfig.build.tsbuildinfo +1 -1
  60. package/package.json +1 -1
  61. package/web/.next/BUILD_ID +1 -1
  62. package/web/.next/build-manifest.json +2 -2
  63. package/web/.next/cache/.previewinfo +1 -1
  64. package/web/.next/cache/.rscinfo +1 -1
  65. package/web/.next/cache/.tsbuildinfo +1 -1
  66. package/web/.next/cache/config.json +3 -3
  67. package/web/.next/fallback-build-manifest.json +2 -2
  68. package/web/.next/prerender-manifest.json +3 -3
  69. package/web/.next/required-server-files.js +1 -1
  70. package/web/.next/required-server-files.json +1 -1
  71. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +16 -16
  72. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  73. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  74. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +19 -19
  75. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  76. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  77. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +14 -14
  78. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  79. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  80. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +16 -16
  81. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  82. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  83. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +19 -19
  84. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  85. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  86. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +14 -14
  87. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  88. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  89. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +14 -14
  90. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  91. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  92. package/web/.next/server/app/_global-error.html +2 -2
  93. package/web/.next/server/app/_global-error.rsc +1 -1
  94. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  95. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  96. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  97. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  98. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  99. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  100. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  101. package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  102. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  103. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  104. package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  105. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  106. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  107. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  108. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  109. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  110. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  111. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_da7eef33.js +1 -1
  112. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_da7eef33.js.map +1 -1
  113. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_0a9251aa.js +1 -1
  114. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_0a9251aa.js.map +1 -1
  115. package/web/.next/server/chunks/ssr/[root-of-the-server]__17a611f0._.js +2 -2
  116. package/web/.next/server/chunks/ssr/[root-of-the-server]__17a611f0._.js.map +1 -1
  117. package/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
  118. package/web/.next/server/chunks/ssr/[root-of-the-server]__45dbf93d._.js +2 -2
  119. package/web/.next/server/chunks/ssr/[root-of-the-server]__45dbf93d._.js.map +1 -1
  120. package/web/.next/server/chunks/ssr/[root-of-the-server]__6258349c._.js +1 -1
  121. package/web/.next/server/chunks/ssr/[root-of-the-server]__6258349c._.js.map +1 -1
  122. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  123. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +1 -1
  124. package/web/.next/server/chunks/ssr/[root-of-the-server]__6cbc1149._.js +2 -2
  125. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  126. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +1 -1
  127. package/web/.next/server/chunks/ssr/[root-of-the-server]__94a6d275._.js +1 -1
  128. package/web/.next/server/chunks/ssr/[root-of-the-server]__94a6d275._.js.map +1 -1
  129. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +1 -1
  130. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
  131. package/web/.next/server/chunks/ssr/_0e9d6bf7._.js +1 -1
  132. package/web/.next/server/chunks/ssr/_0e9d6bf7._.js.map +1 -1
  133. package/web/.next/server/chunks/ssr/_61351ed3._.js +1 -1
  134. package/web/.next/server/chunks/ssr/_61351ed3._.js.map +1 -1
  135. package/web/.next/server/chunks/ssr/{_4472b56f._.js → _70427cc3._.js} +3 -3
  136. package/web/.next/server/chunks/ssr/{_4472b56f._.js.map → _70427cc3._.js.map} +1 -1
  137. package/web/.next/server/chunks/ssr/_8400c8bb._.js +1 -1
  138. package/web/.next/server/chunks/ssr/_8400c8bb._.js.map +1 -1
  139. package/web/.next/server/chunks/ssr/_9f940437._.js +1 -1
  140. package/web/.next/server/chunks/ssr/_9f940437._.js.map +1 -1
  141. package/web/.next/server/chunks/ssr/src_presentation_web_163038ba._.js +2 -2
  142. package/web/.next/server/chunks/ssr/src_presentation_web_163038ba._.js.map +1 -1
  143. package/web/.next/server/chunks/ssr/src_presentation_web_30d7eeda._.js +1 -1
  144. package/web/.next/server/chunks/ssr/src_presentation_web_30d7eeda._.js.map +1 -1
  145. package/web/.next/server/chunks/ssr/src_presentation_web_459cb687._.js +2 -2
  146. package/web/.next/server/chunks/ssr/src_presentation_web_459cb687._.js.map +1 -1
  147. package/web/.next/server/chunks/ssr/src_presentation_web_565a14f8._.js +1 -1
  148. package/web/.next/server/chunks/ssr/src_presentation_web_565a14f8._.js.map +1 -1
  149. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_021a05f2.js +1 -1
  150. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_021a05f2.js.map +1 -1
  151. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
  152. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
  153. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  154. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  155. package/web/.next/server/pages/500.html +2 -2
  156. package/web/.next/server/server-reference-manifest.js +1 -1
  157. package/web/.next/server/server-reference-manifest.json +22 -22
  158. package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
  159. package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +2 -2
  160. package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
  161. package/web/.next/standalone/src/presentation/web/.next/required-server-files.json +1 -1
  162. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +16 -16
  163. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  164. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  165. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +19 -19
  166. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  167. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  168. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +14 -14
  169. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  170. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  171. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +16 -16
  172. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  173. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  174. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +19 -19
  175. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  176. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  177. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +14 -14
  178. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  179. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  180. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +14 -14
  181. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  182. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  183. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
  184. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
  185. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  186. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  187. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  188. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  189. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  190. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  191. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  192. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  193. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page.js.nft.json +1 -1
  194. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  195. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  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/server-reference-manifest.json +1 -1
  199. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  200. 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
  201. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_da7eef33.js +1 -1
  202. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_0a9251aa.js +1 -1
  203. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__17a611f0._.js +2 -2
  204. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
  205. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__45dbf93d._.js +2 -2
  206. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6258349c._.js +1 -1
  207. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  208. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6cbc1149._.js +2 -2
  209. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  210. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__94a6d275._.js +1 -1
  211. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +1 -1
  212. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_0e9d6bf7._.js +1 -1
  213. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_61351ed3._.js +1 -1
  214. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/{_4472b56f._.js → _70427cc3._.js} +3 -3
  215. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_8400c8bb._.js +1 -1
  216. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_9f940437._.js +1 -1
  217. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_163038ba._.js +2 -2
  218. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_30d7eeda._.js +1 -1
  219. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_459cb687._.js +2 -2
  220. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_565a14f8._.js +1 -1
  221. 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
  222. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
  223. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  224. package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
  225. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
  226. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +22 -22
  227. package/web/.next/standalone/src/presentation/web/app/actions/create-feature.ts +6 -1
  228. package/web/.next/standalone/src/presentation/web/app/globals.css +25 -0
  229. package/web/.next/standalone/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.tsx +57 -0
  230. package/web/.next/standalone/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.tsx +21 -0
  231. package/web/.next/standalone/src/presentation/web/components/common/theme-toggle/theme-toggle.tsx +26 -9
  232. package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center-inner.tsx +36 -4
  233. package/web/.next/standalone/src/presentation/web/components/features/control-center/use-control-center-state.ts +7 -3
  234. package/web/.next/standalone/src/presentation/web/components/features/features-canvas/features-canvas.stories.tsx +103 -0
  235. package/web/.next/standalone/src/presentation/web/components/features/features-canvas/features-canvas.tsx +7 -1
  236. package/web/.next/standalone/src/presentation/web/hooks/use-graph-state.ts +7 -0
  237. package/web/.next/standalone/src/presentation/web/hooks/use-viewport-persistence.ts +28 -0
  238. package/web/.next/standalone/src/presentation/web/server.js +1 -1
  239. package/web/.next/static/chunks/{87627605cd90f5ec.js → 224919f6f72a4a90.js} +1 -1
  240. package/web/.next/static/chunks/{7b5870c586e31a48.js → 31a91284309556ca.js} +1 -1
  241. package/web/.next/static/chunks/9b07281f9fa372ca.js +1 -0
  242. package/web/.next/static/chunks/{62567dd4e1da2f42.js → 9de39ba6f1d109ce.js} +1 -1
  243. package/web/.next/static/chunks/{33160c6e15691803.js → 9fd70802deb2e4b6.js} +1 -1
  244. package/web/.next/static/chunks/{d33995d7d4f9204b.js → a88681644bdb457b.js} +1 -1
  245. package/web/.next/static/chunks/{51b4b51b814928dd.js → ab7bce7118a0f933.js} +1 -1
  246. package/web/.next/static/chunks/{cb41849bcfaa304e.js → b6c507fc42d9a277.js} +1 -1
  247. package/web/.next/static/chunks/{74dceed1c60e3023.js → bafdd9797848cd20.js} +3 -3
  248. package/web/.next/static/chunks/{0ffccd7be73305c8.css → e12fff3b57456bc2.css} +1 -1
  249. package/web/.next/static/chunks/{c2ca3105ade4be4d.js → ed9bf11850c038ad.js} +1 -1
  250. package/web/.next/trace +1 -1
  251. package/web/.next/trace-build +1 -1
  252. package/web/.next/static/chunks/9b8efd65a9b1b869.js +0 -1
  253. /package/web/.next/static/{TCaMrDQjQWi1IHri-0r-R → Z3nGW8HgUl_Ajpr-2arJQ}/_buildManifest.js +0 -0
  254. /package/web/.next/static/{TCaMrDQjQWi1IHri-0r-R → Z3nGW8HgUl_Ajpr-2arJQ}/_clientMiddlewareManifest.json +0 -0
  255. /package/web/.next/static/{TCaMrDQjQWi1IHri-0r-R → Z3nGW8HgUl_Ajpr-2arJQ}/_ssgManifest.js +0 -0
@@ -274,6 +274,63 @@ export const PrChecked: Story = {
274
274
  },
275
275
  };
276
276
 
277
+ /* ---------------------------------------------------------------------------
278
+ * Fast mode stories
279
+ * ------------------------------------------------------------------------- */
280
+
281
+ /**
282
+ * Fast Mode off (default) — the "Fast Mode" checkbox in the MODE section
283
+ * is unchecked. The full SDLC pipeline (analyze, requirements, research,
284
+ * plan, implement) will run.
285
+ */
286
+ export const FastModeOff: Story = {
287
+ render: () => <CreateDrawerTrigger label="Open (Fast Mode Off)" />,
288
+ play: async ({ canvasElement }) => {
289
+ const canvas = within(canvasElement);
290
+ await userEvent.click(canvas.getByRole('button', { name: 'Open (Fast Mode Off)' }));
291
+ },
292
+ };
293
+
294
+ /**
295
+ * Fast Mode on — the "Fast Mode" checkbox is checked. When submitted,
296
+ * `fast: true` is included in the payload, skipping SDLC phases and
297
+ * implementing directly from the user's prompt.
298
+ */
299
+ export const FastModeOn: Story = {
300
+ render: () => <CreateDrawerTrigger label="Open (Fast Mode On)" />,
301
+ play: async ({ canvasElement }) => {
302
+ const canvas = within(canvasElement);
303
+ await userEvent.click(canvas.getByRole('button', { name: 'Open (Fast Mode On)' }));
304
+
305
+ const body = within(canvasElement.ownerDocument.body);
306
+ const fastCheckbox = await body.findByLabelText('Fast Mode');
307
+ await userEvent.click(fastCheckbox);
308
+ },
309
+ };
310
+
311
+ /**
312
+ * Fast Mode combined with approval gates and git options — demonstrates
313
+ * that fast mode works alongside other form controls. Here fast mode,
314
+ * auto-approve all, push, and create PR are all enabled.
315
+ */
316
+ export const FastModeWithOptions: Story = {
317
+ render: () => <CreateDrawerTrigger label="Open (Fast + Options)" />,
318
+ play: async ({ canvasElement }) => {
319
+ const canvas = within(canvasElement);
320
+ await userEvent.click(canvas.getByRole('button', { name: 'Open (Fast + Options)' }));
321
+
322
+ const body = within(canvasElement.ownerDocument.body);
323
+ const fastCheckbox = await body.findByLabelText('Fast Mode');
324
+ await userEvent.click(fastCheckbox);
325
+
326
+ const autoApprove = body.getByLabelText('Auto approve all');
327
+ await userEvent.click(autoApprove);
328
+
329
+ const prCheckbox = body.getByLabelText('Create PR');
330
+ await userEvent.click(prCheckbox);
331
+ },
332
+ };
333
+
277
334
  /* ---------------------------------------------------------------------------
278
335
  * Workflow defaults stories
279
336
  * ------------------------------------------------------------------------- */
@@ -49,6 +49,8 @@ export interface FeatureCreatePayload {
49
49
  push: boolean;
50
50
  openPr: boolean;
51
51
  parentId?: string;
52
+ /** When true, skip SDLC phases and implement directly from the prompt. */
53
+ fast: boolean;
52
54
  }
53
55
 
54
56
  const AUTO_APPROVE_OPTIONS = [
@@ -97,6 +99,7 @@ export function FeatureCreateDrawer({
97
99
  const [push, setPush] = useState(defaultPush);
98
100
  const [openPr, setOpenPr] = useState(defaultOpenPr);
99
101
  const [parentId, setParentId] = useState<string | undefined>(undefined);
102
+ const [fast, setFast] = useState(false);
100
103
 
101
104
  // Sync state when workflowDefaults load asynchronously
102
105
  useEffect(() => {
@@ -121,6 +124,7 @@ export function FeatureCreateDrawer({
121
124
  setPush(defaultPush);
122
125
  setOpenPr(defaultOpenPr);
123
126
  setParentId(undefined);
127
+ setFast(false);
124
128
  }, [defaultGates, defaultPush, defaultOpenPr]);
125
129
 
126
130
  // Track whether the form has unsaved data
@@ -145,6 +149,7 @@ export function FeatureCreateDrawer({
145
149
  },
146
150
  push: push || openPr,
147
151
  openPr,
152
+ fast,
148
153
  ...(parentId ? { parentId } : {}),
149
154
  });
150
155
  resetForm();
@@ -157,6 +162,7 @@ export function FeatureCreateDrawer({
157
162
  onSubmit,
158
163
  push,
159
164
  openPr,
165
+ fast,
160
166
  parentId,
161
167
  createSound,
162
168
  resetForm,
@@ -258,6 +264,21 @@ export function FeatureCreateDrawer({
258
264
  </div>
259
265
  ) : null}
260
266
 
267
+ {/* Fast mode toggle */}
268
+ <div className="flex flex-col gap-1.5">
269
+ <Label className="text-muted-foreground text-xs font-semibold tracking-wider">
270
+ MODE
271
+ </Label>
272
+ <CheckboxGroupItem
273
+ id="fast-mode"
274
+ label="Fast Mode"
275
+ description="Skip SDLC phases and implement directly from your prompt."
276
+ checked={fast}
277
+ onCheckedChange={setFast}
278
+ disabled={isSubmitting}
279
+ />
280
+ </div>
281
+
261
282
  {/* Auto-approve checkboxes */}
262
283
  <div className="flex flex-col gap-1.5">
263
284
  <Label className="text-muted-foreground text-xs font-semibold tracking-wider">
@@ -10,25 +10,42 @@ export function ThemeToggle() {
10
10
  const toggleOnSound = useSoundAction('toggle-on');
11
11
  const toggleOffSound = useSoundAction('toggle-off');
12
12
 
13
- const toggleTheme = () => {
14
- // Determine target theme before switching
13
+ const toggleTheme = (e: React.MouseEvent<HTMLButtonElement>) => {
15
14
  const currentResolved = theme === 'system' ? resolvedTheme : theme;
16
15
  const goingToDark = currentResolved !== 'dark';
16
+ const newTheme =
17
+ theme === 'system'
18
+ ? resolvedTheme === 'dark'
19
+ ? 'light'
20
+ : 'dark'
21
+ : theme === 'dark'
22
+ ? 'light'
23
+ : 'dark';
17
24
 
18
- // Play sound before setTheme for immediate feedback
25
+ // Play sound before transition for immediate feedback
19
26
  if (goingToDark) {
20
27
  toggleOnSound.play();
21
28
  } else {
22
29
  toggleOffSound.play();
23
30
  }
24
31
 
25
- // If system theme, switch to explicit light/dark
26
- // If explicit, toggle between light and dark
27
- if (theme === 'system') {
28
- setTheme(resolvedTheme === 'dark' ? 'light' : 'dark');
29
- } else {
30
- setTheme(theme === 'dark' ? 'light' : 'dark');
32
+ const prefersReducedMotion =
33
+ typeof window !== 'undefined' &&
34
+ window.matchMedia('(prefers-reduced-motion: reduce)').matches;
35
+
36
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
+ if (!(document as any).startViewTransition || prefersReducedMotion) {
38
+ setTheme(newTheme);
39
+ return;
31
40
  }
41
+
42
+ document.documentElement.style.setProperty('--x', `${e.clientX}px`);
43
+ document.documentElement.style.setProperty('--y', `${e.clientY}px`);
44
+
45
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
+ (document as any).startViewTransition(() => {
47
+ setTheme(newTheme);
48
+ });
32
49
  };
33
50
 
34
51
  return (
@@ -1,8 +1,9 @@
1
1
  'use client';
2
2
 
3
- import { useCallback, useEffect, useMemo } from 'react';
3
+ import { useCallback, useEffect, useMemo, useRef } from 'react';
4
4
  import { useRouter, usePathname } from 'next/navigation';
5
5
  import type { Edge } from '@xyflow/react';
6
+ import { useReactFlow } from '@xyflow/react';
6
7
  import { FeaturesCanvas } from '@/components/features/features-canvas';
7
8
  import type { CanvasNodeType } from '@/components/features/features-canvas';
8
9
  import type { FeatureNodeData } from '@/components/common/feature-node';
@@ -14,9 +15,18 @@ import {
14
15
  import { useSelectedFeatureId } from '@/hooks/use-selected-feature-id';
15
16
  import { useSoundAction } from '@/hooks/use-sound-action';
16
17
  import { useDrawerCloseGuard } from '@/hooks/drawer-close-guard';
18
+ import { useViewportPersistence } from '@/hooks/use-viewport-persistence';
17
19
  import { ControlCenterEmptyState } from './control-center-empty-state';
18
20
  import { useControlCenterState } from './use-control-center-state';
19
21
 
22
+ const AUTO_FOCUS_OPTIONS = {
23
+ maxZoom: 1.0,
24
+ padding: 0.5,
25
+ duration: 500,
26
+ } as const;
27
+
28
+ const AUTO_FOCUS_DRAWER_DELAY_MS = 600;
29
+
20
30
  interface ControlCenterInnerProps {
21
31
  initialNodes: CanvasNodeType[];
22
32
  initialEdges: Edge[];
@@ -28,6 +38,9 @@ export function ControlCenterInner({ initialNodes, initialEdges }: ControlCenter
28
38
  const selectedFeatureId = useSelectedFeatureId();
29
39
  const clickSound = useSoundAction('click');
30
40
  const { guardedNavigate } = useDrawerCloseGuard();
41
+ const { defaultViewport, onMoveEnd } = useViewportPersistence();
42
+ const { fitView } = useReactFlow();
43
+ const drawerTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
31
44
 
32
45
  const {
33
46
  nodes,
@@ -157,11 +170,28 @@ export function ControlCenterInner({ initialNodes, initialEdges }: ControlCenter
157
170
  useEffect(() => {
158
171
  const handler = (e: Event) => {
159
172
  const path = (e as CustomEvent<{ path: string }>).detail.path;
160
- handleAddRepository(path);
173
+ const { wasEmpty, repoPath } = handleAddRepository(path);
174
+
175
+ if (wasEmpty) {
176
+ // Wait for next render so the repo node exists in the DOM, then auto-focus
177
+ setTimeout(() => {
178
+ fitView(AUTO_FOCUS_OPTIONS);
179
+
180
+ // Open the create-feature drawer after the fitView animation completes
181
+ drawerTimerRef.current = setTimeout(() => {
182
+ guardedNavigate(() => router.push(`/create?repo=${encodeURIComponent(repoPath)}`));
183
+ }, AUTO_FOCUS_DRAWER_DELAY_MS);
184
+ }, 0);
185
+ }
161
186
  };
162
187
  window.addEventListener('shep:add-repository', handler);
163
- return () => window.removeEventListener('shep:add-repository', handler);
164
- }, [handleAddRepository]);
188
+ return () => {
189
+ window.removeEventListener('shep:add-repository', handler);
190
+ if (drawerTimerRef.current != null) {
191
+ clearTimeout(drawerTimerRef.current);
192
+ }
193
+ };
194
+ }, [handleAddRepository, fitView, guardedNavigate, router]);
165
195
 
166
196
  // Listen for create events from the create drawer (with real feature ID from server)
167
197
  useEffect(() => {
@@ -242,11 +272,13 @@ export function ControlCenterInner({ initialNodes, initialEdges }: ControlCenter
242
272
  nodes={nodes}
243
273
  edges={edges}
244
274
  selectedFeatureId={selectedFeatureId}
275
+ defaultViewport={defaultViewport}
245
276
  onNodesChange={onNodesChange}
246
277
  onConnect={handleConnect}
247
278
  onAddFeature={handleAddFeature}
248
279
  onNodeClick={handleNodeClick}
249
280
  onPaneClick={handleClearDrawers}
281
+ onMoveEnd={onMoveEnd}
250
282
  emptyState={<ControlCenterEmptyState onRepositorySelect={handleAddRepository} />}
251
283
  />
252
284
  );
@@ -36,7 +36,7 @@ export interface ControlCenterState {
36
36
  edges: Edge[];
37
37
  onNodesChange: (changes: NodeChange<CanvasNodeType>[]) => void;
38
38
  handleConnect: (connection: Connection) => void;
39
- handleAddRepository: (path: string) => void;
39
+ handleAddRepository: (path: string) => { wasEmpty: boolean; repoPath: string };
40
40
  handleLayout: (direction: LayoutDirection) => void;
41
41
  handleDeleteFeature: (featureId: string) => void;
42
42
  handleDeleteRepository: (repositoryId: string) => Promise<void>;
@@ -79,6 +79,7 @@ export function useControlCenterState(
79
79
  replaceRepository,
80
80
  getFeatureRepositoryPath,
81
81
  getRepositoryData,
82
+ getRepoMapSize,
82
83
  setCallbacks,
83
84
  } = useGraphState(initialNodes, initialEdges);
84
85
 
@@ -384,7 +385,8 @@ export function useControlCenterState(
384
385
  );
385
386
 
386
387
  const handleAddRepository = useCallback(
387
- (path: string) => {
388
+ (path: string): { wasEmpty: boolean; repoPath: string } => {
389
+ const wasEmpty = getRepoMapSize() === 0;
388
390
  const tempId = `repo-temp-${Date.now()}`;
389
391
  const repoName =
390
392
  path
@@ -414,8 +416,10 @@ export function useControlCenterState(
414
416
  removeRepository(tempId);
415
417
  toast.error('Failed to add repository');
416
418
  });
419
+
420
+ return { wasEmpty, repoPath: path };
417
421
  },
418
- [addRepositoryToMap, removeRepository, replaceRepository, createSound]
422
+ [addRepositoryToMap, removeRepository, replaceRepository, createSound, getRepoMapSize]
419
423
  );
420
424
 
421
425
  return {
@@ -5,6 +5,8 @@ import type { CanvasNodeType } from './features-canvas';
5
5
  import type { FeatureNodeType } from '@/components/common/feature-node';
6
6
  import type { RepositoryNodeType } from '@/components/common/repository-node';
7
7
  import { layoutWithDagre } from '@/lib/layout-with-dagre';
8
+ // Viewport type used in story args below
9
+ import type { Viewport } from '@/hooks/use-viewport-persistence';
8
10
 
9
11
  const meta: Meta<typeof FeaturesCanvas> = {
10
12
  title: 'Features/FeaturesCanvas',
@@ -560,3 +562,104 @@ export const InteractiveWithRepository: Story = {
560
562
  onAddFeature: () => undefined,
561
563
  },
562
564
  };
565
+
566
+ // --- Viewport Persistence Stories ---
567
+
568
+ export const SavedViewport: Story = {
569
+ name: 'Saved Viewport (Zoomed & Panned)',
570
+ args: {
571
+ nodes: repoFeatureNodes,
572
+ edges: repoFeatureEdges,
573
+ defaultViewport: { x: 200, y: 150, zoom: 1.5 },
574
+ onMoveEnd: (_viewport: Viewport) => {
575
+ // Viewport change handler — visible in Storybook Actions panel
576
+ },
577
+ },
578
+ };
579
+
580
+ export const DefaultViewport: Story = {
581
+ name: 'Default Viewport (No Saved State)',
582
+ args: {
583
+ nodes: repoFeatureNodes,
584
+ edges: repoFeatureEdges,
585
+ onMoveEnd: (_viewport: Viewport) => {
586
+ // Viewport change handler — visible in Storybook Actions panel
587
+ },
588
+ },
589
+ };
590
+
591
+ // --- Fast-mode feature scenario ---
592
+
593
+ const fastModeNodesRaw: CanvasNodeType[] = [
594
+ {
595
+ id: 'repo-1',
596
+ type: 'repositoryNode',
597
+ position: { x: 0, y: 0 },
598
+ data: { name: 'shep-ai/cli' },
599
+ },
600
+ {
601
+ id: 'feat-fast-1',
602
+ type: 'featureNode',
603
+ position: { x: 0, y: 0 },
604
+ data: {
605
+ name: 'Quick Bug Fix',
606
+ description: 'Fast-mode feature — skips SDLC, starts at implementation',
607
+ featureId: '#ff1',
608
+ lifecycle: 'implementation',
609
+ state: 'running',
610
+ progress: 30,
611
+ repositoryPath: '/home/user/my-repo',
612
+ branch: 'feat/quick-bug-fix',
613
+ },
614
+ },
615
+ {
616
+ id: 'feat-full-1',
617
+ type: 'featureNode',
618
+ position: { x: 0, y: 0 },
619
+ data: {
620
+ name: 'Auth Module',
621
+ description: 'Full-pipeline feature — goes through all SDLC phases',
622
+ featureId: '#ff2',
623
+ lifecycle: 'requirements',
624
+ state: 'running',
625
+ progress: 15,
626
+ repositoryPath: '/home/user/my-repo',
627
+ branch: 'feat/auth-module',
628
+ },
629
+ },
630
+ {
631
+ id: 'feat-fast-2',
632
+ type: 'featureNode',
633
+ position: { x: 0, y: 0 },
634
+ data: {
635
+ name: 'Update README',
636
+ description: 'Fast-mode feature — already done',
637
+ featureId: '#ff3',
638
+ lifecycle: 'deploy',
639
+ state: 'done',
640
+ progress: 100,
641
+ repositoryPath: '/home/user/my-repo',
642
+ branch: 'feat/update-readme',
643
+ },
644
+ },
645
+ ];
646
+
647
+ const fastModeEdges: Edge[] = [
648
+ { id: 'e-r1-ff1', source: 'repo-1', target: 'feat-fast-1', ...dashedEdge },
649
+ { id: 'e-r1-ff2', source: 'repo-1', target: 'feat-full-1', ...dashedEdge },
650
+ { id: 'e-r1-ff3', source: 'repo-1', target: 'feat-fast-2', ...dashedEdge },
651
+ ];
652
+
653
+ const { nodes: fastModeLayoutedNodes, edges: fastModeLayoutedEdges } = layoutWithDagre(
654
+ fastModeNodesRaw,
655
+ fastModeEdges,
656
+ { direction: 'LR' }
657
+ );
658
+
659
+ export const FastModeFeatures: Story = {
660
+ name: 'Fast Mode Features (Mixed Pipeline)',
661
+ args: {
662
+ nodes: fastModeLayoutedNodes,
663
+ edges: fastModeLayoutedEdges,
664
+ },
665
+ };
@@ -11,6 +11,7 @@ import type { FeatureNodeType, FeatureNodeData } from '@/components/common/featu
11
11
  import { RepositoryNode } from '@/components/common/repository-node';
12
12
  import type { RepositoryNodeType } from '@/components/common/repository-node';
13
13
  import { DependencyEdge } from './dependency-edge';
14
+ import { DEFAULT_VIEWPORT, type Viewport } from '@/hooks/use-viewport-persistence';
14
15
 
15
16
  export type CanvasNodeType = FeatureNodeType | RepositoryNodeType;
16
17
 
@@ -18,12 +19,14 @@ export interface FeaturesCanvasProps {
18
19
  nodes: CanvasNodeType[];
19
20
  edges: Edge[];
20
21
  selectedFeatureId?: string | null;
22
+ defaultViewport?: Viewport;
21
23
  onNodesChange?: (changes: NodeChange<CanvasNodeType>[]) => void;
22
24
  onAddFeature?: () => void;
23
25
  onNodeClick?: (event: React.MouseEvent, node: CanvasNodeType) => void;
24
26
  onPaneClick?: (event: React.MouseEvent) => void;
25
27
  onConnect?: (connection: Connection) => void;
26
28
  onCanvasDrag?: () => void;
29
+ onMoveEnd?: (viewport: Viewport) => void;
27
30
  toolbar?: React.ReactNode;
28
31
  emptyState?: React.ReactNode;
29
32
  }
@@ -32,12 +35,14 @@ export function FeaturesCanvas({
32
35
  nodes,
33
36
  edges,
34
37
  selectedFeatureId,
38
+ defaultViewport: defaultViewportProp,
35
39
  onNodesChange,
36
40
  onAddFeature,
37
41
  onConnect,
38
42
  onNodeClick,
39
43
  onPaneClick,
40
44
  onCanvasDrag,
45
+ onMoveEnd,
41
46
  toolbar,
42
47
  emptyState,
43
48
  }: FeaturesCanvasProps) {
@@ -111,7 +116,8 @@ export function FeaturesCanvas({
111
116
  onNodeClick={onNodeClick}
112
117
  onPaneClick={onPaneClick}
113
118
  onMoveStart={onCanvasDrag}
114
- defaultViewport={{ x: 30, y: 30, zoom: 0.85 }}
119
+ onMoveEnd={onMoveEnd ? (_event, viewport) => onMoveEnd(viewport) : undefined}
120
+ defaultViewport={defaultViewportProp ?? DEFAULT_VIEWPORT}
115
121
  nodesDraggable={false}
116
122
  nodesConnectable={false}
117
123
  elementsSelectable={false}
@@ -45,6 +45,8 @@ export interface UseGraphStateReturn {
45
45
  getFeatureRepositoryPath: (featureNodeId: string) => string | undefined;
46
46
  /** Stable lookup: get repository node data by nodeId. */
47
47
  getRepositoryData: (nodeId: string) => RepositoryNodeData | undefined;
48
+ /** Stable lookup: get the current number of repositories in the domain Map. */
49
+ getRepoMapSize: () => number;
48
50
  /** Update callbacks injected into node data (does NOT trigger re-render). */
49
51
  setCallbacks: (callbacks: GraphCallbacks) => void;
50
52
  }
@@ -353,6 +355,10 @@ export function useGraphState(
353
355
  return repoMapRef.current.get(nodeId)?.data;
354
356
  }, []);
355
357
 
358
+ const getRepoMapSize = useCallback((): number => {
359
+ return repoMapRef.current.size;
360
+ }, []);
361
+
356
362
  const setCallbacks = useCallback((callbacks: GraphCallbacks) => {
357
363
  callbacksRef.current = callbacks;
358
364
  }, []);
@@ -371,6 +377,7 @@ export function useGraphState(
371
377
  replaceRepository,
372
378
  getFeatureRepositoryPath,
373
379
  getRepositoryData,
380
+ getRepoMapSize,
374
381
  setCallbacks,
375
382
  };
376
383
  }
@@ -0,0 +1,28 @@
1
+ 'use client';
2
+
3
+ import { useCallback, useRef } from 'react';
4
+
5
+ export interface Viewport {
6
+ x: number;
7
+ y: number;
8
+ zoom: number;
9
+ }
10
+
11
+ export const DEFAULT_VIEWPORT: Viewport = { x: 0, y: 0, zoom: 1 };
12
+
13
+ /**
14
+ * Persists the ReactFlow viewport position across re-renders so the canvas
15
+ * doesn't jump back to the origin when nodes update.
16
+ */
17
+ export function useViewportPersistence() {
18
+ const viewportRef = useRef<Viewport>(DEFAULT_VIEWPORT);
19
+
20
+ const onMoveEnd = useCallback((viewport: Viewport) => {
21
+ viewportRef.current = viewport;
22
+ }, []);
23
+
24
+ return {
25
+ defaultViewport: viewportRef.current,
26
+ onMoveEnd,
27
+ };
28
+ }
@@ -15,7 +15,7 @@ const currentPort = parseInt(process.env.PORT, 10) || 3000
15
15
  const hostname = process.env.HOSTNAME || '0.0.0.0'
16
16
 
17
17
  let keepAliveTimeout = parseInt(process.env.KEEP_ALIVE_TIMEOUT, 10)
18
- const nextConfig = {"env":{"NEXT_PUBLIC_SHEP_VERSION":"1.73.1","NEXT_PUBLIC_SHEP_PACKAGE_NAME":"@shepai/cli","NEXT_PUBLIC_SHEP_DESCRIPTION":"Autonomous AI Native SDLC Platform - Automate the development cycle from idea to deploy"},"webpack":null,"typescript":{"ignoreBuildErrors":false},"typedRoutes":true,"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.ts","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"poweredByHeader":true,"compress":true,"images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":14400,"formats":["image/webp"],"maximumRedirects":3,"maximumResponseBody":50000000,"dangerouslyAllowLocalIP":false,"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"attachment","localPatterns":[{"pathname":"**","search":""}],"remotePatterns":[],"qualities":[75],"unoptimized":false},"devIndicators":{"position":"bottom-left"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"excludeDefaultMomentLocales":true,"reactProductionProfiling":false,"reactStrictMode":null,"reactMaxHeadersLength":6000,"httpAgentOptions":{"keepAlive":true},"logging":{},"compiler":{},"expireTime":31536000,"staticPageGenerationTimeout":60,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"outputFileTracingRoot":"/home/runner/work/cli/cli","cacheComponents":false,"cacheLife":{"default":{"stale":300,"revalidate":900,"expire":4294967294},"seconds":{"stale":30,"revalidate":1,"expire":60},"minutes":{"stale":300,"revalidate":60,"expire":3600},"hours":{"stale":300,"revalidate":3600,"expire":86400},"days":{"stale":300,"revalidate":86400,"expire":604800},"weeks":{"stale":300,"revalidate":604800,"expire":2592000},"max":{"stale":300,"revalidate":2592000,"expire":31536000}},"cacheHandlers":{},"experimental":{"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"dynamicOnHover":false,"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"imgOptSkipMetadata":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"viewTransition":false,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":false,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":false,"serverComponentsHmrCache":true,"staticGenerationMaxConcurrency":8,"staticGenerationMinPagesPerWorker":25,"transitionIndicator":false,"inlineCss":false,"useCache":false,"globalNotFound":false,"browserDebugInfoInTerminal":false,"lockDistDir":true,"isolatedDevBuild":true,"proxyClientMaxBodySize":10485760,"hideLogsAfterAbort":false,"mcpServer":true,"turbopackFileSystemCacheForDev":true,"turbopackFileSystemCacheForBuild":false,"turbopackInferModuleSideEffects":false,"optimizePackageImports":["lucide-react","date-fns","lodash-es","ramda","antd","react-bootstrap","ahooks","@ant-design/icons","@headlessui/react","@headlessui-float/react","@heroicons/react/20/solid","@heroicons/react/24/solid","@heroicons/react/24/outline","@visx/visx","@tremor/react","rxjs","@mui/material","@mui/icons-material","recharts","react-use","effect","@effect/schema","@effect/platform","@effect/platform-node","@effect/platform-browser","@effect/platform-bun","@effect/sql","@effect/sql-mssql","@effect/sql-mysql2","@effect/sql-pg","@effect/sql-sqlite-node","@effect/sql-sqlite-bun","@effect/sql-sqlite-wasm","@effect/sql-sqlite-react-native","@effect/rpc","@effect/rpc-http","@effect/typeclass","@effect/experimental","@effect/opentelemetry","@material-ui/core","@material-ui/icons","@tabler/icons-react","mui-core","react-icons/ai","react-icons/bi","react-icons/bs","react-icons/cg","react-icons/ci","react-icons/di","react-icons/fa","react-icons/fa6","react-icons/fc","react-icons/fi","react-icons/gi","react-icons/go","react-icons/gr","react-icons/hi","react-icons/hi2","react-icons/im","react-icons/io","react-icons/io5","react-icons/lia","react-icons/lib","react-icons/lu","react-icons/md","react-icons/pi","react-icons/ri","react-icons/rx","react-icons/si","react-icons/sl","react-icons/tb","react-icons/tfi","react-icons/ti","react-icons/vsc","react-icons/wi"],"trustHostHeader":false,"isExperimentalCompile":false},"htmlLimitedBots":"[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight","bundlePagesRouterDependencies":false,"configFileName":"next.config.ts","turbopack":{"root":"/home/runner/work/cli/cli"},"serverExternalPackages":["tsyringe","reflect-metadata","better-sqlite3","node:os","node:child_process","node:fs"],"distDirRoot":".next"}
18
+ const nextConfig = {"env":{"NEXT_PUBLIC_SHEP_VERSION":"1.75.0","NEXT_PUBLIC_SHEP_PACKAGE_NAME":"@shepai/cli","NEXT_PUBLIC_SHEP_DESCRIPTION":"Autonomous AI Native SDLC Platform - Automate the development cycle from idea to deploy"},"webpack":null,"typescript":{"ignoreBuildErrors":false},"typedRoutes":true,"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.ts","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"poweredByHeader":true,"compress":true,"images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":14400,"formats":["image/webp"],"maximumRedirects":3,"maximumResponseBody":50000000,"dangerouslyAllowLocalIP":false,"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"attachment","localPatterns":[{"pathname":"**","search":""}],"remotePatterns":[],"qualities":[75],"unoptimized":false},"devIndicators":{"position":"bottom-left"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"excludeDefaultMomentLocales":true,"reactProductionProfiling":false,"reactStrictMode":null,"reactMaxHeadersLength":6000,"httpAgentOptions":{"keepAlive":true},"logging":{},"compiler":{},"expireTime":31536000,"staticPageGenerationTimeout":60,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"outputFileTracingRoot":"/home/runner/work/cli/cli","cacheComponents":false,"cacheLife":{"default":{"stale":300,"revalidate":900,"expire":4294967294},"seconds":{"stale":30,"revalidate":1,"expire":60},"minutes":{"stale":300,"revalidate":60,"expire":3600},"hours":{"stale":300,"revalidate":3600,"expire":86400},"days":{"stale":300,"revalidate":86400,"expire":604800},"weeks":{"stale":300,"revalidate":604800,"expire":2592000},"max":{"stale":300,"revalidate":2592000,"expire":31536000}},"cacheHandlers":{},"experimental":{"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"dynamicOnHover":false,"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"imgOptSkipMetadata":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"viewTransition":false,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":false,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":false,"serverComponentsHmrCache":true,"staticGenerationMaxConcurrency":8,"staticGenerationMinPagesPerWorker":25,"transitionIndicator":false,"inlineCss":false,"useCache":false,"globalNotFound":false,"browserDebugInfoInTerminal":false,"lockDistDir":true,"isolatedDevBuild":true,"proxyClientMaxBodySize":10485760,"hideLogsAfterAbort":false,"mcpServer":true,"turbopackFileSystemCacheForDev":true,"turbopackFileSystemCacheForBuild":false,"turbopackInferModuleSideEffects":false,"optimizePackageImports":["lucide-react","date-fns","lodash-es","ramda","antd","react-bootstrap","ahooks","@ant-design/icons","@headlessui/react","@headlessui-float/react","@heroicons/react/20/solid","@heroicons/react/24/solid","@heroicons/react/24/outline","@visx/visx","@tremor/react","rxjs","@mui/material","@mui/icons-material","recharts","react-use","effect","@effect/schema","@effect/platform","@effect/platform-node","@effect/platform-browser","@effect/platform-bun","@effect/sql","@effect/sql-mssql","@effect/sql-mysql2","@effect/sql-pg","@effect/sql-sqlite-node","@effect/sql-sqlite-bun","@effect/sql-sqlite-wasm","@effect/sql-sqlite-react-native","@effect/rpc","@effect/rpc-http","@effect/typeclass","@effect/experimental","@effect/opentelemetry","@material-ui/core","@material-ui/icons","@tabler/icons-react","mui-core","react-icons/ai","react-icons/bi","react-icons/bs","react-icons/cg","react-icons/ci","react-icons/di","react-icons/fa","react-icons/fa6","react-icons/fc","react-icons/fi","react-icons/gi","react-icons/go","react-icons/gr","react-icons/hi","react-icons/hi2","react-icons/im","react-icons/io","react-icons/io5","react-icons/lia","react-icons/lib","react-icons/lu","react-icons/md","react-icons/pi","react-icons/ri","react-icons/rx","react-icons/si","react-icons/sl","react-icons/tb","react-icons/tfi","react-icons/ti","react-icons/vsc","react-icons/wi"],"trustHostHeader":false,"isExperimentalCompile":false},"htmlLimitedBots":"[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight","bundlePagesRouterDependencies":false,"configFileName":"next.config.ts","turbopack":{"root":"/home/runner/work/cli/cli"},"serverExternalPackages":["tsyringe","reflect-metadata","better-sqlite3","node:os","node:child_process","node:fs"],"distDirRoot":".next"}
19
19
 
20
20
  process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(nextConfig)
21
21