@shepai/cli 1.113.0 → 1.114.0-pr361.c9914c5

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 (190) hide show
  1. package/dist/src/presentation/web/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.d.ts.map +1 -1
  2. package/dist/src/presentation/web/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js +4 -0
  3. package/dist/src/presentation/web/app/(dashboard)/@drawer/feature/[featureId]/page.d.ts.map +1 -1
  4. package/dist/src/presentation/web/app/(dashboard)/@drawer/feature/[featureId]/page.js +6 -1
  5. package/dist/src/presentation/web/app/(dashboard)/get-graph-data.d.ts.map +1 -1
  6. package/dist/src/presentation/web/app/(dashboard)/get-graph-data.js +6 -1
  7. package/dist/src/presentation/web/app/actions/get-feature-drawer-data.d.ts.map +1 -1
  8. package/dist/src/presentation/web/app/actions/get-feature-drawer-data.js +4 -0
  9. package/dist/src/presentation/web/app/build-feature-node-data.d.ts +4 -0
  10. package/dist/src/presentation/web/app/build-feature-node-data.d.ts.map +1 -1
  11. package/dist/src/presentation/web/app/build-feature-node-data.js +5 -0
  12. package/dist/src/presentation/web/app/build-graph-nodes.d.ts +7 -1
  13. package/dist/src/presentation/web/app/build-graph-nodes.d.ts.map +1 -1
  14. package/dist/src/presentation/web/app/build-graph-nodes.js +9 -12
  15. package/dist/src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.d.ts +5 -0
  16. package/dist/src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.d.ts.map +1 -0
  17. package/dist/src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.js +115 -0
  18. package/dist/src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.stories.d.ts +18 -0
  19. package/dist/src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.stories.d.ts.map +1 -0
  20. package/dist/src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.stories.js +88 -0
  21. package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.d.ts.map +1 -1
  22. package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.js +10 -2
  23. package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.stories.d.ts +5 -3
  24. package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.stories.d.ts.map +1 -1
  25. package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.stories.js +92 -9
  26. package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.d.ts.map +1 -1
  27. package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.js +17 -2
  28. package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.stories.d.ts +10 -0
  29. package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.stories.d.ts.map +1 -1
  30. package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.stories.js +69 -0
  31. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts +14 -0
  32. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts.map +1 -1
  33. package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
  34. package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +28 -7
  35. package/dist/src/presentation/web/hooks/use-viewport-persistence.d.ts +2 -0
  36. package/dist/src/presentation/web/hooks/use-viewport-persistence.d.ts.map +1 -1
  37. package/dist/src/presentation/web/hooks/use-viewport-persistence.js +19 -6
  38. package/dist/src/presentation/web/lib/layout-with-dagre.d.ts.map +1 -1
  39. package/dist/src/presentation/web/lib/layout-with-dagre.js +11 -2
  40. package/dist/src/presentation/web/lib/parse-log-line.d.ts +49 -0
  41. package/dist/src/presentation/web/lib/parse-log-line.d.ts.map +1 -0
  42. package/dist/src/presentation/web/lib/parse-log-line.js +126 -0
  43. package/dist/tsconfig.build.tsbuildinfo +1 -1
  44. package/package.json +1 -1
  45. package/web/.next/BUILD_ID +1 -1
  46. package/web/.next/build-manifest.json +2 -2
  47. package/web/.next/fallback-build-manifest.json +2 -2
  48. package/web/.next/prerender-manifest.json +3 -3
  49. package/web/.next/required-server-files.js +3 -3
  50. package/web/.next/required-server-files.json +3 -3
  51. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +20 -20
  52. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  53. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  54. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +26 -26
  55. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  56. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  57. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +26 -26
  58. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  59. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  60. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +18 -18
  61. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  62. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  63. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +20 -20
  64. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  65. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  66. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +26 -26
  67. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  68. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  69. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +26 -26
  70. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  71. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  72. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +18 -18
  73. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  74. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  75. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +18 -18
  76. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  77. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  78. package/web/.next/server/app/_global-error.html +2 -2
  79. package/web/.next/server/app/_global-error.rsc +1 -1
  80. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  81. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  82. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  83. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  84. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  85. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  86. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  87. package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
  88. package/web/.next/server/app/api/cli-upgrade/route.js +2 -2
  89. package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
  90. package/web/.next/server/app/settings/page/server-reference-manifest.json +5 -5
  91. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  92. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  93. package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  94. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  95. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  96. package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  97. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  98. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  99. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  100. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  101. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js +1 -1
  102. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js.map +1 -1
  103. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  104. package/web/.next/server/chunks/[root-of-the-server]__d2c18946._.js +2 -2
  105. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  106. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  107. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_a1104008.js +1 -1
  108. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_a1104008.js.map +1 -1
  109. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_92642200.js +1 -1
  110. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_92642200.js.map +1 -1
  111. package/web/.next/server/chunks/ssr/[root-of-the-server]__039967e3._.js +1 -1
  112. package/web/.next/server/chunks/ssr/[root-of-the-server]__039967e3._.js.map +1 -1
  113. package/web/.next/server/chunks/ssr/[root-of-the-server]__07a39ff2._.js +1 -1
  114. package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js +1 -1
  115. package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js.map +1 -1
  116. package/web/.next/server/chunks/ssr/[root-of-the-server]__24dd0927._.js +2 -2
  117. package/web/.next/server/chunks/ssr/[root-of-the-server]__2773312c._.js +1 -1
  118. package/web/.next/server/chunks/ssr/[root-of-the-server]__2773312c._.js.map +1 -1
  119. package/web/.next/server/chunks/ssr/[root-of-the-server]__5d87af2e._.js +1 -1
  120. package/web/.next/server/chunks/ssr/[root-of-the-server]__6367aea0._.js +1 -1
  121. package/web/.next/server/chunks/ssr/[root-of-the-server]__6367aea0._.js.map +1 -1
  122. package/web/.next/server/chunks/ssr/[root-of-the-server]__684a868c._.js +1 -1
  123. package/web/.next/server/chunks/ssr/[root-of-the-server]__684a868c._.js.map +1 -1
  124. package/web/.next/server/chunks/ssr/[root-of-the-server]__89e8a5cc._.js +2 -2
  125. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +2 -2
  126. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
  127. package/web/.next/server/chunks/ssr/[root-of-the-server]__b1e68e34._.js +3 -0
  128. package/web/.next/server/chunks/ssr/{[root-of-the-server]__d91fdd51._.js.map → [root-of-the-server]__b1e68e34._.js.map} +1 -1
  129. package/web/.next/server/chunks/ssr/[root-of-the-server]__c16bf5de._.js +1 -1
  130. package/web/.next/server/chunks/ssr/[root-of-the-server]__c16bf5de._.js.map +1 -1
  131. package/web/.next/server/chunks/ssr/[root-of-the-server]__cbd8062c._.js +1 -1
  132. package/web/.next/server/chunks/ssr/[root-of-the-server]__cbd8062c._.js.map +1 -1
  133. package/web/.next/server/chunks/ssr/[root-of-the-server]__e70c5627._.js +1 -1
  134. package/web/.next/server/chunks/ssr/[root-of-the-server]__e70c5627._.js.map +1 -1
  135. package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js +1 -1
  136. package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js.map +1 -1
  137. package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
  138. package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
  139. package/web/.next/server/chunks/ssr/{_fcfc1141._.js → _174489cc._.js} +2 -2
  140. package/web/.next/server/chunks/ssr/{_fcfc1141._.js.map → _174489cc._.js.map} +1 -1
  141. package/web/.next/server/chunks/ssr/{_88e359a0._.js → _5f564526._.js} +2 -2
  142. package/web/.next/server/chunks/ssr/{_88e359a0._.js.map → _5f564526._.js.map} +1 -1
  143. package/web/.next/server/chunks/ssr/{_e6b5ebbd._.js → _605157e5._.js} +2 -2
  144. package/web/.next/server/chunks/ssr/{_e6b5ebbd._.js.map → _605157e5._.js.map} +1 -1
  145. package/web/.next/server/chunks/ssr/_8dacd1e7._.js +1 -1
  146. package/web/.next/server/chunks/ssr/_8dacd1e7._.js.map +1 -1
  147. package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
  148. package/web/.next/server/chunks/ssr/_cc77a143._.js.map +1 -1
  149. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  150. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  151. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_888633e1.js +1 -1
  152. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_888633e1.js.map +1 -1
  153. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
  154. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
  155. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
  156. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
  157. package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js +1 -1
  158. package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js.map +1 -1
  159. package/web/.next/server/chunks/ssr/src_presentation_web_ce7cbc3c._.js +2 -2
  160. package/web/.next/server/chunks/ssr/src_presentation_web_ce7cbc3c._.js.map +1 -1
  161. package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
  162. package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js.map +1 -1
  163. package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +1 -1
  164. package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js.map +1 -1
  165. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  166. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  167. package/web/.next/server/chunks/ssr/src_presentation_web_e2604413._.js +2 -2
  168. package/web/.next/server/chunks/ssr/src_presentation_web_e2604413._.js.map +1 -1
  169. package/web/.next/server/pages/500.html +2 -2
  170. package/web/.next/server/server-reference-manifest.js +1 -1
  171. package/web/.next/server/server-reference-manifest.json +31 -31
  172. package/web/.next/static/chunks/{af4d18c173729fc0.js → 04de201e125688be.js} +1 -1
  173. package/web/.next/static/chunks/{7249bab754695c9b.js → 1b9cd00f0260dc94.js} +2 -2
  174. package/web/.next/static/chunks/{1213d5af738d8e44.js → 285373584362256a.js} +1 -1
  175. package/web/.next/static/chunks/{45687d169255cd7a.js → 4ae58f388ee0a927.js} +1 -1
  176. package/web/.next/static/chunks/{ebf7b7a1414b813f.js → 4ec746230535814b.js} +1 -1
  177. package/web/.next/static/chunks/57b45edf86522369.css +1 -0
  178. package/web/.next/static/chunks/{d3ae2e0768e0361a.js → 9b8df96f693d7509.js} +1 -1
  179. package/web/.next/static/chunks/b1f3c0e8e9872ef8.js +1 -0
  180. package/web/.next/static/chunks/{9bfafbbd2d362548.js → ca316d69021e3799.js} +2 -2
  181. package/web/.next/static/chunks/{0e3793f87c0d2be4.js → d36f7fcbbd2bc9e5.js} +1 -1
  182. package/web/.next/static/chunks/d5a710e0c22e97f7.js +1 -0
  183. package/web/.next/static/chunks/{e870d8454835338c.js → f4a43c0fecb47dbd.js} +1 -1
  184. package/web/.next/server/chunks/ssr/[root-of-the-server]__d91fdd51._.js +0 -3
  185. package/web/.next/static/chunks/07b853e29af1e5f2.js +0 -1
  186. package/web/.next/static/chunks/694fc9a1173043d8.css +0 -1
  187. package/web/.next/static/chunks/e7d33f2288fea0d0.js +0 -1
  188. /package/web/.next/static/{f-Ju5FEgjPPi1hAjRWRoZ → qW3bkLKlrX8uFT2umfH8C}/_buildManifest.js +0 -0
  189. /package/web/.next/static/{f-Ju5FEgjPPi1hAjRWRoZ → qW3bkLKlrX8uFT2umfH8C}/_clientMiddlewareManifest.json +0 -0
  190. /package/web/.next/static/{f-Ju5FEgjPPi1hAjRWRoZ → qW3bkLKlrX8uFT2umfH8C}/_ssgManifest.js +0 -0
