@shepai/cli 1.43.0 → 1.44.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 (179) hide show
  1. package/dist/packages/core/src/application/ports/output/repositories/index.d.ts +1 -0
  2. package/dist/packages/core/src/application/ports/output/repositories/index.d.ts.map +1 -1
  3. package/dist/packages/core/src/application/ports/output/repositories/repository-repository.interface.d.ts +19 -0
  4. package/dist/packages/core/src/application/ports/output/repositories/repository-repository.interface.d.ts.map +1 -0
  5. package/dist/packages/core/src/application/ports/output/repositories/repository-repository.interface.js +6 -0
  6. package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts +3 -1
  7. package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts.map +1 -1
  8. package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.js +20 -2
  9. package/dist/packages/core/src/application/use-cases/repositories/add-repository.use-case.d.ts +18 -0
  10. package/dist/packages/core/src/application/use-cases/repositories/add-repository.use-case.d.ts.map +1 -0
  11. package/dist/packages/core/src/application/use-cases/repositories/add-repository.use-case.js +64 -0
  12. package/dist/packages/core/src/application/use-cases/repositories/delete-repository.use-case.d.ts +13 -0
  13. package/dist/packages/core/src/application/use-cases/repositories/delete-repository.use-case.d.ts.map +1 -0
  14. package/dist/packages/core/src/application/use-cases/repositories/delete-repository.use-case.js +38 -0
  15. package/dist/packages/core/src/application/use-cases/repositories/list-repositories.use-case.d.ts +13 -0
  16. package/dist/packages/core/src/application/use-cases/repositories/list-repositories.use-case.d.ts.map +1 -0
  17. package/dist/packages/core/src/application/use-cases/repositories/list-repositories.use-case.js +33 -0
  18. package/dist/packages/core/src/domain/generated/output.d.ts +17 -0
  19. package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
  20. package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
  21. package/dist/packages/core/src/infrastructure/di/container.js +22 -0
  22. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.d.ts +1 -0
  23. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.d.ts.map +1 -1
  24. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.js +4 -0
  25. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/repository.mapper.d.ts +30 -0
  26. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/repository.mapper.d.ts.map +1 -0
  27. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/repository.mapper.js +39 -0
  28. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations.d.ts.map +1 -1
  29. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations.js +60 -1
  30. package/dist/packages/core/src/infrastructure/repositories/sqlite-repository.repository.d.ts +21 -0
  31. package/dist/packages/core/src/infrastructure/repositories/sqlite-repository.repository.d.ts.map +1 -0
  32. package/dist/packages/core/src/infrastructure/repositories/sqlite-repository.repository.js +69 -0
  33. package/dist/src/presentation/web/app/actions/add-repository.d.ts +11 -0
  34. package/dist/src/presentation/web/app/actions/add-repository.d.ts.map +1 -0
  35. package/dist/src/presentation/web/app/actions/add-repository.js +17 -0
  36. package/dist/src/presentation/web/app/actions/delete-repository.d.ts +5 -0
  37. package/dist/src/presentation/web/app/actions/delete-repository.d.ts.map +1 -0
  38. package/dist/src/presentation/web/app/actions/delete-repository.js +16 -0
  39. package/dist/src/presentation/web/app/page.d.ts.map +1 -1
  40. package/dist/src/presentation/web/app/page.js +29 -8
  41. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-config.d.ts +2 -0
  42. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-config.d.ts.map +1 -1
  43. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-drawer.d.ts +1 -1
  44. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-drawer.d.ts.map +1 -1
  45. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-drawer.js +2 -2
  46. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.d.ts.map +1 -1
  47. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.js +1 -1
  48. package/dist/src/presentation/web/components/common/repository-node/repository-node-config.d.ts +3 -0
  49. package/dist/src/presentation/web/components/common/repository-node/repository-node-config.d.ts.map +1 -1
  50. package/dist/src/presentation/web/components/common/repository-node/repository-node.d.ts.map +1 -1
  51. package/dist/src/presentation/web/components/common/repository-node/repository-node.js +8 -2
  52. package/dist/src/presentation/web/components/common/repository-node/repository-node.stories.d.ts +1 -0
  53. package/dist/src/presentation/web/components/common/repository-node/repository-node.stories.d.ts.map +1 -1
  54. package/dist/src/presentation/web/components/common/repository-node/repository-node.stories.js +28 -3
  55. package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell-config.d.ts +2 -0
  56. package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell-config.d.ts.map +1 -1
  57. package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.d.ts +1 -1
  58. package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.d.ts.map +1 -1
  59. package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.js +2 -2
  60. package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.stories.d.ts.map +1 -1
  61. package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.stories.js +1 -1
  62. package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
  63. package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +2 -2
  64. package/dist/src/presentation/web/components/features/control-center/control-center.stories.d.ts.map +1 -1
  65. package/dist/src/presentation/web/components/features/control-center/control-center.stories.js +2 -1
  66. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts +1 -0
  67. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
  68. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +81 -19
  69. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts +2 -1
  70. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts.map +1 -1
  71. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.js +11 -2
  72. package/dist/src/presentation/web/lib/layout-with-dagre.js +1 -1
  73. package/dist/tsconfig.build.tsbuildinfo +1 -1
  74. package/package.json +1 -1
  75. package/web/.next/BUILD_ID +1 -1
  76. package/web/.next/build-manifest.json +2 -2
  77. package/web/.next/cache/.previewinfo +1 -1
  78. package/web/.next/cache/.rscinfo +1 -1
  79. package/web/.next/cache/.tsbuildinfo +1 -1
  80. package/web/.next/cache/config.json +3 -3
  81. package/web/.next/fallback-build-manifest.json +2 -2
  82. package/web/.next/prerender-manifest.json +3 -3
  83. package/web/.next/required-server-files.js +1 -1
  84. package/web/.next/required-server-files.json +1 -1
  85. package/web/.next/server/app/_global-error.html +2 -2
  86. package/web/.next/server/app/_global-error.rsc +1 -1
  87. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  88. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  89. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  90. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  91. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  92. package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  93. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  94. package/web/.next/server/app/page/server-reference-manifest.json +48 -18
  95. package/web/.next/server/app/page.js +1 -1
  96. package/web/.next/server/app/page.js.nft.json +1 -1
  97. package/web/.next/server/app/page_client-reference-manifest.js +1 -1
  98. package/web/.next/server/app/version/page.js.nft.json +1 -1
  99. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  100. package/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js +4 -4
  101. package/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js.map +1 -1
  102. package/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
  103. package/web/.next/server/chunks/ssr/{[root-of-the-server]__77c0dfc4._.js → [root-of-the-server]__4e8ca89c._.js} +3 -3
  104. package/web/.next/server/chunks/ssr/[root-of-the-server]__4e8ca89c._.js.map +1 -0
  105. package/web/.next/server/chunks/ssr/_3ac3601c._.js +10 -0
  106. package/web/.next/server/chunks/ssr/_3ac3601c._.js.map +1 -0
  107. package/web/.next/server/chunks/ssr/_a35f2870._.js +3 -0
  108. package/web/.next/server/chunks/ssr/_a35f2870._.js.map +1 -0
  109. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
  110. package/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.js +1 -1
  111. package/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.js.map +1 -1
  112. package/web/.next/server/pages/500.html +2 -2
  113. package/web/.next/server/server-reference-manifest.js +1 -1
  114. package/web/.next/server/server-reference-manifest.json +49 -19
  115. package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
  116. package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +2 -2
  117. package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
  118. package/web/.next/standalone/src/presentation/web/.next/required-server-files.json +1 -1
  119. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
  120. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
  121. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  122. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  123. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  124. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  125. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  126. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  127. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  128. package/web/.next/standalone/src/presentation/web/.next/server/app/page/server-reference-manifest.json +48 -18
  129. package/web/.next/standalone/src/presentation/web/.next/server/app/page.js +1 -1
  130. package/web/.next/standalone/src/presentation/web/.next/server/app/page.js.nft.json +1 -1
  131. package/web/.next/standalone/src/presentation/web/.next/server/app/page_client-reference-manifest.js +1 -1
  132. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page.js.nft.json +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]__77c0dfc4._.js → [root-of-the-server]__4e8ca89c._.js} +3 -3
  137. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_3ac3601c._.js +10 -0
  138. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_a35f2870._.js +3 -0
  139. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.js +1 -1
  140. package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
  141. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
  142. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +49 -19
  143. package/web/.next/standalone/src/presentation/web/app/actions/add-repository.ts +29 -0
  144. package/web/.next/standalone/src/presentation/web/app/actions/delete-repository.ts +21 -0
  145. package/web/.next/standalone/src/presentation/web/app/page.tsx +34 -8
  146. package/web/.next/standalone/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-config.ts +2 -0
  147. package/web/.next/standalone/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-drawer.tsx +2 -0
  148. package/web/.next/standalone/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.tsx +1 -0
  149. package/web/.next/standalone/src/presentation/web/components/common/repository-node/repository-node-config.ts +3 -0
  150. package/web/.next/standalone/src/presentation/web/components/common/repository-node/repository-node.stories.tsx +30 -3
  151. package/web/.next/standalone/src/presentation/web/components/common/repository-node/repository-node.tsx +57 -1
  152. package/web/.next/standalone/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell-config.ts +2 -0
  153. package/web/.next/standalone/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.stories.tsx +1 -0
  154. package/web/.next/standalone/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.tsx +4 -1
  155. package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center-inner.tsx +3 -0
  156. package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center.stories.tsx +6 -3
  157. package/web/.next/standalone/src/presentation/web/components/features/control-center/use-control-center-state.ts +122 -34
  158. package/web/.next/standalone/src/presentation/web/components/features/features-canvas/features-canvas.tsx +12 -1
  159. package/web/.next/standalone/src/presentation/web/lib/layout-with-dagre.ts +1 -1
  160. package/web/.next/standalone/src/presentation/web/server.js +1 -1
  161. package/web/.next/static/chunks/{8c0b96eb95dd31a9.js → 00f6ac2dde225eb7.js} +1 -1
  162. package/web/.next/static/chunks/631933b137e91fb2.js +10 -0
  163. package/web/.next/static/chunks/9f8e71029fb04681.js +5 -0
  164. package/web/.next/static/chunks/b7b7abe79e05b229.css +2 -0
  165. package/web/.next/trace +1 -1
  166. package/web/.next/trace-build +1 -1
  167. package/web/.next/server/chunks/ssr/[root-of-the-server]__77c0dfc4._.js.map +0 -1
  168. package/web/.next/server/chunks/ssr/_285de9aa._.js +0 -3
  169. package/web/.next/server/chunks/ssr/_285de9aa._.js.map +0 -1
  170. package/web/.next/server/chunks/ssr/_b1f2507a._.js +0 -10
  171. package/web/.next/server/chunks/ssr/_b1f2507a._.js.map +0 -1
  172. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_285de9aa._.js +0 -3
  173. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_b1f2507a._.js +0 -10
  174. package/web/.next/static/chunks/36bb03a0314fb990.css +0 -2
  175. package/web/.next/static/chunks/ac2bd2a7ffc02cd4.js +0 -10
  176. package/web/.next/static/chunks/fe6427c156bda6b0.js +0 -5
  177. /package/web/.next/static/{qVAyP83VDRO7ohQMjLw8T → aWm2zr_Js7tN6yFqI9qT-}/_buildManifest.js +0 -0
  178. /package/web/.next/static/{qVAyP83VDRO7ohQMjLw8T → aWm2zr_Js7tN6yFqI9qT-}/_clientMiddlewareManifest.json +0 -0
  179. /package/web/.next/static/{qVAyP83VDRO7ohQMjLw8T → aWm2zr_Js7tN6yFqI9qT-}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/persistence/sqlite/migrations.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAgP3C;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAA4C,CAAC;AAE/E;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB9E"}
