@shepai/cli 1.48.0 → 1.49.1

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 (175) hide show
  1. package/apis/json-schema/RejectionFeedbackEntry.yaml +4 -1
  2. package/dist/packages/core/src/application/use-cases/agents/reject-agent-run.use-case.d.ts.map +1 -1
  3. package/dist/packages/core/src/application/use-cases/agents/reject-agent-run.use-case.js +3 -0
  4. package/dist/packages/core/src/domain/generated/output.d.ts +5 -1
  5. package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
  6. package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
  7. package/dist/packages/core/src/infrastructure/di/container.js +3 -0
  8. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.js +1 -1
  9. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.d.ts.map +1 -1
  10. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.js +65 -36
  11. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.d.ts.map +1 -1
  12. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.js +34 -1
  13. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/plan.prompt.d.ts.map +1 -1
  14. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/plan.prompt.js +30 -0
  15. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/requirements.prompt.d.ts.map +1 -1
  16. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/requirements.prompt.js +8 -4
  17. package/dist/src/presentation/cli/commands/feat/show.command.d.ts +6 -0
  18. package/dist/src/presentation/cli/commands/feat/show.command.d.ts.map +1 -1
  19. package/dist/src/presentation/cli/commands/feat/show.command.js +52 -14
  20. package/dist/src/presentation/web/app/actions/approve-feature.d.ts +2 -1
  21. package/dist/src/presentation/web/app/actions/approve-feature.d.ts.map +1 -1
  22. package/dist/src/presentation/web/app/actions/approve-feature.js +2 -2
  23. package/dist/src/presentation/web/app/actions/reject-feature.d.ts +7 -0
  24. package/dist/src/presentation/web/app/actions/reject-feature.d.ts.map +1 -0
  25. package/dist/src/presentation/web/app/actions/reject-feature.js +34 -0
  26. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.d.ts +24 -0
  27. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.d.ts.map +1 -0
  28. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.js +1 -0
  29. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.d.ts +3 -0
  30. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.d.ts.map +1 -0
  31. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.js +12 -0
  32. package/dist/src/presentation/web/components/common/drawer-action-bar/index.d.ts +3 -0
  33. package/dist/src/presentation/web/components/common/drawer-action-bar/index.d.ts.map +1 -0
  34. package/dist/src/presentation/web/components/common/drawer-action-bar/index.js +1 -0
  35. package/dist/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input-config.d.ts +11 -0
  36. package/dist/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input-config.d.ts.map +1 -0
  37. package/dist/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input-config.js +1 -0
  38. package/dist/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input.d.ts +3 -0
  39. package/dist/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input.d.ts.map +1 -0
  40. package/dist/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input.js +18 -0
  41. package/dist/src/presentation/web/components/common/drawer-revision-input/index.d.ts +3 -0
  42. package/dist/src/presentation/web/components/common/drawer-revision-input/index.d.ts.map +1 -0
  43. package/dist/src/presentation/web/components/common/drawer-revision-input/index.js +1 -0
  44. package/dist/src/presentation/web/components/common/merge-review/merge-review-config.d.ts +4 -2
  45. package/dist/src/presentation/web/components/common/merge-review/merge-review-config.d.ts.map +1 -1
  46. package/dist/src/presentation/web/components/common/merge-review/merge-review.d.ts +1 -1
  47. package/dist/src/presentation/web/components/common/merge-review/merge-review.d.ts.map +1 -1
  48. package/dist/src/presentation/web/components/common/merge-review/merge-review.js +4 -15
  49. package/dist/src/presentation/web/components/common/merge-review/merge-review.stories.js +1 -1
  50. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-config.d.ts +4 -2
  51. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-config.d.ts.map +1 -1
  52. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.d.ts +1 -1
  53. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.d.ts.map +1 -1
  54. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.js +6 -15
  55. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.d.ts +4 -0
  56. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.d.ts.map +1 -1
  57. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.js +24 -3
  58. package/dist/src/presentation/web/components/common/reject-feedback-dialog/index.d.ts +3 -0
  59. package/dist/src/presentation/web/components/common/reject-feedback-dialog/index.d.ts.map +1 -0
  60. package/dist/src/presentation/web/components/common/reject-feedback-dialog/index.js +1 -0
  61. package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog-config.d.ts +9 -0
  62. package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog-config.d.ts.map +1 -0
  63. package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog-config.js +1 -0
  64. package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.d.ts +3 -0
  65. package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.d.ts.map +1 -0
  66. package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.js +19 -0
  67. package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.stories.d.ts +14 -0
  68. package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.stories.d.ts.map +1 -0
  69. package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.stories.js +46 -0
  70. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review-config.d.ts +4 -2
  71. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review-config.d.ts.map +1 -1
  72. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.d.ts +1 -1
  73. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.d.ts.map +1 -1
  74. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.js +4 -14
  75. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.stories.d.ts +4 -0
  76. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.stories.d.ts.map +1 -1
  77. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.stories.js +24 -6
  78. package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
  79. package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +48 -33
  80. package/dist/tsconfig.build.tsbuildinfo +1 -1
  81. package/package.json +1 -1
  82. package/web/.next/BUILD_ID +1 -1
  83. package/web/.next/build-manifest.json +2 -2
  84. package/web/.next/cache/.previewinfo +1 -1
  85. package/web/.next/cache/.rscinfo +1 -1
  86. package/web/.next/cache/.tsbuildinfo +1 -1
  87. package/web/.next/cache/config.json +3 -3
  88. package/web/.next/fallback-build-manifest.json +2 -2
  89. package/web/.next/prerender-manifest.json +3 -3
  90. package/web/.next/required-server-files.js +1 -1
  91. package/web/.next/required-server-files.json +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_client-reference-manifest.js +1 -1
  100. package/web/.next/server/app/page/server-reference-manifest.json +41 -26
  101. package/web/.next/server/app/page.js +2 -1
  102. package/web/.next/server/app/page.js.nft.json +1 -1
  103. package/web/.next/server/app/page_client-reference-manifest.js +1 -1
  104. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  105. package/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js +4 -4
  106. package/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js.map +1 -1
  107. package/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
  108. package/web/.next/server/chunks/ssr/[root-of-the-server]__2d1a8e37._.js +9 -0
  109. package/web/.next/server/chunks/ssr/[root-of-the-server]__2d1a8e37._.js.map +1 -0
  110. package/web/.next/server/chunks/ssr/[root-of-the-server]__d8fbe735._.js +3 -0
  111. package/web/.next/server/chunks/ssr/[root-of-the-server]__d8fbe735._.js.map +1 -0
  112. package/web/.next/server/chunks/ssr/_1fafa9db._.js.map +1 -1
  113. package/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.js.map +1 -1
  114. package/web/.next/server/pages/500.html +2 -2
  115. package/web/.next/server/server-reference-manifest.js +1 -1
  116. package/web/.next/server/server-reference-manifest.json +42 -27
  117. package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
  118. package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +2 -2
  119. package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
  120. package/web/.next/standalone/src/presentation/web/.next/required-server-files.json +1 -1
  121. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
  122. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
  123. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  124. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  125. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  126. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  127. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  128. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  129. package/web/.next/standalone/src/presentation/web/.next/server/app/page/server-reference-manifest.json +41 -26
  130. package/web/.next/standalone/src/presentation/web/.next/server/app/page.js +2 -1
  131. package/web/.next/standalone/src/presentation/web/.next/server/app/page.js.nft.json +1 -1
  132. package/web/.next/standalone/src/presentation/web/.next/server/app/page_client-reference-manifest.js +1 -1
  133. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  134. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js +4 -4
  135. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
  136. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__2d1a8e37._.js +9 -0
  137. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__d8fbe735._.js +3 -0
  138. package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
  139. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
  140. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +42 -27
  141. package/web/.next/standalone/src/presentation/web/app/actions/approve-feature.ts +4 -2
  142. package/web/.next/standalone/src/presentation/web/app/actions/reject-feature.ts +52 -0
  143. package/web/.next/standalone/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.ts +24 -0
  144. package/web/.next/standalone/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.tsx +64 -0
  145. package/web/.next/standalone/src/presentation/web/components/common/drawer-action-bar/index.ts +2 -0
  146. package/web/.next/standalone/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input-config.ts +10 -0
  147. package/web/.next/standalone/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input.tsx +41 -0
  148. package/web/.next/standalone/src/presentation/web/components/common/drawer-revision-input/index.ts +2 -0
  149. package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review-config.ts +4 -2
  150. package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review.stories.tsx +1 -1
  151. package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review.tsx +24 -53
  152. package/web/.next/standalone/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-config.ts +4 -2
  153. package/web/.next/standalone/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.tsx +36 -8
  154. package/web/.next/standalone/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.tsx +16 -47
  155. package/web/.next/standalone/src/presentation/web/components/common/reject-feedback-dialog/index.ts +2 -0
  156. package/web/.next/standalone/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog-config.ts +8 -0
  157. package/web/.next/standalone/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.stories.tsx +63 -0
  158. package/web/.next/standalone/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.tsx +78 -0
  159. package/web/.next/standalone/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review-config.ts +4 -2
  160. package/web/.next/standalone/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.stories.tsx +27 -6
  161. package/web/.next/standalone/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.tsx +14 -42
  162. package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center-inner.tsx +94 -49
  163. package/web/.next/standalone/src/presentation/web/server.js +1 -1
  164. package/web/.next/static/chunks/25cab79117866d51.js +10 -0
  165. package/web/.next/static/chunks/59b8bd47023e0249.css +2 -0
  166. package/web/.next/trace +1 -1
  167. package/web/.next/trace-build +1 -1
  168. package/web/.next/server/chunks/ssr/[root-of-the-server]__19d52794._.js +0 -9
  169. package/web/.next/server/chunks/ssr/[root-of-the-server]__19d52794._.js.map +0 -1
  170. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__19d52794._.js +0 -9
  171. package/web/.next/static/chunks/66378a6c055c4e67.js +0 -10
  172. package/web/.next/static/chunks/8668962d3e682263.css +0 -2
  173. /package/web/.next/static/{1kZFDMQ0i-Y8dy1KkHlzv → y92RZZcCAiudDG54kYSQf}/_buildManifest.js +0 -0
  174. /package/web/.next/static/{1kZFDMQ0i-Y8dy1KkHlzv → y92RZZcCAiudDG54kYSQf}/_clientMiddlewareManifest.json +0 -0
  175. /package/web/.next/static/{1kZFDMQ0i-Y8dy1KkHlzv → y92RZZcCAiudDG54kYSQf}/_ssgManifest.js +0 -0