@@ -8,14 +8,61 @@ const meta = {
8
8
  layout: 'fullscreen',
9
9
  },
10
10
  decorators: [
11
- (Story) => (_jsx("div", { style: { height: '600px', width: '400px', border: '1px solid var(--color-border)' }, children: _jsx(Story, {}) })),
11
+ (Story) => (_jsx("div", { style: { height: '600px', width: '480px', border: '1px solid var(--color-border)' }, children: _jsx(Story, {}) })),
12
12
  ],
13
13
  };
14
14
  export default meta;
15
15
  /* ---------------------------------------------------------------------------
16
16
  * Data fixtures
17
17
  * ------------------------------------------------------------------------- */
18
- const typicalLogContent = `[2026-03-08T10:00:01.123Z] Starting agent run for feature "auth-module"
18
+ const structuredLogContent = `[2026-03-08T10:00:01.000Z] [claude-code|claude-sonnet-4-6] [WORKER] Starting worker full command:
19
+ [2026-03-08T10:00:01.001Z] [claude-code|claude-sonnet-4-6] [WORKER] feature-agent-worker --feature-id auth-module --run-id run-123 --repo /home/user/myproject --agent-type claude-code --model claude-sonnet-4-6
20
+ [2026-03-08T10:00:01.010Z] [claude-code|claude-sonnet-4-6] [WORKER] Initializing container...
21
+ [2026-03-08T10:00:01.050Z] [claude-code|claude-sonnet-4-6] [WORKER] Creating executor from pinned agent type: claude-code
22
+ [2026-03-08T10:00:01.100Z] [claude-code|claude-sonnet-4-6] [WORKER] Updating status to running (PID 54321)...
23
+ [2026-03-08T10:00:01.110Z] [claude-code|claude-sonnet-4-6] [WORKER] Starting graph invocation...
24
+ [2026-03-08T10:00:05.000Z] [requirements] [claude-code|claude-sonnet-4-6] Starting...
25
+ [2026-03-08T10:00:05.010Z] [requirements] [claude-code|claude-sonnet-4-6] Executing agent at cwd=/home/user/myproject
26
+ [2026-03-08T10:00:05.020Z] [requirements] [claude-code|claude-sonnet-4-6] Prompt length: 2847 chars
27
+ [2026-03-08T10:00:05.100Z] [requirements] [claude-code|claude-sonnet-4-6] Spawning: claude -p "Analyze this project..." --output-format stream-json --verbose
28
+ [2026-03-08T10:00:05.102Z] [requirements] [claude-code|claude-sonnet-4-6] Subprocess PID: 54322
29
+ [2026-03-08T10:00:08.234Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Read {"file_path": "src/main.ts"}
30
+ [2026-03-08T10:00:10.345Z] [requirements] [claude-code|claude-sonnet-4-6] [text] Analyzing the codebase structure and identifying key entry points for the authentication module
31
+ [2026-03-08T10:00:12.567Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Glob {"pattern": "src/**/*.ts"}
32
+ [2026-03-08T10:00:14.789Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Read {"file_path": "src/auth/providers.ts"}
33
+ [2026-03-08T10:00:16.012Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Grep {"pattern": "interface.*Auth", "path": "src/"}
34
+ [2026-03-08T10:00:18.234Z] [requirements] [claude-code|claude-sonnet-4-6] [text] The project uses a clean architecture pattern with dependency injection. I can see the auth interfaces are defined in the domain layer
35
+ [2026-03-08T10:00:20.456Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Bash {"command": "find src -name '*.test.ts' | wc -l"}
36
+ [2026-03-08T10:00:45.789Z] [requirements] [claude-code|claude-sonnet-4-6] [result] 8920 chars, session=sess-abc123def456
37
+ [2026-03-08T10:00:45.790Z] [requirements] [claude-code|claude-sonnet-4-6] [tokens] 2450 in / 4560 out
38
+ [2026-03-08T10:00:45.791Z] [requirements] [claude-code|claude-sonnet-4-6] Process closed with code 0, result=8920 chars
39
+ [2026-03-08T10:00:45.800Z] [requirements] [claude-code|claude-sonnet-4-6] Complete (8920 chars, 40.8s)
40
+ [2026-03-08T10:00:45.900Z] [requirements] [claude-code|claude-sonnet-4-6] Interrupting for human approval
41
+ [2026-03-08T10:02:30.000Z] [requirements] [claude-code|claude-sonnet-4-6] Phase approved, skipping re-execution
42
+ [2026-03-08T10:02:30.100Z] [plan] [claude-code|claude-sonnet-4-6] Starting...
43
+ [2026-03-08T10:02:30.110Z] [plan] [claude-code|claude-sonnet-4-6] Executing agent at cwd=/home/user/myproject
44
+ [2026-03-08T10:02:30.120Z] [plan] [claude-code|claude-sonnet-4-6] Prompt length: 15234 chars
45
+ [2026-03-08T10:02:35.100Z] [plan] [claude-code|claude-sonnet-4-6] [tool] Read {"file_path": "CLAUDE.md"}
46
+ [2026-03-08T10:02:38.200Z] [plan] [claude-code|claude-sonnet-4-6] [text] Creating implementation plan with TDD approach as required by project conventions
47
+ [2026-03-08T10:02:42.300Z] [plan] [claude-code|claude-sonnet-4-6] [tool] Write {"file_path": "specs/001-auth/plan.yaml"}
48
+ [2026-03-08T10:02:45.400Z] [plan] [claude-code|claude-sonnet-4-6] [text] Plan includes 3 phases: scaffold auth module, implement OAuth2 providers, add tests and documentation
49
+ [2026-03-08T10:03:15.234Z] [plan] [claude-code|claude-sonnet-4-6] [result] 12345 chars, session=sess-abc123def456
50
+ [2026-03-08T10:03:15.235Z] [plan] [claude-code|claude-sonnet-4-6] [tokens] 8900 in / 3456 out
51
+ [2026-03-08T10:03:15.300Z] [plan] [claude-code|claude-sonnet-4-6] Complete (12345 chars, 45.1s)
52
+ [2026-03-08T10:05:00.000Z] [implement] [claude-code|claude-sonnet-4-6] Starting...
53
+ [2026-03-08T10:05:01.000Z] [implement] [claude-code|claude-sonnet-4-6] [tool] Write {"file_path": "src/auth/oauth-provider.ts"}
54
+ [2026-03-08T10:05:03.000Z] [implement] [claude-code|claude-sonnet-4-6] [tool] Write {"file_path": "src/auth/token-manager.ts"}
55
+ [2026-03-08T10:05:05.000Z] [implement] [claude-code|claude-sonnet-4-6] [tool] Edit {"file_path": "src/auth/index.ts"}
56
+ [2026-03-08T10:05:07.000Z] [implement] [claude-code|claude-sonnet-4-6] [tool] Bash {"command": "pnpm test:unit"}
57
+ [2026-03-08T10:05:30.000Z] [implement] [claude-code|claude-sonnet-4-6] [text] All 14 unit tests passing. Moving to integration tests
58
+ [2026-03-08T10:05:35.000Z] [implement] [claude-code|claude-sonnet-4-6] [tool] Bash {"command": "pnpm test:int"}
59
+ [2026-03-08T10:05:55.000Z] [implement] [claude-code|claude-sonnet-4-6] [result] 24560 chars, session=sess-abc123def456
60
+ [2026-03-08T10:05:55.001Z] [implement] [claude-code|claude-sonnet-4-6] [tokens] 15200 in / 9360 out
61
+ [2026-03-08T10:05:55.100Z] [implement] [claude-code|claude-sonnet-4-6] Complete (24560 chars, 54.1s)
62
+ [2026-03-08T10:06:00.000Z] [claude-code|claude-sonnet-4-6] [WORKER] Graph invocation completed. Error: none
63
+ [2026-03-08T10:06:00.100Z] [claude-code|claude-sonnet-4-6] [WORKER] Run marked as completed
64
+ [2026-03-08T10:06:00.200Z] [claude-code|claude-sonnet-4-6] [WORKER] Worker completed successfully, exiting.`;
65
+ const rawLogContent = `[2026-03-08T10:00:01.123Z] Starting agent run for feature "auth-module"
19
66
  [2026-03-08T10:00:02.789Z] Agent started — analyzing codebase
20
67
  [2026-03-08T10:00:03.456Z] Scanning repository structure...
21
68
  [2026-03-08T10:00:04.012Z] Found 127 source files across 14 packages
@@ -35,22 +82,58 @@ const typicalLogContent = `[2026-03-08T10:00:01.123Z] Starting agent run for fea
35
82
  [2026-03-08T10:00:24.789Z] Phase 3: add tests and documentation
36
83
  [2026-03-08T10:00:26.456Z] Generating test suite...
37
84
  [2026-03-08T10:00:28.012Z] All phases complete — feature "auth-module" ready for review`;
38
- const longLogContent = Array.from({ length: 200 }, (_, i) => `[2026-03-08T10:${String(Math.floor(i / 60)).padStart(2, '0')}:${String(i % 60).padStart(2, '0')}.${String((i * 7) % 1000).padStart(3, '0')}Z] Step ${i + 1}: processing task batch ${Math.floor(i / 10) + 1} — file ${i + 1} of 200`).join('\n');
85
+ const longStructuredContent = Array.from({ length: 100 }, (_, i) => {
86
+ const min = String(Math.floor(i / 60)).padStart(2, '0');
87
+ const sec = String(i % 60).padStart(2, '0');
88
+ const ms = String((i * 7) % 1000).padStart(3, '0');
89
+ const ts = `2026-03-08T10:${min}:${sec}.${ms}Z`;
90
+ const phase = ['requirements', 'research', 'plan', 'implement'][i % 4];
91
+ const tags = ['[tool]', '[text]', '[tool]', '[text]', '[result]', '[tokens]'];
92
+ const tag = tags[i % tags.length];
93
+ const messages = {
94
+ '[tool]': [
95
+ 'Read {"file_path": "src/components/button.tsx"}',
96
+ 'Bash {"command": "pnpm test:unit"}',
97
+ 'Grep {"pattern": "export function", "path": "src/"}',
98
+ 'Write {"file_path": "src/new-file.ts"}',
99
+ 'Glob {"pattern": "**/*.test.ts"}',
100
+ ],
101
+ '[text]': [
102
+ 'Analyzing the component structure for potential improvements',
103
+ 'The test suite is comprehensive with good coverage',
104
+ 'Implementing the authentication flow with OAuth2 providers',
105
+ 'Refactoring to use dependency injection pattern',
106
+ ],
107
+ '[result]': ['4520 chars, session=sess-xyz789'],
108
+ '[tokens]': ['3200 in / 1800 out'],
109
+ };
110
+ const msgList = messages[tag] ?? messages['[text]'];
111
+ const msg = msgList[i % msgList.length];
112
+ return `[${ts}] [${phase}] [claude-code|claude-sonnet-4-6] ${tag} ${msg}`;
113
+ }).join('\n');
39
114
  /* ---------------------------------------------------------------------------
40
115
  * Stories
41
116
  * ------------------------------------------------------------------------- */
42
- /** Default — typical agent log output with live connection. */
117
+ /** Default — structured agent log output with live connection (claude-code). */
43
118
  export const Default = {
44
119
  args: {
45
- content: typicalLogContent,
120
+ content: structuredLogContent,
46
121
  isConnected: true,
47
122
  error: null,
48
123
  },
49
124
  };
50
- /** LongLog200 lines of log output to test scrolling behavior. */
51
- export const LongLog = {
125
+ /** LongStructured100 structured events to test scrolling behavior. */
126
+ export const LongStructured = {
52
127
  args: {
53
- content: longLogContent,
128
+ content: longStructuredContent,
129
+ isConnected: true,
130
+ error: null,
131
+ },
132
+ };
133
+ /** RawFallback — unstructured log content falls back gracefully. */
134
+ export const RawFallback = {
135
+ args: {
136
+ content: rawLogContent,
54
137
  isConnected: true,
55
138
  error: null,
56
139
  },
@@ -58,7 +141,7 @@ export const LongLog = {
58
141
  /** Disconnected — log content present but connection is lost. */
59
142
  export const Disconnected = {
60
143
  args: {
61
- content: typicalLogContent,
144
+ content: structuredLogContent,
62
145
  isConnected: false,
63
146
  error: null,
64
147
  },
@@ -1 +1 @@
1
- {"version":3,"file":"overview-tab.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/overview-tab.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAOxE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,eAAe,CAAC;CACvB;AAED,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE,gBAAgB,2CAoDrD"}
1
+ {"version":3,"file":"overview-tab.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/overview-tab.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAQxE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,eAAe,CAAC;CACvB;AAED,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE,gBAAgB,2CAqDrD"}
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { useState, useEffect, useRef } from 'react';
4
- import { AlertTriangle, ExternalLink, GitBranch, GitCommitHorizontal, RotateCcw, Zap, } from 'lucide-react';
4
+ import { AlertTriangle, Check, ExternalLink, FileSearch, GitBranch, GitCommitHorizontal, RotateCcw, ShieldCheck, X, Zap, } from 'lucide-react';
5
5
  import { InlineAttachments } from '../../common/inline-attachments/index.js';
6
6
  import { PrStatus } from '../../../../../../packages/core/src/domain/generated/output.js';
7
7
  import { cn } from '../../../lib/utils.js';
@@ -11,10 +11,11 @@ import { CiStatusBadge } from '../../common/ci-status-badge/index.js';
11
11
  import { CometSpinner } from '../../ui/comet-spinner.js';
12
12
  import { featureNodeStateConfig, lifecycleDisplayLabels } from '../../common/feature-node/index.js';
13
13
  import { getAgentTypeIcon, agentTypeLabels, } from '../../common/feature-node/agent-type-icons.js';
14
+ import { getModelMeta } from '../../../lib/model-metadata.js';
14
15
  import { formatDuration } from '../../../lib/format-duration.js';
15
16
  export function OverviewTab({ data }) {
16
17
  const isCompleted = data.lifecycle === 'maintain';
17
- return (_jsxs(_Fragment, { children: [_jsxs("div", { "data-testid": "feature-drawer-status", className: "flex flex-col gap-3 p-4", children: [_jsx("div", { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: lifecycleDisplayLabels[data.lifecycle] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(FeatureStateBadge, { data: data }), data.state === 'error' && data.onRetry ? (_jsxs("button", { "data-testid": "feature-drawer-retry-button", onClick: () => data.onRetry(data.featureId), className: "flex shrink-0 cursor-pointer items-center gap-1.5 rounded-full bg-red-50 px-3 py-1.5 text-sm font-medium text-red-700 transition-colors hover:bg-red-100", children: [_jsx(RotateCcw, { className: "h-3.5 w-3.5" }), "Retry"] })) : null] }), !isCompleted && data.progress > 0 ? (_jsxs("div", { "data-testid": "feature-drawer-progress", className: "flex flex-col gap-1", children: [_jsxs("div", { className: "text-muted-foreground flex items-center justify-between text-xs", children: [_jsx("span", { children: "Progress" }), _jsxs("span", { children: [data.progress, "%"] })] }), _jsx("div", { className: "bg-muted h-2 w-full overflow-hidden rounded-full", children: _jsx("div", { className: cn('h-full rounded-full transition-all', featureNodeStateConfig[data.state].progressClass), style: { width: `${data.progress}%` } }) })] })) : null, isCompleted && data.pr ? _jsx(FeaturePrInfo, { pr: data.pr }) : null] }), _jsx(FeatureInfo, { data: data }), !isCompleted && data.pr ? (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsx("div", { className: "p-4", children: _jsx(FeaturePrInfo, { pr: data.pr }) })] })) : null, _jsx(FeatureDetails, { data: data })] }));
18
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { "data-testid": "feature-drawer-status", className: "flex flex-col gap-3 p-4", children: [_jsx("div", { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: lifecycleDisplayLabels[data.lifecycle] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(FeatureStateBadge, { data: data }), data.state === 'error' && data.onRetry ? (_jsxs("button", { "data-testid": "feature-drawer-retry-button", onClick: () => data.onRetry(data.featureId), className: "flex shrink-0 cursor-pointer items-center gap-1.5 rounded-full bg-red-50 px-3 py-1.5 text-sm font-medium text-red-700 transition-colors hover:bg-red-100", children: [_jsx(RotateCcw, { className: "h-3.5 w-3.5" }), "Retry"] })) : null] }), !isCompleted && data.progress > 0 ? (_jsxs("div", { "data-testid": "feature-drawer-progress", className: "flex flex-col gap-1", children: [_jsxs("div", { className: "text-muted-foreground flex items-center justify-between text-xs", children: [_jsx("span", { children: "Progress" }), _jsxs("span", { children: [data.progress, "%"] })] }), _jsx("div", { className: "bg-muted h-2 w-full overflow-hidden rounded-full", children: _jsx("div", { className: cn('h-full rounded-full transition-all', featureNodeStateConfig[data.state].progressClass), style: { width: `${data.progress}%` } }) })] })) : null, isCompleted && data.pr ? _jsx(FeaturePrInfo, { pr: data.pr }) : null] }), _jsx(FeatureInfo, { data: data }), !isCompleted && data.pr ? (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsx("div", { className: "p-4", children: _jsx(FeaturePrInfo, { pr: data.pr }) })] })) : null, _jsx(FeatureDetails, { data: data }), _jsx(FeatureSettings, { data: data })] }));
18
19
  }
