@shepai/cli 1.118.0-pr379.a71d408 → 1.118.0-pr380.dfa57ad

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 (145) hide show
  1. package/dist/src/presentation/web/app/actions/get-merge-review-data.d.ts.map +1 -1
  2. package/dist/src/presentation/web/app/actions/get-merge-review-data.js +49 -13
  3. package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.d.ts.map +1 -1
  4. package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.js +4 -0
  5. package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.d.ts.map +1 -1
  6. package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.js +7 -2
  7. package/dist/src/presentation/web/components/common/merge-review/merge-review-config.d.ts +3 -3
  8. package/dist/src/presentation/web/components/common/merge-review/merge-review-config.d.ts.map +1 -1
  9. package/dist/src/presentation/web/components/common/merge-review/merge-review.d.ts +1 -1
  10. package/dist/src/presentation/web/components/common/merge-review/merge-review.d.ts.map +1 -1
  11. package/dist/src/presentation/web/components/common/merge-review/merge-review.js +14 -20
  12. package/dist/src/presentation/web/components/common/merge-review/merge-review.stories.d.ts +6 -0
  13. package/dist/src/presentation/web/components/common/merge-review/merge-review.stories.d.ts.map +1 -1
  14. package/dist/src/presentation/web/components/common/merge-review/merge-review.stories.js +74 -0
  15. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
  16. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +6 -2
  17. package/dist/tsconfig.build.tsbuildinfo +1 -1
  18. package/package.json +1 -1
  19. package/web/.next/BUILD_ID +1 -1
  20. package/web/.next/build-manifest.json +2 -2
  21. package/web/.next/fallback-build-manifest.json +2 -2
  22. package/web/.next/prerender-manifest.json +3 -3
  23. package/web/.next/required-server-files.js +1 -1
  24. package/web/.next/required-server-files.json +1 -1
  25. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +21 -21
  26. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  27. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  28. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +27 -27
  29. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  30. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  31. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +27 -27
  32. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  33. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  34. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +19 -19
  35. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  36. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  37. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +21 -21
  38. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  39. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  40. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +27 -27
  41. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  42. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  43. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +27 -27
  44. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  45. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  46. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +19 -19
  47. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  48. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  49. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +19 -19
  50. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  51. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  52. package/web/.next/server/app/_global-error.html +2 -2
  53. package/web/.next/server/app/_global-error.rsc +1 -1
  54. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  55. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  56. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  57. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  58. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  59. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  60. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  61. package/web/.next/server/app/settings/page/server-reference-manifest.json +6 -6
  62. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  63. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  64. package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  65. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  66. package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  67. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  68. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  69. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  70. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  71. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  72. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  73. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_ed372306.js +1 -1
  74. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_ed372306.js.map +1 -1
  75. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_32e26434.js +1 -1
  76. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_32e26434.js.map +1 -1
  77. package/web/.next/server/chunks/ssr/[root-of-the-server]__07a39ff2._.js +1 -1
  78. package/web/.next/server/chunks/ssr/[root-of-the-server]__2ff2daf6._.js +2 -2
  79. package/web/.next/server/chunks/ssr/[root-of-the-server]__3155add4._.js +1 -1
  80. package/web/.next/server/chunks/ssr/[root-of-the-server]__3155add4._.js.map +1 -1
  81. package/web/.next/server/chunks/ssr/[root-of-the-server]__6367aea0._.js +1 -1
  82. package/web/.next/server/chunks/ssr/[root-of-the-server]__6367aea0._.js.map +1 -1
  83. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  84. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +1 -1
  85. package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js +2 -2
  86. package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js.map +1 -1
  87. package/web/.next/server/chunks/ssr/[root-of-the-server]__7b707feb._.js +2 -2
  88. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  89. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +1 -1
  90. package/web/.next/server/chunks/ssr/[root-of-the-server]__8763fd7a._.js +2 -2
  91. package/web/.next/server/chunks/ssr/[root-of-the-server]__9c56d724._.js +1 -1
  92. package/web/.next/server/chunks/ssr/[root-of-the-server]__9c56d724._.js.map +1 -1
  93. package/web/.next/server/chunks/ssr/[root-of-the-server]__cfc116d5._.js +1 -1
  94. package/web/.next/server/chunks/ssr/[root-of-the-server]__cfc116d5._.js.map +1 -1
  95. package/web/.next/server/chunks/ssr/[root-of-the-server]__d3841d9e._.js +1 -1
  96. package/web/.next/server/chunks/ssr/[root-of-the-server]__d3841d9e._.js.map +1 -1
  97. package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
  98. package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
  99. package/web/.next/server/chunks/ssr/_2f6f48b8._.js +1 -1
  100. package/web/.next/server/chunks/ssr/_2f6f48b8._.js.map +1 -1
  101. package/web/.next/server/chunks/ssr/{_08d85106._.js → _6cbd1f4e._.js} +2 -2
  102. package/web/.next/server/chunks/ssr/{_08d85106._.js.map → _6cbd1f4e._.js.map} +1 -1
  103. package/web/.next/server/chunks/ssr/{_367737e0._.js → _c55029ff._.js} +2 -2
  104. package/web/.next/server/chunks/ssr/{_367737e0._.js.map → _c55029ff._.js.map} +1 -1
  105. package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
  106. package/web/.next/server/chunks/ssr/_cc77a143._.js.map +1 -1
  107. package/web/.next/server/chunks/ssr/{_34950c42._.js → _f84ed520._.js} +2 -2
  108. package/web/.next/server/chunks/ssr/{_34950c42._.js.map → _f84ed520._.js.map} +1 -1
  109. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  110. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  111. package/web/.next/server/chunks/ssr/src_presentation_web_0835b28e._.js +2 -2
  112. package/web/.next/server/chunks/ssr/src_presentation_web_0835b28e._.js.map +1 -1
  113. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_e99d78dd.js +1 -1
  114. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_e99d78dd.js.map +1 -1
  115. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
  116. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
  117. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
  118. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
  119. package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
  120. package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js.map +1 -1
  121. package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +1 -1
  122. package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js.map +1 -1
  123. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  124. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  125. package/web/.next/server/chunks/ssr/src_presentation_web_e8034a29._.js +2 -2
  126. package/web/.next/server/chunks/ssr/src_presentation_web_e8034a29._.js.map +1 -1
  127. package/web/.next/server/pages/500.html +2 -2
  128. package/web/.next/server/server-reference-manifest.js +1 -1
  129. package/web/.next/server/server-reference-manifest.json +33 -33
  130. package/web/.next/static/chunks/{cc5b77d2674bae26.js → 1ea3371ba4e67de9.js} +1 -1
  131. package/web/.next/static/chunks/{b8796bba61c5f1f9.js → 441c9e090ed3421e.js} +1 -1
  132. package/web/.next/static/chunks/{a9523cf5247ee791.js → 497a6eb33eb6be8e.js} +1 -1
  133. package/web/.next/static/chunks/646d3e433c9abfbd.js +1 -0
  134. package/web/.next/static/chunks/77bea4cc562269e5.js +1 -0
  135. package/web/.next/static/chunks/{2ff4e51636afec0a.js → 7b6130916427c7d5.js} +1 -1
  136. package/web/.next/static/chunks/{2ccf294babe8a526.js → 7d7e7ee812313120.js} +1 -1
  137. package/web/.next/static/chunks/8840985592c9f6f4.js +2 -0
  138. package/web/.next/static/chunks/{149c044db14ba247.js → bd6fca67f592dddf.js} +1 -1
  139. package/web/.next/static/chunks/{f5021ad2ecc5916b.js → be5124f9bf7e5c20.js} +2 -2
  140. package/web/.next/static/chunks/6e33380b294e51db.js +0 -1
  141. package/web/.next/static/chunks/8ce7853a87d4957e.js +0 -1
  142. package/web/.next/static/chunks/a07b01a57cdb92f2.js +0 -2
  143. /package/web/.next/static/{4lwbtGuLakkOP4dusXn2B → 7j2XghmmOeoShEIApfXDS}/_buildManifest.js +0 -0
  144. /package/web/.next/static/{4lwbtGuLakkOP4dusXn2B → 7j2XghmmOeoShEIApfXDS}/_clientMiddlewareManifest.json +0 -0
  145. /package/web/.next/static/{4lwbtGuLakkOP4dusXn2B → 7j2XghmmOeoShEIApfXDS}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"get-merge-review-data.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/get-merge-review-data.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,sDAAsD,CAAC;AAG9D,KAAK,wBAAwB,GAAG,eAAe,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpE,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAiF7F"}
