@shepai/cli 1.47.0 → 1.48.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 (161) hide show
  1. package/apis/json-schema/ApprovalGateDefaults.yaml +26 -0
  2. package/apis/json-schema/Feature.yaml +3 -0
  3. package/apis/json-schema/Repository.yaml +16 -0
  4. package/apis/json-schema/Settings.yaml +5 -0
  5. package/apis/json-schema/WorkflowConfig.yaml +4 -20
  6. package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.d.ts +17 -0
  7. package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.d.ts.map +1 -1
  8. package/dist/packages/core/src/application/ports/output/services/worktree-service.interface.d.ts +11 -1
  9. package/dist/packages/core/src/application/ports/output/services/worktree-service.interface.d.ts.map +1 -1
  10. package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts +3 -1
  11. package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts.map +1 -1
  12. package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.js +11 -4
  13. package/dist/packages/core/src/application/use-cases/features/get-plan-artifact.use-case.d.ts +19 -0
  14. package/dist/packages/core/src/application/use-cases/features/get-plan-artifact.use-case.d.ts.map +1 -0
  15. package/dist/packages/core/src/application/use-cases/features/get-plan-artifact.use-case.js +52 -0
  16. package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
  17. package/dist/packages/core/src/infrastructure/di/container.js +5 -0
  18. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts.map +1 -1
  19. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js +2 -0
  20. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.d.ts +2 -0
  21. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.d.ts.map +1 -1
  22. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.js +10 -3
  23. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.d.ts.map +1 -1
  24. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.js +15 -7
  25. package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts +2 -0
  26. package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts.map +1 -1
  27. package/dist/packages/core/src/infrastructure/services/git/git-pr.service.js +41 -0
  28. package/dist/packages/core/src/infrastructure/services/git/worktree.service.d.ts +2 -1
  29. package/dist/packages/core/src/infrastructure/services/git/worktree.service.d.ts.map +1 -1
  30. package/dist/packages/core/src/infrastructure/services/git/worktree.service.js +29 -4
  31. package/dist/src/presentation/cli/ui/messages.d.ts.map +1 -1
  32. package/dist/src/presentation/cli/ui/messages.js +1 -7
  33. package/dist/src/presentation/web/app/actions/get-merge-review-data.d.ts +7 -0
  34. package/dist/src/presentation/web/app/actions/get-merge-review-data.d.ts.map +1 -0
  35. package/dist/src/presentation/web/app/actions/get-merge-review-data.js +49 -0
  36. package/dist/src/presentation/web/app/page.d.ts.map +1 -1
  37. package/dist/src/presentation/web/app/page.js +1 -0
  38. package/dist/src/presentation/web/components/common/feature-node/feature-node.d.ts.map +1 -1
  39. package/dist/src/presentation/web/components/common/feature-node/feature-node.js +8 -1
  40. package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts +1 -0
  41. package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts.map +1 -1
  42. package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.js +22 -1
  43. package/dist/src/presentation/web/components/common/merge-review/index.d.ts +4 -0
  44. package/dist/src/presentation/web/components/common/merge-review/index.d.ts.map +1 -0
  45. package/dist/src/presentation/web/components/common/merge-review/index.js +2 -0
  46. package/dist/src/presentation/web/components/common/merge-review/merge-review-config.d.ts +75 -0
  47. package/dist/src/presentation/web/components/common/merge-review/merge-review-config.d.ts.map +1 -0
  48. package/dist/src/presentation/web/components/common/merge-review/merge-review-config.js +1 -0
  49. package/dist/src/presentation/web/components/common/merge-review/merge-review-drawer.d.ts +3 -0
  50. package/dist/src/presentation/web/components/common/merge-review/merge-review-drawer.d.ts.map +1 -0
  51. package/dist/src/presentation/web/components/common/merge-review/merge-review-drawer.js +7 -0
  52. package/dist/src/presentation/web/components/common/merge-review/merge-review.d.ts +3 -0
  53. package/dist/src/presentation/web/components/common/merge-review/merge-review.d.ts.map +1 -0
  54. package/dist/src/presentation/web/components/common/merge-review/merge-review.js +36 -0
  55. package/dist/src/presentation/web/components/common/merge-review/merge-review.stories.d.ts +32 -0
  56. package/dist/src/presentation/web/components/common/merge-review/merge-review.stories.d.ts.map +1 -0
  57. package/dist/src/presentation/web/components/common/merge-review/merge-review.stories.js +165 -0
  58. package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
  59. package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +55 -1
  60. package/dist/src/presentation/web/components/features/control-center/control-center.stories.d.ts.map +1 -1
  61. package/dist/src/presentation/web/components/features/control-center/control-center.stories.js +15 -0
  62. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
  63. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +37 -15
  64. package/dist/tsconfig.build.tsbuildinfo +1 -1
  65. package/package.json +1 -1
  66. package/web/.next/BUILD_ID +1 -1
  67. package/web/.next/build-manifest.json +2 -2
  68. package/web/.next/cache/.previewinfo +1 -1
  69. package/web/.next/cache/.rscinfo +1 -1
  70. package/web/.next/cache/.tsbuildinfo +1 -1
  71. package/web/.next/cache/config.json +3 -3
  72. package/web/.next/fallback-build-manifest.json +2 -2
  73. package/web/.next/prerender-manifest.json +3 -3
  74. package/web/.next/required-server-files.js +1 -1
  75. package/web/.next/required-server-files.json +1 -1
  76. package/web/.next/server/app/_global-error.html +2 -2
  77. package/web/.next/server/app/_global-error.rsc +1 -1
  78. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  79. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  80. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  81. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  82. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  83. package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  84. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  85. package/web/.next/server/app/page/server-reference-manifest.json +39 -24
  86. package/web/.next/server/app/page.js +1 -1
  87. package/web/.next/server/app/page.js.nft.json +1 -1
  88. package/web/.next/server/app/page_client-reference-manifest.js +1 -1
  89. package/web/.next/server/app/version/page.js.nft.json +1 -1
  90. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  91. package/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js +4 -4
  92. package/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js.map +1 -1
  93. package/web/.next/server/chunks/ssr/[root-of-the-server]__19d52794._.js +9 -0
  94. package/web/.next/server/chunks/ssr/[root-of-the-server]__19d52794._.js.map +1 -0
  95. package/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
  96. package/web/.next/{standalone/src/presentation/web/.next/server/chunks/ssr/_3ac3601c._.js → server/chunks/ssr/_1fafa9db._.js} +2 -2
  97. package/web/.next/server/chunks/ssr/_1fafa9db._.js.map +1 -0
  98. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
  99. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
  100. package/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.js +1 -1
  101. package/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.js.map +1 -1
  102. package/web/.next/server/pages/500.html +2 -2
  103. package/web/.next/server/server-reference-manifest.js +1 -1
  104. package/web/.next/server/server-reference-manifest.json +40 -25
  105. package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
  106. package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +2 -2
  107. package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
  108. package/web/.next/standalone/src/presentation/web/.next/required-server-files.json +1 -1
  109. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
  110. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
  111. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  112. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  113. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  114. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  115. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  116. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  117. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  118. package/web/.next/standalone/src/presentation/web/.next/server/app/page/server-reference-manifest.json +39 -24
  119. package/web/.next/standalone/src/presentation/web/.next/server/app/page.js +1 -1
  120. package/web/.next/standalone/src/presentation/web/.next/server/app/page.js.nft.json +1 -1
  121. package/web/.next/standalone/src/presentation/web/.next/server/app/page_client-reference-manifest.js +1 -1
  122. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page.js.nft.json +1 -1
  123. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  124. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js +4 -4
  125. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__19d52794._.js +9 -0
  126. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
  127. package/web/.next/{server/chunks/ssr/_3ac3601c._.js → standalone/src/presentation/web/.next/server/chunks/ssr/_1fafa9db._.js} +2 -2
  128. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
  129. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.js +1 -1
  130. package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
  131. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
  132. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +40 -25
  133. package/web/.next/standalone/src/presentation/web/app/actions/get-merge-review-data.ts +64 -0
  134. package/web/.next/standalone/src/presentation/web/app/page.tsx +1 -0
  135. package/web/.next/standalone/src/presentation/web/components/common/feature-node/feature-node.stories.tsx +23 -1
  136. package/web/.next/standalone/src/presentation/web/components/common/feature-node/feature-node.tsx +6 -1
  137. package/web/.next/standalone/src/presentation/web/components/common/merge-review/index.ts +7 -0
  138. package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review-config.ts +81 -0
  139. package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review-drawer.tsx +34 -0
  140. package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review.stories.tsx +240 -0
  141. package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review.tsx +252 -0
  142. package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center-inner.tsx +82 -1
  143. package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center.stories.tsx +15 -0
  144. package/web/.next/standalone/src/presentation/web/components/features/control-center/use-control-center-state.ts +47 -17
  145. package/web/.next/standalone/src/presentation/web/server.js +1 -1
  146. package/web/.next/static/chunks/{9f8e71029fb04681.js → 0da7a9860fa6ae05.js} +2 -2
  147. package/web/.next/static/chunks/22f30ce91a3c79c1.js +1 -0
  148. package/web/.next/static/chunks/66378a6c055c4e67.js +10 -0
  149. package/web/.next/static/chunks/8668962d3e682263.css +2 -0
  150. package/web/.next/trace +1 -1
  151. package/web/.next/trace-build +1 -1
  152. package/web/.next/server/chunks/ssr/[root-of-the-server]__d6d75c22._.js +0 -9
  153. package/web/.next/server/chunks/ssr/[root-of-the-server]__d6d75c22._.js.map +0 -1
  154. package/web/.next/server/chunks/ssr/_3ac3601c._.js.map +0 -1
  155. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__d6d75c22._.js +0 -9
  156. package/web/.next/static/chunks/779c99975c85389e.js +0 -10
  157. package/web/.next/static/chunks/83ff3b6bbee54bce.js +0 -1
  158. package/web/.next/static/chunks/b7b7abe79e05b229.css +0 -2
  159. /package/web/.next/static/{wQ3vPV9I8JeacVNyp4HFg → 1kZFDMQ0i-Y8dy1KkHlzv}/_buildManifest.js +0 -0
  160. /package/web/.next/static/{wQ3vPV9I8JeacVNyp4HFg → 1kZFDMQ0i-Y8dy1KkHlzv}/_clientMiddlewareManifest.json +0 -0
  161. /package/web/.next/static/{wQ3vPV9I8JeacVNyp4HFg → 1kZFDMQ0i-Y8dy1KkHlzv}/_ssgManifest.js +0 -0
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "node": {
3
- "40d0a3e706fa8b01e4364b67a1f80c2f26dc02af10": {
3
+ "405927de7a51b3fdbf3bce187705d5f3a33c599793": {
4
4
  "workers": {
5
5
  "app/page": {
6
- "moduleId": 94090,
6
+ "moduleId": 30953,
7
7
  "async": false,
8
8
  "exportedName": "approveFeature",
9
9
  "filename": "src/presentation/web/app/actions/approve-feature.ts"
@@ -15,10 +15,10 @@
15
15
  "filename": "src/presentation/web/app/actions/approve-feature.ts",
16
16
  "exportedName": "approveFeature"
17
17
  },
18
- "40115d3ddb31ff86dafde210f83d4d01739ef550de": {
18
+ "40bd05da6b59c64afa59bd767ea7563b23608711a0": {
19
19
  "workers": {
20
20
  "app/page": {
21
- "moduleId": 94090,
21
+ "moduleId": 30953,
22
22
  "async": false,
23
23
  "exportedName": "getFeatureArtifact",
24
24
  "filename": "src/presentation/web/app/actions/get-feature-artifact.ts"
@@ -30,10 +30,10 @@
30
30
  "filename": "src/presentation/web/app/actions/get-feature-artifact.ts",
31
31
  "exportedName": "getFeatureArtifact"
32
32
  },
33
- "403ea6c9bd10b21438b631731894e18e2c9a72a037": {
33
+ "4052167b4529af8c247a75b3051a28f058af8a0ac9": {
34
34
  "workers": {
35
35
  "app/page": {
36
- "moduleId": 94090,
36
+ "moduleId": 30953,
37
37
  "async": false,
38
38
  "exportedName": "getResearchArtifact",
39
39
  "filename": "src/presentation/web/app/actions/get-research-artifact.ts"
@@ -45,10 +45,10 @@
45
45
  "filename": "src/presentation/web/app/actions/get-research-artifact.ts",
46
46
  "exportedName": "getResearchArtifact"
47
47
  },
48
- "0093c723faa4b6cfd43ff6a346973c45dcdafd917c": {
48
+ "00fd01b28bb7867f8544c9906f5037e63c7202fa8e": {
49
49
  "workers": {
50
50
  "app/page": {
51
- "moduleId": 94090,
51
+ "moduleId": 30953,
52
52
  "async": false,
53
53
  "exportedName": "getWorkflowDefaults",
54
54
  "filename": "src/presentation/web/app/actions/get-workflow-defaults.ts"
@@ -60,10 +60,25 @@
60
60
  "filename": "src/presentation/web/app/actions/get-workflow-defaults.ts",
61
61
  "exportedName": "getWorkflowDefaults"
62
62
  },
63
- "40a30ff303cb355d994314077a44146c2afe41633a": {
63
+ "40952da4050947a94de113924015351244089d8ffe": {
64
64
  "workers": {
65
65
  "app/page": {
66
- "moduleId": 94090,
66
+ "moduleId": 30953,
67
+ "async": false,
68
+ "exportedName": "getMergeReviewData",
69
+ "filename": "src/presentation/web/app/actions/get-merge-review-data.ts"
70
+ }
71
+ },
72
+ "layer": {
73
+ "app/page": "action-browser"
74
+ },
75
+ "filename": "src/presentation/web/app/actions/get-merge-review-data.ts",
76
+ "exportedName": "getMergeReviewData"
77
+ },
78
+ "40bfc128861432d76522cc52efd6249895ce00ab03": {
79
+ "workers": {
80
+ "app/page": {
81
+ "moduleId": 30953,
67
82
  "async": false,
68
83
  "exportedName": "openIde",
69
84
  "filename": "src/presentation/web/app/actions/open-ide.ts"
@@ -75,10 +90,10 @@
75
90
  "filename": "src/presentation/web/app/actions/open-ide.ts",
76
91
  "exportedName": "openIde"
77
92
  },
78
- "40c994b683284ab7c96f945c8b95fb023aa0ffc854": {
93
+ "4033b24b3695151d1f14d8d9b2df4db2ab821d1aa1": {
79
94
  "workers": {
80
95
  "app/page": {
81
- "moduleId": 94090,
96
+ "moduleId": 30953,
82
97
  "async": false,
83
98
  "exportedName": "openShell",
84
99
  "filename": "src/presentation/web/app/actions/open-shell.ts"
@@ -90,10 +105,10 @@
90
105
  "filename": "src/presentation/web/app/actions/open-shell.ts",
91
106
  "exportedName": "openShell"
92
107
  },
93
- "40ed3604b89a263f2d2428a04b03e0397d4d1dfe14": {
108
+ "400805d5028779c5a42a1b209d0ccd103df6aae782": {
94
109
  "workers": {
95
110
  "app/page": {
96
- "moduleId": 94090,
111
+ "moduleId": 30953,
97
112
  "async": false,
98
113
  "exportedName": "openFolder",
99
114
  "filename": "src/presentation/web/app/actions/open-folder.ts"
@@ -105,10 +120,10 @@
105
120
  "filename": "src/presentation/web/app/actions/open-folder.ts",
106
121
  "exportedName": "openFolder"
107
122
  },
108
- "002cfb464c1d3ab32bd963f49035b100891de6215e": {
123
+ "002086e55ab6adb498958985cc6b499caadb8efe8a": {
109
124
  "workers": {
110
125
  "app/page": {
111
- "moduleId": 94090,
126
+ "moduleId": 30953,
112
127
  "async": false,
113
128
  "exportedName": "pickFolder",
114
129
  "filename": "src/presentation/web/app/actions/pick-folder.ts"
@@ -120,10 +135,10 @@
120
135
  "filename": "src/presentation/web/app/actions/pick-folder.ts",
121
136
  "exportedName": "pickFolder"
122
137
  },
123
- "40ebcd0e44246e2d829ed41e5882ccfc8f2d9ea549": {
138
+ "4070bbfbc7263457fbf281a0e0dcd7a43c12b30a17": {
124
139
  "workers": {
125
140
  "app/page": {
126
- "moduleId": 94090,
141
+ "moduleId": 30953,
127
142
  "async": false,
128
143
  "exportedName": "createFeature",
129
144
  "filename": "src/presentation/web/app/actions/create-feature.ts"
@@ -135,10 +150,10 @@
135
150
  "filename": "src/presentation/web/app/actions/create-feature.ts",
136
151
  "exportedName": "createFeature"
137
152
  },
138
- "40aeecbe93c1ac4107b91ca18021b180088949d524": {
153
+ "4045ff41ea532f2c3e9970f8022b64a977da6e2eca": {
139
154
  "workers": {
140
155
  "app/page": {
141
- "moduleId": 94090,
156
+ "moduleId": 30953,
142
157
  "async": false,
143
158
  "exportedName": "deleteFeature",
144
159
  "filename": "src/presentation/web/app/actions/delete-feature.ts"
@@ -150,10 +165,10 @@
150
165
  "filename": "src/presentation/web/app/actions/delete-feature.ts",
151
166
  "exportedName": "deleteFeature"
152
167
  },
153
- "40f460f3a71643a4470fe6b0624a42ffe4328ac96a": {
168
+ "40c7ab52e7389ec3d2f6a78fdd2b5686746b247b24": {
154
169
  "workers": {
155
170
  "app/page": {
156
- "moduleId": 94090,
171
+ "moduleId": 30953,
157
172
  "async": false,
158
173
  "exportedName": "addRepository",
159
174
  "filename": "src/presentation/web/app/actions/add-repository.ts"
@@ -165,10 +180,10 @@
165
180
  "filename": "src/presentation/web/app/actions/add-repository.ts",
166
181
  "exportedName": "addRepository"
167
182
  },
168
- "40076d6aa59873fb8fc1482d79ec46f1190e5586ed": {
183
+ "406251232c435014ef64078d485da082110be0fb37": {
169
184
  "workers": {
170
185
  "app/page": {
171
- "moduleId": 94090,
186
+ "moduleId": 30953,
172
187
  "async": false,
173
188
  "exportedName": "deleteRepository",
174
189
  "filename": "src/presentation/web/app/actions/delete-repository.ts"
@@ -182,5 +197,5 @@
182
197
  }
183
198
  },
184
199
  "edge": {},
185
- "encryptionKey": "NtfNvj3HgiKgYLoNQgEO3FR4k83Rs/qJeYJ3CJR63lI="
200
+ "encryptionKey": "hCzppyIeZCi6mpL+ZJ0dlbq42XLKa14KFhRtB9jR6iI="
186
201
  }
@@ -0,0 +1,64 @@
1
+ 'use server';
2
+
3
+ import { resolve } from '@/lib/server-container';
4
+ import type { IFeatureRepository } from '@shepai/core/application/ports/output/repositories/feature-repository.interface';
5
+ import type { IGitPrService } from '@shepai/core/application/ports/output/services/git-pr-service.interface';
6
+ import type { GetPlanArtifactUseCase } from '@shepai/core/application/use-cases/features/get-plan-artifact.use-case';
7
+ import type {
8
+ MergeReviewData,
9
+ MergeReviewPhase,
10
+ } from '@/components/common/merge-review/merge-review-config';
11
+
12
+ type GetMergeReviewDataResult = MergeReviewData | { error: string };
13
+
14
+ export async function getMergeReviewData(featureId: string): Promise<GetMergeReviewDataResult> {
15
+ if (!featureId.trim()) {
16
+ return { error: 'Feature id is required' };
17
+ }
18
+
19
+ try {
20
+ const featureRepo = resolve<IFeatureRepository>('IFeatureRepository');
21
+ const feature = await featureRepo.findById(featureId);
22
+
23
+ if (!feature) {
24
+ return { error: 'Feature not found' };
25
+ }
26
+
27
+ const pr = feature.pr
28
+ ? {
29
+ url: feature.pr.url,
30
+ number: feature.pr.number,
31
+ status: feature.pr.status,
32
+ commitHash: feature.pr.commitHash,
33
+ ciStatus: feature.pr.ciStatus,
34
+ }
35
+ : undefined;
36
+
37
+ const branch = feature.branch ? { source: feature.branch, target: 'main' } : undefined;
38
+
39
+ // Load plan phases (best-effort)
40
+ let phases: MergeReviewPhase[] | undefined;
41
+ try {
42
+ const planUseCase = resolve<GetPlanArtifactUseCase>('GetPlanArtifactUseCase');
43
+ const plan = await planUseCase.execute(featureId);
44
+ phases = plan.phases.map(({ id, name, description }) => ({ id, name, description }));
45
+ } catch {
46
+ // Plan unavailable — not critical
47
+ }
48
+
49
+ if (!feature.worktreePath) {
50
+ return { pr, branch, phases, warning: pr ? undefined : 'No PR or diff data available' };
51
+ }
52
+
53
+ try {
54
+ const gitPrService = resolve<IGitPrService>('IGitPrService');
55
+ const diffSummary = await gitPrService.getPrDiffSummary(feature.worktreePath, 'main');
56
+ return { pr, branch, phases, diffSummary };
57
+ } catch {
58
+ return { pr, branch, phases, warning: 'Diff statistics unavailable' };
59
+ }
60
+ } catch (error: unknown) {
61
+ const message = error instanceof Error ? error.message : 'Failed to load merge review data';
62
+ return { error: message };
63
+ }
64
+ }
@@ -32,6 +32,7 @@ const nodeToLifecyclePhase: Record<string, FeatureLifecyclePhase> = {
32
32
  research: 'research',
33
33
  plan: 'implementation',
34
34
  implement: 'implementation',
35
+ merge: 'review',
35
36
  };
36
37
 
37
38
  export default async function HomePage() {
@@ -106,6 +106,16 @@ const allStatesData: FeatureNodeData[] = [
106
106
  repositoryPath: '/home/user/my-repo',
107
107
  branch: 'feat/data-pipeline',
108
108
  },
109
+ {
110
+ name: 'Merge Review',
111
+ description: 'PR ready for merge approval',
112
+ featureId: '#bi3',
113
+ lifecycle: 'review' as FeatureLifecyclePhase,
114
+ state: 'action-required',
115
+ progress: 90,
116
+ repositoryPath: '/home/user/my-repo',
117
+ branch: 'feat/merge-review',
118
+ },
109
119
  {
110
120
  name: 'Payment Gateway',
111
121
  description: 'Stripe integration for subscriptions',
@@ -145,7 +155,7 @@ export const AllStates: Story = {
145
155
  render: () => (
146
156
  <div className="flex flex-wrap gap-6">
147
157
  {allStatesData.map((data) => (
148
- <FeatureNodeCanvas key={data.state} style={{ width: 500, height: 350 }} data={data} />
158
+ <FeatureNodeCanvas key={data.featureId} style={{ width: 500, height: 350 }} data={data} />
149
159
  ))}
150
160
  </div>
151
161
  ),
@@ -316,6 +326,18 @@ export const Creating: Story = {
316
326
  render: (args) => <FeatureNodeCanvas data={args} />,
317
327
  };
318
328
 
329
+ export const MergeReviewActionRequired: Story = {
330
+ args: {
331
+ name: 'Merge Review',
332
+ description: 'PR ready for merge approval',
333
+ featureId: '#bi3',
334
+ lifecycle: 'review',
335
+ state: 'action-required',
336
+ progress: 90,
337
+ },
338
+ render: (args) => <FeatureNodeCanvas data={args} />,
339
+ };
340
+
319
341
  export const ErrorWithMessage: Story = {
320
342
  args: {
321
343
  name: 'Email Service',
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { Handle, Position } from '@xyflow/react';
4
- import { Settings, Plus, FileText, Wrench, type LucideIcon } from 'lucide-react';
4
+ import { Settings, Plus, FileText, Wrench, GitMerge, type LucideIcon } from 'lucide-react';
5
5
  import { cn } from '@/lib/utils';
6
6
  import {
7
7
  featureNodeStateConfig,
@@ -21,6 +21,7 @@ function getBadgeIcon(data: FeatureNodeData): LucideIcon {
21
21
  if (data.state === 'action-required') {
22
22
  if (data.lifecycle === 'requirements') return FileText;
23
23
  if (data.lifecycle === 'implementation') return Wrench;
24
+ if (data.lifecycle === 'review') return GitMerge;
24
25
  }
25
26
  return config.icon;
26
27
  }
@@ -34,6 +35,9 @@ function getActionRequiredBadgeClasses(data: FeatureNodeData): {
34
35
  if (data.lifecycle === 'implementation') {
35
36
  return { badgeClass: 'text-indigo-700', badgeBgClass: 'bg-indigo-50' };
36
37
  }
38
+ if (data.lifecycle === 'review') {
39
+ return { badgeClass: 'text-emerald-700', badgeBgClass: 'bg-emerald-50' };
40
+ }
37
41
  return null; // requirements stays amber (default)
38
42
  }
39
43
 
@@ -51,6 +55,7 @@ function getBadgeText(data: FeatureNodeData): string {
51
55
  case 'action-required':
52
56
  if (data.lifecycle === 'requirements') return 'Review Product Requirements';
53
57
  if (data.lifecycle === 'implementation') return 'Review Technical Planning';
58
+ if (data.lifecycle === 'review') return 'Review Merge Request';
54
59
  return config.label;
55
60
  case 'error':
56
61
  return data.errorMessage ?? 'Something went wrong';
@@ -0,0 +1,7 @@
1
+ export { MergeReview } from './merge-review';
2
+ export { MergeReviewDrawer } from './merge-review-drawer';
3
+ export type {
4
+ MergeReviewProps,
5
+ MergeReviewDrawerProps,
6
+ MergeReviewData,
7
+ } from './merge-review-config';
@@ -0,0 +1,81 @@
1
+ import type { PrStatus, CiStatus } from '@shepai/core/domain/generated/output';
2
+
3
+ /** Diff summary statistics for the PR */
4
+ export interface MergeReviewDiffSummary {
5
+ filesChanged: number;
6
+ additions: number;
7
+ deletions: number;
8
+ commitCount: number;
9
+ }
10
+
11
+ /** PR metadata extracted from Feature.pr */
12
+ export interface MergeReviewPr {
13
+ url: string;
14
+ number: number;
15
+ status: PrStatus;
16
+ commitHash?: string;
17
+ ciStatus?: CiStatus;
18
+ }
19
+
20
+ /** A phase from the implementation plan */
21
+ export interface MergeReviewPhase {
22
+ id: string;
23
+ name: string;
24
+ description?: string;
25
+ }
26
+
27
+ /** Branch merge direction info */
28
+ export interface MergeReviewBranch {
29
+ /** Feature branch name */
30
+ source: string;
31
+ /** Target branch name (e.g. 'main') */
32
+ target: string;
33
+ }
34
+
35
+ /** Data returned by the getMergeReviewData server action */
36
+ export interface MergeReviewData {
37
+ /** PR metadata (omitted when the feature has no PR) */
38
+ pr?: MergeReviewPr;
39
+ /** Aggregate diff statistics (omitted when worktree is unavailable) */
40
+ diffSummary?: MergeReviewDiffSummary;
41
+ /** Implementation phases from plan.yaml */
42
+ phases?: MergeReviewPhase[];
43
+ /** Branch merge direction */
44
+ branch?: MergeReviewBranch;
45
+ /** Warning message when diff summary could not be retrieved */
46
+ warning?: string;
47
+ }
48
+
49
+ /** Props for the merge review content component */
50
+ export interface MergeReviewProps {
51
+ /** Merge review data from the server action */
52
+ data: MergeReviewData;
53
+ /** Approve merge callback */
54
+ onApprove: () => void;
55
+ /** Send refinement text to AI */
56
+ onRefine: (text: string) => void;
57
+ /** Controls disabled state during approval */
58
+ isProcessing?: boolean;
59
+ }
60
+
61
+ /** Props for the merge review drawer (shell wrapper) */
62
+ export interface MergeReviewDrawerProps extends MergeReviewProps {
63
+ /** Whether the drawer is open */
64
+ open: boolean;
65
+ /** Callback when drawer should close */
66
+ onClose: () => void;
67
+ /** Feature name shown in drawer header */
68
+ featureName: string;
69
+ /** Feature ID shown below the name */
70
+ featureId?: string;
71
+ /** Absolute path to the repository on disk */
72
+ repositoryPath?: string;
73
+ /** Git branch name — passed to ReviewDrawerShell for actions */
74
+ branch?: string;
75
+ /** Absolute path to the specs folder on disk */
76
+ specPath?: string;
77
+ /** Callback to delete the feature — shows delete button when provided */
78
+ onDelete?: (featureId: string) => void;
79
+ /** Whether a delete operation is in progress */
80
+ isDeleting?: boolean;
81
+ }
@@ -0,0 +1,34 @@
1
+ 'use client';
2
+
3
+ import { ReviewDrawerShell } from '@/components/common/review-drawer-shell';
4
+ import { MergeReview } from './merge-review';
5
+ import type { MergeReviewDrawerProps } from './merge-review-config';
6
+
7
+ export function MergeReviewDrawer({
8
+ open,
9
+ onClose,
10
+ featureName,
11
+ featureId,
12
+ repositoryPath,
13
+ branch,
14
+ specPath,
15
+ onDelete,
16
+ isDeleting,
17
+ ...reviewProps
18
+ }: MergeReviewDrawerProps) {
19
+ return (
20
+ <ReviewDrawerShell
21
+ open={open}
22
+ onClose={onClose}
23
+ featureName={featureName}
24
+ featureId={featureId}
25
+ repositoryPath={repositoryPath}
26
+ branch={branch}
27
+ specPath={specPath}
28
+ onDelete={onDelete}
29
+ isDeleting={isDeleting}
30
+ >
31
+ <MergeReview {...reviewProps} />
32
+ </ReviewDrawerShell>
33
+ );
34
+ }
@@ -0,0 +1,240 @@
1
+ import { useState } from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import { fn } from '@storybook/test';
4
+ import { PrStatus, CiStatus } from '@shepai/core/domain/generated/output';
5
+ import { MergeReview } from './merge-review';
6
+ import { MergeReviewDrawer } from './merge-review-drawer';
7
+ import type { MergeReviewData } from './merge-review-config';
8
+
9
+ const fullPr = {
10
+ url: 'https://github.com/shep-ai/cli/pull/42',
11
+ number: 42,
12
+ status: PrStatus.Open,
13
+ commitHash: 'a1b2c3d4e5f6789',
14
+ ciStatus: CiStatus.Success,
15
+ } as const;
16
+
17
+ const samplePhases = [
18
+ { id: 'phase-1', name: 'Foundation & Config', description: 'Set up types and server action' },
19
+ { id: 'phase-2', name: 'Component Implementation', description: 'Build the merge review UI' },
20
+ { id: 'phase-3', name: 'Integration & Wiring', description: 'Connect to control center' },
21
+ ];
22
+
23
+ const sampleBranch = { source: 'feat/add-auth', target: 'main' };
24
+
25
+ const fullData: MergeReviewData = {
26
+ pr: fullPr,
27
+ branch: sampleBranch,
28
+ phases: samplePhases,
29
+ diffSummary: {
30
+ filesChanged: 12,
31
+ additions: 340,
32
+ deletions: 85,
33
+ commitCount: 5,
34
+ },
35
+ };
36
+
37
+ const defaultActions = {
38
+ onApprove: fn().mockName('onApprove'),
39
+ onRefine: fn().mockName('onRefine'),
40
+ };
41
+
42
+ /* ─── Standalone MergeReview ─── */
43
+
44
+ const meta: Meta<typeof MergeReview> = {
45
+ title: 'Common/MergeReview',
46
+ component: MergeReview,
47
+ tags: ['autodocs'],
48
+ parameters: {
49
+ layout: 'fullscreen',
50
+ },
51
+ decorators: [
52
+ (Story) => (
53
+ <div style={{ height: '600px', width: '400px', border: '1px solid var(--color-border)' }}>
54
+ <Story />
55
+ </div>
56
+ ),
57
+ ],
58
+ };
59
+
60
+ export default meta;
61
+ type Story = StoryObj<typeof MergeReview>;
62
+
63
+ /** Default — all data present with CI success. */
64
+ export const Default: Story = {
65
+ args: {
66
+ data: fullData,
67
+ ...defaultActions,
68
+ },
69
+ };
70
+
71
+ /** CI status is Pending — shows yellow badge with spinner. */
72
+ export const CIPending: Story = {
73
+ args: {
74
+ data: {
75
+ ...fullData,
76
+ pr: { ...fullPr, ciStatus: CiStatus.Pending },
77
+ },
78
+ ...defaultActions,
79
+ },
80
+ };
81
+
82
+ /** CI status is Failure — shows red badge. */
83
+ export const CIFailure: Story = {
84
+ args: {
85
+ data: {
86
+ ...fullData,
87
+ pr: { ...fullPr, ciStatus: CiStatus.Failure },
88
+ },
89
+ ...defaultActions,
90
+ },
91
+ };
92
+
93
+ /** Diff summary unavailable — shows warning message. */
94
+ export const NoDiffSummary: Story = {
95
+ args: {
96
+ data: {
97
+ pr: fullPr,
98
+ branch: sampleBranch,
99
+ warning: 'Diff statistics unavailable — worktree may have been removed',
100
+ },
101
+ ...defaultActions,
102
+ },
103
+ };
104
+
105
+ /** CI status undefined — CI section omitted entirely. */
106
+ export const NoCIStatus: Story = {
107
+ args: {
108
+ data: {
109
+ ...fullData,
110
+ pr: { ...fullPr, ciStatus: undefined },
111
+ },
112
+ ...defaultActions,
113
+ },
114
+ };
115
+
116
+ /** Processing state — approve button disabled with spinner. */
117
+ export const Processing: Story = {
118
+ args: {
119
+ data: fullData,
120
+ ...defaultActions,
121
+ isProcessing: true,
122
+ },
123
+ };
124
+
125
+ /** No PR — merge without a pull request, shows branch direction and diff summary. */
126
+ export const NoPrWithDiff: Story = {
127
+ args: {
128
+ data: {
129
+ branch: { source: 'feat/fix-login', target: 'main' },
130
+ phases: samplePhases,
131
+ diffSummary: fullData.diffSummary,
132
+ },
133
+ ...defaultActions,
134
+ },
135
+ };
136
+
137
+ /** No PR and no diff — bare merge approval with branch info. */
138
+ export const NoPrNoDiff: Story = {
139
+ args: {
140
+ data: {
141
+ branch: { source: 'feat/fix-login', target: 'main' },
142
+ warning: 'No PR or diff data available',
143
+ },
144
+ ...defaultActions,
145
+ },
146
+ };
147
+
148
+ /** With implementation phases shown. */
149
+ export const WithPhases: Story = {
150
+ args: {
151
+ data: {
152
+ ...fullData,
153
+ phases: samplePhases,
154
+ },
155
+ ...defaultActions,
156
+ },
157
+ };
158
+
159
+ /* ─── Drawer Variant ─── */
160
+
161
+ type DrawerStory = StoryObj<typeof MergeReviewDrawer>;
162
+
163
+ const drawerMeta = {
164
+ title: 'Common/MergeReviewDrawer',
165
+ component: MergeReviewDrawer,
166
+ tags: ['autodocs'],
167
+ parameters: {
168
+ layout: 'fullscreen',
169
+ },
170
+ };
171
+
172
+ function DrawerTemplate(
173
+ props: Omit<React.ComponentProps<typeof MergeReviewDrawer>, 'open' | 'onClose'>
174
+ ) {
175
+ const [open, setOpen] = useState(true);
176
+
177
+ return (
178
+ <div style={{ height: '100vh', background: '#f8fafc', padding: '2rem' }}>
179
+ <button
180
+ type="button"
181
+ onClick={() => setOpen(true)}
182
+ style={{ padding: '8px 16px', border: '1px solid #ccc', borderRadius: '6px' }}
183
+ >
184
+ Open Drawer
185
+ </button>
186
+ <MergeReviewDrawer {...props} open={open} onClose={() => setOpen(false)} />
187
+ </div>
188
+ );
189
+ }
190
+
191
+ /** Merge review drawer with full data. */
192
+ export const InDrawer: DrawerStory = {
193
+ ...drawerMeta,
194
+ render: () => (
195
+ <DrawerTemplate
196
+ featureName="Add User Authentication"
197
+ featureId="FEAT-042"
198
+ repositoryPath="/home/user/projects/my-app"
199
+ branch="feat/add-auth"
200
+ data={fullData}
201
+ {...defaultActions}
202
+ />
203
+ ),
204
+ };
205
+
206
+ /** Drawer with delete button visible. */
207
+ export const WithDeleteButton: DrawerStory = {
208
+ ...drawerMeta,
209
+ render: () => (
210
+ <DrawerTemplate
211
+ featureName="Add User Authentication"
212
+ featureId="FEAT-042"
213
+ repositoryPath="/home/user/projects/my-app"
214
+ branch="feat/add-auth"
215
+ data={fullData}
216
+ {...defaultActions}
217
+ onDelete={fn().mockName('onDelete')}
218
+ />
219
+ ),
220
+ };
221
+
222
+ /** Drawer without PR — direct merge with diff summary and branch info. */
223
+ export const InDrawerNoPr: DrawerStory = {
224
+ ...drawerMeta,
225
+ render: () => (
226
+ <DrawerTemplate
227
+ featureName="Fix Login Bug"
228
+ featureId="FEAT-099"
229
+ repositoryPath="/home/user/projects/my-app"
230
+ branch="feat/fix-login"
231
+ data={{
232
+ branch: { source: 'feat/fix-login', target: 'main' },
233
+ phases: samplePhases,
234
+ diffSummary: fullData.diffSummary,
235
+ }}
236
+ {...defaultActions}
237
+ onDelete={fn().mockName('onDelete')}
238
+ />
239
+ ),
240
+ };