19
20
  function FeatureStateBadge({ data }) {
20
21
  const config = featureNodeStateConfig[data.state];
@@ -108,6 +109,20 @@ function AgentDetailRow({ agentType }) {
108
109
  const label = agentTypeLabels[agentType] ?? agentType;
109
110
  return (_jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: "Agent" }), _jsxs("span", { className: "flex items-center gap-2 text-sm", children: [_jsx(Icon, { className: "h-4 w-4 shrink-0" }), label] })] }));
110
111
  }
112
+ // ── Settings section ─────────────────────────────────────────────────
113
+ function SettingBadge({ enabled, label }) {
114
+ return (_jsxs("span", { className: cn('inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium', enabled ? 'bg-emerald-50 text-emerald-700' : 'bg-muted text-muted-foreground'), children: [enabled ? _jsx(Check, { className: "h-3 w-3" }) : _jsx(X, { className: "h-3 w-3" }), label] }));
115
+ }
116
+ function FeatureSettings({ data }) {
117
+ const hasSettings = data.approvalGates != null ||
118
+ data.push != null ||
119
+ data.openPr != null ||
120
+ data.enableEvidence != null ||
121
+ data.modelId;
122
+ if (!hasSettings)
123
+ return null;
124
+ return (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsxs("div", { "data-testid": "feature-drawer-settings", className: "flex flex-col gap-3 p-4", children: [_jsx("span", { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "SETTINGS" }), data.modelId ? (_jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: "Model" }), _jsx("span", { className: "text-sm", children: getModelMeta(data.modelId).displayName || data.modelId })] })) : null, data.approvalGates ? (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsxs("span", { className: "text-muted-foreground flex items-center gap-1 text-xs font-medium", children: [_jsx(ShieldCheck, { className: "h-3 w-3" }), "Auto-Approve"] }), _jsxs("div", { className: "flex flex-wrap gap-1.5", children: [_jsx(SettingBadge, { enabled: data.approvalGates.allowPrd, label: "PRD" }), _jsx(SettingBadge, { enabled: data.approvalGates.allowPlan, label: "Plan" }), _jsx(SettingBadge, { enabled: data.approvalGates.allowMerge, label: "Merge" })] })] })) : null, data.enableEvidence != null ? (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsxs("span", { className: "text-muted-foreground flex items-center gap-1 text-xs font-medium", children: [_jsx(FileSearch, { className: "h-3 w-3" }), "Evidence"] }), _jsxs("div", { className: "flex flex-wrap gap-1.5", children: [_jsx(SettingBadge, { enabled: data.enableEvidence, label: "Collect" }), data.commitEvidence != null ? (_jsx(SettingBadge, { enabled: data.commitEvidence, label: "Add to PR" })) : null] })] })) : null, data.push != null || data.openPr != null ? (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsxs("span", { className: "text-muted-foreground flex items-center gap-1 text-xs font-medium", children: [_jsx(GitBranch, { className: "h-3 w-3" }), "Git"] }), _jsxs("div", { className: "flex flex-wrap gap-1.5", children: [data.push != null ? _jsx(SettingBadge, { enabled: data.push, label: "Push" }) : null, data.openPr != null ? _jsx(SettingBadge, { enabled: data.openPr, label: "PR" }) : null] })] })) : null] })] }));
125
+ }
111
126
  function DetailRow({ label, value }) {
112
127
  return (_jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: label }), _jsx("span", { className: "text-sm", children: value })] }));