1
+ {"version":3,"file":"get-merge-review-data.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/get-merge-review-data.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,sDAAsD,CAAC;AAI9D,KAAK,wBAAwB,GAAG,eAAe,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAqCpE,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAoF7F"}
@@ -1,8 +1,42 @@
1
1
  'use server';
2
+ import { createHash } from 'node:crypto';
2
3
  import { readFileSync, existsSync } from 'node:fs';
3
- import { join, dirname } from 'node:path';
4
+ import { basename, join, dirname } from 'node:path';
4
5
  import { resolve } from '../../lib/server-container.js';
5
6
  import { computeWorktreePath } from '../../../../../packages/core/src/infrastructure/services/ide-launchers/compute-worktree-path.js';
7
+ import { getShepHomeDir } from '../../../../../packages/core/src/infrastructure/services/filesystem/shep-directory.service.js';
8
+ /**
9
+ * Compute the shep evidence directory for a given repository and feature.
10
+ * Path: ~/.shep/repos/<sha256-hash-prefix>/evidence/<featureId>/
11
+ */
12
+ function computeEvidenceDir(repositoryPath, featureId) {
13
+ const repoHash = createHash('sha256').update(repositoryPath).digest('hex').slice(0, 16);
14
+ return join(getShepHomeDir(), 'repos', repoHash, 'evidence', featureId).replace(/\\/g, '/');
15
+ }
16
+ /**
17
+ * Normalize evidence paths so they all point to the shep evidence directory.
18
+ * When commitEvidence was enabled, the manifest may contain relative paths
19
+ * (e.g. "specs/066-feature/evidence/file.png"). After merge the worktree is
20
+ * deleted so those paths no longer resolve. The evidence files were also saved
21
+ * to the shep evidence dir with the same filename, so we map relative paths
22
+ * to absolute paths there.
23
+ */
24
+ function normalizeEvidencePaths(evidence, evidenceDir) {
25
+ return evidence.map((e) => {
26
+ if (e.relativePath.startsWith('/')) {
27
+ // Already absolute — check if the file exists; if not, try the evidence dir
28
+ if (existsSync(e.relativePath))
29
+ return e;
30
+ const fallback = join(evidenceDir, basename(e.relativePath)).replace(/\\/g, '/');
31
+ if (existsSync(fallback))
32
+ return { ...e, relativePath: fallback };
33
+ return e;
34
+ }
35
+ // Relative path — resolve to evidence dir using the filename
36
+ const absolutePath = join(evidenceDir, basename(e.relativePath)).replace(/\\/g, '/');
37
+ return { ...e, relativePath: absolutePath };
38
+ });
39
+ }
6
40
  export async function getMergeReviewData(featureId) {
7
41
  if (!featureId.trim()) {
8
42
  return { error: 'Feature id is required' };
@@ -28,19 +62,23 @@ export async function getMergeReviewData(featureId) {
28
62
  (feature.repositoryPath && feature.branch
29
63
  ? computeWorktreePath(feature.repositoryPath, feature.branch)
30
64
  : null);
31
- // Load evidence manifest (best-effort)
65
+ // Load evidence manifest (best-effort).
66
+ // Evidence is stored independently of the worktree at:
67
+ // ~/.shep/repos/<hash>/evidence/<featureId>/manifest.json
68
+ // We compute this path from repositoryPath so evidence is accessible
69
+ // even after the worktree has been deleted post-merge.
32
70
  let evidence;
33
- let evidenceBasePath;
34
- if (worktreePath) {
71
+ const evidenceDir = feature.repositoryPath
72
+ ? computeEvidenceDir(feature.repositoryPath, featureId)
73
+ : worktreePath
74
+ ? join(dirname(dirname(worktreePath)), 'evidence', featureId).replace(/\\/g, '/')
75
+ : null;
76
+ if (evidenceDir) {
35
77
  try {
36
- // Worktree path: ~/.shep/repos/<hash>/wt/<slug>
37
- // Evidence manifest: ~/.shep/repos/<hash>/evidence/<featureId>/manifest.json
38
- const repoHashDir = dirname(dirname(worktreePath));
39
- const evidenceDir = join(repoHashDir, 'evidence', featureId);
40
78
  const manifestPath = join(evidenceDir, 'manifest.json');
41
79
  if (existsSync(manifestPath)) {
42
- evidence = JSON.parse(readFileSync(manifestPath, 'utf-8'));
43
- evidenceBasePath = worktreePath;
80
+ const raw = JSON.parse(readFileSync(manifestPath, 'utf-8'));
81
+ evidence = normalizeEvidencePaths(raw, evidenceDir);
44
82
  }
45
83
  }
46
84
  catch {
@@ -52,7 +90,6 @@ export async function getMergeReviewData(featureId) {
52
90
  pr,
53
91
  branch,
54
92
  evidence,
55
- evidenceBasePath,
56
93
  warning: pr ? undefined : 'No PR or diff data available',
57
94
  };
58
95
  }
@@ -62,14 +99,13 @@ export async function getMergeReviewData(featureId) {
62
99
  gitPrService.getPrDiffSummary(worktreePath, 'main'),
63
100
  gitPrService.getFileDiffs(worktreePath, 'main').catch(() => undefined),
64
101
  ]);
65
- return { pr, branch, diffSummary, fileDiffs, evidence, evidenceBasePath };
102
+ return { pr, branch, diffSummary, fileDiffs, evidence };
66
103
  }
67
104
  catch {
68
105
  return {
69
106
  pr,
70
107
  branch,
71
108
  evidence,
72
- evidenceBasePath,
73
109
  warning: 'Diff statistics unavailable',
74
110
  };
75
111
  }
@@ -1 +1 @@
1
- {"version":3,"file":"feature-drawer-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/control-center-drawer/feature-drawer-client.tsx"],"names":[],"mappings":"AAuCA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAI/D,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,UAAU,CAAC;IACjB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,wBAAwB,2CA+jB1F"}
1
+ {"version":3,"file":"feature-drawer-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/control-center-drawer/feature-drawer-client.tsx"],"names":[],"mappings":"AAuCA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAI/D,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,UAAU,CAAC;IACjB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,wBAAwB,2CAqkB1F"}
@@ -194,6 +194,10 @@ export function FeatureDrawerClient({ view: initialView, urlTab }) {
194
194
  if (result.iterationWarning) {
195
195
  toast.warning(`Iteration ${result.iteration} — consider approving or adjusting feedback to avoid excessive iterations`);
196
196
  }
197
+ // Optimistically update canvas node before SSE arrives (~500ms delay)
198
+ window.dispatchEvent(new CustomEvent('shep:feature-approved', {
199
+ detail: { featureId: featureNode.featureId },
200
+ }));
197
201
  onClose();
198
202
  onDone?.();
199
203
  }
@@ -1 +1 @@
1
- {"version":3,"file":"feature-drawer-tabs.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAS9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AACzF,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,+CAA+C,CAAC;AACjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAMxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAQ9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uDAAuD,CAAC;AA2C3F,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,eAAe,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,gFAAgF;IAChF,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,mFAAmF;IACnF,SAAS,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAGzC,OAAO,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;IAGvB,QAAQ,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAC1C,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC3E,aAAa,CAAC,EAAE,OAAO,CAAC;IAGxB,WAAW,CAAC,EAAE,2BAA2B,GAAG,IAAI,CAAC;IAGjD,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC5E,cAAc,CAAC,EAAE,OAAO,CAAC;IAGzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAwBD,wBAAgB,iBAAiB,CAAC,EAChC,WAAW,EACX,SAAS,EACT,UAAU,EACV,MAAM,EACN,OAAO,EACP,aAAa,EACb,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,aAAa,EACb,WAAW,EACX,SAAS,EACT,cAAc,EACd,aAAa,EACb,cAAc,EACd,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,SAAS,GACV,EAAE,sBAAsB,2CA2TxB"}
1
+ {"version":3,"file":"feature-drawer-tabs.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAS9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AACzF,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,+CAA+C,CAAC;AACjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAMxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAQ9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uDAAuD,CAAC;AA8C3F,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,eAAe,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,gFAAgF;IAChF,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,mFAAmF;IACnF,SAAS,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAGzC,OAAO,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;IAGvB,QAAQ,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAC1C,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC3E,aAAa,CAAC,EAAE,OAAO,CAAC;IAGxB,WAAW,CAAC,EAAE,2BAA2B,GAAG,IAAI,CAAC;IAGjD,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC5E,cAAc,CAAC,EAAE,OAAO,CAAC;IAGzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAwBD,wBAAgB,iBAAiB,CAAC,EAChC,WAAW,EACX,SAAS,EACT,UAAU,EACV,MAAM,EACN,OAAO,EACP,aAAa,EACb,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,aAAa,EACb,WAAW,EACX,SAAS,EACT,cAAc,EACd,aAAa,EACb,cAAc,EACd,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,SAAS,GACV,EAAE,sBAAsB,2CAiUxB"}
@@ -43,6 +43,9 @@ function computeVisibleTabs(node) {
43
43
  if (node.lifecycle === 'review' && (node.state === 'action-required' || node.state === 'error')) {
44
44
  tabs.push('merge-review');
45
45
  }
46
+ if (node.lifecycle === 'maintain' && node.pr) {
47
+ tabs.push('merge-review');
48
+ }
46
49
  return tabs;
47
50
  }
48
51
  async function fetchActivity(featureId) {
@@ -64,7 +67,9 @@ const TAB_FETCHERS = {
64
67
  export function FeatureDrawerTabs({ featureNode, featureId, initialTab, urlTab, prdData, prdSelections, onPrdSelect, onPrdApprove, onPrdReject, isPrdLoading, techData, onTechApprove, onTechReject, isTechLoading, productData, mergeData, onMergeApprove, onMergeReject, isMergeLoading, isRejecting, chatInput, onChatInputChange, sseEvents, }) {
65
68
  const pathname = usePathname();
66
69
  const visibleTabs = useMemo(() => computeVisibleTabs(featureNode), [featureNode]);
67
- const visibleTabDefs = useMemo(() => ALL_TABS.filter((t) => visibleTabs.includes(t.key)), [visibleTabs]);
70
+ const visibleTabDefs = useMemo(() => ALL_TABS.filter((t) => visibleTabs.includes(t.key)).map((t) => t.key === 'merge-review' && featureNode.lifecycle === 'maintain'
71
+ ? { ...t, label: 'Merge History' }
72
+ : t), [visibleTabs, featureNode.lifecycle]);
68
73
  // Derive the base path (without tab segment) from the current pathname.
69
74
  // e.g. /feature/abc123/activity → /feature/abc123
70
75
  const basePath = useMemo(() => {
@@ -223,7 +228,7 @@ export function FeatureDrawerTabs({ featureNode, featureId, initialTab, urlTab,
223
228
  fetchTab(tab);
224
229
  }
225
230
  }, [fetchTab]);
226
- return (_jsx("div", { className: "flex min-h-0 flex-1 flex-col", children: _jsxs(Tabs, { value: activeTab, onValueChange: handleTabChange, className: "flex min-h-0 flex-1 flex-col", children: [_jsx("div", { className: "shrink-0 overflow-x-auto px-4 pt-4", children: _jsx(TabsList, { className: "flex w-full", children: visibleTabDefs.map((tab) => (_jsx(TabsTrigger, { value: tab.key, className: "flex-1", children: tab.label }, tab.key))) }) }), _jsx(TabsContent, { value: "overview", className: "mt-0 flex-1 overflow-y-auto", children: _jsx(OverviewTab, { data: featureNode }) }), _jsx(TabsContent, { value: "activity", className: "mt-0 flex-1 overflow-y-auto", children: _jsx(ActivityTab, { timings: tabs.activity.data?.timings ?? null, loading: tabs.activity.loading, error: tabs.activity.error, rejectionFeedback: tabs.activity.data?.rejectionFeedback }) }), _jsx(TabsContent, { value: "log", className: "mt-0 flex-1 overflow-hidden", children: _jsx(LogTab, { content: featureLogs.content, isConnected: featureLogs.isConnected, error: featureLogs.error }) }), _jsx(TabsContent, { value: "plan", className: "mt-0 flex-1 overflow-y-auto", children: _jsx(PlanTab, { plan: tabs.plan.data, loading: tabs.plan.loading, error: tabs.plan.error }) }), visibleTabs.includes('prd-review') ? (_jsx(TabsContent, { value: "prd-review", className: "mt-0 flex min-h-0 flex-1 flex-col", children: prdData ? (_jsx(PrdQuestionnaire, { data: prdData, selections: prdSelections ?? {}, onSelect: onPrdSelect ?? (() => undefined), onApprove: onPrdApprove ?? (() => undefined), onReject: onPrdReject, isProcessing: isPrdLoading, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: onChatInputChange })) : (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) })) })) : null, visibleTabs.includes('tech-decisions') ? (_jsx(TabsContent, { value: "tech-decisions", className: "mt-0 flex min-h-0 flex-1 flex-col", children: techData ? (_jsxs("div", { className: "flex min-h-0 flex-1 flex-col", children: [_jsx("div", { className: "flex-1 overflow-y-auto", children: _jsx(TechDecisionsContent, { data: techData }) }), _jsx(DrawerActionBarForTech, { onApprove: onTechApprove ?? (() => undefined), onReject: onTechReject, isProcessing: isTechLoading, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: onChatInputChange })] })) : (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) })) })) : null, visibleTabs.includes('product-decisions') ? (_jsx(TabsContent, { value: "product-decisions", className: "mt-0 flex-1 overflow-y-auto", children: productData === null ? (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) })) : productData ? (_jsx(ProductDecisionsSummary, { data: productData })) : (_jsx("p", { className: "text-muted-foreground p-4 text-center text-sm", children: "No product decisions available." })) })) : null, visibleTabs.includes('merge-review') ? (_jsx(TabsContent, { value: "merge-review", className: "mt-0 flex min-h-0 flex-1 flex-col", children: mergeData ? (_jsx(MergeReview, { data: mergeData, onApprove: onMergeApprove ?? (() => undefined), onReject: onMergeReject, isProcessing: isMergeLoading, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: onChatInputChange })) : (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) })) })) : null] }) }));
231
+ return (_jsx("div", { className: "flex min-h-0 flex-1 flex-col", children: _jsxs(Tabs, { value: activeTab, onValueChange: handleTabChange, className: "flex min-h-0 flex-1 flex-col", children: [_jsx("div", { className: "shrink-0 overflow-x-auto px-4 pt-4", children: _jsx(TabsList, { className: "flex w-full", children: visibleTabDefs.map((tab) => (_jsx(TabsTrigger, { value: tab.key, className: "flex-1", children: tab.label }, tab.key))) }) }), _jsx(TabsContent, { value: "overview", className: "mt-0 flex-1 overflow-y-auto", children: _jsx(OverviewTab, { data: featureNode }) }), _jsx(TabsContent, { value: "activity", className: "mt-0 flex-1 overflow-y-auto", children: _jsx(ActivityTab, { timings: tabs.activity.data?.timings ?? null, loading: tabs.activity.loading, error: tabs.activity.error, rejectionFeedback: tabs.activity.data?.rejectionFeedback }) }), _jsx(TabsContent, { value: "log", className: "mt-0 flex-1 overflow-hidden", children: _jsx(LogTab, { content: featureLogs.content, isConnected: featureLogs.isConnected, error: featureLogs.error }) }), _jsx(TabsContent, { value: "plan", className: "mt-0 flex-1 overflow-y-auto", children: _jsx(PlanTab, { plan: tabs.plan.data, loading: tabs.plan.loading, error: tabs.plan.error }) }), visibleTabs.includes('prd-review') ? (_jsx(TabsContent, { value: "prd-review", className: "mt-0 flex min-h-0 flex-1 flex-col", children: prdData ? (_jsx(PrdQuestionnaire, { data: prdData, selections: prdSelections ?? {}, onSelect: onPrdSelect ?? (() => undefined), onApprove: onPrdApprove ?? (() => undefined), onReject: onPrdReject, isProcessing: isPrdLoading, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: onChatInputChange })) : (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) })) })) : null, visibleTabs.includes('tech-decisions') ? (_jsx(TabsContent, { value: "tech-decisions", className: "mt-0 flex min-h-0 flex-1 flex-col", children: techData ? (_jsxs("div", { className: "flex min-h-0 flex-1 flex-col", children: [_jsx("div", { className: "flex-1 overflow-y-auto", children: _jsx(TechDecisionsContent, { data: techData }) }), _jsx(DrawerActionBarForTech, { onApprove: onTechApprove ?? (() => undefined), onReject: onTechReject, isProcessing: isTechLoading, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: onChatInputChange })] })) : (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) })) })) : null, visibleTabs.includes('product-decisions') ? (_jsx(TabsContent, { value: "product-decisions", className: "mt-0 flex-1 overflow-y-auto", children: productData === null ? (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) })) : productData ? (_jsx(ProductDecisionsSummary, { data: productData })) : (_jsx("p", { className: "text-muted-foreground p-4 text-center text-sm", children: "No product decisions available." })) })) : null, visibleTabs.includes('merge-review') ? (_jsx(TabsContent, { value: "merge-review", className: "mt-0 flex min-h-0 flex-1 flex-col", children: mergeData ? (_jsx(MergeReview, { data: mergeData, readOnly: featureNode.lifecycle === 'maintain', onApprove: onMergeApprove ?? (() => undefined), onReject: onMergeReject, isProcessing: isMergeLoading, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: onChatInputChange })) : (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) })) })) : null] }) }));
227
232
  }