@@ -3,7 +3,12 @@
3
3
  import { useCallback, useEffect, useState } from 'react';
4
4
  import type { Edge } from '@xyflow/react';
5
5
  import { toast } from 'sonner';
6
+ import type {
7
+ PrdApprovalPayload,
8
+ QuestionSelectionChange,
9
+ } from '@shepai/core/domain/generated/output';
6
10
  import { approveFeature } from '@/app/actions/approve-feature';
11
+ import { rejectFeature } from '@/app/actions/reject-feature';
7
12
  import { getFeatureArtifact } from '@/app/actions/get-feature-artifact';
8
13
  import { getResearchArtifact } from '@/app/actions/get-research-artifact';
9
14
  import { getWorkflowDefaults } from '@/app/actions/get-workflow-defaults';
@@ -61,10 +66,12 @@ export function ControlCenterInner({ initialNodes, initialEdges }: ControlCenter
61
66
 
62
67
  // PRD questionnaire drawer state
63
68
  const [prdSelections, setPrdSelections] = useState<Record<string, string>>({});
64
- const [isPrdProcessing, setIsPrdProcessing] = useState(false);
65
69
  const [questionnaireData, setQuestionnaireData] = useState<PrdQuestionnaireData | null>(null);
66
70
  const [isLoadingQuestionnaire, setIsLoadingQuestionnaire] = useState(false);
67
71
 
72
+ // Reject state (shared by both drawers)
73
+ const [isRejecting, setIsRejecting] = useState(false);
74
+
68
75
  // Tech decisions drawer state
69
76
  const [techDecisionsData, setTechDecisionsData] = useState<TechDecisionsReviewData | null>(null);
70
77
  const [isLoadingTechDecisions, setIsLoadingTechDecisions] = useState(false);
@@ -86,20 +93,28 @@ export function ControlCenterInner({ initialNodes, initialEdges }: ControlCenter
86
93
  setPrdSelections((prev) => ({ ...prev, [questionId]: optionId }));
87
94
  }, []);