113
128
  }
@@ -37,4 +37,14 @@ export declare const DuplicateSummaryHidden: Story;
37
37
  export declare const DifferentSummary: Story;
38
38
  /** Completed feature with PR — progress hidden, PR shown in status section without borders. */
39
39
  export declare const CompletedWithPr: Story;
40
+ /** Feature with all settings visible — approval gates, evidence, git, and model. */
41
+ export declare const WithAllSettings: Story;
42
+ /** Feature with no auto-approve gates enabled. */
43
+ export declare const WithSettingsAllDisabled: Story;
44
+ /** Feature with all auto-approve gates enabled. */
45
+ export declare const WithSettingsAllApproved: Story;
46
+ /** Feature with settings and fast mode. */
47
+ export declare const FastModeWithSettings: Story;
48
+ /** Feature with evidence enabled but commit to PR disabled. */
49
+ export declare const EvidenceCollectOnly: Story;
40
50
  //# sourceMappingURL=overview-tab.stories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"overview-tab.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/overview-tab.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,WAAW,CAclC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,WAAW,CAAC,CAAC;AA0G1C,uEAAuE;AACvE,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,IAAI,EAAE,KAElB,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,UAAU,EAAE,KAExB,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,gBAAgB,EAAE,KAE9B,CAAC;AAEF,iDAAiD;AACjD,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,gDAAgD;AAChD,eAAO,MAAM,KAAK,EAAE,KAEnB,CAAC;AAOF,6CAA6C;AAC7C,eAAO,MAAM,cAAc,EAAE,KAE5B,CAAC;AAEF,sEAAsE;AACtE,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAwBF,mEAAmE;AACnE,eAAO,MAAM,QAAQ,EAAE,KAEtB,CAAC;AAMF,0BAA0B;AAC1B,eAAO,MAAM,iBAAiB,EAAE,KAE/B,CAAC;AAEF,sBAAsB;AACtB,eAAO,MAAM,aAAa,EAAE,KAE3B,CAAC;AAEF,oBAAoB;AACpB,eAAO,MAAM,WAAW,EAAE,KAEzB,CAAC;AAEF,sBAAsB;AACtB,eAAO,MAAM,aAAa,EAAE,KAE3B,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,oBAAoB,EAAE,KAclC,CAAC;AAqBF,4DAA4D;AAC5D,eAAO,MAAM,sBAAsB,EAAE,KAEpC,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,gBAAgB,EAAE,KAO9B,CAAC;AAEF,+FAA+F;AAC/F,eAAO,MAAM,eAAe,EAAE,KAgB7B,CAAC"}