228
233
  // ── Private helper ──────────────────────────────────────────────────────
229
234
  function DrawerActionBarForTech({ onApprove, onReject, isProcessing, isRejecting, chatInput, onChatInputChange, }) {
@@ -65,15 +65,15 @@ export interface MergeReviewData {
65
65
  branch?: MergeReviewBranch;
66
66
  /** Warning message when diff summary could not be retrieved */
67
67
  warning?: string;
68
- /** Evidence captured during implementation */
68
+ /** Evidence captured during implementation (paths are absolute) */
69
69
  evidence?: MergeReviewEvidence[];
70
- /** Absolute path to the evidence directory (for serving files via API) */
71
- evidenceBasePath?: string;
72
70
  }
73
71
  /** Props for the merge review content component */
74
72
  export interface MergeReviewProps {
75
73
  /** Merge review data from the server action */
76
74
  data: MergeReviewData;
75
+ /** When true, hides the action bar and shows archival header text (post-merge history mode) */
76
+ readOnly?: boolean;
77
77
  /** Approve merge callback */
78
78
  onApprove: () => void;
79
79
  /** Reject merge callback — opens feedback dialog when provided; also used for inline text rejection */
@@ -1 +1 @@
1
- {"version":3,"file":"merge-review-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/merge-review/merge-review-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"merge-review-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/merge-review/merge-review-config.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,3 @@
1
1
  import type { MergeReviewProps } from './merge-review-config.js';
2
- export declare function MergeReview({ data, onApprove, onReject, isProcessing, isRejecting, chatInput, onChatInputChange, }: MergeReviewProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function MergeReview({ data, readOnly, onApprove, onReject, isProcessing, isRejecting, chatInput, onChatInputChange, }: MergeReviewProps): import("react/jsx-runtime").JSX.Element;
3
3
  //# sourceMappingURL=merge-review.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"merge-review.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/merge-review/merge-review.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,gBAAgB,EAAuB,MAAM,uBAAuB,CAAC;AA0KnF,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,YAAoB,EACpB,WAAmB,EACnB,SAAS,EACT,iBAAiB,GAClB,EAAE,gBAAgB,2CA2JlB"}
1
+ {"version":3,"file":"merge-review.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/merge-review/merge-review.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,gBAAgB,EAAuB,MAAM,uBAAuB,CAAC;AAuJnF,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,QAAgB,EAChB,SAAS,EACT,QAAQ,EACR,YAAoB,EACpB,WAAmB,EACnB,SAAS,EACT,iBAAiB,GAClB,EAAE,gBAAgB,2CA+JlB"}
@@ -18,23 +18,15 @@ function getExtension(path) {
18
18
  const dot = path.lastIndexOf('.');
19
19
  return dot >= 0 ? path.slice(dot).toLowerCase() : '';
20
20
  }
21
- /** Build the API URL for serving an evidence file. */
22
- function buildEvidenceUrl(relativePath, basePath) {
23
- // If relativePath is already absolute, use it directly
24
- const filePath = relativePath.startsWith('/')
25
- ? relativePath
26
- : basePath
27
- ? `${basePath}/${relativePath}`
28
- : undefined;
29
- if (!filePath)
30
- return undefined;
31
- return `/api/evidence?path=${encodeURIComponent(filePath)}`;
21
+ /** Build the API URL for serving an evidence file (paths are pre-normalized to absolute). */
22
+ function buildEvidenceUrl(absolutePath) {
23
+ return `/api/evidence?path=${encodeURIComponent(absolutePath)}`;
32
24
  }
33
- function EvidenceItem({ evidence, basePath, }) {
25
+ function EvidenceItem({ evidence }) {
34
26
  const [expanded, setExpanded] = useState(true);
35
27
  const Icon = EVIDENCE_ICONS[evidence.type] ?? Camera;
36
28
  const ext = getExtension(evidence.relativePath);
37
- const url = buildEvidenceUrl(evidence.relativePath, basePath);
29
+ const url = buildEvidenceUrl(evidence.relativePath);
38
30
  const isImage = evidence.type === 'Screenshot' || IMAGE_EXTENSIONS.has(ext);
39
31
  const isVideo = evidence.type === 'Video' || VIDEO_EXTENSIONS.has(ext);
40
32
  const isText = evidence.type === 'TestOutput' || evidence.type === 'TerminalRecording';
@@ -62,14 +54,16 @@ function EvidenceTextPreview({ url }) {
62
54
  }
63
55
  return (_jsx("pre", { className: "bg-muted/50 max-h-60 overflow-auto rounded-md p-3 font-mono text-[11px] leading-relaxed", children: content }));
64
56
  }
65
- function EvidenceList({ evidence, basePath, }) {
66
- return (_jsx("div", { className: "border-border rounded-lg border", children: _jsxs("div", { className: "px-4 py-3", children: [_jsxs("div", { className: "mb-3 flex items-center gap-2", children: [_jsx(Camera, { className: "text-muted-foreground h-4 w-4" }), _jsx("span", { className: "text-foreground text-xs font-semibold", children: "Evidence" }), _jsx(Badge, { variant: "secondary", className: "text-[10px]", children: evidence.length })] }), _jsx("ul", { className: "space-y-2", children: evidence.map((e) => (_jsx(EvidenceItem, { evidence: e, basePath: basePath }, `${e.type}-${e.relativePath}`))) })] }) }));
57
+ function EvidenceList({ evidence }) {
58
+ return (_jsx("div", { className: "border-border rounded-lg border", children: _jsxs("div", { className: "px-4 py-3", children: [_jsxs("div", { className: "mb-3 flex items-center gap-2", children: [_jsx(Camera, { className: "text-muted-foreground h-4 w-4" }), _jsx("span", { className: "text-foreground text-xs font-semibold", children: "Evidence" }), _jsx(Badge, { variant: "secondary", className: "text-[10px]", children: evidence.length })] }), _jsx("ul", { className: "space-y-2", children: evidence.map((e) => (_jsx(EvidenceItem, { evidence: e }, `${e.type}-${e.relativePath}`))) })] }) }));
67
59
  }
68
- export function MergeReview({ data, onApprove, onReject, isProcessing = false, isRejecting = false, chatInput, onChatInputChange, }) {
69
- const { pr, diffSummary, fileDiffs, branch, warning, evidence, evidenceBasePath } = data;
60
+ export function MergeReview({ data, readOnly = false, onApprove, onReject, isProcessing = false, isRejecting = false, chatInput, onChatInputChange, }) {
61
+ const { pr, diffSummary, fileDiffs, branch, warning, evidence } = data;
70
62
  const hasConflicts = pr?.mergeable === false;
71
63
  const handleApproveOrResolve = hasConflicts && onReject ? () => onReject('Resolve merge conflicts', []) : onApprove;
72
- return (_jsxs("div", { className: "flex min-h-0 flex-1 flex-col", children: [_jsxs("div", { className: "flex-1 space-y-4 overflow-y-auto p-4", children: [_jsxs("div", { className: "flex items-start gap-3", children: [_jsx("div", { className: "mt-1.5 h-2.5 w-2.5 shrink-0 rounded-full bg-emerald-500" }), _jsxs("div", { className: "flex-1", children: [_jsx("h2", { className: "text-foreground text-sm font-bold", children: "Merge Review" }), _jsx("p", { className: "text-muted-foreground mt-1 text-xs leading-relaxed", children: pr
73
- ? 'Review the pull request details and approve to merge.'
74
- : 'Review the changes and approve to merge.' })] })] }), branch ? (_jsx("div", { className: "border-border rounded-lg border", children: _jsxs("div", { className: "flex items-center gap-2 px-4 py-3", children: [_jsx(GitBranch, { className: "text-muted-foreground h-4 w-4 shrink-0" }), _jsx(Badge, { variant: "secondary", className: "font-mono text-[11px]", children: branch.source }), _jsx(ArrowRight, { className: "text-muted-foreground h-3.5 w-3.5 shrink-0" }), _jsx(Badge, { variant: "outline", className: "font-mono text-[11px]", children: branch.target })] }) })) : null, pr ? (_jsx("div", { className: "border-border rounded-lg border", children: _jsxs("div", { className: "space-y-3 px-4 py-3", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("a", { href: pr.url, target: "_blank", rel: "noopener noreferrer", className: "text-primary flex items-center gap-1.5 text-sm font-semibold underline underline-offset-2", children: ["PR #", pr.number, _jsx(ExternalLink, { className: "h-3.5 w-3.5" })] }), _jsx(Badge, { variant: "outline", className: "text-xs", children: pr.status })] }), pr.mergeable === false ? (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: "Merge Status" }), _jsxs(Badge, { className: "border-transparent bg-orange-50 text-orange-700 hover:bg-orange-50", children: [_jsx(AlertTriangle, { className: "mr-1 h-3.5 w-3.5" }), "Conflicts"] })] })) : null, pr.ciStatus ? (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: "CI Status" }), _jsx(CiStatusBadge, { status: pr.ciStatus })] })) : null, pr.commitHash ? (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: "Commit" }), _jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx(GitCommitHorizontal, { className: "text-muted-foreground h-3.5 w-3.5" }), _jsx("code", { className: "bg-muted text-foreground rounded-md px-1.5 py-0.5 font-mono text-[11px]", children: pr.commitHash.slice(0, 7) })] })] })) : null] }) })) : null, diffSummary ? (_jsx("div", { className: "border-border rounded-lg border", children: _jsxs("div", { className: "px-4 py-3", children: [_jsxs("div", { className: "mb-3 flex items-center gap-2", children: [_jsx(FileDiff, { className: "text-muted-foreground h-4 w-4" }), _jsx("span", { className: "text-foreground text-xs font-semibold", children: "Changes" })] }), _jsxs("div", { className: "grid grid-cols-4 gap-3", children: [_jsxs("div", { className: "text-center", children: [_jsx("div", { className: "text-foreground text-sm font-bold", children: diffSummary.filesChanged }), _jsx("div", { className: "text-muted-foreground text-[10px]", children: "files" })] }), _jsxs("div", { className: "text-center", children: [_jsxs("div", { className: "text-sm font-bold text-green-600", children: ["+", diffSummary.additions] }), _jsx("div", { className: "text-muted-foreground text-[10px]", children: "additions" })] }), _jsxs("div", { className: "text-center", children: [_jsxs("div", { className: "text-sm font-bold text-red-600", children: ["-", diffSummary.deletions] }), _jsx("div", { className: "text-muted-foreground text-[10px]", children: "deletions" })] }), _jsxs("div", { className: "text-center", children: [_jsx("div", { className: "text-foreground text-sm font-bold", children: diffSummary.commitCount }), _jsx("div", { className: "text-muted-foreground text-[10px]", children: "commits" })] })] })] }) })) : warning ? (_jsx("div", { className: "border-border rounded-lg border", children: _jsxs("div", { className: "flex items-center gap-2 px-4 py-3", children: [_jsx(AlertTriangle, { className: "text-muted-foreground h-4 w-4 shrink-0" }), _jsx("span", { className: "text-muted-foreground text-xs", children: warning })] }) })) : null, evidence && evidence.length > 0 ? (_jsx(EvidenceList, { evidence: evidence, basePath: evidenceBasePath })) : null, fileDiffs && fileDiffs.length > 0 ? _jsx(DiffView, { fileDiffs: fileDiffs }) : null] }), _jsx(DrawerActionBar, { onReject: onReject, onApprove: handleApproveOrResolve, approveLabel: hasConflicts ? 'Resolve Conflicts' : 'Approve Merge', approveVariant: hasConflicts ? 'warning' : 'default', revisionPlaceholder: "Ask AI to revise before merging...", isProcessing: isProcessing, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: onChatInputChange })] }));
64
+ return (_jsxs("div", { className: "flex min-h-0 flex-1 flex-col", children: [_jsxs("div", { className: "flex-1 space-y-4 overflow-y-auto p-4", children: [_jsxs("div", { className: "flex items-start gap-3", children: [_jsx("div", { className: "mt-1.5 h-2.5 w-2.5 shrink-0 rounded-full bg-emerald-500" }), _jsxs("div", { className: "flex-1", children: [_jsx("h2", { className: "text-foreground text-sm font-bold", children: readOnly ? 'Merge History' : 'Merge Review' }), _jsx("p", { className: "text-muted-foreground mt-1 text-xs leading-relaxed", children: readOnly
65
+ ? 'This feature was merged. Review the pull request details and evidence below.'
66
+ : pr
67
+ ? 'Review the pull request details and approve to merge.'
68
+ : 'Review the changes and approve to merge.' })] })] }), branch ? (_jsx("div", { className: "border-border rounded-lg border", children: _jsxs("div", { className: "flex items-center gap-2 px-4 py-3", children: [_jsx(GitBranch, { className: "text-muted-foreground h-4 w-4 shrink-0" }), _jsx(Badge, { variant: "secondary", className: "font-mono text-[11px]", children: branch.source }), _jsx(ArrowRight, { className: "text-muted-foreground h-3.5 w-3.5 shrink-0" }), _jsx(Badge, { variant: "outline", className: "font-mono text-[11px]", children: branch.target })] }) })) : null, pr ? (_jsx("div", { className: "border-border rounded-lg border", children: _jsxs("div", { className: "space-y-3 px-4 py-3", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("a", { href: pr.url, target: "_blank", rel: "noopener noreferrer", className: "text-primary flex items-center gap-1.5 text-sm font-semibold underline underline-offset-2", children: ["PR #", pr.number, _jsx(ExternalLink, { className: "h-3.5 w-3.5" })] }), _jsx(Badge, { variant: "outline", className: "text-xs", children: pr.status })] }), pr.mergeable === false ? (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: "Merge Status" }), _jsxs(Badge, { className: "border-transparent bg-orange-50 text-orange-700 hover:bg-orange-50", children: [_jsx(AlertTriangle, { className: "mr-1 h-3.5 w-3.5" }), "Conflicts"] })] })) : null, pr.ciStatus ? (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: "CI Status" }), _jsx(CiStatusBadge, { status: pr.ciStatus })] })) : null, pr.commitHash ? (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: "Commit" }), _jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx(GitCommitHorizontal, { className: "text-muted-foreground h-3.5 w-3.5" }), _jsx("code", { className: "bg-muted text-foreground rounded-md px-1.5 py-0.5 font-mono text-[11px]", children: pr.commitHash.slice(0, 7) })] })] })) : null] }) })) : null, diffSummary ? (_jsx("div", { className: "border-border rounded-lg border", children: _jsxs("div", { className: "px-4 py-3", children: [_jsxs("div", { className: "mb-3 flex items-center gap-2", children: [_jsx(FileDiff, { className: "text-muted-foreground h-4 w-4" }), _jsx("span", { className: "text-foreground text-xs font-semibold", children: "Changes" })] }), _jsxs("div", { className: "grid grid-cols-4 gap-3", children: [_jsxs("div", { className: "text-center", children: [_jsx("div", { className: "text-foreground text-sm font-bold", children: diffSummary.filesChanged }), _jsx("div", { className: "text-muted-foreground text-[10px]", children: "files" })] }), _jsxs("div", { className: "text-center", children: [_jsxs("div", { className: "text-sm font-bold text-green-600", children: ["+", diffSummary.additions] }), _jsx("div", { className: "text-muted-foreground text-[10px]", children: "additions" })] }), _jsxs("div", { className: "text-center", children: [_jsxs("div", { className: "text-sm font-bold text-red-600", children: ["-", diffSummary.deletions] }), _jsx("div", { className: "text-muted-foreground text-[10px]", children: "deletions" })] }), _jsxs("div", { className: "text-center", children: [_jsx("div", { className: "text-foreground text-sm font-bold", children: diffSummary.commitCount }), _jsx("div", { className: "text-muted-foreground text-[10px]", children: "commits" })] })] })] }) })) : warning ? (_jsx("div", { className: "border-border rounded-lg border", children: _jsxs("div", { className: "flex items-center gap-2 px-4 py-3", children: [_jsx(AlertTriangle, { className: "text-muted-foreground h-4 w-4 shrink-0" }), _jsx("span", { className: "text-muted-foreground text-xs", children: warning })] }) })) : null, evidence && evidence.length > 0 ? _jsx(EvidenceList, { evidence: evidence }) : null, fileDiffs && fileDiffs.length > 0 ? _jsx(DiffView, { fileDiffs: fileDiffs }) : null] }), !readOnly && (_jsx(DrawerActionBar, { onReject: onReject, onApprove: handleApproveOrResolve, approveLabel: hasConflicts ? 'Resolve Conflicts' : 'Approve Merge', approveVariant: hasConflicts ? 'warning' : 'default', revisionPlaceholder: "Ask AI to revise before merging...", isProcessing: isProcessing, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: onChatInputChange }))] }));
75
69
  }
