@shepai/cli 1.116.3 → 1.117.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 (271) hide show
  1. package/apis/json-schema/AnalyzeRepoTimeouts.yaml +10 -0
  2. package/apis/json-schema/SdlcLifecycle.yaml +1 -0
  3. package/apis/json-schema/StageTimeouts.yaml +35 -0
  4. package/apis/json-schema/WorkflowConfig.yaml +6 -0
  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 +17 -8
  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/application/use-cases/features/start-feature.use-case.d.ts +25 -0
  10. package/dist/packages/core/src/application/use-cases/features/start-feature.use-case.d.ts.map +1 -0
  11. package/dist/packages/core/src/application/use-cases/features/start-feature.use-case.js +116 -0
  12. package/dist/packages/core/src/domain/generated/output.d.ts +47 -0
  13. package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
  14. package/dist/packages/core/src/domain/generated/output.js +1 -0
  15. package/dist/packages/core/src/domain/lifecycle-gates.d.ts +3 -0
  16. package/dist/packages/core/src/domain/lifecycle-gates.d.ts.map +1 -1
  17. package/dist/packages/core/src/domain/lifecycle-gates.js +3 -0
  18. package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
  19. package/dist/packages/core/src/infrastructure/di/container.js +5 -0
  20. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts +7 -0
  21. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts.map +1 -1
  22. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.js +44 -0
  23. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/035-add-stage-timeout-ms.d.ts +22 -0
  24. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/035-add-stage-timeout-ms.d.ts.map +1 -0
  25. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/035-add-stage-timeout-ms.js +53 -0
  26. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations.d.ts.map +1 -1
  27. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations.js +15 -6
  28. package/dist/packages/core/src/infrastructure/repositories/sqlite-settings.repository.d.ts.map +1 -1
  29. package/dist/packages/core/src/infrastructure/repositories/sqlite-settings.repository.js +15 -0
  30. package/dist/packages/core/src/infrastructure/services/agents/analyze-repo/analyze-repository-graph.d.ts.map +1 -1
  31. package/dist/packages/core/src/infrastructure/services/agents/analyze-repo/analyze-repository-graph.js +15 -0
  32. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts +11 -1
  33. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts.map +1 -1
  34. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.js +42 -3
  35. package/dist/src/presentation/cli/commands/feat/index.d.ts.map +1 -1
  36. package/dist/src/presentation/cli/commands/feat/index.js +2 -0
  37. package/dist/src/presentation/cli/commands/feat/ls.command.d.ts.map +1 -1
  38. package/dist/src/presentation/cli/commands/feat/ls.command.js +3 -0
  39. package/dist/src/presentation/cli/commands/feat/new.command.d.ts.map +1 -1
  40. package/dist/src/presentation/cli/commands/feat/new.command.js +9 -1
  41. package/dist/src/presentation/cli/commands/feat/start.command.d.ts +12 -0
  42. package/dist/src/presentation/cli/commands/feat/start.command.d.ts.map +1 -0
  43. package/dist/src/presentation/cli/commands/feat/start.command.js +43 -0
  44. package/dist/src/presentation/web/app/actions/create-feature.d.ts +2 -0
  45. package/dist/src/presentation/web/app/actions/create-feature.d.ts.map +1 -1
  46. package/dist/src/presentation/web/app/actions/create-feature.js +3 -1
  47. package/dist/src/presentation/web/app/actions/start-feature.d.ts +5 -0
  48. package/dist/src/presentation/web/app/actions/start-feature.d.ts.map +1 -0
  49. package/dist/src/presentation/web/app/actions/start-feature.js +16 -0
  50. package/dist/src/presentation/web/app/api/agent-events/route.d.ts.map +1 -1
  51. package/dist/src/presentation/web/app/api/agent-events/route.js +1 -0
  52. package/dist/src/presentation/web/components/common/base-drawer/base-drawer.js +1 -1
  53. package/dist/src/presentation/web/components/common/base-drawer/base-drawer.stories.js +1 -1
  54. package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.d.ts.map +1 -1
  55. package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.js +20 -1
  56. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts +2 -0
  57. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts.map +1 -1
  58. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.js +6 -2
  59. package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.d.ts.map +1 -1
  60. package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.js +6 -0
  61. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts +3 -2
  62. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts.map +1 -1
  63. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.js +13 -1
  64. package/dist/src/presentation/web/components/common/feature-node/feature-node.d.ts.map +1 -1
  65. package/dist/src/presentation/web/components/common/feature-node/feature-node.js +12 -3
  66. package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts +2 -0
  67. package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts.map +1 -1
  68. package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.js +36 -2
  69. package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
  70. package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +3 -1
  71. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts +1 -0
  72. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
  73. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +23 -0
  74. package/dist/src/presentation/web/components/features/settings/settings-page-client.d.ts.map +1 -1
  75. package/dist/src/presentation/web/components/features/settings/settings-page-client.js +75 -2
  76. package/dist/src/presentation/web/components/features/settings/settings-page-client.stories.d.ts +1 -0
  77. package/dist/src/presentation/web/components/features/settings/settings-page-client.stories.d.ts.map +1 -1
  78. package/dist/src/presentation/web/components/features/settings/settings-page-client.stories.js +23 -0
  79. package/dist/src/presentation/web/components/features/settings/timeout-slider.d.ts +11 -0
  80. package/dist/src/presentation/web/components/features/settings/timeout-slider.d.ts.map +1 -0
  81. package/dist/src/presentation/web/components/features/settings/timeout-slider.js +63 -0
  82. package/dist/src/presentation/web/components/features/settings/timeout-slider.stories.d.ts +10 -0
  83. package/dist/src/presentation/web/components/features/settings/timeout-slider.stories.d.ts.map +1 -0
  84. package/dist/src/presentation/web/components/features/settings/timeout-slider.stories.js +24 -0
  85. package/dist/src/presentation/web/components/features/settings/workflow-settings-section.d.ts.map +1 -1
  86. package/dist/src/presentation/web/components/features/settings/workflow-settings-section.js +97 -2
  87. package/dist/src/presentation/web/components/features/settings/workflow-settings-section.stories.d.ts.map +1 -1
  88. package/dist/src/presentation/web/components/features/settings/workflow-settings-section.stories.js +22 -0
  89. package/dist/src/presentation/web/components/ui/slider.d.ts +5 -0
  90. package/dist/src/presentation/web/components/ui/slider.d.ts.map +1 -0
  91. package/dist/src/presentation/web/components/ui/slider.js +10 -0
  92. package/dist/src/presentation/web/components/ui/slider.stories.d.ts +7 -0
  93. package/dist/src/presentation/web/components/ui/slider.stories.d.ts.map +1 -0
  94. package/dist/src/presentation/web/components/ui/slider.stories.js +15 -0
  95. package/dist/src/presentation/web/hooks/sidebar-features-context.d.ts.map +1 -1
  96. package/dist/src/presentation/web/hooks/sidebar-features-context.js +1 -0
  97. package/dist/src/presentation/web/hooks/use-graph-state.d.ts.map +1 -1
  98. package/dist/src/presentation/web/hooks/use-graph-state.js +1 -0
  99. package/dist/src/presentation/web/lib/derive-graph.d.ts +2 -0
  100. package/dist/src/presentation/web/lib/derive-graph.d.ts.map +1 -1
  101. package/dist/src/presentation/web/lib/derive-graph.js +5 -0
  102. package/dist/tsconfig.build.tsbuildinfo +1 -1
  103. package/package.json +1 -1
  104. package/web/.next/BUILD_ID +1 -1
  105. package/web/.next/build-manifest.json +2 -2
  106. package/web/.next/fallback-build-manifest.json +2 -2
  107. package/web/.next/prerender-manifest.json +3 -3
  108. package/web/.next/required-server-files.js +2 -2
  109. package/web/.next/required-server-files.json +2 -2
  110. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +55 -40
  111. package/web/.next/server/app/(dashboard)/@drawer/create/page.js +1 -1
  112. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  113. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  114. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +67 -52
  115. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js +1 -1
  116. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  117. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  118. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +67 -52
  119. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +1 -1
  120. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  121. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  122. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +51 -36
  123. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js +1 -1
  124. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  125. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  126. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +55 -40
  127. package/web/.next/server/app/(dashboard)/create/page.js +1 -1
  128. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  129. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  130. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +67 -52
  131. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js +1 -1
  132. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  133. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  134. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +67 -52
  135. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +1 -1
  136. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  137. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  138. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +51 -36
  139. package/web/.next/server/app/(dashboard)/page.js +1 -1
  140. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  141. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  142. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +51 -36
  143. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js +1 -1
  144. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  145. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  146. package/web/.next/server/app/_global-error.html +2 -2
  147. package/web/.next/server/app/_global-error.rsc +1 -1
  148. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  149. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  150. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  151. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  152. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  153. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  154. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  155. package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
  156. package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
  157. package/web/.next/server/app/settings/page/server-reference-manifest.json +5 -5
  158. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  159. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  160. package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  161. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  162. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  163. package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  164. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  165. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  166. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  167. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  168. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js +1 -1
  169. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js.map +1 -1
  170. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js +2 -2
  171. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js.map +1 -1
  172. package/web/.next/server/chunks/[root-of-the-server]__7d5492a0._.js +1 -1
  173. package/web/.next/server/chunks/[root-of-the-server]__7d5492a0._.js.map +1 -1
  174. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  175. package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js +1 -1
  176. package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js.map +1 -1
  177. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  178. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  179. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_ed372306.js +3 -0
  180. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_ed372306.js.map +1 -0
  181. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_32e26434.js +3 -0
  182. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_32e26434.js.map +1 -0
  183. package/web/.next/server/chunks/ssr/[root-of-the-server]__07a39ff2._.js +1 -1
  184. package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js +1 -1
  185. package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js.map +1 -1
  186. package/web/.next/server/chunks/ssr/{[root-of-the-server]__cbd8062c._.js → [root-of-the-server]__172d9576._.js} +2 -2
  187. package/web/.next/server/chunks/ssr/{[root-of-the-server]__e70c5627._.js.map → [root-of-the-server]__172d9576._.js.map} +1 -1
  188. package/web/.next/server/chunks/ssr/[root-of-the-server]__24dd0927._.js +2 -2
  189. package/web/.next/server/chunks/ssr/[root-of-the-server]__24dd0927._.js.map +1 -1
  190. package/web/.next/server/chunks/ssr/{[root-of-the-server]__039967e3._.js → [root-of-the-server]__2a5592d5._.js} +2 -2
  191. package/web/.next/server/chunks/ssr/{[root-of-the-server]__cbd8062c._.js.map → [root-of-the-server]__2a5592d5._.js.map} +1 -1
  192. package/web/.next/server/chunks/ssr/[root-of-the-server]__5d87af2e._.js +1 -1
  193. package/web/.next/server/chunks/ssr/[root-of-the-server]__6367aea0._.js +1 -1
  194. package/web/.next/server/chunks/ssr/[root-of-the-server]__6367aea0._.js.map +1 -1
  195. package/web/.next/server/chunks/ssr/[root-of-the-server]__89e8a5cc._.js +2 -2
  196. package/web/.next/server/chunks/ssr/[root-of-the-server]__89e8a5cc._.js.map +1 -1
  197. package/web/.next/server/chunks/ssr/{[root-of-the-server]__e70c5627._.js → [root-of-the-server]__a93289b0._.js} +2 -2
  198. package/web/.next/server/chunks/ssr/{[root-of-the-server]__2773312c._.js.map → [root-of-the-server]__a93289b0._.js.map} +1 -1
  199. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +2 -2
  200. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
  201. package/web/.next/server/chunks/ssr/{[root-of-the-server]__2773312c._.js → [root-of-the-server]__ac0304e7._.js} +2 -2
  202. package/web/.next/server/chunks/ssr/{[root-of-the-server]__039967e3._.js.map → [root-of-the-server]__ac0304e7._.js.map} +1 -1
  203. package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js +1 -1
  204. package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js.map +1 -1
  205. package/web/.next/server/chunks/ssr/_125679ad._.js +3 -0
  206. package/web/.next/server/chunks/ssr/_125679ad._.js.map +1 -0
  207. package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
  208. package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
  209. package/web/.next/server/chunks/ssr/_1bb131c4._.js.map +1 -1
  210. package/web/.next/server/chunks/ssr/_250a63ae._.js +1 -1
  211. package/web/.next/server/chunks/ssr/_250a63ae._.js.map +1 -1
  212. package/web/.next/server/chunks/ssr/_8dacd1e7._.js +1 -1
  213. package/web/.next/server/chunks/ssr/_8dacd1e7._.js.map +1 -1
  214. package/web/.next/server/chunks/ssr/_a8d14ab2._.js +3 -0
  215. package/web/.next/server/chunks/ssr/{_c5f84841._.js.map → _a8d14ab2._.js.map} +1 -1
  216. package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
  217. package/web/.next/server/chunks/ssr/_cc77a143._.js.map +1 -1
  218. package/web/.next/server/chunks/ssr/{_6f0118a0._.js → _d6a1ec27._.js} +2 -2
  219. package/web/.next/server/chunks/ssr/_d6a1ec27._.js.map +1 -0
  220. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  221. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  222. package/web/.next/server/chunks/ssr/src_presentation_web_0835b28e._.js +5 -0
  223. package/web/.next/server/chunks/ssr/src_presentation_web_0835b28e._.js.map +1 -0
  224. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_e99d78dd.js +3 -0
  225. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_e99d78dd.js.map +1 -0
  226. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
  227. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
  228. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
  229. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
  230. package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
  231. package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +1 -1
  232. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  233. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  234. package/web/.next/server/chunks/ssr/src_presentation_web_e8034a29._.js +5 -0
  235. package/web/.next/server/chunks/ssr/src_presentation_web_e8034a29._.js.map +1 -0
  236. package/web/.next/server/pages/500.html +2 -2
  237. package/web/.next/server/server-reference-manifest.js +1 -1
  238. package/web/.next/server/server-reference-manifest.json +300 -229
  239. package/web/.next/static/chunks/{c172f4a6010cb5b5.js → 2251df6427162751.js} +1 -1
  240. package/web/.next/static/chunks/2c98935265aa3622.js +2 -0
  241. package/web/.next/static/chunks/{2babc8e3ae9ba6e8.js → 34b275db4ad6fb5d.js} +1 -1
  242. package/web/.next/static/chunks/{5de387864b89e64c.js → 425894e5bf370bd2.js} +2 -2
  243. package/web/.next/static/chunks/{52285fdb39925ad5.js → 498777301470975b.js} +1 -1
  244. package/web/.next/static/chunks/50f06bb71bace452.js +1 -0
  245. package/web/.next/static/chunks/5fe03deadb83628b.js +1 -0
  246. package/web/.next/static/chunks/62a8173911f8f130.css +1 -0
  247. package/web/.next/static/chunks/{e12f41ac3d49a7b5.js → b855de1b1e5458f6.js} +1 -1
  248. package/web/.next/static/chunks/{18de73b2f14204d3.js → c76f6d06b1b69b57.js} +1 -1
  249. package/web/.next/static/chunks/e2caffa0bb759c6c.js +1 -0
  250. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_a1104008.js +0 -3
  251. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_a1104008.js.map +0 -1
  252. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_92642200.js +0 -3
  253. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_92642200.js.map +0 -1
  254. package/web/.next/server/chunks/ssr/_6f0118a0._.js.map +0 -1
  255. package/web/.next/server/chunks/ssr/_c5f84841._.js +0 -3
  256. package/web/.next/server/chunks/ssr/_d2e408a9._.js +0 -3
  257. package/web/.next/server/chunks/ssr/_d2e408a9._.js.map +0 -1
  258. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_888633e1.js +0 -3
  259. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_888633e1.js.map +0 -1
  260. package/web/.next/server/chunks/ssr/src_presentation_web_ce7cbc3c._.js +0 -5
  261. package/web/.next/server/chunks/ssr/src_presentation_web_ce7cbc3c._.js.map +0 -1
  262. package/web/.next/server/chunks/ssr/src_presentation_web_e2604413._.js +0 -5
  263. package/web/.next/server/chunks/ssr/src_presentation_web_e2604413._.js.map +0 -1
  264. package/web/.next/static/chunks/0b3ab176958a8286.js +0 -1
  265. package/web/.next/static/chunks/242446982e8d196e.js +0 -1
  266. package/web/.next/static/chunks/552e0f129144b54d.js +0 -1
  267. package/web/.next/static/chunks/57b45edf86522369.css +0 -1
  268. package/web/.next/static/chunks/7b924c47dd2a5a53.js +0 -2
  269. /package/web/.next/static/{CStnC7-QgiTd6U99YUc1N → bAT4Gm6M7U0lGmNAN3mTn}/_buildManifest.js +0 -0
  270. /package/web/.next/static/{CStnC7-QgiTd6U99YUc1N → bAT4Gm6M7U0lGmNAN3mTn}/_clientMiddlewareManifest.json +0 -0
  271. /package/web/.next/static/{CStnC7-QgiTd6U99YUc1N → bAT4Gm6M7U0lGmNAN3mTn}/_ssgManifest.js +0 -0
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Migration 035: Add per-stage timeout columns to settings table.
3
+ *
4
+ * Replaces the single stage_timeout_ms column with individual per-stage
5
+ * timeout columns. Each is a nullable INTEGER (milliseconds). When NULL,
6
+ * the application falls back to the hardcoded default of 600_000 ms
7
+ * (10 minutes).
8
+ *
9
+ * Columns added:
10
+ * - stage_timeout_analyze_ms
11
+ * - stage_timeout_requirements_ms
12
+ * - stage_timeout_research_ms
13
+ * - stage_timeout_plan_ms
14
+ * - stage_timeout_implement_ms
15
+ * - stage_timeout_merge_ms
16
+ * - analyze_repo_timeout_analyze_ms
17
+ */
18
+ import type { MigrationParams } from 'umzug';
19
+ import type Database from 'better-sqlite3';
20
+ export declare function up({ context: db }: MigrationParams<Database.Database>): Promise<void>;
21
+ export declare function down({ context: db }: MigrationParams<Database.Database>): Promise<void>;
22
+ //# sourceMappingURL=035-add-stage-timeout-ms.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"035-add-stage-timeout-ms.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/persistence/sqlite/migrations/035-add-stage-timeout-ms.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAY3C,wBAAsB,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,eAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB3F;AAED,wBAAsB,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,eAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAI7F"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Migration 035: Add per-stage timeout columns to settings table.
3
+ *
4
+ * Replaces the single stage_timeout_ms column with individual per-stage
5
+ * timeout columns. Each is a nullable INTEGER (milliseconds). When NULL,
6
+ * the application falls back to the hardcoded default of 600_000 ms
7
+ * (10 minutes).
8
+ *
9
+ * Columns added:
10
+ * - stage_timeout_analyze_ms
11
+ * - stage_timeout_requirements_ms
12
+ * - stage_timeout_research_ms
13
+ * - stage_timeout_plan_ms
14
+ * - stage_timeout_implement_ms
15
+ * - stage_timeout_merge_ms
16
+ * - analyze_repo_timeout_analyze_ms
17
+ */
18
+ const STAGE_COLUMNS = [
19
+ 'stage_timeout_analyze_ms',
20
+ 'stage_timeout_requirements_ms',
21
+ 'stage_timeout_research_ms',
22
+ 'stage_timeout_plan_ms',
23
+ 'stage_timeout_implement_ms',
24
+ 'stage_timeout_merge_ms',
25
+ 'analyze_repo_timeout_analyze_ms',
26
+ ];
27
+ export async function up({ context: db }) {
28
+ const columns = db.pragma('table_info(settings)');
29
+ const existingNames = new Set(columns.map((c) => c.name));
30
+ for (const col of STAGE_COLUMNS) {
31
+ if (!existingNames.has(col)) {
32
+ db.exec(`ALTER TABLE settings ADD COLUMN ${col} INTEGER`);
33
+ }
34
+ }
35
+ // Migrate existing stage_timeout_ms value to all per-stage columns
36
+ if (existingNames.has('stage_timeout_ms')) {
37
+ db.exec(`
38
+ UPDATE settings SET
39
+ stage_timeout_analyze_ms = COALESCE(stage_timeout_analyze_ms, stage_timeout_ms),
40
+ stage_timeout_requirements_ms = COALESCE(stage_timeout_requirements_ms, stage_timeout_ms),
41
+ stage_timeout_research_ms = COALESCE(stage_timeout_research_ms, stage_timeout_ms),
42
+ stage_timeout_plan_ms = COALESCE(stage_timeout_plan_ms, stage_timeout_ms),
43
+ stage_timeout_implement_ms = COALESCE(stage_timeout_implement_ms, stage_timeout_ms),
44
+ stage_timeout_merge_ms = COALESCE(stage_timeout_merge_ms, stage_timeout_ms)
45
+ WHERE stage_timeout_ms IS NOT NULL
46
+ `);
47
+ }
48
+ }
49
+ export async function down({ context: db }) {
50
+ // SQLite does not support DROP COLUMN before 3.35.0; the columns are
51
+ // nullable and ignored when absent, so this is a no-op.
52
+ void db;
53
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/persistence/sqlite/migrations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAI3C;;;GAGG;AACH,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAwFxC;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAS9E"}
1
+ {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/persistence/sqlite/migrations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAI3C;;;GAGG;AACH,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAoGxC;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAS9E"}
@@ -11,7 +11,7 @@
11
11
  */
12
12
  import { readdirSync } from 'node:fs';
13
13
  import { dirname, join } from 'node:path';
14
- import { pathToFileURL } from 'node:url';
14
+ import { fileURLToPath, pathToFileURL } from 'node:url';
15
15
  import { Umzug } from 'umzug';
16
16
  import { SQLiteMigrationStorage } from './sqlite-migration-storage.js';
17
17
  import { LEGACY_MIGRATIONS, LEGACY_MIGRATION_NAMES } from './legacy-migrations.js';
@@ -27,7 +27,7 @@ export const LATEST_SCHEMA_VERSION = 34;
27
27
  function getMigrationsDir() {
28
28
  // import.meta.url is available in ESM; fallback to __dirname for CJS
29
29
  // The migrations/ directory is a sibling of this file
30
- return join(dirname(new URL(import.meta.url).pathname), 'migrations');
30
+ return join(dirname(fileURLToPath(import.meta.url)), 'migrations');
31
31
  }
32
32
  /**
33
33
  * Discovers new migration files (035+) in the migrations/ directory.
@@ -41,9 +41,18 @@ function getMigrationsDir() {
41
41
  async function discoverNewMigrations(migrationsDir) {
42
42
  let files;
43
43
  try {
44
- files = readdirSync(migrationsDir)
45
- .filter((f) => f.endsWith('.js') && !f.endsWith('.d.js'))
46
- .sort();
44
+ const allFiles = readdirSync(migrationsDir);
45
+ // Accept .js (compiled) and .ts (dev via tsx) but exclude .d.ts declaration files
46
+ const candidates = allFiles.filter((f) => (f.endsWith('.js') || f.endsWith('.ts')) && !f.endsWith('.d.ts') && !f.endsWith('.d.js'));
47
+ // Deduplicate: if both .ts and .js exist for the same migration, prefer .js
48
+ const byName = new Map();
49
+ for (const f of candidates) {
50
+ const base = f.replace(/\.(js|ts)$/, '');
51
+ if (!byName.has(base) || f.endsWith('.js')) {
52
+ byName.set(base, f);
53
+ }
54
+ }
55
+ files = [...byName.values()].sort();
47
56
  }
48
57
  catch {
49
58
  // Directory doesn't exist or is unreadable — no new migrations
@@ -52,7 +61,7 @@ async function discoverNewMigrations(migrationsDir) {
52
61
  const migrations = [];
53
62
  for (const file of files) {
54
63
  const filePath = join(migrationsDir, file);
55
- const name = file.replace(/\.js$/, '');
64
+ const name = file.replace(/\.(js|ts)$/, '');
56
65
  const mod = (await import(pathToFileURL(filePath).href));
57
66
  migrations.push({
58
67
  name,
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite-settings.repository.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/src/infrastructure/repositories/sqlite-settings.repository.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8EAA8E,CAAC;AACxH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAOjE;;;GAGG;AACH,qBACa,wBAAyB,YAAW,mBAAmB;IACtD,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAElD;;;;;;OAMG;IACG,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IA2DnD;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAgBtC;;;;;OAKG;IACG,MAAM,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAqEhD"}
1
+ {"version":3,"file":"sqlite-settings.repository.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/src/infrastructure/repositories/sqlite-settings.repository.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8EAA8E,CAAC;AACxH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAOjE;;;GAGG;AACH,qBACa,wBAAyB,YAAW,mBAAmB;IACtD,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAElD;;;;;;OAMG;IACG,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAmEnD;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAgBtC;;;;;OAKG;IACG,MAAM,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CA4EhD"}
@@ -57,6 +57,10 @@ let SQLiteSettingsRepository = class SQLiteSettingsRepository {
57
57
  notif_evt_pr_blocked, notif_evt_merge_review_ready,
58
58
  workflow_open_pr_on_impl_complete,
59
59
  ci_max_fix_attempts, ci_watch_timeout_ms, ci_log_max_chars,
60
+ stage_timeout_analyze_ms, stage_timeout_requirements_ms,
61
+ stage_timeout_research_ms, stage_timeout_plan_ms,
62
+ stage_timeout_implement_ms, stage_timeout_merge_ms,
63
+ analyze_repo_timeout_analyze_ms,
60
64
  onboarding_complete,
61
65
  approval_gate_allow_prd, approval_gate_allow_plan,
62
66
  approval_gate_allow_merge, approval_gate_push_on_impl_complete,
@@ -77,6 +81,10 @@ let SQLiteSettingsRepository = class SQLiteSettingsRepository {
77
81
  @notif_evt_pr_blocked, @notif_evt_merge_review_ready,
78
82
  @workflow_open_pr_on_impl_complete,
79
83
  @ci_max_fix_attempts, @ci_watch_timeout_ms, @ci_log_max_chars,
84
+ @stage_timeout_analyze_ms, @stage_timeout_requirements_ms,
85
+ @stage_timeout_research_ms, @stage_timeout_plan_ms,
86
+ @stage_timeout_implement_ms, @stage_timeout_merge_ms,
87
+ @analyze_repo_timeout_analyze_ms,
80
88
  @onboarding_complete,
81
89
  @approval_gate_allow_prd, @approval_gate_allow_plan,
82
90
  @approval_gate_allow_merge, @approval_gate_push_on_impl_complete,
@@ -156,6 +164,13 @@ let SQLiteSettingsRepository = class SQLiteSettingsRepository {
156
164
  ci_max_fix_attempts = @ci_max_fix_attempts,
157
165
  ci_watch_timeout_ms = @ci_watch_timeout_ms,
158
166
  ci_log_max_chars = @ci_log_max_chars,
167
+ stage_timeout_analyze_ms = @stage_timeout_analyze_ms,
168
+ stage_timeout_requirements_ms = @stage_timeout_requirements_ms,
169
+ stage_timeout_research_ms = @stage_timeout_research_ms,
170
+ stage_timeout_plan_ms = @stage_timeout_plan_ms,
171
+ stage_timeout_implement_ms = @stage_timeout_implement_ms,
172
+ stage_timeout_merge_ms = @stage_timeout_merge_ms,
173
+ analyze_repo_timeout_analyze_ms = @analyze_repo_timeout_analyze_ms,
159
174
  onboarding_complete = @onboarding_complete,
160
175
  approval_gate_allow_prd = @approval_gate_allow_prd,
161
176
  approval_gate_allow_plan = @approval_gate_allow_plan,
@@ -1 +1 @@
1
- {"version":3,"file":"analyze-repository-graph.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/services/agents/analyze-repo/analyze-repository-graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACpG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AAGpG;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;EAIjC,CAAC;AAEH,MAAM,MAAM,0BAA0B,GAAG,OAAO,sBAAsB,CAAC,KAAK,CAAC;AAyB7E;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,cAAc,EACxB,YAAY,CAAC,EAAE,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAQnC"}
1
+ {"version":3,"file":"analyze-repository-graph.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/services/agents/analyze-repo/analyze-repository-graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACpG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AAkBpG;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;EAIjC,CAAC;AAEH,MAAM,MAAM,0BAA0B,GAAG,OAAO,sBAAsB,CAAC,KAAK,CAAC;AA0B7E;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,cAAc,EACxB,YAAY,CAAC,EAAE,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAQnC"}
@@ -1,5 +1,19 @@
1
1
  import { Annotation, StateGraph, START, END } from '@langchain/langgraph';
2
2
  import { buildAnalyzePrompt } from './prompts/analyze-repository.prompt.js';
3
+ import { hasSettings, getSettings } from '../../../services/settings.service.js';
4
+ /** Default timeout for analyze-repo agent (10 minutes) — prevents infinite hangs. */
5
+ const DEFAULT_ANALYZE_REPO_TIMEOUT_MS = 600_000;
6
+ /**
7
+ * Resolve the timeout for the analyze-repository agent.
8
+ * Reads from settings (workflow.analyzeRepoTimeouts.analyzeMs),
9
+ * falling back to DEFAULT_ANALYZE_REPO_TIMEOUT_MS when not configured.
10
+ */
11
+ function getAnalyzeRepoTimeoutMs() {
12
+ if (!hasSettings())
13
+ return DEFAULT_ANALYZE_REPO_TIMEOUT_MS;
14
+ const timeouts = getSettings().workflow?.analyzeRepoTimeouts;
15
+ return timeouts?.analyzeMs ?? DEFAULT_ANALYZE_REPO_TIMEOUT_MS;
16
+ }
3
17
  /**
4
18
  * State annotation for the analyze-repository graph.
5
19
  *
@@ -23,6 +37,7 @@ function createAnalyzeNode(executor) {
23
37
  const prompt = buildAnalyzePrompt(state.repositoryPath);
24
38
  const result = await executor.execute(prompt, {
25
39
  cwd: state.repositoryPath,
40
+ timeout: getAnalyzeRepoTimeoutMs(),
26
41
  });
27
42
  return {
28
43
  analysisMarkdown: result.result,
@@ -23,10 +23,20 @@ export type NodeLogger = ReturnType<typeof createNodeLogger>;
23
23
  * Safely read a file from the spec directory. Returns empty string if file doesn't exist.
24
24
  */
25
25
  export declare function readSpecFile(specDir: string, filename: string): string;
26
+ /**
27
+ * Resolve the timeout for a specific stage.
28
+ * Reads per-stage timeout from settings (workflow.stageTimeouts.<stage>Ms),
29
+ * falling back to DEFAULT_STAGE_TIMEOUT_MS when not configured.
30
+ */
31
+ export declare function getStageTimeoutMs(nodeName: string): number;
26
32
  /**
27
33
  * Build executor options with cwd. Each node gets a clean agent context.
34
+ * The timeout is resolved per-stage from settings (workflow.stageTimeouts)
35
+ * with a fallback to DEFAULT_STAGE_TIMEOUT_MS (10 min).
36
+ *
37
+ * When no `nodeName` is provided, the current node from state is used.
28
38
  */
29
- export declare function buildExecutorOptions(state: FeatureAgentState, overrides?: Partial<Pick<AgentExecutionOptions, 'timeout'>>): AgentExecutionOptions;
39
+ export declare function buildExecutorOptions(state: FeatureAgentState, overrides?: Partial<Pick<AgentExecutionOptions, 'timeout'>>, nodeName?: string): AgentExecutionOptions;
30
40
  /**
31
41
  * Parse YAML with automatic sanitization of common AI-generated issues.
32
42
  * First attempts normal parsing; on failure, sanitizes unquoted braces
@@ -1 +1 @@
1
- {"version":3,"file":"node-helpers.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"node-helpers.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,7 @@ import yaml from 'js-yaml';
8
8
  import { readFileSync, writeFileSync, renameSync, unlinkSync } from 'node:fs';
9
9
  import { join } from 'node:path';
10
10
  import { interrupt, isGraphBubbleUp } from '@langchain/langgraph';
11
+ import { hasSettings, getSettings } from '../../../../services/settings.service.js';
11
12
  import { reportNodeStart } from '../heartbeat.js';
12
13
  import { recordPhaseStart, recordPhaseEnd, recordApprovalWaitStart, } from '../phase-timing-context.js';
13
14
  import { updateNodeLifecycle } from '../lifecycle-context.js';
@@ -44,14 +45,52 @@ export function readSpecFile(specDir, filename) {
44
45
  return '';
45
46
  }
46
47
  }
48
+ /** Default timeout per agent call (30 minutes) — prevents infinite hangs. */
49
+ const DEFAULT_STAGE_TIMEOUT_MS = 1_800_000;
50
+ /**
51
+ * Map from node name to the corresponding StageTimeouts field.
52
+ * `fast-implement` reuses the implement timeout; `evidence` also reuses implement.
53
+ */
54
+ const STAGE_TIMEOUT_KEY = {
55
+ analyze: 'analyzeMs',
56
+ requirements: 'requirementsMs',
57
+ research: 'researchMs',
58
+ plan: 'planMs',
59
+ implement: 'implementMs',
60
+ 'fast-implement': 'implementMs',
61
+ evidence: 'implementMs',
62
+ merge: 'mergeMs',
63
+ };
64
+ /**
65
+ * Resolve the timeout for a specific stage.
66
+ * Reads per-stage timeout from settings (workflow.stageTimeouts.<stage>Ms),
67
+ * falling back to DEFAULT_STAGE_TIMEOUT_MS when not configured.
68
+ */
69
+ export function getStageTimeoutMs(nodeName) {
70
+ if (!hasSettings())
71
+ return DEFAULT_STAGE_TIMEOUT_MS;
72
+ const timeouts = getSettings().workflow?.stageTimeouts;
73
+ if (!timeouts)
74
+ return DEFAULT_STAGE_TIMEOUT_MS;
75
+ const key = STAGE_TIMEOUT_KEY[nodeName];
76
+ if (!key)
77
+ return DEFAULT_STAGE_TIMEOUT_MS;
78
+ return timeouts[key] ?? DEFAULT_STAGE_TIMEOUT_MS;
79
+ }
47
80
  /**
48
81
  * Build executor options with cwd. Each node gets a clean agent context.
82
+ * The timeout is resolved per-stage from settings (workflow.stageTimeouts)
83
+ * with a fallback to DEFAULT_STAGE_TIMEOUT_MS (10 min).
84
+ *
85
+ * When no `nodeName` is provided, the current node from state is used.
49
86
  */
50
- export function buildExecutorOptions(state, overrides) {
87
+ export function buildExecutorOptions(state, overrides, nodeName) {
88
+ const stage = nodeName ?? state.currentNode ?? '';
89
+ const stageTimeout = getStageTimeoutMs(stage);
51
90
  return {
52
91
  cwd: state.worktreePath || state.repositoryPath,
53
92
  maxTurns: 5000,
54
- timeout: 1_800_000, // 30 minutes per agent call — prevents infinite hangs
93
+ timeout: stageTimeout,
55
94
  ...(state.model ? { model: state.model } : {}),
56
95
  ...overrides,
57
96
  };
@@ -373,7 +412,7 @@ export function executeNode(nodeName, executor, buildPrompt) {
373
412
  try {
374
413
  const resumePrefix = buildResumeContext(state.resumeReason);
375
414
  const prompt = resumePrefix + buildPrompt(state, log);
376
- const options = buildExecutorOptions(state);
415
+ const options = buildExecutorOptions(state, undefined, nodeName);
377
416
  log.info(`Executing agent at cwd=${options.cwd}`);
378
417
  log.info(`Prompt length: ${prompt.length} chars`);
379
418
  const result = await executor.execute(prompt, options);
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAY3C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAa3C"}
@@ -15,6 +15,7 @@ import { createLsCommand } from './ls.command.js';
15
15
  import { createShowCommand } from './show.command.js';
16
16
  import { createDelCommand } from './del.command.js';
17
17
  import { createResumeCommand } from './resume.command.js';
18
+ import { createStartCommand } from './start.command.js';
18
19
  import { createReviewCommand } from './review.command.js';
19
20
  import { createApproveCommand } from './approve.command.js';
20
21
  import { createRejectCommand } from './reject.command.js';
@@ -30,6 +31,7 @@ export function createFeatCommand() {
30
31
  .addCommand(createShowCommand())
31
32
  .addCommand(createDelCommand())
32
33
  .addCommand(createResumeCommand())
34
+ .addCommand(createStartCommand())
33
35
  .addCommand(createReviewCommand())
34
36
  .addCommand(createApproveCommand())
35
37
  .addCommand(createRejectCommand())
@@ -1 +1 @@
1
- {"version":3,"file":"ls.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/ls.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyKpC,wBAAgB,eAAe,IAAI,OAAO,CAsGzC"}
1
+ {"version":3,"file":"ls.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/ls.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6KpC,wBAAgB,eAAe,IAAI,OAAO,CAsGzC"}
@@ -54,6 +54,9 @@ function formatStatus(feature, run) {
54
54
  if (feature.lifecycle === 'Blocked') {
55
55
  return `${colors.warning(symbols.dotEmpty)} ${colors.warning('Blocked')}`;
56
56
  }
57
+ if (feature.lifecycle === 'Pending') {
58
+ return `${colors.muted(symbols.dotEmpty)} ${colors.muted('Pending')}`;
59
+ }
57
60
  if (!run) {
58
61
  return `${colors.muted(symbols.dotEmpty)} ${colors.muted(feature.lifecycle)}`;
59
62
  }
@@ -1 +1 @@
1
- {"version":3,"file":"new.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/new.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4DpC;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAwI1C"}
1
+ {"version":3,"file":"new.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/new.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6DpC;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAmJ1C"}
@@ -55,6 +55,7 @@ export function createNewCommand() {
55
55
  .option('--allow-merge', 'Auto-approve merge phase')
56
56
  .option('--allow-all', 'Run fully autonomous (no approval pauses)')
57
57
  .option('--parent <fid>', 'Parent feature ID (full or partial prefix)')
58
+ .option('--pending', 'Create feature without starting the agent')
58
59
  .option('--fast', 'Skip SDLC phases and implement directly from your prompt')
59
60
  .option('--model <model>', 'LLM model identifier for this run (e.g. claude-opus-4-6)')
60
61
  .option('--attach <path>', 'Attach a file (repeatable)', collect, [])
@@ -113,6 +114,7 @@ export function createNewCommand() {
113
114
  push,
114
115
  openPr,
115
116
  ...(parentId !== undefined && { parentId }),
117
+ ...(options.pending && { pending: true }),
116
118
  ...(options.fast && { fast: true }),
117
119
  ...(options.model !== undefined && { model: options.model }),
118
120
  ...(attachmentPaths.length > 0 && { attachmentPaths }),
@@ -129,6 +131,9 @@ export function createNewCommand() {
129
131
  if (feature.lifecycle === SdlcLifecycle.Blocked) {
130
132
  messages.info(`Feature created in Blocked state — waiting for parent to reach Implementation`);
131
133
  }
134
+ if (feature.lifecycle === SdlcLifecycle.Pending) {
135
+ messages.info(`Feature created in Pending state — run ${colors.accent(`shep feat start ${feature.id.slice(0, 8)}`)} to begin`);
136
+ }
132
137
  console.log(` ${colors.muted('ID:')} ${colors.accent(feature.id)}`);
133
138
  console.log(` ${colors.muted('Name:')} ${feature.name}`);
134
139
  console.log(` ${colors.muted('Branch:')} ${colors.accent(feature.branch)}`);
@@ -138,7 +143,10 @@ export function createNewCommand() {
138
143
  console.log(` ${colors.muted('Spec:')} ${feature.specPath}`);
139
144
  }
140
145
  if (feature.agentRunId) {
141
- console.log(` ${colors.muted('Agent:')} ${colors.success('spawned')} (run ${feature.agentRunId.slice(0, 8)})`);
146
+ const agentStatus = feature.lifecycle === SdlcLifecycle.Pending
147
+ ? colors.muted('pending')
148
+ : colors.success('spawned');
149
+ console.log(` ${colors.muted('Agent:')} ${agentStatus} (run ${feature.agentRunId.slice(0, 8)})`);
142
150
  }
143
151
  if (push || openPr) {
144
152
  const pushHint = openPr ? 'push + PR' : 'push only';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Feature Start Command
3
+ *
4
+ * Starts a pending feature by transitioning it to its active lifecycle
5
+ * and spawning the agent.
6
+ *
7
+ * Usage:
8
+ * shep feat start <id>
9
+ */
10
+ import { Command } from 'commander';
11
+ export declare function createStartCommand(): Command;
12
+ //# sourceMappingURL=start.command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/start.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,kBAAkB,IAAI,OAAO,CAgC5C"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Feature Start Command
3
+ *
4
+ * Starts a pending feature by transitioning it to its active lifecycle
5
+ * and spawning the agent.
6
+ *
7
+ * Usage:
8
+ * shep feat start <id>
9
+ */
10
+ import { Command } from 'commander';
11
+ import { container } from '../../../../../packages/core/src/infrastructure/di/container.js';
12
+ import { StartFeatureUseCase } from '../../../../../packages/core/src/application/use-cases/features/start-feature.use-case.js';
13
+ import { colors, messages, spinner } from '../../ui/index.js';
14
+ export function createStartCommand() {
15
+ return new Command('start')
16
+ .description('Start a pending feature (spawn the agent)')
17
+ .argument('<id>', 'Feature ID (or prefix)')
18
+ .action(async (id) => {
19
+ try {
20
+ const useCase = container.resolve(StartFeatureUseCase);
21
+ const { feature, agentRun } = await spinner('Starting feature', () => useCase.execute(id));
22
+ messages.newline();
23
+ if (feature.lifecycle === 'Blocked') {
24
+ messages.warning(`Feature transitioned to Blocked — parent has not reached Implementation`);
25
+ }
26
+ else {
27
+ messages.success('Feature started');
28
+ }
29
+ console.log(` ${colors.muted('Feature:')} ${feature.name}`);
30
+ console.log(` ${colors.muted('Branch:')} ${colors.accent(feature.branch)}`);
31
+ console.log(` ${colors.muted('Status:')} ${feature.lifecycle}`);
32
+ if (feature.lifecycle !== 'Blocked') {
33
+ console.log(` ${colors.muted('Agent:')} ${colors.success('spawned')} (run ${agentRun.id.slice(0, 8)})`);
34
+ }
35
+ messages.newline();
36
+ }
37
+ catch (error) {
38
+ const err = error instanceof Error ? error : new Error(String(error));
39
+ messages.error('Failed to start feature', err);
40
+ process.exitCode = 1;
41
+ }
42
+ });
43
+ }
@@ -18,6 +18,8 @@ interface CreateFeatureInput {
18
18
  parentId?: string;
19
19
  /** When true, skip SDLC phases and implement directly from the prompt. */
20
20
  fast?: boolean;
21
+ /** When true, create the feature in pending state (no agent spawned). */
22
+ pending?: boolean;
21
23
  /** Optional agent type override for this feature run */
22
24
  agentType?: string;
23
25
  /** Optional model identifier for this feature run */
@@ -1 +1 @@
1
- {"version":3,"file":"create-feature.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/create-feature.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AAGpE,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAQD,UAAU,kBAAkB;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE;QACd,QAAQ,EAAE,OAAO,CAAC;QAClB,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC;IACF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA4EhD"}
1
+ {"version":3,"file":"create-feature.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/create-feature.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AAGpE,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAQD,UAAU,kBAAkB;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE;QACd,QAAQ,EAAE,OAAO,CAAC;QAClB,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC;IACF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA+EhD"}
@@ -2,7 +2,7 @@
2
2
  import { resolve } from '../../lib/server-container.js';
3
3
  import { composeUserInput } from './compose-user-input.js';
4
4
  export async function createFeature(input) {
5
- const { description, repositoryPath, attachments, sessionId, approvalGates, push, openPr, parentId, fast, agentType, model, } = input;
5
+ const { description, repositoryPath, attachments, sessionId, approvalGates, push, openPr, parentId, fast, pending, agentType, model, } = input;
6
6
  if (!description?.trim()) {
7
7
  return { error: 'description is required' };
8
8
  }
@@ -27,6 +27,7 @@ export async function createFeature(input) {
27
27
  ...(parentId ? { parentId } : {}),
28
28
  description,
29
29
  ...(fast ? { fast } : {}),
30
+ ...(pending ? { pending } : {}),
30
31
  ...(agentType ? { agentType } : {}),
31
32
  ...(model ? { model } : {}),
32
33
  });
@@ -41,6 +42,7 @@ export async function createFeature(input) {
41
42
  openPr: openPr ?? false,
42
43
  ...(parentId ? { parentId } : {}),
43
44
  ...(fast ? { fast } : {}),
45
+ ...(pending ? { pending } : {}),
44
46
  ...(agentType ? { agentType } : {}),
45
47
  ...(model ? { model } : {}),
46
48
  ...(sessionId ? { sessionId } : {}),
@@ -0,0 +1,5 @@
1
+ export declare function startFeature(featureId: string): Promise<{
2
+ started: boolean;
3
+ error?: string;
4
+ }>;
5
+ //# sourceMappingURL=start-feature.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-feature.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/start-feature.ts"],"names":[],"mappings":"AAKA,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAa/C"}
@@ -0,0 +1,16 @@
1
+ 'use server';
2
+ import { resolve } from '../../lib/server-container.js';
3
+ export async function startFeature(featureId) {
4
+ if (!featureId.trim()) {
5
+ return { started: false, error: 'Feature id is required' };
6
+ }
7
+ try {
8
+ const useCase = resolve('StartFeatureUseCase');
9
+ await useCase.execute(featureId);
10
+ return { started: true };
11
+ }
12
+ catch (error) {
13
+ const message = error instanceof Error ? error.message : 'Failed to start feature';
14
+ return { started: false, error: message };
15
+ }
16
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/app/api/agent-events/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAiBH,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAqEvC,wBAAgB,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CA4R9C"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/app/api/agent-events/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAiBH,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAsEvC,wBAAgB,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CA4R9C"}
@@ -34,6 +34,7 @@ const LIFECYCLE_TO_NODE = {
34
34
  [SdlcLifecycle.Review]: 'merge',
35
35
  [SdlcLifecycle.Maintain]: 'maintain',
36
36
  [SdlcLifecycle.Blocked]: 'blocked',
37
+ [SdlcLifecycle.Pending]: 'pending',
37
38
  [SdlcLifecycle.Deleting]: 'blocked',
38
39
  };
39
40
  const STATUS_TO_EVENT = {
@@ -15,7 +15,7 @@ const drawerVariants = cva('', {
15
15
  variants: {
16
16
  size: {
17
17
  sm: 'w-96',
18
- md: 'w-xl',
18
+ md: 'w-2xl',
19
19
  },
20
20
  },
21
21
  defaultVariants: {
@@ -32,7 +32,7 @@ export const SmallSize = {
32
32
  };
33
33
  /** Medium size with content-rich review-style content. */
34
34
  export const MediumSize = {
35
- render: () => (_jsx(DrawerTrigger, { size: "md", children: _jsxs("div", { className: "flex flex-col gap-4 p-4", children: [_jsx("h3", { className: "text-sm font-semibold", children: "Review Content" }), _jsx("p", { className: "text-muted-foreground text-sm", children: "This drawer uses size=\"md\" (w-xl / 576px) for content-rich review panels that need more horizontal space for diff summaries, tables, and code blocks." }), _jsx("div", { className: "bg-muted rounded-md p-3", children: _jsx("pre", { className: "text-xs", children: `+ Added authentication middleware\n- Removed legacy session handler\n Updated user model schema` }) })] }) })),
35
+ render: () => (_jsx(DrawerTrigger, { size: "md", children: _jsxs("div", { className: "flex flex-col gap-4 p-4", children: [_jsx("h3", { className: "text-sm font-semibold", children: "Review Content" }), _jsx("p", { className: "text-muted-foreground text-sm", children: "This drawer uses size=\"md\" (w-2xl / 672px) for content-rich review panels that need more horizontal space for diff summaries, tables, and code blocks." }), _jsx("div", { className: "bg-muted rounded-md p-3", children: _jsx("pre", { className: "text-xs", children: `+ Added authentication middleware\n- Removed legacy session handler\n Updated user model schema` }) })] }) })),
36
36
  };
37
37
  /** Modal drawer with overlay. */
38
38
  export const Modal = {
@@ -1 +1 @@
1
- {"version":3,"file":"feature-drawer-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/control-center-drawer/feature-drawer-client.tsx"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAI/D,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,UAAU,CAAC;IACjB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,wBAAwB,2CA8iB1F"}
1
+ {"version":3,"file":"feature-drawer-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/control-center-drawer/feature-drawer-client.tsx"],"names":[],"mappings":"AAuCA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAI/D,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,UAAU,CAAC;IACjB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,wBAAwB,2CA+jB1F"}
@@ -6,6 +6,7 @@ import { toast } from 'sonner';
6
6
  import { Loader2, Trash2, Play, Square, Copy, Check, Code2, ExternalLink } from 'lucide-react';
7
7
  import { approveFeature } from '../../../app/actions/approve-feature.js';
8
8
  import { resumeFeature } from '../../../app/actions/resume-feature.js';
9
+ import { startFeature } from '../../../app/actions/start-feature.js';
9
10
  import { rejectFeature } from '../../../app/actions/reject-feature.js';
10
11
  import { getFeatureArtifact } from '../../../app/actions/get-feature-artifact.js';
11
12
  import { getResearchArtifact } from '../../../app/actions/get-research-artifact.js';
@@ -281,6 +282,20 @@ export function FeatureDrawerClient({ view: initialView, urlTab }) {
281
282
  return { ...prev, node: { ...prev.node, state: 'running' } };
282
283
  });
283
284
  }, []);
285
+ const handleStart = useCallback(async (featureId) => {
286
+ const result = await startFeature(featureId);
287
+ if (result.error) {
288
+ toast.error(result.error);
289
+ return;
290
+ }
291
+ toast.success('Feature started');
292
+ // Optimistically update the drawer view
293
+ setView((prev) => {
294
+ if (prev.type !== 'feature')
295
+ return prev;
296
+ return { ...prev, node: { ...prev.node, state: 'running' } };
297
+ });
298
+ }, []);
284
299
  // ── Hooks (always called unconditionally per Rules of Hooks) ──────────
285
300
  const featureActionsInput = featureNode?.repositoryPath && featureNode?.branch
286
301
  ? {
@@ -322,7 +337,11 @@ export function FeatureDrawerClient({ view: initialView, urlTab }) {
322
337
  // ── Body ──────────────────────────────────────────────────────────────
323
338
  let body = null;
324
339
  if (view.type === 'feature' && featureNode) {
325
- const enrichedNode = featureNode.state === 'error' ? { ...featureNode, onRetry: handleRetry } : featureNode;
340
+ const enrichedNode = {
341
+ ...featureNode,
342
+ ...(featureNode.state === 'error' && { onRetry: handleRetry }),
343
+ ...(featureNode.state === 'pending' && { onStart: handleStart }),
344
+ };
326
345
  body = (_jsx(FeatureDrawerTabs, { featureNode: enrichedNode, featureId: featureNode.featureId, initialTab: view.initialTab, urlTab: urlTab, sseEvents: events, prdData: prdData, prdSelections: prdSelections, onPrdSelect: (qId, oId) => setPrdSelections((prev) => ({ ...prev, [qId]: oId })), onPrdApprove: handlePrdApprove, onPrdReject: handlePrdReject, isPrdLoading: isLoadingPrd, techData: techData, onTechApprove: handleTechApprove, onTechReject: handleTechReject, isTechLoading: isLoadingTech, productData: isLoadingTechProduct ? null : techProductData, mergeData: mergeData, onMergeApprove: handleMergeApprove, onMergeReject: handleMergeReject, isMergeLoading: isLoadingMerge, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: setChatInput }));
327
346
  }
328
347
  return (_jsx(BaseDrawer, { open: isOpen, onClose: attemptClose, size: "md", modal: false, header: header, "data-testid": view.type === 'feature' ? 'feature-drawer' : 'repository-drawer', children: body }));