1
+ {"version":3,"file":"overview-tab.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/overview-tab.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,WAAW,CAclC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,WAAW,CAAC,CAAC;AA0G1C,uEAAuE;AACvE,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,IAAI,EAAE,KAElB,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,UAAU,EAAE,KAExB,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,gBAAgB,EAAE,KAE9B,CAAC;AAEF,iDAAiD;AACjD,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,gDAAgD;AAChD,eAAO,MAAM,KAAK,EAAE,KAEnB,CAAC;AAOF,6CAA6C;AAC7C,eAAO,MAAM,cAAc,EAAE,KAE5B,CAAC;AAEF,sEAAsE;AACtE,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAwBF,mEAAmE;AACnE,eAAO,MAAM,QAAQ,EAAE,KAEtB,CAAC;AAMF,0BAA0B;AAC1B,eAAO,MAAM,iBAAiB,EAAE,KAE/B,CAAC;AAEF,sBAAsB;AACtB,eAAO,MAAM,aAAa,EAAE,KAE3B,CAAC;AAEF,oBAAoB;AACpB,eAAO,MAAM,WAAW,EAAE,KAEzB,CAAC;AAEF,sBAAsB;AACtB,eAAO,MAAM,aAAa,EAAE,KAE3B,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,oBAAoB,EAAE,KAclC,CAAC;AAqBF,4DAA4D;AAC5D,eAAO,MAAM,sBAAsB,EAAE,KAEpC,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,gBAAgB,EAAE,KAO9B,CAAC;AAEF,+FAA+F;AAC/F,eAAO,MAAM,eAAe,EAAE,KAgB7B,CAAC;AAMF,oFAAoF;AACpF,eAAO,MAAM,eAAe,EAAE,KAY7B,CAAC;AAEF,kDAAkD;AAClD,eAAO,MAAM,uBAAuB,EAAE,KAYrC,CAAC;AAEF,mDAAmD;AACnD,eAAO,MAAM,uBAAuB,EAAE,KAYrC,CAAC;AAEF,2CAA2C;AAC3C,eAAO,MAAM,oBAAoB,EAAE,KAYlC,CAAC;AAEF,+DAA+D;AAC/D,eAAO,MAAM,mBAAmB,EAAE,KAQjC,CAAC"}
@@ -252,3 +252,72 @@ export const CompletedWithPr = {
252
252
  },