@@ -25,4 +25,10 @@ export declare const NoPrNoDiff: Story;
25
25
  export declare const WithFileDiffs: Story;
26
26
  /** With evidence — shows evidence items captured during implementation. */
27
27
  export declare const WithEvidence: Story;
28
+ /** Read-only mode with full data — PR, diff summary, evidence, and file diffs. No action bar. */
29
+ export declare const ReadOnlyFullData: Story;
30
+ /** Read-only mode with evidence but no diffs — warning message shown for unavailable diffs. */
31
+ export declare const ReadOnlyEvidenceNoDiffs: Story;
32
+ /** Read-only mode with PR metadata only — no evidence, no diffs. */
33
+ export declare const ReadOnlyPrOnly: Story;
28
34
  //# sourceMappingURL=merge-review.stories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"merge-review.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/merge-review/merge-review.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AA2F7C,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,WAAW,CAclC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,WAAW,CAAC,CAAC;AAE1C,kDAAkD;AAClD,eAAO,MAAM,OAAO,EAAE,KAKrB,CAAC;AAEF,mDAAmD;AACnD,eAAO,MAAM,cAAc,EAAE,KAQ5B,CAAC;AAEF,8DAA8D;AAC9D,eAAO,MAAM,SAAS,EAAE,KAQvB,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,SAAS,EAAE,KAQvB,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,aAAa,EAAE,KAS3B,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,UAAU,EAAE,KAQxB,CAAC;AAEF,+DAA+D;AAC/D,eAAO,MAAM,UAAU,EAAE,KAMxB,CAAC;AAEF,qFAAqF;AACrF,eAAO,MAAM,YAAY,EAAE,KAQ1B,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,UAAU,EAAE,KAQxB,CAAC;AAEF,4EAA4E;AAC5E,eAAO,MAAM,aAAa,EAAE,KAQ3B,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,YAAY,EAAE,KAoC1B,CAAC"}