88
95
 
89
- const handlePrdRefine = useCallback(async (_text: string) => {
90
- setIsPrdProcessing(true);
91
- // TODO: Call API to refine requirements
92
- // For now simulate a delay
93
- await new Promise((resolve) => setTimeout(resolve, 1500));
94
- setIsPrdProcessing(false);
95
- }, []);
96
-
97
96
  const handlePrdApprove = useCallback(
98
97
  async (_actionId: string) => {
99
98
  const featureId = selectedNode?.featureId;
100
99
  if (!featureId) return;
101
100
 
102
- const result = await approveFeature(featureId);
101
+ let payload: PrdApprovalPayload | undefined;
102
+ if (questionnaireData) {
103
+ const changedSelections: QuestionSelectionChange[] = [];
104
+ for (const [questionId, optionId] of Object.entries(prdSelections)) {
105
+ const question = questionnaireData.questions.find((q) => q.id === questionId);
106
+ const option = question?.options.find((o) => o.id === optionId);
107
+ if (question && option) {
108
+ changedSelections.push({
109
+ questionId: question.question,
110
+ selectedOption: option.label,
111
+ });
112
+ }
113
+ }
114
+ payload = { approved: true, changedSelections };
115
+ }
116
+
117
+ const result = await approveFeature(featureId, payload);
103
118
 
104
119
  if (!result.approved) {
105
120
  toast.error(result.error ?? 'Failed to approve requirements');
@@ -110,52 +125,79 @@ export function ControlCenterInner({ initialNodes, initialEdges }: ControlCenter
110
125
  clearSelection();
111
126
  setPrdSelections({});
112
127
  },
113
- [selectedNode?.featureId, clearSelection]
128
+ [selectedNode?.featureId, clearSelection, questionnaireData, prdSelections]
114
129
  );
115
130
 
116
- const handleTechDecisionsRefine = useCallback(async (_text: string) => {
117
- setIsLoadingTechDecisions(true);
118
- // TODO: Call API to refine tech decisions
119
- await new Promise((resolve) => setTimeout(resolve, 1500));
120
- setIsLoadingTechDecisions(false);
121
- }, []);
131
+ // Shared reject handler all drawers use the same rejectFeature flow
132
+ const handleReject = useCallback(
133
+ async (feedback: string, label: string, onDone?: () => void) => {
134
+ const featureId = selectedNode?.featureId;
135
+ if (!featureId) return;
122
136
 
123
- const handleTechDecisionsApprove = useCallback(async () => {
124
- const featureId = selectedNode?.featureId;
125
- if (!featureId) return;
137
+ setIsRejecting(true);
138
+ try {
139
+ const result = await rejectFeature(featureId, feedback);
126
140
 
127
- const result = await approveFeature(featureId);
141
+ if (!result.rejected) {
142
+ toast.error(result.error ?? `Failed to reject ${label.toLowerCase()}`);
143
+ return;
144
+ }
128
145
 
129
- if (!result.approved) {
130
- toast.error(result.error ?? 'Failed to approve plan');
131
- return;
132
- }
146
+ toast.success(`${label} rejected — agent re-iterating (iteration ${result.iteration})`);
147
+ if (result.iterationWarning) {
148
+ toast.warning(
149
+ `Iteration ${result.iteration} — consider approving or adjusting feedback to avoid excessive iterations`
150
+ );
151
+ }
152
+ clearSelection();
153
+ onDone?.();
154
+ } finally {
155
+ setIsRejecting(false);
156
+ }
157
+ },
158
+ [selectedNode?.featureId, clearSelection]
159
+ );
133
160
 
134
- toast.success('Plan approved agent resuming');
135
- clearSelection();
136
- }, [selectedNode?.featureId, clearSelection]);
161
+ const handlePrdReject = useCallback(
162
+ (feedback: string) => handleReject(feedback, 'Requirements', () => setPrdSelections({})),
163
+ [handleReject]
164
+ );
137
165
 
138
- const handleMergeApprove = useCallback(async () => {
139
- const featureId = selectedNode?.featureId;
140
- if (!featureId) return;
166
+ const handleTechDecisionsReject = useCallback(
167
+ (feedback: string) => handleReject(feedback, 'Plan'),
168
+ [handleReject]
169
+ );
141
170
 
142
- const result = await approveFeature(featureId);
171
+ const handleMergeReject = useCallback(
172
+ (feedback: string) => handleReject(feedback, 'Merge'),
173
+ [handleReject]
174
+ );
143
175
 
144
- if (!result.approved) {
145
- toast.error(result.error ?? 'Failed to approve merge');
146
- return;
147
- }
176
+ // Shared approve handler — tech decisions and merge use identical approve flows
177
+ const handleSimpleApprove = useCallback(
178
+ async (label: string) => {
179
+ const featureId = selectedNode?.featureId;
180
+ if (!featureId) return;
148
181
 
149
- toast.success('Merge approved agent resuming');
150
- clearSelection();
151
- }, [selectedNode?.featureId, clearSelection]);
182
+ const result = await approveFeature(featureId);
152
183
 
153
- const handleMergeRefine = useCallback(async (_text: string) => {
154
- setIsLoadingMergeReview(true);
155
- // TODO: Call API to refine merge
156
- await new Promise((resolve) => setTimeout(resolve, 1500));
157
- setIsLoadingMergeReview(false);
158
- }, []);
184
+ if (!result.approved) {
185
+ toast.error(result.error ?? `Failed to approve ${label.toLowerCase()}`);
186
+ return;
187
+ }
188
+
189
+ toast.success(`${label} approved — agent resuming`);
190
+ clearSelection();
191
+ },
192
+ [selectedNode?.featureId, clearSelection]
193
+ );
194
+
195
+ const handleTechDecisionsApprove = useCallback(
196
+ () => handleSimpleApprove('Plan'),
197
+ [handleSimpleApprove]
198
+ );
199
+
200
+ const handleMergeApprove = useCallback(() => handleSimpleApprove('Merge'), [handleSimpleApprove]);
159
201
 
160
202
  // Fetch questionnaire data and reset selections when a different feature is selected
161
203
  const prdFeatureId = showPrdDrawer ? selectedNode?.featureId : null;
@@ -322,11 +364,12 @@ export function ControlCenterInner({ initialNodes, initialEdges }: ControlCenter
322
364
  data={questionnaireData}
323
365
  selections={prdSelections}
324
366
  onSelect={handlePrdSelect}
325
- onRefine={handlePrdRefine}
326
367
  onApprove={handlePrdApprove}
368
+ onReject={handlePrdReject}
369
+ isRejecting={isRejecting}
327
370
  onDelete={handleDeleteFeature}
328
371
  isDeleting={isDeleting}
329
- isProcessing={isPrdProcessing || isLoadingQuestionnaire}
372
+ isProcessing={isLoadingQuestionnaire}
330
373
  />
331
374
  ) : null}
332
375
  {techDecisionsData ? (
@@ -339,8 +382,9 @@ export function ControlCenterInner({ initialNodes, initialEdges }: ControlCenter
339
382
  branch={selectedNode?.branch}
340
383
  specPath={selectedNode?.specPath}
341
384
  data={techDecisionsData}
342
- onRefine={handleTechDecisionsRefine}
343
385
  onApprove={handleTechDecisionsApprove}
386
+ onReject={handleTechDecisionsReject}
387
+ isRejecting={isRejecting}
344
388
  onDelete={handleDeleteFeature}
345
389
  isDeleting={isDeleting}
346
390
  isProcessing={isLoadingTechDecisions}
@@ -357,7 +401,8 @@ export function ControlCenterInner({ initialNodes, initialEdges }: ControlCenter
357
401
  specPath={selectedNode?.specPath}
358
402
  data={mergeReviewData}
359
403
  onApprove={handleMergeApprove}
360
- onRefine={handleMergeRefine}
404
+ onReject={handleMergeReject}
405
+ isRejecting={isRejecting}
361
406
  onDelete={handleDeleteFeature}
362
407
  isDeleting={isDeleting}
363
408
  isProcessing={isLoadingMergeReview}
@@ -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.47.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"],"distDirRoot":".next"}
18
+ const nextConfig = {"env":{"NEXT_PUBLIC_SHEP_VERSION":"1.49.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"],"distDirRoot":".next"}
19
19
 
20
20
  process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(nextConfig)
21
21