253
253
  },
254
254
  };
255
+ /* ---------------------------------------------------------------------------
256
+ * Settings section stories
257
+ * ------------------------------------------------------------------------- */
258
+ /** Feature with all settings visible — approval gates, evidence, git, and model. */
259
+ export const WithAllSettings = {
260
+ args: {
261
+ data: {
262
+ ...noPrData,
263
+ modelId: 'claude-sonnet-4-6',
264
+ approvalGates: { allowPrd: true, allowPlan: true, allowMerge: false },
265
+ enableEvidence: true,
266
+ commitEvidence: true,
267
+ push: true,
268
+ openPr: true,
269
+ },
270
+ },
271
+ };
272
+ /** Feature with no auto-approve gates enabled. */
273
+ export const WithSettingsAllDisabled = {
274
+ args: {
275
+ data: {
276
+ ...noPrData,
277
+ modelId: 'gemini-2.5-pro',
278
+ approvalGates: { allowPrd: false, allowPlan: false, allowMerge: false },
279
+ enableEvidence: false,
280
+ commitEvidence: false,
281
+ push: false,
282
+ openPr: false,
283
+ },
284
+ },
285
+ };
286
+ /** Feature with all auto-approve gates enabled. */
287
+ export const WithSettingsAllApproved = {
288
+ args: {
289
+ data: {
290
+ ...noPrData,
291
+ modelId: 'claude-opus-4-6',
292
+ approvalGates: { allowPrd: true, allowPlan: true, allowMerge: true },
293
+ enableEvidence: true,
294
+ commitEvidence: true,
295
+ push: true,
296
+ openPr: true,
297
+ },
298
+ },
299
+ };
300
+ /** Feature with settings and fast mode. */
301
+ export const FastModeWithSettings = {
302
+ args: {
303
+ data: {
304
+ ...fastModeData,
305
+ modelId: 'claude-sonnet-4-6',
306
+ approvalGates: { allowPrd: false, allowPlan: false, allowMerge: true },
307
+ enableEvidence: true,
308
+ commitEvidence: false,
309
+ push: true,
310
+ openPr: true,
311
+ },
312
+ },
313
+ };
314
+ /** Feature with evidence enabled but commit to PR disabled. */
315
+ export const EvidenceCollectOnly = {
316
+ args: {
317
+ data: {
318
+ ...noPrData,
319
+ enableEvidence: true,
320
+ commitEvidence: false,
321
+ },
322
+ },
323
+ };
@@ -59,6 +59,20 @@ export interface FeatureNodeData {
59
59
  commitHash?: string;
60
60
  mergeable?: boolean;
61
61
  };
62
+ /** Approval gates configuration for phase transitions */
63
+ approvalGates?: {
64
+ allowPrd: boolean;
65
+ allowPlan: boolean;
66
+ allowMerge: boolean;
67
+ };
68
+ /** Whether to push branch to remote after implementation */
69
+ push?: boolean;
70
+ /** Whether to open a PR after implementation */
71
+ openPr?: boolean;
72
+ /** Whether evidence collection is enabled for this feature */
73
+ enableEvidence?: boolean;
74
+ /** Whether evidence is committed to the PR body */
75
+ commitEvidence?: boolean;
62
76
  /** Whether the feature has plan data available */
63
77
  hasPlan?: boolean;
64
78
  /** Deployment status for features with an active deployment */