1
+ {"version":3,"file":"merge-review.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/merge-review/merge-review.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AA2F7C,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,WAAW,CAclC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,WAAW,CAAC,CAAC;AAE1C,kDAAkD;AAClD,eAAO,MAAM,OAAO,EAAE,KAKrB,CAAC;AAEF,mDAAmD;AACnD,eAAO,MAAM,cAAc,EAAE,KAQ5B,CAAC;AAEF,8DAA8D;AAC9D,eAAO,MAAM,SAAS,EAAE,KAQvB,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,SAAS,EAAE,KAQvB,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,aAAa,EAAE,KAS3B,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,UAAU,EAAE,KAQxB,CAAC;AAEF,+DAA+D;AAC/D,eAAO,MAAM,UAAU,EAAE,KAMxB,CAAC;AAEF,qFAAqF;AACrF,eAAO,MAAM,YAAY,EAAE,KAQ1B,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,UAAU,EAAE,KAQxB,CAAC;AAEF,4EAA4E;AAC5E,eAAO,MAAM,aAAa,EAAE,KAQ3B,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,YAAY,EAAE,KAoC1B,CAAC;AAaF,iGAAiG;AACjG,eAAO,MAAM,gBAAgB,EAAE,KA2B9B,CAAC;AAEF,+FAA+F;AAC/F,eAAO,MAAM,uBAAuB,EAAE,KAwBrC,CAAC;AAEF,oEAAoE;AACpE,eAAO,MAAM,cAAc,EAAE,KAS5B,CAAC"}
@@ -230,3 +230,77 @@ export const WithEvidence = {
230
230
  ...defaultActions,
231
231
  },