1
+ {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/persistence/sqlite/migrations.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AA2S3C;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAA4C,CAAC;AAE/E;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB9E"}
@@ -224,7 +224,66 @@ ALTER TABLE phase_timings ADD COLUMN approval_wait_ms INTEGER;
224
224
  {
225
225
  version: 15,
226
226
  sql: `
227
- -- Migration 015: Add onboarding and approval gate default columns
227
+ -- Migration 015: Create Repositories Table and backfill from features
228
+
229
+ -- 1. Create repositories table
230
+ CREATE TABLE repositories (
231
+ id TEXT PRIMARY KEY,
232
+ name TEXT NOT NULL,
233
+ path TEXT NOT NULL UNIQUE,
234
+ created_at INTEGER NOT NULL,
235
+ updated_at INTEGER NOT NULL
236
+ );
237
+
238
+ CREATE INDEX idx_repositories_path ON repositories(path);
239
+
240
+ -- 2. Extract unique repository_path values from features into repositories
241
+ INSERT INTO repositories (id, name, path, created_at, updated_at)
242
+ SELECT
243
+ lower(hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-4' || substr(hex(randomblob(2)),2) || '-' || substr('89ab', abs(random()) % 4 + 1, 1) || substr(hex(randomblob(2)),2) || '-' || hex(randomblob(6))) AS id,
244
+ CASE
245
+ WHEN instr(repository_path, '/') > 0
246
+ THEN replace(repository_path, rtrim(repository_path, replace(repository_path, '/', '')), '')
247
+ ELSE repository_path
248
+ END AS name,
249
+ repository_path AS path,
250
+ MIN(created_at) AS created_at,
251
+ MAX(updated_at) AS updated_at
252
+ FROM features
253
+ WHERE repository_path IS NOT NULL AND repository_path != ''
254
+ GROUP BY repository_path;
255
+
256
+ -- 3. Add repository_id column to features
257
+ ALTER TABLE features ADD COLUMN repository_id TEXT;
258
+
259
+ -- 4. Backfill repository_id on all existing features
260
+ UPDATE features SET repository_id = (
261
+ SELECT r.id FROM repositories r WHERE r.path = features.repository_path
262
+ );
263
+ `,
264
+ },
265
+ {
266
+ version: 16,
267
+ sql: `
268
+ -- Migration 016: Add soft delete support to repositories
269
+ ALTER TABLE repositories ADD COLUMN deleted_at INTEGER;
270
+ `,
271
+ },
272
+ {
273
+ version: 17,
274
+ sql: `
275
+ -- Migration 017: Fix repository names backfilled incorrectly in migration 015
276
+ -- The original substr formula extracted from the wrong position.
277
+ -- Correct approach: strip the last path segment using rtrim trick.
278
+ UPDATE repositories
279
+ SET name = replace(path, rtrim(path, replace(path, '/', '')), '')
280
+ WHERE instr(path, '/') > 0;
281
+ `,
282
+ },
283
+ {
284
+ version: 18,
285
+ sql: `
286
+ -- Migration 018: Add onboarding and approval gate default columns
228
287
  ALTER TABLE settings ADD COLUMN onboarding_complete INTEGER NOT NULL DEFAULT 0;
229
288
  ALTER TABLE settings ADD COLUMN approval_gate_allow_prd INTEGER NOT NULL DEFAULT 0;
230
289
  ALTER TABLE settings ADD COLUMN approval_gate_allow_plan INTEGER NOT NULL DEFAULT 0;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * SQLite Repository Repository Implementation
3
+ *
4
+ * Implements IRepositoryRepository using better-sqlite3.
5
+ */
6
+ import type Database from 'better-sqlite3';
7
+ import type { IRepositoryRepository } from '../../application/ports/output/repositories/repository-repository.interface.js';
8
+ import type { Repository } from '../../domain/generated/output.js';
9
+ export declare class SQLiteRepositoryRepository implements IRepositoryRepository {
10
+ private readonly db;
11
+ constructor(db: Database.Database);
12
+ create(repository: Repository): Promise<void>;
13
+ findById(id: string): Promise<Repository | null>;
14
+ findByPath(path: string): Promise<Repository | null>;
15
+ list(): Promise<Repository[]>;
16
+ remove(id: string): Promise<void>;
17
+ findByPathIncludingDeleted(path: string): Promise<Repository | null>;
18
+ softDelete(id: string): Promise<void>;
19
+ restore(id: string): Promise<void>;
20
+ }
21
+ //# sourceMappingURL=sqlite-repository.repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-repository.repository.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/src/infrastructure/repositories/sqlite-repository.repository.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gFAAgF,CAAC;AAC5H,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAOnE,qBACa,0BAA2B,YAAW,qBAAqB;IAC1D,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAE5C,MAAM,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAS7C,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAMhD,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAQpD,IAAI,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAQ7B,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjC,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAMpE,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQrC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAOzC"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * SQLite Repository Repository Implementation
3
+ *
4
+ * Implements IRepositoryRepository using better-sqlite3.
5
+ */
6
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
7
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
8
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
9
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
10
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
11
+ };
12
+ var __metadata = (this && this.__metadata) || function (k, v) {
13
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
14
+ };
15
+ import { injectable } from 'tsyringe';
16
+ import { toDatabase, fromDatabase, } from '../persistence/sqlite/mappers/repository.mapper.js';
17
+ let SQLiteRepositoryRepository = class SQLiteRepositoryRepository {
18
+ db;
19
+ constructor(db) {
20
+ this.db = db;
21
+ }
22
+ async create(repository) {
23
+ const row = toDatabase(repository);
24
+ const stmt = this.db.prepare(`
25
+ INSERT OR IGNORE INTO repositories (id, name, path, created_at, updated_at)
26
+ VALUES (@id, @name, @path, @created_at, @updated_at)
27
+ `);
28
+ stmt.run(row);
29
+ }
30
+ async findById(id) {
31
+ const stmt = this.db.prepare('SELECT * FROM repositories WHERE id = ? AND deleted_at IS NULL');
32
+ const row = stmt.get(id);
33
+ return row ? fromDatabase(row) : null;
34
+ }
35
+ async findByPath(path) {
36
+ const stmt = this.db.prepare('SELECT * FROM repositories WHERE path = ? AND deleted_at IS NULL');
37
+ const row = stmt.get(path);
38
+ return row ? fromDatabase(row) : null;
39
+ }
40
+ async list() {
41
+ const stmt = this.db.prepare('SELECT * FROM repositories WHERE deleted_at IS NULL ORDER BY name');
42
+ const rows = stmt.all();
43
+ return rows.map(fromDatabase);
44
+ }
45
+ async remove(id) {
46
+ const stmt = this.db.prepare('DELETE FROM repositories WHERE id = ?');
47
+ stmt.run(id);
48
+ }
49
+ async findByPathIncludingDeleted(path) {
50
+ const stmt = this.db.prepare('SELECT * FROM repositories WHERE path = ?');
51
+ const row = stmt.get(path);
52
+ return row ? fromDatabase(row) : null;
53
+ }
54
+ async softDelete(id) {
55
+ const now = Date.now();
56
+ const stmt = this.db.prepare('UPDATE repositories SET deleted_at = ?, updated_at = ? WHERE id = ?');
57
+ stmt.run(now, now, id);
58
+ }
59
+ async restore(id) {
60
+ const now = Date.now();
61
+ const stmt = this.db.prepare('UPDATE repositories SET deleted_at = NULL, updated_at = ? WHERE id = ?');
62
+ stmt.run(now, id);
63
+ }
64
+ };
65
+ SQLiteRepositoryRepository = __decorate([
66
+ injectable(),
67
+ __metadata("design:paramtypes", [Object])
68
+ ], SQLiteRepositoryRepository);
69
+ export { SQLiteRepositoryRepository };
@@ -0,0 +1,11 @@
1
+ import type { Repository } from '../../../../../packages/core/src/domain/generated/output.js';
2
+ interface AddRepositoryInput {
3
+ path: string;
4
+ name?: string;
5
+ }
6
+ export declare function addRepository(input: AddRepositoryInput): Promise<{
7
+ repository?: Repository;
8
+ error?: string;
9
+ }>;
10
+ export {};
11
+ //# sourceMappingURL=add-repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-repository.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/add-repository.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sCAAsC,CAAC;AAEvE,UAAU,kBAAkB;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC;IAAE,UAAU,CAAC,EAAE,UAAU,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAetD"}
@@ -0,0 +1,17 @@
1
+ 'use server';
2
+ import { resolve } from '../../lib/server-container.js';
3
+ export async function addRepository(input) {
4
+ const { path, name } = input;
5
+ if (!path?.trim()) {
6
+ return { error: 'path is required' };
7
+ }
8
+ try {
9
+ const addRepoUseCase = resolve('AddRepositoryUseCase');
10
+ const repository = await addRepoUseCase.execute({ path, name });
11
+ return { repository };
12
+ }
13
+ catch (error) {
14
+ const message = error instanceof Error ? error.message : 'Failed to add repository';
15
+ return { error: message };
16
+ }
17
+ }
@@ -0,0 +1,5 @@
1
+ export declare function deleteRepository(repositoryId: string): Promise<{
2
+ success: boolean;
3
+ error?: string;
4
+ }>;
5
+ //# sourceMappingURL=delete-repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete-repository.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/delete-repository.ts"],"names":[],"mappings":"AAKA,wBAAsB,gBAAgB,CACpC,YAAY,EAAE,MAAM,GACnB,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 deleteRepository(repositoryId) {
4
+ if (!repositoryId?.trim()) {
5
+ return { success: false, error: 'id is required' };
6
+ }
7
+ try {
8
+ const useCase = resolve('DeleteRepositoryUseCase');
9
+ await useCase.execute(repositoryId);
10
+ return { success: true };
11
+ }
12
+ catch (error) {
13
+ const message = error instanceof Error ? error.message : 'Failed to delete repository';
14
+ return { success: false, error: message };
15
+ }
16
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/app/page.tsx"],"names":[],"mappings":"AAaA,uFAAuF;AACvF,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAqBvC,wBAA8B,QAAQ,qDAsFrC"}
1
+ {"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/app/page.tsx"],"names":[],"mappings":"AAcA,uFAAuF;AACvF,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAqBvC,wBAA8B,QAAQ,qDA+GrC"}
@@ -24,13 +24,14 @@ const nodeToLifecyclePhase = {
24
24
  };
25
25
  export default async function HomePage() {
26
26
  const listFeatures = resolve('ListFeaturesUseCase');
27
+ const listRepos = resolve('ListRepositoriesUseCase');
27
28
  const agentRunRepo = resolve('IAgentRunRepository');
28
- const features = await listFeatures.execute();
29
+ const [features, repositories] = await Promise.all([listFeatures.execute(), listRepos.execute()]);
29
30
  const featuresWithRuns = await Promise.all(features.map(async (feature) => {
30
31
  const run = feature.agentRunId ? await agentRunRepo.findById(feature.agentRunId) : null;
31
32
  return { feature, run };
32
33
  }));
33
- // Group features by repository path
34
+ // Group features by repository path (features may still reference paths not yet in repositories table)
34
35
  const featuresByRepo = {};
35
36
  featuresWithRuns.forEach((entry) => {
36
37
  const repoKey = entry.feature.repositoryPath;
@@ -41,15 +42,16 @@ export default async function HomePage() {
41
42
  });
42
43
  const nodes = [];
43
44
  const edges = [];
44
- Object.entries(featuresByRepo).forEach(([repoPath, repoFeatures]) => {
45
- const repoNodeId = `repo-${repoPath}`;
46
- const repoName = repoPath.split('/').pop() ?? repoPath;
45
+ // First, add nodes for all persisted repositories (including those without features)
46
+ for (const repo of repositories) {
47
+ const repoNodeId = `repo-${repo.id}`;
47
48
  nodes.push({
48
49
  id: repoNodeId,
49
50
  type: 'repositoryNode',
50
51
  position: { x: 0, y: 0 },
51
- data: { name: repoName, repositoryPath: repoPath },
52
+ data: { name: repo.name, repositoryPath: repo.path, id: repo.id },
52
53
  });
54
+ const repoFeatures = featuresByRepo[repo.path] ?? [];
53
55
  repoFeatures.forEach(({ feature, run }) => {
54
56
  const agentNode = run?.result?.startsWith('node:') ? run.result.slice(5) : undefined;
55
57
  const lifecycle = run?.status === 'completed'
@@ -84,12 +86,31 @@ export default async function HomePage() {
84
86
  style: { strokeDasharray: '5 5' },
85
87
  });
86
88
  });
87
- });
89
+ }
88
90
  // Use dagre LR layout for compact, automatic positioning
89
91
  const laid = layoutWithDagre(nodes, edges, {
90
92
  direction: 'LR',
91
93
  ranksep: 200,
92
- nodesep: 60,
94
+ nodesep: 15,
95
+ });
96
+ // Position "+ Add Repository" vertically centered with the bottom-most feature node,
97
+ // mirroring how Dagre centers repo nodes with their connected features.
98
+ const repoNodes = laid.nodes.filter((n) => n.type === 'repositoryNode');
99
+ const featureNodes = laid.nodes.filter((n) => n.type === 'featureNode');
100
+ const sortedFeatures = [...featureNodes].sort((a, b) => a.position.y - b.position.y);
101
+ // Pick the feature node just below center (one past the midpoint index)
102
+ const centerIdx = Math.floor(sortedFeatures.length / 2);
103
+ const targetFeature = sortedFeatures[centerIdx + 1] ?? sortedFeatures[sortedFeatures.length - 1];
104
+ const repoX = repoNodes[0]?.position.x ?? 0;
105
+ // Center the add-repo node (h=50) with the target feature node (h=140)
106
+ const addRepoPosition = targetFeature
107
+ ? { x: repoX, y: targetFeature.position.y + 70 - 25 }
108
+ : { x: repoX, y: (repoNodes[0]?.position.y ?? 0) + 150 };
109
+ laid.nodes.push({
110
+ id: 'add-repository',
111
+ type: 'addRepositoryNode',
112
+ position: addRepoPosition,
113
+ data: {},
93
114
  });
94
115
  return (_jsx("div", { className: "h-screen w-full", children: _jsx(ControlCenter, { initialNodes: laid.nodes, initialEdges: laid.edges }) }));
95
116
  }
@@ -23,6 +23,8 @@ export interface PrdQuestionnaireDrawerProps extends PrdQuestionnaireProps {
23
23
  onClose: () => void;
24
24
  /** Feature name shown in drawer header */
25
25
  featureName: string;
26
+ /** Short description shown below the feature name */
27
+ featureDescription?: string;
26
28
  /** Feature ID shown below the name */
27
29
  featureId?: string;
28
30
  /** Current lifecycle stage label */
@@ -1 +1 @@
1
- {"version":3,"file":"prd-questionnaire-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,WAAW,EACX,cAAc,EACd,oBAAoB,EACrB,MAAM,sCAAsC,CAAC;AAE9C,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,cAAc,EAAE,oBAAoB,EAAE,CAAC;AAE7E,MAAM,WAAW,qBAAqB;IACpC,2EAA2E;IAC3E,IAAI,EAAE,oBAAoB,CAAC;IAC3B,gEAAgE;IAChE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,gCAAgC;IAChC,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,sCAAsC;IACtC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,qCAAqC;IACrC,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,yDAAyD;IACzD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oDAAoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,2BAA4B,SAAQ,qBAAqB;IACxE,iCAAiC;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,wCAAwC;IACxC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,gDAAgD;IAChD,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB"}
1
+ {"version":3,"file":"prd-questionnaire-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,WAAW,EACX,cAAc,EACd,oBAAoB,EACrB,MAAM,sCAAsC,CAAC;AAE9C,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,cAAc,EAAE,oBAAoB,EAAE,CAAC;AAE7E,MAAM,WAAW,qBAAqB;IACpC,2EAA2E;IAC3E,IAAI,EAAE,oBAAoB,CAAC;IAC3B,gEAAgE;IAChE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,gCAAgC;IAChC,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,sCAAsC;IACtC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,qCAAqC;IACrC,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,yDAAyD;IACzD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oDAAoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,2BAA4B,SAAQ,qBAAqB;IACxE,iCAAiC;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,wCAAwC;IACxC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,gDAAgD;IAChD,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB"}
@@ -1,3 +1,3 @@
1
1
  import type { PrdQuestionnaireDrawerProps } from './prd-questionnaire-config.js';
2
- export declare function PrdQuestionnaireDrawer({ open, onClose, featureName, featureId, repositoryPath, branch, specPath, onDelete, isDeleting, ...questionnaireProps }: PrdQuestionnaireDrawerProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function PrdQuestionnaireDrawer({ open, onClose, featureName, featureDescription, featureId, repositoryPath, branch, specPath, onDelete, isDeleting, ...questionnaireProps }: PrdQuestionnaireDrawerProps): import("react/jsx-runtime").JSX.Element;
3
3
  //# sourceMappingURL=prd-questionnaire-drawer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prd-questionnaire-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-drawer.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAE9E,wBAAgB,sBAAsB,CAAC,EACrC,IAAI,EACJ,OAAO,EACP,WAAW,EACX,SAAS,EACT,cAAc,EACd,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,GAAG,kBAAkB,EACtB,EAAE,2BAA2B,2CAgB7B"}
1
+ {"version":3,"file":"prd-questionnaire-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-drawer.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAE9E,wBAAgB,sBAAsB,CAAC,EACrC,IAAI,EACJ,OAAO,EACP,WAAW,EACX,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,GAAG,kBAAkB,EACtB,EAAE,2BAA2B,2CAiB7B"}
@@ -2,6 +2,6 @@
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { ReviewDrawerShell } from '../../common/review-drawer-shell/index.js';
4
4
  import { PrdQuestionnaire } from './prd-questionnaire.js';
5
- export function PrdQuestionnaireDrawer({ open, onClose, featureName, featureId, repositoryPath, branch, specPath, onDelete, isDeleting, ...questionnaireProps }) {
6
- return (_jsx(ReviewDrawerShell, { open: open, onClose: onClose, featureName: featureName, featureId: featureId, repositoryPath: repositoryPath, branch: branch, specPath: specPath, onDelete: onDelete, isDeleting: isDeleting, children: _jsx(PrdQuestionnaire, { ...questionnaireProps }) }));
5
+ export function PrdQuestionnaireDrawer({ open, onClose, featureName, featureDescription, featureId, repositoryPath, branch, specPath, onDelete, isDeleting, ...questionnaireProps }) {
6
+ return (_jsx(ReviewDrawerShell, { open: open, onClose: onClose, featureName: featureName, featureDescription: featureDescription, featureId: featureId, repositoryPath: repositoryPath, branch: branch, specPath: specPath, onDelete: onDelete, isDeleting: isDeleting, children: _jsx(PrdQuestionnaire, { ...questionnaireProps }) }));
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"prd-questionnaire.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAmKpE,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,gBAAgB,CAmBvC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAU/C,sFAAsF;AACtF,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,cAAc,EAAE,KAW5B,CAAC;AAEF,uEAAuE;AACvE,eAAO,MAAM,WAAW,EAAE,KAczB,CAAC;AAEF,0EAA0E;AAC1E,eAAO,MAAM,QAAQ,EAAE,KAStB,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,WAAW,EAAE,KA8BzB,CAAC;AAIF,KAAK,WAAW,GAAG,QAAQ,CAAC,OAAO,sBAAsB,CAAC,CAAC;AA2C3D,8DAA8D;AAC9D,eAAO,MAAM,QAAQ,EAAE,WAUtB,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,sBAAsB,EAAE,WAepC,CAAC;AAEF,yCAAyC;AACzC,eAAO,MAAM,gBAAgB,EAAE,WAW9B,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,aAAa,EAAE,WAY3B,CAAC"}
1
+ {"version":3,"file":"prd-questionnaire.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAmKpE,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,gBAAgB,CAmBvC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAU/C,sFAAsF;AACtF,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,cAAc,EAAE,KAW5B,CAAC;AAEF,uEAAuE;AACvE,eAAO,MAAM,WAAW,EAAE,KAczB,CAAC;AAEF,0EAA0E;AAC1E,eAAO,MAAM,QAAQ,EAAE,KAStB,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,WAAW,EAAE,KA8BzB,CAAC;AAIF,KAAK,WAAW,GAAG,QAAQ,CAAC,OAAO,sBAAsB,CAAC,CAAC;AA2C3D,8DAA8D;AAC9D,eAAO,MAAM,QAAQ,EAAE,WAWtB,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,sBAAsB,EAAE,WAepC,CAAC;AAEF,yCAAyC;AACzC,eAAO,MAAM,gBAAgB,EAAE,WAW9B,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,aAAa,EAAE,WAY3B,CAAC"}
@@ -244,7 +244,7 @@ function DrawerTemplate({ selections: initialSelections = {}, ...props }) {
244
244
  /** Drawer with stepper — navigate questions one at a time. */
245
245
  export const InDrawer = {
246
246
  ...drawerMeta,
247
- render: () => (_jsx(DrawerTemplate, { featureName: "User Authentication Flow", featureId: "FEAT-042", lifecycleLabel: "Requirements", data: mockData })),
247
+ render: () => (_jsx(DrawerTemplate, { featureName: "User Authentication Flow", featureDescription: "Implement OAuth2 login with social providers and MFA support", featureId: "FEAT-042", lifecycleLabel: "Requirements", data: mockData })),
248
248
  };
249
249
  /** Drawer with partial selections showing progress dots. */
250
250
  export const InDrawerWithSelections = {
@@ -1,12 +1,15 @@
1
1
  import type { Node } from '@xyflow/react';
2
2
  export interface RepositoryNodeData {
3
3
  [key: string]: unknown;
4
+ /** Repository domain entity ID (UUID), used for delete operations */
5
+ id?: string;
4
6
  /** Repository name, e.g. "shep-ai/cli" */
5
7
  name: string;
6
8
  /** Absolute path to the repository root, used for IDE/shell actions */
7
9
  repositoryPath?: string;
8
10
  onClick?: () => void;
9
11
  onAdd?: () => void;
12
+ onDelete?: (repositoryId: string) => void;
10
13
  showHandles?: boolean;
11
14
  }
12
15
  export type RepositoryNodeType = Node<RepositoryNodeData, 'repositoryNode'>;
@@ -1 +1 @@
1
- {"version":3,"file":"repository-node-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAE1C,MAAM,WAAW,kBAAkB;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC"}
1
+ {"version":3,"file":"repository-node-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAE1C,MAAM,WAAW,kBAAkB;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,qEAAqE;IACrE,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"repository-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAGnE,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,2CA6I5F"}
1
+ {"version":3,"file":"repository-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAGnE,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,2CA0L5F"}
@@ -1,14 +1,20 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useState } from 'react';
3
4
  import { Handle, Position } from '@xyflow/react';
4
- import { Github, Plus, Code2, Terminal, FolderOpen } from 'lucide-react';
5
+ import { Github, Plus, Code2, Terminal, FolderOpen, Trash2 } from 'lucide-react';
5
6
  import { cn } from '../../../lib/utils.js';
6
7
  import { ActionButton } from '../../common/action-button/index.js';
8
+ import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '../../ui/alert-dialog.js';
7
9
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../ui/tooltip.js';
8
10
  import { useRepositoryActions } from './use-repository-actions.js';
9
11
  export function RepositoryNode({ data }) {
12
+ const [confirmOpen, setConfirmOpen] = useState(false);
10
13
  const actions = useRepositoryActions(data.repositoryPath ? { repositoryPath: data.repositoryPath } : null);
11
- return (_jsxs("div", { className: "group relative", children: [data.showHandles ? (_jsx(Handle, { type: "target", position: Position.Left, isConnectable: false, className: "opacity-0!" })) : null, _jsxs("div", { role: "button", tabIndex: 0, "data-testid": "repository-node-card", onClick: (e) => {
14
+ return (_jsxs("div", { className: "group relative", children: [data.showHandles ? (_jsx(Handle, { type: "target", position: Position.Left, isConnectable: false, className: "opacity-0!" })) : null, data.onDelete && data.id ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "absolute top-1/2 -left-10 -translate-y-1/2 opacity-0 transition-opacity group-hover:opacity-100", children: _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { "aria-label": "Remove repository", "data-testid": "repository-node-delete-button", onClick: (e) => {
15
+ e.stopPropagation();
16
+ setConfirmOpen(true);
17
+ }, className: "bg-card text-muted-foreground hover:border-destructive hover:text-destructive flex h-7 w-7 cursor-pointer items-center justify-center rounded-full border shadow-sm transition-colors", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "Remove repository" })] }) }) }), _jsx(AlertDialog, { open: confirmOpen, onOpenChange: setConfirmOpen, children: _jsxs(AlertDialogContent, { size: "sm", children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Remove repository?" }), _jsxs(AlertDialogDescription, { children: ["This will remove ", _jsx("strong", { children: data.name }), " from your workspace. The repository files on disk won't be affected."] })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: "Cancel" }), _jsx(AlertDialogAction, { variant: "destructive", onClick: () => data.onDelete?.(data.id), children: "Remove" })] })] }) })] })) : null, _jsxs("div", { role: "button", tabIndex: 0, "data-testid": "repository-node-card", onClick: (e) => {
12
18
  e.stopPropagation();
13
19
  data.onClick?.();
14
20
  }, onKeyDown: (e) => {
@@ -11,5 +11,6 @@ export declare const Multiple: Story;
11
11
  export declare const MultipleWithButton: Story;
12
12
  export declare const WithActions: Story;
13
13
  export declare const WithActionsAndAddButton: Story;
14
+ export declare const WithDeleteButton: Story;
14
15
  export declare const MultipleWithActions: Story;
15
16
  //# sourceMappingURL=repository-node.stories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"repository-node.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,KAAK,EAAE,kBAAkB,EAAsB,MAAM,0BAA0B,CAAC;AAgCvF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,kBAAkB,CASlC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,kBAAkB,CAAC,CAAC;AAE1C,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAK3B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAKzB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAKtB,CAAC;AAWF,eAAO,MAAM,QAAQ,EAAE,KAwBtB,CAAC;AASF,eAAO,MAAM,kBAAkB,EAAE,KAwBhC,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAKzB,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,KAQrC,CAAC;AAaF,eAAO,MAAM,mBAAmB,EAAE,KAwBjC,CAAC"}
1
+ {"version":3,"file":"repository-node.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,KAAK,EAAE,kBAAkB,EAAsB,MAAM,0BAA0B,CAAC;AAgCvF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,kBAAkB,CASlC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,kBAAkB,CAAC,CAAC;AAE1C,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAK3B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAKzB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAKtB,CAAC;AAWF,eAAO,MAAM,QAAQ,EAAE,KAwBtB,CAAC;AASF,eAAO,MAAM,kBAAkB,EAAE,KAwBhC,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAKzB,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,KAQrC,CAAC;AAIF,eAAO,MAAM,gBAAgB,EAAE,KAS9B,CAAC;AA2BF,eAAO,MAAM,mBAAmB,EAAE,KAwBjC,CAAC"}
@@ -89,15 +89,40 @@ export const WithActionsAndAddButton = {
89
89
  },
90
90
  render: (args) => _jsx(RepositoryNodeCanvas, { data: args }),
91
91
  };
92
+ const onDelete = () => undefined;
93
+ export const WithDeleteButton = {
94
+ args: {
95
+ id: 'repo-abc-123',
96
+ repositoryPath: '/home/user/shep-ai/cli',
97
+ },
98
+ argTypes: {
99
+ onDelete: { action: 'onDelete' },
100
+ },
101
+ render: (args) => _jsx(RepositoryNodeCanvas, { data: args, style: { width: 550, height: 250 } }),
102
+ };
92
103
  const multipleReposWithActions = [
93
- { name: 'shep-ai/cli', repositoryPath: '/home/user/shep-ai/cli', onAdd },
94
- { name: 'vercel/edge-runtime', repositoryPath: '/home/user/vercel/edge-runtime', onAdd },
104
+ { id: 'r1', name: 'shep-ai/cli', repositoryPath: '/home/user/shep-ai/cli', onAdd, onDelete },
95
105
  {
106
+ id: 'r2',
107
+ name: 'vercel/edge-runtime',
108
+ repositoryPath: '/home/user/vercel/edge-runtime',
109
+ onAdd,
110
+ onDelete,
111
+ },
112
+ {
113
+ id: 'r3',
96
114
  name: 'acme-corp/web-dashboard-v2',
97
115
  repositoryPath: '/home/user/acme-corp/web-dashboard-v2',
98
116
  onAdd,
117
+ onDelete,
118
+ },
119
+ {
120
+ id: 'r4',
121
+ name: 'openai/tiktoken',
122
+ repositoryPath: '/home/user/openai/tiktoken',
123
+ onAdd,
124
+ onDelete,
99
125
  },
100
- { name: 'openai/tiktoken', repositoryPath: '/home/user/openai/tiktoken', onAdd },
101
126
  ];
102
127
  export const MultipleWithActions = {
103
128
  render: () => {
@@ -6,6 +6,8 @@ export interface ReviewDrawerShellProps {
6
6
  onClose: () => void;
7
7
  /** Feature name shown in drawer header */
8
8
  featureName: string;
9
+ /** Short description shown below the feature name */
10
+ featureDescription?: string;
9
11
  /** Feature ID shown below the name (sr-only) */
10
12
  featureId?: string;
11
13
  /** Absolute path to the repository on disk */
@@ -1 +1 @@
1
- {"version":3,"file":"review-drawer-shell-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/review-drawer-shell/review-drawer-shell-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,sBAAsB;IACrC,iCAAiC;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,wCAAwC;IACxC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,gDAAgD;IAChD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,0BAA0B;IAC1B,QAAQ,EAAE,SAAS,CAAC;CACrB"}
1
+ {"version":3,"file":"review-drawer-shell-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/review-drawer-shell/review-drawer-shell-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,sBAAsB;IACrC,iCAAiC;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,wCAAwC;IACxC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,gDAAgD;IAChD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,0BAA0B;IAC1B,QAAQ,EAAE,SAAS,CAAC;CACrB"}
@@ -1,3 +1,3 @@
1
1
  import type { ReviewDrawerShellProps } from './review-drawer-shell-config.js';
2
- export declare function ReviewDrawerShell({ open, onClose, featureName, featureId, repositoryPath, branch, specPath, onDelete, isDeleting, children, }: ReviewDrawerShellProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function ReviewDrawerShell({ open, onClose, featureName, featureDescription, featureId, repositoryPath, branch, specPath, onDelete, isDeleting, children, }: ReviewDrawerShellProps): import("react/jsx-runtime").JSX.Element;
3
3
  //# sourceMappingURL=review-drawer-shell.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"review-drawer-shell.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAE3E,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,OAAO,EACP,WAAW,EACX,SAAS,EACT,cAAc,EACd,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,QAAQ,GACT,EAAE,sBAAsB,2CAoGxB"}
1
+ {"version":3,"file":"review-drawer-shell.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAE3E,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,OAAO,EACP,WAAW,EACX,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,QAAQ,GACT,EAAE,sBAAsB,2CAsGxB"}
@@ -7,11 +7,11 @@ import { Separator } from '../../ui/separator.js';
7
7
  import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from '../../ui/alert-dialog.js';
8
8
  import { OpenActionMenu } from '../../common/open-action-menu/index.js';
9
9
  import { useFeatureActions } from '../../common/feature-drawer/use-feature-actions.js';
10
- export function ReviewDrawerShell({ open, onClose, featureName, featureId, repositoryPath, branch, specPath, onDelete, isDeleting, children, }) {
10
+ export function ReviewDrawerShell({ open, onClose, featureName, featureDescription, featureId, repositoryPath, branch, specPath, onDelete, isDeleting, children, }) {
11
11
  const actionsInput = repositoryPath && branch ? { repositoryPath, branch, specPath } : null;
12
12
  const actions = useFeatureActions(actionsInput);
13
13
  return (_jsx(Drawer, { direction: "right", modal: false, handleOnly: true, open: open, onOpenChange: (isOpen) => {
14
14
  if (!isOpen)
15
15
  onClose();
16
- }, children: _jsxs(DrawerContent, { direction: "right", className: "w-xl", showCloseButton: false, children: [_jsx("button", { type: "button", "aria-label": "Close", onClick: onClose, className: "ring-offset-background focus:ring-ring absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden", children: _jsx(XIcon, { className: "size-4" }) }), _jsxs(DrawerHeader, { children: [_jsx(DrawerTitle, { children: featureName }), featureId ? (_jsx(DrawerDescription, { className: "sr-only", children: featureId })) : null] }), actionsInput ? (_jsxs("div", { className: "flex items-center gap-2 px-4 pb-3", children: [_jsx(OpenActionMenu, { actions: actions, repositoryPath: actionsInput.repositoryPath, showSpecs: !!specPath }), onDelete && featureId ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "bg-border mx-1 h-4 w-px" }), _jsxs(AlertDialog, { children: [_jsx(AlertDialogTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Delete feature", disabled: isDeleting, className: "text-muted-foreground hover:text-destructive", "data-testid": "review-drawer-delete", children: isDeleting ? (_jsx(Loader2, { className: "size-4 animate-spin" })) : (_jsx(Trash2, { className: "size-4" })) }) }), _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Delete feature?" }), _jsxs(AlertDialogDescription, { children: ["This will permanently delete ", _jsx("strong", { children: featureName }), " (", featureId, "). This action cannot be undone."] })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: isDeleting, children: "Cancel" }), _jsx(AlertDialogAction, { variant: "destructive", disabled: isDeleting, onClick: () => onDelete(featureId), children: isDeleting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Deleting\u2026"] })) : ('Delete') })] })] })] })] })) : null] })) : null, _jsx(Separator, {}), _jsx("div", { className: "flex min-h-0 flex-1 flex-col", children: children })] }) }));
16
+ }, children: _jsxs(DrawerContent, { direction: "right", className: "w-xl", showCloseButton: false, children: [_jsx("button", { type: "button", "aria-label": "Close", onClick: onClose, className: "ring-offset-background focus:ring-ring absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden", children: _jsx(XIcon, { className: "size-4" }) }), _jsxs(DrawerHeader, { children: [_jsx(DrawerTitle, { children: featureName }), featureDescription ? (_jsx(DrawerDescription, { children: featureDescription })) : featureId ? (_jsx(DrawerDescription, { className: "sr-only", children: featureId })) : null] }), actionsInput ? (_jsxs("div", { className: "flex items-center gap-2 px-4 pb-3", children: [_jsx(OpenActionMenu, { actions: actions, repositoryPath: actionsInput.repositoryPath, showSpecs: !!specPath }), onDelete && featureId ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "bg-border mx-1 h-4 w-px" }), _jsxs(AlertDialog, { children: [_jsx(AlertDialogTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Delete feature", disabled: isDeleting, className: "text-muted-foreground hover:text-destructive", "data-testid": "review-drawer-delete", children: isDeleting ? (_jsx(Loader2, { className: "size-4 animate-spin" })) : (_jsx(Trash2, { className: "size-4" })) }) }), _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Delete feature?" }), _jsxs(AlertDialogDescription, { children: ["This will permanently delete ", _jsx("strong", { children: featureName }), " (", featureId, "). This action cannot be undone."] })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: isDeleting, children: "Cancel" }), _jsx(AlertDialogAction, { variant: "destructive", disabled: isDeleting, onClick: () => onDelete(featureId), children: isDeleting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Deleting\u2026"] })) : ('Delete') })] })] })] })] })) : null] })) : null, _jsx(Separator, {}), _jsx("div", { className: "flex min-h-0 flex-1 flex-col", children: children })] }) }));
17
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"review-drawer-shell.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,iBAAiB,CAOxC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAyBhD,yCAAyC;AACzC,eAAO,MAAM,OAAO,EAAE,KAUrB,CAAC;AAEF,uCAAuC;AACvC,eAAO,MAAM,UAAU,EAAE,KAWxB,CAAC;AAEF,qCAAqC;AACrC,eAAO,MAAM,aAAa,EAAE,KAW3B,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,SAAS,EAAE,KAEvB,CAAC"}
1
+ {"version":3,"file":"review-drawer-shell.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,iBAAiB,CAOxC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAyBhD,yCAAyC;AACzC,eAAO,MAAM,OAAO,EAAE,KAWrB,CAAC;AAEF,uCAAuC;AACvC,eAAO,MAAM,UAAU,EAAE,KAWxB,CAAC;AAEF,qCAAqC;AACrC,eAAO,MAAM,aAAa,EAAE,KAW3B,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,SAAS,EAAE,KAEvB,CAAC"}
@@ -17,7 +17,7 @@ function ShellTemplate(props) {
17
17
  }
18
18
  /** Default shell with action buttons. */
19
19
  export const Default = {
20
- render: () => (_jsx(ShellTemplate, { featureName: "User Authentication Flow", featureId: "FEAT-042", repositoryPath: "/Users/dev/my-project", branch: "feat/auth-flow", specPath: "/Users/dev/my-project/specs/042-auth-flow" })),
20
+ render: () => (_jsx(ShellTemplate, { featureName: "User Authentication Flow", featureDescription: "Implement OAuth2 login with social providers and MFA support", featureId: "FEAT-042", repositoryPath: "/Users/dev/my-project", branch: "feat/auth-flow", specPath: "/Users/dev/my-project/specs/042-auth-flow" })),
21
21
  };
22
22
  /** Shell with inline delete button. */
23
23
  export const WithDelete = {
@@ -1 +1 @@
1
- {"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAO1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAS5E,UAAU,uBAAuB;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,uBAAuB,2CA2OzF"}
1
+ {"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAO1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAS5E,UAAU,uBAAuB;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,uBAAuB,2CA8OzF"}
@@ -13,7 +13,7 @@ import { NotificationPermissionBanner } from '../../common/notification-permissi
13
13
  import { ControlCenterEmptyState } from './control-center-empty-state.js';
14
14
  import { useControlCenterState } from './use-control-center-state.js';
15
15
  export function ControlCenterInner({ initialNodes, initialEdges }) {
16
- const { nodes, edges, selectedNode, isCreateDrawerOpen, isDeleting, pendingRepositoryPath, onNodesChange, handleConnect, handleAddFeature, handleAddFeatureToRepo, handleAddFeatureToFeature, handleAddRepository, handleNodeClick, clearSelection, handleCreateFeatureSubmit, handleDeleteFeature, closeCreateDrawer, } = useControlCenterState(initialNodes, initialEdges);
16
+ const { nodes, edges, selectedNode, isCreateDrawerOpen, isDeleting, pendingRepositoryPath, onNodesChange, handleConnect, handleAddFeature, handleAddFeatureToRepo, handleAddFeatureToFeature, handleAddRepository, handleNodeClick, clearSelection, handleCreateFeatureSubmit, handleDeleteFeature, handleDeleteRepository, closeCreateDrawer, } = useControlCenterState(initialNodes, initialEdges);
17
17
  // PRD questionnaire drawer state
18
18
  const [prdSelections, setPrdSelections] = useState({});
19
19
  const [isPrdProcessing, setIsPrdProcessing] = useState(false);
@@ -144,5 +144,5 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
144
144
  window.addEventListener('shep:open-create-drawer', handler);
145
145
  return () => window.removeEventListener('shep:open-create-drawer', handler);
146
146
  }, [handleAddFeature]);
147
- return (_jsxs(_Fragment, { children: [_jsx(NotificationPermissionBanner, {}), _jsx(FeaturesCanvas, { nodes: nodes, edges: edges, onNodesChange: onNodesChange, onConnect: handleConnect, onAddFeature: handleAddFeature, onNodeAction: handleAddFeatureToFeature, onNodeClick: handleNodeClick, onPaneClick: clearSelection, onRepositoryAdd: handleAddFeatureToRepo, onRepositorySelect: handleAddRepository, emptyState: _jsx(ControlCenterEmptyState, { onRepositorySelect: handleAddRepository }) }), _jsx(FeatureDrawer, { selectedNode: showPrdDrawer || showTechDecisionsDrawer ? null : selectedNode, onClose: clearSelection, onDelete: handleDeleteFeature, isDeleting: isDeleting }), questionnaireData ? (_jsx(PrdQuestionnaireDrawer, { open: showPrdDrawer, onClose: clearSelection, featureName: selectedNode?.name ?? '', featureId: selectedNode?.featureId, repositoryPath: selectedNode?.repositoryPath, branch: selectedNode?.branch, specPath: selectedNode?.specPath, data: questionnaireData, selections: prdSelections, onSelect: handlePrdSelect, onRefine: handlePrdRefine, onApprove: handlePrdApprove, onDelete: handleDeleteFeature, isDeleting: isDeleting, isProcessing: isPrdProcessing || isLoadingQuestionnaire })) : null, techDecisionsData ? (_jsx(TechDecisionsDrawer, { open: showTechDecisionsDrawer, onClose: clearSelection, featureName: selectedNode?.name ?? '', featureId: selectedNode?.featureId, repositoryPath: selectedNode?.repositoryPath, branch: selectedNode?.branch, specPath: selectedNode?.specPath, data: techDecisionsData, onRefine: handleTechDecisionsRefine, onApprove: handleTechDecisionsApprove, onDelete: handleDeleteFeature, isDeleting: isDeleting, isProcessing: isLoadingTechDecisions })) : null, _jsx(FeatureCreateDrawer, { open: isCreateDrawerOpen, onClose: closeCreateDrawer, onSubmit: handleCreateFeatureSubmit, repositoryPath: pendingRepositoryPath })] }));
147
+ return (_jsxs(_Fragment, { children: [_jsx(NotificationPermissionBanner, {}), _jsx(FeaturesCanvas, { nodes: nodes, edges: edges, onNodesChange: onNodesChange, onConnect: handleConnect, onAddFeature: handleAddFeature, onNodeAction: handleAddFeatureToFeature, onNodeClick: handleNodeClick, onPaneClick: clearSelection, onRepositoryAdd: handleAddFeatureToRepo, onRepositoryDelete: handleDeleteRepository, onRepositorySelect: handleAddRepository, emptyState: _jsx(ControlCenterEmptyState, { onRepositorySelect: handleAddRepository }) }), _jsx(FeatureDrawer, { selectedNode: showPrdDrawer || showTechDecisionsDrawer ? null : selectedNode, onClose: clearSelection, onDelete: handleDeleteFeature, isDeleting: isDeleting }), questionnaireData ? (_jsx(PrdQuestionnaireDrawer, { open: showPrdDrawer, onClose: clearSelection, featureName: selectedNode?.name ?? '', featureDescription: selectedNode?.description, featureId: selectedNode?.featureId, repositoryPath: selectedNode?.repositoryPath, branch: selectedNode?.branch, specPath: selectedNode?.specPath, data: questionnaireData, selections: prdSelections, onSelect: handlePrdSelect, onRefine: handlePrdRefine, onApprove: handlePrdApprove, onDelete: handleDeleteFeature, isDeleting: isDeleting, isProcessing: isPrdProcessing || isLoadingQuestionnaire })) : null, techDecisionsData ? (_jsx(TechDecisionsDrawer, { open: showTechDecisionsDrawer, onClose: clearSelection, featureName: selectedNode?.name ?? '', featureId: selectedNode?.featureId, repositoryPath: selectedNode?.repositoryPath, branch: selectedNode?.branch, specPath: selectedNode?.specPath, data: techDecisionsData, onRefine: handleTechDecisionsRefine, onApprove: handleTechDecisionsApprove, onDelete: handleDeleteFeature, isDeleting: isDeleting, isProcessing: isLoadingTechDecisions })) : null, _jsx(FeatureCreateDrawer, { open: isCreateDrawerOpen, onClose: closeCreateDrawer, onSubmit: handleCreateFeatureSubmit, repositoryPath: pendingRepositoryPath })] }));
148
148
  }
@@ -1 +1 @@
1
- {"version":3,"file":"control-center.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAOjD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,aAAa,CAcpC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAkEnC,eAAO,MAAM,KAAK,EAAE,KAKnB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAQ1B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAKzB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAS7B,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,EAAE,KAYzB,CAAC;AAwIF;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,EAAE,KAKzB,CAAC"}
1
+ {"version":3,"file":"control-center.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAQjD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,aAAa,CAgBpC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAkEnC,eAAO,MAAM,KAAK,EAAE,KAKnB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAQ1B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAKzB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAS7B,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,EAAE,KAYzB,CAAC;AAwIF;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,EAAE,KAKzB,CAAC"}