@@ -1 +1 @@
1
- {"version":3,"file":"feature-node-state-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node-state-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"feature-node-state-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node-state-config.ts"],"names":[],"mappings":"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"}
@@ -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":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AAGpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAuB5E,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,2CAqUzF"}
1
+ {"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AAGpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAuB5E,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,2CA4VzF"}
@@ -124,16 +124,22 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
124
124
  const handler = (e) => {
125
125
  const path = e.detail.path;
126
126
  const { wasEmpty, repoPath } = handleAddRepository(path);
127
- if (wasEmpty) {
128
- // Wait for next render so the repo node exists in the DOM, then auto-focus
129
- setTimeout(() => {
130
- fitView(AUTO_FOCUS_OPTIONS);
127
+ // Always center the viewport on the new repo, ignoring any stored
128
+ // pan/zoom position. This guarantees the repo is visible after adding
129
+ // even if the user previously panned far away or deleted everything.
130
+ resetViewport();
131
+ // Use a short delay to allow React to flush the state update and
132
+ // the showCanvas latch to transition, ensuring ReactFlow has the
133
+ // new nodes rendered before fitView calculates bounds.
134
+ requestAnimationFrame(() => {
135
+ fitView(AUTO_FOCUS_OPTIONS);
136
+ if (wasEmpty) {
131
137
  // Open the create-feature drawer after the fitView animation completes
132
138
  drawerTimerRef.current = setTimeout(() => {
133
139
  guardedNavigate(() => router.push(`/create?repo=${encodeURIComponent(repoPath)}`));
134
140
  }, AUTO_FOCUS_DRAWER_DELAY_MS);
135
- }, 0);
136
- }
141
+ }
142
+ });
137
143
  };
138
144
  window.addEventListener('shep:add-repository', handler);
139
145
  return () => {
@@ -142,7 +148,7 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
142
148
  clearTimeout(drawerTimerRef.current);
143
149
  }
144
150
  };
145
- }, [handleAddRepository, fitView, guardedNavigate, router]);
151
+ }, [handleAddRepository, fitView, guardedNavigate, router, resetViewport]);
146
152
  // Listen for create events from the create drawer (with real feature ID from server)