232
232
  };
233
+ /* ─── Read-Only / History Mode ─── */
234
+ const mergedPr = {
235
+ ...fullPr,
236
+ status: PrStatus.Merged,
237
+ };
238
+ const readOnlyActions = {
239
+ onApprove: fn().mockName('onApprove'),
240
+ };
241
+ /** Read-only mode with full data — PR, diff summary, evidence, and file diffs. No action bar. */
242
+ export const ReadOnlyFullData = {
243
+ args: {
244
+ data: {
245
+ pr: mergedPr,
246
+ branch: sampleBranch,
247
+ diffSummary: fullData.diffSummary,
248
+ fileDiffs: sampleFileDiffs,
249
+ evidence: [
250
+ {
251
+ type: 'Screenshot',
252
+ capturedAt: '2026-03-09T12:00:00Z',
253
+ description: 'Homepage showing new auth banner',
254
+ relativePath: '.shep/evidence/homepage-banner.png',
255
+ taskRef: 'task-1',
256
+ },
257
+ {
258
+ type: 'TestOutput',
259
+ capturedAt: '2026-03-09T12:01:00Z',
260
+ description: 'Unit tests — all 42 passing',
261
+ relativePath: '.shep/evidence/unit-test-results.txt',
262
+ taskRef: 'task-2',
263
+ },
264
+ ],
265
+ },
266
+ readOnly: true,
267
+ ...readOnlyActions,
268
+ },
269
+ };
270
+ /** Read-only mode with evidence but no diffs — warning message shown for unavailable diffs. */
271
+ export const ReadOnlyEvidenceNoDiffs = {
272
+ args: {
273
+ data: {
274
+ pr: mergedPr,
275
+ branch: sampleBranch,
276
+ warning: 'Diff statistics unavailable — worktree was removed after merge',
277
+ evidence: [
278
+ {
279
+ type: 'Screenshot',
280
+ capturedAt: '2026-03-09T12:00:00Z',
281
+ description: 'Final state of the feature',
282
+ relativePath: '.shep/evidence/final-state.png',
283
+ },
284
+ {
285
+ type: 'Video',
286
+ capturedAt: '2026-03-09T12:02:00Z',
287
+ description: 'Demo walkthrough recording',
288
+ relativePath: '.shep/evidence/demo.mp4',
289
+ },
290
+ ],
291
+ },
292
+ readOnly: true,
293
+ ...readOnlyActions,
294
+ },
295
+ };
296
+ /** Read-only mode with PR metadata only — no evidence, no diffs. */
297
+ export const ReadOnlyPrOnly = {
298
+ args: {
299
+ data: {
300
+ pr: mergedPr,
301
+ branch: sampleBranch,
302
+ },
303
+ readOnly: true,
304
+ ...readOnlyActions,
305
+ },
306
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"use-control-center-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-control-center-state.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AAejC,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAM7E,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,aAAa,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,IAAI,CAAC;IAC/D,aAAa,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAChD,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/E,YAAY,EAAE,CAAC,SAAS,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7F,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,sBAAsB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,iBAAiB,EAAE,CACjB,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,YAAY,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,EACvC,QAAQ,CAAC,EAAE,MAAM,KACd,MAAM,CAAC;IACZ,wDAAwD;IACxD,wBAAwB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACxE,gDAAgD;IAChD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IACtE,0EAA0E;IAC1E,YAAY,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;AAQD,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,cAAc,EAAE,EAC9B,YAAY,EAAE,IAAI,EAAE,GACnB,kBAAkB,CAofpB"}
1
+ {"version":3,"file":"use-control-center-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-control-center-state.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AAejC,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAM7E,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,aAAa,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,IAAI,CAAC;IAC/D,aAAa,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAChD,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/E,YAAY,EAAE,CAAC,SAAS,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7F,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,sBAAsB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,iBAAiB,EAAE,CACjB,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,YAAY,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,EACvC,QAAQ,CAAC,EAAE,MAAM,KACd,MAAM,CAAC;IACZ,wDAAwD;IACxD,wBAAwB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACxE,gDAAgD;IAChD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IACtE,0EAA0E;IAC1E,YAAY,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;AAQD,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,cAAc,EAAE,EAC9B,YAAY,EAAE,IAAI,EAAE,GACnB,kBAAkB,CAwfpB"}
@@ -114,15 +114,19 @@ export function useControlCenterState(initialNodes, initialEdges) {
114
114
  }
115
115
  }
116
116
  }, [events, updateFeature]);
117
- // Listen for optimistic approval events from the drawer (fires before SSE arrives)
117
+ // Listen for optimistic approval/rejection events from the drawer (fires before SSE arrives).
118
+ // Uses beginMutation + endMutation to prevent stale poll/reconcile data from overwriting
119
+ // the optimistic 'running' state during the transition window (avoids brief "Something went wrong" flash).
118
120
  useEffect(() => {
119
121
  const handler = (e) => {
120
122
  const { featureId } = e.detail;
123
+ beginMutation();
121
124
  updateFeature(`feat-${featureId}`, { state: 'running' });
125
+ endMutation();
122
126
  };
123
127
  window.addEventListener('shep:feature-approved', handler);
124
128
  return () => window.removeEventListener('shep:feature-approved', handler);
125
- }, [updateFeature]);
129
+ }, [updateFeature, beginMutation, endMutation]);
126
130
  // Separate effect: fetch metadata (name + description) when SSE reports it changed
127
131
  const metadataFetchedRef = useRef(new Set());
128
132
  const processedMetadataCountRef = useRef(0);