147
153
  useEffect(() => {
148
154
  const handler = (e) => {
@@ -204,6 +210,21 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
204
210
  handleRepositoryClick,
205
211
  handleDeleteRepository,
206
212
  ]);
213
+ // Auto-center whenever the canvas transitions from empty to having nodes.
214
+ // This covers both initial page load AND re-adding repos after deleting
215
+ // everything — the view always centers so the repo is visible, ignoring
216
+ // any previously stored pan/zoom position.
217
+ const hadNodesRef = useRef(nodes.length > 0);
218
+ useEffect(() => {
219
+ const hasNodes = nodes.length > 0;
220
+ if (hasNodes && !hadNodesRef.current) {
221
+ // Went from empty → has nodes — center the view
222
+ resetViewport();
223
+ // Yield to React so nodes are rendered in the DOM before fitView calculates bounds.
224
+ setTimeout(() => fitView(AUTO_FOCUS_OPTIONS), 0);
225
+ }
226
+ hadNodesRef.current = hasNodes;
227
+ }, [nodes.length, fitView, resetViewport]);
207
228
  const handleMoveEnd = useCallback((_event, viewport) => {
208
229
  handleViewportChange(viewport);
209
230
  }, [handleViewportChange]);
@@ -5,6 +5,8 @@ export declare const DEBOUNCE_MS = 500;
5
5
  export declare const DEFAULT_VIEWPORT: Viewport;
6
6
  export interface UseViewportPersistenceResult {
7
7
  defaultViewport: Viewport;
8
+ /** True when a valid viewport was restored from localStorage. */
9
+ hasSavedViewport: boolean;
8
10
  onMoveEnd: (viewport: Viewport) => void;
9
11
  resetViewport: () => Viewport;
10
12
  }
@@ -1 +1 @@
1
- {"version":3,"file":"use-viewport-persistence.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/hooks/use-viewport-persistence.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,eAAO,MAAM,WAAW,yBAAyB,CAAC;AAClD,eAAO,MAAM,WAAW,MAAM,CAAC;AAE/B,eAAO,MAAM,gBAAgB,EAAE,QAAuC,CAAC;AAEvE,MAAM,WAAW,4BAA4B;IAC3C,eAAe,EAAE,QAAQ,CAAC;IAC1B,SAAS,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;IACxC,aAAa,EAAE,MAAM,QAAQ,CAAC;CAC/B;AA6BD,wBAAgB,sBAAsB,IAAI,4BAA4B,CAmCrE"}
1
+ {"version":3,"file":"use-viewport-persistence.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/hooks/use-viewport-persistence.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,eAAO,MAAM,WAAW,yBAAyB,CAAC;AAClD,eAAO,MAAM,WAAW,MAAM,CAAC;AAE/B,eAAO,MAAM,gBAAgB,EAAE,QAAuC,CAAC;AAEvE,MAAM,WAAW,4BAA4B;IAC3C,eAAe,EAAE,QAAQ,CAAC;IAC1B,iEAAiE;IACjE,gBAAgB,EAAE,OAAO,CAAC;IAC1B,SAAS,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;IACxC,aAAa,EAAE,MAAM,QAAQ,CAAC;CAC/B;AA8BD,wBAAgB,sBAAsB,IAAI,4BAA4B,CA8CrE"}
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { useCallback, useEffect, useRef } from 'react';
2
+ import { useCallback, useEffect, useRef, useState } from 'react';
3
3
  export const STORAGE_KEY = 'shep-canvas-viewport';
4
4
  export const DEBOUNCE_MS = 500;
5
5
  export const DEFAULT_VIEWPORT = { x: 30, y: 30, zoom: 0.85 };
@@ -20,16 +20,20 @@ function readViewport() {
20
20
  try {
21
21
  const raw = localStorage.getItem(STORAGE_KEY);
22
22
  if (raw == null)
23
- return DEFAULT_VIEWPORT;
23
+ return { viewport: DEFAULT_VIEWPORT, fromStorage: false };
24
24
  const parsed = JSON.parse(raw);
25
- return isValidViewport(parsed) ? parsed : DEFAULT_VIEWPORT;
25
+ if (isValidViewport(parsed))
26
+ return { viewport: parsed, fromStorage: true };
27
+ return { viewport: DEFAULT_VIEWPORT, fromStorage: false };
26
28
  }
27
29
  catch {
28
- return DEFAULT_VIEWPORT;
30
+ return { viewport: DEFAULT_VIEWPORT, fromStorage: false };
29
31
  }
30
32
  }
31
33
  export function useViewportPersistence() {
32
- const defaultViewport = useRef(readViewport()).current;
34
+ const stored = useRef(readViewport()).current;
35
+ const [defaultViewport, setDefaultViewport] = useState(stored.viewport);
36
+ const hasSavedViewport = stored.fromStorage;
33
37
  const timerRef = useRef(null);
34
38
  useEffect(() => {
35
39
  return () => {
@@ -52,13 +56,22 @@ export function useViewportPersistence() {
52
56
  }, DEBOUNCE_MS);
53
57
  }, []);
54
58
  const resetViewport = useCallback(() => {
59
+ // Cancel any pending debounced save so it cannot overwrite the reset
60
+ if (timerRef.current != null) {
61
+ clearTimeout(timerRef.current);
62
+ timerRef.current = null;
63
+ }
55
64
  try {
56
65
  localStorage.removeItem(STORAGE_KEY);
57
66
  }
58
67
  catch {
59
68
  // Silently ignore localStorage errors
60
69
  }
70
+ // Update the defaultViewport so that if ReactFlow re-mounts (e.g. after
71
+ // showCanvas toggles), it initializes at the default position instead of
72
+ // the stale saved viewport.
73
+ setDefaultViewport(DEFAULT_VIEWPORT);
61
74
  return DEFAULT_VIEWPORT;
62
75
  }, []);
63
- return { defaultViewport, onMoveEnd, resetViewport };
76
+ return { defaultViewport, hasSavedViewport, onMoveEnd, resetViewport };
64
77
  }
@@ -1 +1 @@
1
- {"version":3,"file":"layout-with-dagre.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/lib/layout-with-dagre.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,iEAAiE;IACjE,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,+DAA+D;AAC/D,eAAO,MAAM,sBAAsB,EAAE,aAIpC,CAAC;AAkCF;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,IAAI,EAC5C,KAAK,EAAE,CAAC,EAAE,EACV,KAAK,EAAE,IAAI,EAAE,EACb,IAAI,GAAE,aAAkB,GACvB;IAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IAAC,KAAK,EAAE,IAAI,EAAE,CAAA;CAAE,CAqL/B"}
1
+ {"version":3,"file":"layout-with-dagre.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/lib/layout-with-dagre.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,iEAAiE;IACjE,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,+DAA+D;AAC/D,eAAO,MAAM,sBAAsB,EAAE,aAIpC,CAAC;AAkCF;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,IAAI,EAC5C,KAAK,EAAE,CAAC,EAAE,EACV,KAAK,EAAE,IAAI,EAAE,EACb,IAAI,GAAE,aAAkB,GACvB;IAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IAAC,KAAK,EAAE,IAAI,EAAE,CAAA;CAAE,CA8L/B"}
@@ -78,6 +78,10 @@ export function layoutWithDagre(nodes, edges, opts = {}) {
78
78
  // Add disconnected nodes to centerMap so they participate in root positioning.
79
79
  // Use the same primary-axis position as connected roots (rank 0) so they align
80
80
  // visually with repos that have features attached.
81
+ // When there are NO connected nodes (e.g. repos with no features), use half the
82
+ // node's own dimension so the leading edge sits at the canvas origin — preventing
83
+ // nodes from rendering off-screen with the default viewport.
84
+ const hasCenterMap = centerMap.size > 0;
81
85
  let rootPrimaryAxis = 0;
82
86
  for (const c of centerMap.values()) {
83
87
  rootPrimaryAxis = isHorizontal ? c.cx : c.cy;
@@ -85,9 +89,14 @@ export function layoutWithDagre(nodes, edges, opts = {}) {
85
89
  }
86
90
  for (const node of disconnectedNodes) {
87
91
  const size = getNodeSize(node, nodeSize);
92
+ const primaryAxisCenter = hasCenterMap
93
+ ? rootPrimaryAxis
94
+ : isHorizontal
95
+ ? size.width / 2
96
+ : size.height / 2;
88
97
  centerMap.set(node.id, {
89
- cx: isHorizontal ? rootPrimaryAxis : 0,
90
- cy: isHorizontal ? 0 : rootPrimaryAxis,
98
+ cx: isHorizontal ? primaryAxisCenter : 0,
99
+ cy: isHorizontal ? 0 : primaryAxisCenter,
91
100
  w: size.width,
92
101
  h: size.height,
93
102
  });
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Parses structured log lines from the feature agent worker process.
3
+ *
4
+ * Log format: [timestamp] [phase] [agent|model] [tag] message
5
+ * Worker format: [timestamp] [agent|model] [WORKER] message
6
+ * Fallback: raw string lines
7
+ */
8
+ export type LogEventTag = 'tool' | 'text' | 'result' | 'tokens' | 'raw' | 'worker' | 'info';
9
+ export interface ParsedLogLine {
10
+ /** ISO timestamp */
11
+ timestamp: string | null;
12
+ /** Phase name (e.g. "requirements", "implement") */
13
+ phase: string | null;
14
+ /** Agent type (e.g. "claude-code") */
15
+ agent: string | null;
16
+ /** Model name (e.g. "claude-haiku-4-5") */
17
+ model: string | null;
18
+ /** Event tag */
19
+ tag: LogEventTag;
20
+ /** The message content after tags */
21
+ message: string;
22
+ /** Original raw line */
23
+ raw: string;
24
+ }
25
+ export declare function parseLogLine(raw: string): ParsedLogLine;
26
+ /** Tool call info extracted from [tool] messages */
27
+ export interface ToolCallInfo {
28
+ toolName: string;
29
+ args: string;
30
+ }
31
+ /** Parse a [tool] message into tool name and args */
32
+ export declare function parseToolCall(message: string): ToolCallInfo;
33
+ /** Result info extracted from [result] messages */
34
+ export interface ResultInfo {
35
+ chars: number;
36
+ sessionId: string | null;
37
+ }
38
+ /** Parse a [result] message */
39
+ export declare function parseResultMessage(message: string): ResultInfo;
40
+ /** Token info extracted from [tokens] messages */
41
+ export interface TokenInfo {
42
+ inputTokens: number;
43
+ outputTokens: number;
44
+ }
45
+ /** Parse a [tokens] message */
46
+ export declare function parseTokensMessage(message: string): TokenInfo;
47
+ /** Parse all lines from raw content string */
48
+ export declare function parseLogContent(content: string): ParsedLogLine[];
49
+ //# sourceMappingURL=parse-log-line.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-log-line.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/lib/parse-log-line.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE5F,MAAM,WAAW,aAAa;IAC5B,oBAAoB;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,oDAAoD;IACpD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,sCAAsC;IACtC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,gBAAgB;IAChB,GAAG,EAAE,WAAW,CAAC;IACjB,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,wBAAwB;IACxB,GAAG,EAAE,MAAM,CAAC;CACb;AAgBD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAwEvD;AAED,oDAAoD;AACpD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAS3D;AAED,mDAAmD;AACnD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,+BAA+B;AAC/B,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,CAO9D;AAED,kDAAkD;AAClD,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,+BAA+B;AAC/B,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAO7D;AAED,8CAA8C;AAC9C,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE,CAMhE"}