@stigmer/react 3.1.1 → 3.1.3

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 (483) hide show
  1. package/composer/SessionComposer.d.ts +25 -1
  2. package/composer/SessionComposer.d.ts.map +1 -1
  3. package/composer/SessionComposer.js +19 -8
  4. package/composer/SessionComposer.js.map +1 -1
  5. package/execution/ArtifactContentRenderer.d.ts +11 -1
  6. package/execution/ArtifactContentRenderer.d.ts.map +1 -1
  7. package/execution/ArtifactContentRenderer.js +39 -15
  8. package/execution/ArtifactContentRenderer.js.map +1 -1
  9. package/execution/ArtifactPreviewModal.d.ts +5 -5
  10. package/execution/ArtifactPreviewModal.js +4 -4
  11. package/execution/ArtifactPreviewModal.js.map +1 -1
  12. package/execution/FileChangeProgressBar.d.ts +47 -0
  13. package/execution/FileChangeProgressBar.d.ts.map +1 -0
  14. package/execution/FileChangeProgressBar.js +49 -0
  15. package/execution/FileChangeProgressBar.js.map +1 -0
  16. package/execution/FileChangesView.d.ts.map +1 -1
  17. package/execution/FileChangesView.js +19 -4
  18. package/execution/FileChangesView.js.map +1 -1
  19. package/execution/FilePathContext.d.ts +8 -1
  20. package/execution/FilePathContext.d.ts.map +1 -1
  21. package/execution/FilePathContext.js.map +1 -1
  22. package/execution/FilePathLink.d.ts.map +1 -1
  23. package/execution/FilePathLink.js +21 -6
  24. package/execution/FilePathLink.js.map +1 -1
  25. package/execution/FileReviewAtoms.d.ts +27 -0
  26. package/execution/FileReviewAtoms.d.ts.map +1 -0
  27. package/execution/FileReviewAtoms.js +64 -0
  28. package/execution/FileReviewAtoms.js.map +1 -0
  29. package/execution/FileReviewCard.d.ts +2 -2
  30. package/execution/FileReviewCard.d.ts.map +1 -1
  31. package/execution/FileReviewCard.js +32 -62
  32. package/execution/FileReviewCard.js.map +1 -1
  33. package/execution/MessageEntry.d.ts +20 -0
  34. package/execution/MessageEntry.d.ts.map +1 -1
  35. package/execution/MessageEntry.js +19 -5
  36. package/execution/MessageEntry.js.map +1 -1
  37. package/execution/MessageThread.d.ts +75 -13
  38. package/execution/MessageThread.d.ts.map +1 -1
  39. package/execution/MessageThread.js +195 -27
  40. package/execution/MessageThread.js.map +1 -1
  41. package/execution/PlanArtifactCard.d.ts +36 -21
  42. package/execution/PlanArtifactCard.d.ts.map +1 -1
  43. package/execution/PlanArtifactCard.js +39 -25
  44. package/execution/PlanArtifactCard.js.map +1 -1
  45. package/execution/PlanCompletionCard.d.ts +4 -4
  46. package/execution/PlanCompletionCard.d.ts.map +1 -1
  47. package/execution/PlanCompletionCard.js +4 -4
  48. package/execution/PlanCompletionCard.js.map +1 -1
  49. package/execution/PlanDocumentMessage.d.ts +32 -0
  50. package/execution/PlanDocumentMessage.d.ts.map +1 -0
  51. package/execution/PlanDocumentMessage.js +37 -0
  52. package/execution/PlanDocumentMessage.js.map +1 -0
  53. package/execution/PlanStreamingCard.d.ts +50 -0
  54. package/execution/PlanStreamingCard.d.ts.map +1 -0
  55. package/execution/PlanStreamingCard.js +40 -0
  56. package/execution/PlanStreamingCard.js.map +1 -0
  57. package/execution/index.d.ts +9 -1
  58. package/execution/index.d.ts.map +1 -1
  59. package/execution/index.js +4 -0
  60. package/execution/index.js.map +1 -1
  61. package/execution/use-build-from-plan-hotkey.d.ts +1 -1
  62. package/execution/use-build-from-plan-hotkey.js +1 -1
  63. package/execution/useArtifactCopy.d.ts +51 -0
  64. package/execution/useArtifactCopy.d.ts.map +1 -0
  65. package/execution/useArtifactCopy.js +75 -0
  66. package/execution/useArtifactCopy.js.map +1 -0
  67. package/execution/useArtifactDownload.d.ts.map +1 -1
  68. package/execution/useArtifactDownload.js +17 -5
  69. package/execution/useArtifactDownload.js.map +1 -1
  70. package/execution/useCreateAgentExecution.d.ts +12 -0
  71. package/execution/useCreateAgentExecution.d.ts.map +1 -1
  72. package/execution/useCreateAgentExecution.js +5 -1
  73. package/execution/useCreateAgentExecution.js.map +1 -1
  74. package/github/decodeGitHubContent.d.ts +29 -0
  75. package/github/decodeGitHubContent.d.ts.map +1 -0
  76. package/github/decodeGitHubContent.js +72 -0
  77. package/github/decodeGitHubContent.js.map +1 -0
  78. package/github/index.d.ts +1 -0
  79. package/github/index.d.ts.map +1 -1
  80. package/github/index.js +1 -0
  81. package/github/index.js.map +1 -1
  82. package/github/useGitHubFileReader.d.ts +26 -0
  83. package/github/useGitHubFileReader.d.ts.map +1 -0
  84. package/github/useGitHubFileReader.js +106 -0
  85. package/github/useGitHubFileReader.js.map +1 -0
  86. package/github/useGitHubTreeLister.d.ts.map +1 -1
  87. package/github/useGitHubTreeLister.js +6 -2
  88. package/github/useGitHubTreeLister.js.map +1 -1
  89. package/index.d.ts +9 -9
  90. package/index.d.ts.map +1 -1
  91. package/index.js +5 -5
  92. package/index.js.map +1 -1
  93. package/internal/ResizableSplit.d.ts +72 -22
  94. package/internal/ResizableSplit.d.ts.map +1 -1
  95. package/internal/ResizableSplit.js +96 -38
  96. package/internal/ResizableSplit.js.map +1 -1
  97. package/internal/VirtualizedThread.d.ts +5 -3
  98. package/internal/VirtualizedThread.d.ts.map +1 -1
  99. package/internal/VirtualizedThread.js +6 -4
  100. package/internal/VirtualizedThread.js.map +1 -1
  101. package/internal/file-icons/index.d.ts +17 -0
  102. package/internal/file-icons/index.d.ts.map +1 -0
  103. package/internal/file-icons/index.js +60 -0
  104. package/internal/file-icons/index.js.map +1 -0
  105. package/internal/file-tree/FileTreeNode.d.ts +18 -1
  106. package/internal/file-tree/FileTreeNode.d.ts.map +1 -1
  107. package/internal/file-tree/FileTreeNode.js +11 -2
  108. package/internal/file-tree/FileTreeNode.js.map +1 -1
  109. package/internal/markdown-components.d.ts +38 -1
  110. package/internal/markdown-components.d.ts.map +1 -1
  111. package/internal/markdown-components.js +86 -11
  112. package/internal/markdown-components.js.map +1 -1
  113. package/{workflow → internal}/motion-preference.d.ts +7 -4
  114. package/internal/motion-preference.d.ts.map +1 -0
  115. package/{workflow → internal}/motion-preference.js +7 -4
  116. package/internal/motion-preference.js.map +1 -0
  117. package/internal/store/index.d.ts +33 -0
  118. package/internal/store/index.d.ts.map +1 -1
  119. package/internal/store/index.js +59 -0
  120. package/internal/store/index.js.map +1 -1
  121. package/internal/store/workspace-editors-store.d.ts +145 -0
  122. package/internal/store/workspace-editors-store.d.ts.map +1 -0
  123. package/internal/store/workspace-editors-store.js +208 -0
  124. package/internal/store/workspace-editors-store.js.map +1 -0
  125. package/internal/store/workspace-file-selection-store.d.ts +38 -0
  126. package/internal/store/workspace-file-selection-store.d.ts.map +1 -0
  127. package/internal/store/workspace-file-selection-store.js +62 -0
  128. package/internal/store/workspace-file-selection-store.js.map +1 -0
  129. package/internal/useRevealLine.d.ts +49 -0
  130. package/internal/useRevealLine.d.ts.map +1 -0
  131. package/internal/useRevealLine.js +43 -0
  132. package/internal/useRevealLine.js.map +1 -0
  133. package/library/detect-plan-artifact.d.ts +43 -4
  134. package/library/detect-plan-artifact.d.ts.map +1 -1
  135. package/library/detect-plan-artifact.js +45 -5
  136. package/library/detect-plan-artifact.js.map +1 -1
  137. package/library/detect-streaming-plan.d.ts +45 -0
  138. package/library/detect-streaming-plan.d.ts.map +1 -0
  139. package/library/detect-streaming-plan.js +83 -0
  140. package/library/detect-streaming-plan.js.map +1 -0
  141. package/library/index.d.ts +4 -1
  142. package/library/index.d.ts.map +1 -1
  143. package/library/index.js +2 -1
  144. package/library/index.js.map +1 -1
  145. package/package.json +4 -4
  146. package/session/NewSessionViewer.d.ts +19 -4
  147. package/session/NewSessionViewer.d.ts.map +1 -1
  148. package/session/NewSessionViewer.js +52 -25
  149. package/session/NewSessionViewer.js.map +1 -1
  150. package/session/PlanEditor.d.ts +55 -0
  151. package/session/PlanEditor.d.ts.map +1 -0
  152. package/session/PlanEditor.js +88 -0
  153. package/session/PlanEditor.js.map +1 -0
  154. package/session/PlanStreamingDocument.d.ts +30 -0
  155. package/session/PlanStreamingDocument.d.ts.map +1 -0
  156. package/session/PlanStreamingDocument.js +37 -0
  157. package/session/PlanStreamingDocument.js.map +1 -0
  158. package/session/SessionPanelChip.d.ts +26 -0
  159. package/session/SessionPanelChip.d.ts.map +1 -0
  160. package/session/SessionPanelChip.js +40 -0
  161. package/session/SessionPanelChip.js.map +1 -0
  162. package/session/SessionViewer.d.ts +34 -7
  163. package/session/SessionViewer.d.ts.map +1 -1
  164. package/session/SessionViewer.js +334 -33
  165. package/session/SessionViewer.js.map +1 -1
  166. package/session/{inspector → facets}/ArtifactsTab.d.ts +10 -2
  167. package/session/facets/ArtifactsTab.d.ts.map +1 -0
  168. package/session/{inspector → facets}/ArtifactsTab.js +8 -3
  169. package/session/facets/ArtifactsTab.js.map +1 -0
  170. package/session/{inspector → facets}/ChangesTab.d.ts +3 -3
  171. package/session/facets/ChangesTab.d.ts.map +1 -0
  172. package/session/{inspector → facets}/ChangesTab.js +3 -3
  173. package/session/facets/ChangesTab.js.map +1 -0
  174. package/session/facets/InspectTab.d.ts.map +1 -0
  175. package/session/facets/InspectTab.js.map +1 -0
  176. package/session/{inspector → facets}/SetupTab.d.ts +11 -2
  177. package/session/facets/SetupTab.d.ts.map +1 -0
  178. package/session/{inspector → facets}/SetupTab.js +4 -3
  179. package/session/facets/SetupTab.js.map +1 -0
  180. package/session/{inspector → facets}/UsageTab.d.ts +1 -1
  181. package/session/facets/UsageTab.d.ts.map +1 -0
  182. package/session/{inspector → facets}/UsageTab.js +1 -1
  183. package/session/facets/UsageTab.js.map +1 -0
  184. package/session/{inspector → facets}/index.d.ts +0 -6
  185. package/session/facets/index.d.ts.map +1 -0
  186. package/session/{inspector → facets}/index.js +0 -3
  187. package/session/facets/index.js.map +1 -0
  188. package/session/index.d.ts +11 -2
  189. package/session/index.d.ts.map +1 -1
  190. package/session/index.js +15 -2
  191. package/session/index.js.map +1 -1
  192. package/session/plan-document.d.ts +21 -0
  193. package/session/plan-document.d.ts.map +1 -0
  194. package/session/plan-document.js +28 -0
  195. package/session/plan-document.js.map +1 -0
  196. package/session/useOpenFileChange.d.ts +20 -0
  197. package/session/useOpenFileChange.d.ts.map +1 -0
  198. package/session/useOpenFileChange.js +31 -0
  199. package/session/useOpenFileChange.js.map +1 -0
  200. package/session/usePlanDraft.d.ts +52 -0
  201. package/session/usePlanDraft.d.ts.map +1 -0
  202. package/session/usePlanDraft.js +63 -0
  203. package/session/usePlanDraft.js.map +1 -0
  204. package/session/useSessionConversation.d.ts +14 -1
  205. package/session/useSessionConversation.d.ts.map +1 -1
  206. package/session/useSessionConversation.js +20 -2
  207. package/session/useSessionConversation.js.map +1 -1
  208. package/session/useSessionPageFlow.d.ts.map +1 -1
  209. package/session/useSessionPageFlow.js +1 -0
  210. package/session/useSessionPageFlow.js.map +1 -1
  211. package/session/useSessionPanel.d.ts +120 -0
  212. package/session/useSessionPanel.d.ts.map +1 -0
  213. package/session/useSessionPanel.js +130 -0
  214. package/session/useSessionPanel.js.map +1 -0
  215. package/session/useSessionRailViews.d.ts +45 -0
  216. package/session/useSessionRailViews.d.ts.map +1 -0
  217. package/session/useSessionRailViews.js +105 -0
  218. package/session/useSessionRailViews.js.map +1 -0
  219. package/src/composer/SessionComposer.tsx +53 -10
  220. package/src/composer/__tests__/SessionComposer-contract.test.tsx +58 -4
  221. package/src/execution/ArtifactContentRenderer.tsx +101 -24
  222. package/src/execution/ArtifactPreviewModal.tsx +9 -9
  223. package/src/execution/FileChangeProgressBar.tsx +121 -0
  224. package/src/execution/FileChangesView.tsx +18 -4
  225. package/src/execution/FilePathContext.tsx +8 -1
  226. package/src/execution/FilePathLink.tsx +22 -6
  227. package/src/execution/FileReviewAtoms.tsx +89 -0
  228. package/src/execution/FileReviewCard.tsx +57 -90
  229. package/src/execution/MessageEntry.tsx +49 -1
  230. package/src/execution/MessageThread.tsx +308 -39
  231. package/src/execution/PlanArtifactCard.tsx +174 -64
  232. package/src/execution/PlanCompletionCard.tsx +5 -5
  233. package/src/execution/PlanDocumentMessage.tsx +96 -0
  234. package/src/execution/PlanStreamingCard.tsx +141 -0
  235. package/src/execution/__tests__/ArtifactContentRenderer.test.tsx +80 -1
  236. package/src/execution/__tests__/ArtifactPreviewModal.test.tsx +6 -6
  237. package/src/execution/__tests__/FileChangeProgressBar.test.tsx +125 -0
  238. package/src/execution/__tests__/FilePathLink.test.tsx +87 -0
  239. package/src/execution/__tests__/FileReviewCard.test.tsx +66 -7
  240. package/src/execution/__tests__/MessageThread.test.tsx +102 -1
  241. package/src/execution/__tests__/PlanArtifactCard.test.tsx +114 -26
  242. package/src/execution/__tests__/PlanCompletionCard.test.tsx +2 -2
  243. package/src/execution/__tests__/PlanDocumentMessage.test.tsx +55 -0
  244. package/src/execution/__tests__/PlanStreamingCard.test.tsx +56 -0
  245. package/src/execution/__tests__/buildThreadItems-plan-completion.test.ts +600 -22
  246. package/src/execution/__tests__/message-entry.test.tsx +17 -0
  247. package/src/execution/__tests__/useArtifactCopy.test.tsx +90 -0
  248. package/src/execution/__tests__/useArtifactDownload.test.tsx +2 -0
  249. package/src/execution/__tests__/useCreateAgentExecution.test.tsx +85 -0
  250. package/src/execution/index.ts +13 -1
  251. package/src/execution/use-build-from-plan-hotkey.ts +1 -1
  252. package/src/execution/useArtifactCopy.ts +109 -0
  253. package/src/execution/useArtifactDownload.ts +17 -5
  254. package/src/execution/useCreateAgentExecution.ts +18 -1
  255. package/src/github/__tests__/decodeGitHubContent.test.ts +102 -0
  256. package/src/github/__tests__/useGitHubFileReader.test.ts +183 -0
  257. package/src/github/decodeGitHubContent.ts +83 -0
  258. package/src/github/index.ts +1 -0
  259. package/src/github/useGitHubFileReader.ts +152 -0
  260. package/src/github/useGitHubTreeLister.ts +6 -2
  261. package/src/index.ts +69 -9
  262. package/src/internal/ResizableSplit.tsx +184 -51
  263. package/src/internal/VirtualizedThread.tsx +12 -4
  264. package/src/internal/__tests__/ResizableSplit.test.tsx +125 -3
  265. package/src/internal/__tests__/markdown-components.test.tsx +68 -0
  266. package/src/internal/__tests__/useRevealLine.test.tsx +97 -0
  267. package/src/internal/file-icons/__tests__/file-icons.test.tsx +35 -0
  268. package/src/internal/file-icons/index.tsx +137 -0
  269. package/src/internal/file-tree/FileTreeNode.tsx +56 -5
  270. package/src/internal/file-tree/__tests__/FileTreeNode-explorer.test.tsx +86 -0
  271. package/src/internal/markdown-components.tsx +116 -11
  272. package/src/{workflow → internal}/motion-preference.ts +7 -4
  273. package/src/internal/store/__tests__/workspace-editors-store.test.ts +216 -0
  274. package/src/internal/store/__tests__/workspace-file-selection-store.test.ts +118 -0
  275. package/src/internal/store/index.ts +94 -0
  276. package/src/internal/store/workspace-editors-store.ts +315 -0
  277. package/src/internal/store/workspace-file-selection-store.ts +88 -0
  278. package/src/internal/useRevealLine.ts +81 -0
  279. package/src/library/__tests__/detect-plan-artifact.test.ts +69 -0
  280. package/src/library/__tests__/detect-streaming-plan.test.ts +234 -0
  281. package/src/library/detect-plan-artifact.ts +62 -5
  282. package/src/library/detect-streaming-plan.ts +108 -0
  283. package/src/library/index.ts +7 -0
  284. package/src/session/NewSessionViewer.tsx +123 -55
  285. package/src/session/PlanEditor.tsx +361 -0
  286. package/src/session/PlanStreamingDocument.tsx +97 -0
  287. package/src/session/SessionPanelChip.tsx +103 -0
  288. package/src/session/SessionViewer.tsx +655 -96
  289. package/src/session/__tests__/NewSessionViewer.test.tsx +148 -0
  290. package/src/session/__tests__/PlanEditor.test.tsx +217 -0
  291. package/src/session/__tests__/PlanStreamingDocument.test.tsx +50 -0
  292. package/src/session/__tests__/SessionPanelChip.test.tsx +42 -0
  293. package/src/session/__tests__/SessionViewer-fileReviewDock.test.tsx +66 -4
  294. package/src/session/__tests__/SessionViewer-transcriptFileOpen.test.tsx +205 -0
  295. package/src/session/__tests__/audienceWiring.test.tsx +55 -19
  296. package/src/session/__tests__/useOpenFileChange.test.tsx +82 -0
  297. package/src/session/__tests__/usePlanDraft.test.ts +102 -0
  298. package/src/session/__tests__/useSessionConversation.test.tsx +44 -0
  299. package/src/session/__tests__/useSessionPanel.test.ts +298 -0
  300. package/src/session/__tests__/useSessionRailViews.test.tsx +124 -0
  301. package/src/session/{inspector → facets}/ArtifactsTab.tsx +27 -5
  302. package/src/session/{inspector → facets}/ChangesTab.tsx +3 -3
  303. package/src/session/{inspector → facets}/SetupTab.tsx +13 -1
  304. package/src/session/{inspector → facets}/UsageTab.tsx +1 -1
  305. package/src/session/{inspector → facets}/__tests__/ArtifactsTab.test.tsx +42 -8
  306. package/src/session/facets/__tests__/SetupTab.test.tsx +44 -0
  307. package/src/session/{inspector → facets}/index.ts +0 -16
  308. package/src/session/index.ts +30 -13
  309. package/src/session/plan-document.ts +30 -0
  310. package/src/session/useOpenFileChange.ts +53 -0
  311. package/src/session/usePlanDraft.ts +109 -0
  312. package/src/session/useSessionConversation.ts +38 -3
  313. package/src/session/useSessionPageFlow.ts +1 -0
  314. package/src/session/useSessionPanel.ts +288 -0
  315. package/src/session/useSessionRailViews.tsx +200 -0
  316. package/src/workflow/WorkflowExecutionGraph.tsx +1 -1
  317. package/src/workflow/index.ts +1 -1
  318. package/src/workflow/useFollowExecution.ts +1 -1
  319. package/src/workspace/EditorTabs.tsx +174 -0
  320. package/src/workspace/ExplorerTree.tsx +253 -0
  321. package/src/workspace/FileViewer.tsx +537 -0
  322. package/src/workspace/WorkspaceContentSearch.tsx +502 -0
  323. package/src/workspace/WorkspaceContentSearcher.ts +70 -0
  324. package/src/workspace/WorkspaceEditor.tsx +19 -16
  325. package/src/workspace/WorkspaceFileLister.ts +11 -0
  326. package/src/workspace/WorkspaceFileReader.ts +57 -0
  327. package/src/workspace/WorkspaceFileSearch.tsx +452 -0
  328. package/src/workspace/WorkspaceSurface.tsx +839 -0
  329. package/src/workspace/__tests__/EditorTabs.test.tsx +102 -0
  330. package/src/workspace/__tests__/ExplorerTree.test.tsx +204 -0
  331. package/src/workspace/__tests__/FileViewer.test.tsx +439 -0
  332. package/src/workspace/__tests__/WorkspaceContentSearch.test.tsx +229 -0
  333. package/src/workspace/__tests__/WorkspaceEditor-initialPanel.test.tsx +19 -0
  334. package/src/workspace/__tests__/WorkspaceFileSearch.test.tsx +227 -0
  335. package/src/workspace/__tests__/WorkspaceSurface.test.tsx +418 -0
  336. package/src/workspace/__tests__/a11y/harness.tsx +140 -0
  337. package/src/workspace/__tests__/a11y/mock-capabilities.ts +138 -0
  338. package/src/workspace/__tests__/a11y/workspace-editor.a11y.test.tsx +65 -0
  339. package/src/workspace/__tests__/a11y/workspace-explorer-search.a11y.test.tsx +112 -0
  340. package/src/workspace/__tests__/a11y/workspace-viewer-tabs.a11y.test.tsx +69 -0
  341. package/src/workspace/__tests__/findChangeForSelection.test.ts +132 -0
  342. package/src/workspace/__tests__/matchContentPreview.test.ts +55 -0
  343. package/src/workspace/__tests__/matchWorkspaceFiles.test.ts +104 -0
  344. package/src/workspace/__tests__/resolveWorkspaceFileSelection.test.ts +135 -0
  345. package/src/workspace/__tests__/useWorkspaceContentSearch.test.tsx +196 -0
  346. package/src/workspace/__tests__/useWorkspaceFileContent.test.tsx +190 -0
  347. package/src/workspace/__tests__/useWorkspaceFileSearch.test.tsx +162 -0
  348. package/src/workspace/findChangeForSelection.ts +61 -0
  349. package/src/workspace/index.ts +56 -2
  350. package/src/workspace/matchContentPreview.ts +51 -0
  351. package/src/workspace/matchWorkspaceFiles.ts +86 -0
  352. package/src/workspace/resolveWorkspaceFileSelection.ts +119 -0
  353. package/src/workspace/useWorkspaceContentSearch.ts +228 -0
  354. package/src/workspace/useWorkspaceFileContent.ts +129 -0
  355. package/src/workspace/useWorkspaceFileSearch.ts +184 -0
  356. package/src/workspace/useWorkspaceFiles.ts +27 -27
  357. package/src/workspace/workspaceListingCache.ts +93 -0
  358. package/styles.css +1 -1
  359. package/workflow/WorkflowExecutionGraph.js +1 -1
  360. package/workflow/WorkflowExecutionGraph.js.map +1 -1
  361. package/workflow/index.d.ts +1 -1
  362. package/workflow/index.d.ts.map +1 -1
  363. package/workflow/index.js +1 -1
  364. package/workflow/index.js.map +1 -1
  365. package/workflow/useFollowExecution.js +1 -1
  366. package/workflow/useFollowExecution.js.map +1 -1
  367. package/workspace/EditorTabs.d.ts +47 -0
  368. package/workspace/EditorTabs.d.ts.map +1 -0
  369. package/workspace/EditorTabs.js +78 -0
  370. package/workspace/EditorTabs.js.map +1 -0
  371. package/workspace/ExplorerTree.d.ts +32 -0
  372. package/workspace/ExplorerTree.d.ts.map +1 -0
  373. package/workspace/ExplorerTree.js +49 -0
  374. package/workspace/ExplorerTree.js.map +1 -0
  375. package/workspace/FileViewer.d.ts +93 -0
  376. package/workspace/FileViewer.d.ts.map +1 -0
  377. package/workspace/FileViewer.js +193 -0
  378. package/workspace/FileViewer.js.map +1 -0
  379. package/workspace/WorkspaceContentSearch.d.ts +41 -0
  380. package/workspace/WorkspaceContentSearch.d.ts.map +1 -0
  381. package/workspace/WorkspaceContentSearch.js +216 -0
  382. package/workspace/WorkspaceContentSearch.js.map +1 -0
  383. package/workspace/WorkspaceContentSearcher.d.ts +59 -0
  384. package/workspace/WorkspaceContentSearcher.d.ts.map +1 -0
  385. package/workspace/WorkspaceContentSearcher.js +7 -0
  386. package/workspace/WorkspaceContentSearcher.js.map +1 -0
  387. package/workspace/WorkspaceEditor.d.ts.map +1 -1
  388. package/workspace/WorkspaceEditor.js +8 -10
  389. package/workspace/WorkspaceEditor.js.map +1 -1
  390. package/workspace/WorkspaceFileLister.d.ts +11 -0
  391. package/workspace/WorkspaceFileLister.d.ts.map +1 -1
  392. package/workspace/WorkspaceFileReader.d.ts +48 -0
  393. package/workspace/WorkspaceFileReader.d.ts.map +1 -0
  394. package/workspace/WorkspaceFileReader.js +11 -0
  395. package/workspace/WorkspaceFileReader.js.map +1 -0
  396. package/workspace/WorkspaceFileSearch.d.ts +32 -0
  397. package/workspace/WorkspaceFileSearch.d.ts.map +1 -0
  398. package/workspace/WorkspaceFileSearch.js +175 -0
  399. package/workspace/WorkspaceFileSearch.js.map +1 -0
  400. package/workspace/WorkspaceSurface.d.ts +151 -0
  401. package/workspace/WorkspaceSurface.d.ts.map +1 -0
  402. package/workspace/WorkspaceSurface.js +220 -0
  403. package/workspace/WorkspaceSurface.js.map +1 -0
  404. package/workspace/findChangeForSelection.d.ts +19 -0
  405. package/workspace/findChangeForSelection.d.ts.map +1 -0
  406. package/workspace/findChangeForSelection.js +46 -0
  407. package/workspace/findChangeForSelection.js.map +1 -0
  408. package/workspace/index.d.ts +24 -2
  409. package/workspace/index.d.ts.map +1 -1
  410. package/workspace/index.js +13 -1
  411. package/workspace/index.js.map +1 -1
  412. package/workspace/matchContentPreview.d.ts +21 -0
  413. package/workspace/matchContentPreview.d.ts.map +1 -0
  414. package/workspace/matchContentPreview.js +36 -0
  415. package/workspace/matchContentPreview.js.map +1 -0
  416. package/workspace/matchWorkspaceFiles.d.ts +30 -0
  417. package/workspace/matchWorkspaceFiles.d.ts.map +1 -0
  418. package/workspace/matchWorkspaceFiles.js +58 -0
  419. package/workspace/matchWorkspaceFiles.js.map +1 -0
  420. package/workspace/resolveWorkspaceFileSelection.d.ts +19 -0
  421. package/workspace/resolveWorkspaceFileSelection.d.ts.map +1 -0
  422. package/workspace/resolveWorkspaceFileSelection.js +115 -0
  423. package/workspace/resolveWorkspaceFileSelection.js.map +1 -0
  424. package/workspace/useWorkspaceContentSearch.d.ts +69 -0
  425. package/workspace/useWorkspaceContentSearch.d.ts.map +1 -0
  426. package/workspace/useWorkspaceContentSearch.js +154 -0
  427. package/workspace/useWorkspaceContentSearch.js.map +1 -0
  428. package/workspace/useWorkspaceFileContent.d.ts +73 -0
  429. package/workspace/useWorkspaceFileContent.d.ts.map +1 -0
  430. package/workspace/useWorkspaceFileContent.js +57 -0
  431. package/workspace/useWorkspaceFileContent.js.map +1 -0
  432. package/workspace/useWorkspaceFileSearch.d.ts +61 -0
  433. package/workspace/useWorkspaceFileSearch.d.ts.map +1 -0
  434. package/workspace/useWorkspaceFileSearch.js +119 -0
  435. package/workspace/useWorkspaceFileSearch.js.map +1 -0
  436. package/workspace/useWorkspaceFiles.d.ts +13 -5
  437. package/workspace/useWorkspaceFiles.d.ts.map +1 -1
  438. package/workspace/useWorkspaceFiles.js +18 -19
  439. package/workspace/useWorkspaceFiles.js.map +1 -1
  440. package/workspace/workspaceListingCache.d.ts +47 -0
  441. package/workspace/workspaceListingCache.d.ts.map +1 -0
  442. package/workspace/workspaceListingCache.js +55 -0
  443. package/workspace/workspaceListingCache.js.map +1 -0
  444. package/session/inspector/ArtifactsTab.d.ts.map +0 -1
  445. package/session/inspector/ArtifactsTab.js.map +0 -1
  446. package/session/inspector/ChangesTab.d.ts.map +0 -1
  447. package/session/inspector/ChangesTab.js.map +0 -1
  448. package/session/inspector/InspectTab.d.ts.map +0 -1
  449. package/session/inspector/InspectTab.js.map +0 -1
  450. package/session/inspector/SessionInspector.d.ts +0 -64
  451. package/session/inspector/SessionInspector.d.ts.map +0 -1
  452. package/session/inspector/SessionInspector.js +0 -53
  453. package/session/inspector/SessionInspector.js.map +0 -1
  454. package/session/inspector/SetupTab.d.ts.map +0 -1
  455. package/session/inspector/SetupTab.js.map +0 -1
  456. package/session/inspector/UsageTab.d.ts.map +0 -1
  457. package/session/inspector/UsageTab.js.map +0 -1
  458. package/session/inspector/WorkspaceTab.d.ts +0 -35
  459. package/session/inspector/WorkspaceTab.d.ts.map +0 -1
  460. package/session/inspector/WorkspaceTab.js +0 -75
  461. package/session/inspector/WorkspaceTab.js.map +0 -1
  462. package/session/inspector/index.d.ts.map +0 -1
  463. package/session/inspector/index.js.map +0 -1
  464. package/session/inspector/useSessionInspector.d.ts +0 -49
  465. package/session/inspector/useSessionInspector.d.ts.map +0 -1
  466. package/session/inspector/useSessionInspector.js +0 -122
  467. package/session/inspector/useSessionInspector.js.map +0 -1
  468. package/src/session/inspector/SessionInspector.tsx +0 -162
  469. package/src/session/inspector/WorkspaceTab.tsx +0 -245
  470. package/src/session/inspector/__tests__/useSessionInspector.test.ts +0 -251
  471. package/src/session/inspector/useSessionInspector.ts +0 -178
  472. package/src/workspace/WorkspaceEntryFiles.tsx +0 -196
  473. package/workflow/motion-preference.d.ts.map +0 -1
  474. package/workflow/motion-preference.js.map +0 -1
  475. package/workspace/WorkspaceEntryFiles.d.ts +0 -22
  476. package/workspace/WorkspaceEntryFiles.d.ts.map +0 -1
  477. package/workspace/WorkspaceEntryFiles.js +0 -58
  478. package/workspace/WorkspaceEntryFiles.js.map +0 -1
  479. /package/session/{inspector → facets}/InspectTab.d.ts +0 -0
  480. /package/session/{inspector → facets}/InspectTab.js +0 -0
  481. /package/src/{workflow → internal}/__tests__/motion-preference.test.ts +0 -0
  482. /package/src/session/{inspector → facets}/InspectTab.tsx +0 -0
  483. /package/src/session/{inspector → facets}/__tests__/ChangesTab.test.tsx +0 -0
@@ -47,18 +47,32 @@ function renderCard(ui: ReactNode) {
47
47
 
48
48
  afterEach(cleanup);
49
49
 
50
- describe("PlanArtifactCard — action surface", () => {
51
- it("is an accessible region labelled as the plan's actions, with name + size", () => {
50
+ describe("PlanArtifactCard — compact document card", () => {
51
+ it("is an accessible region with the plan's title, filename, and size", () => {
52
52
  renderCard(
53
- <PlanArtifactCard executionId="aex_1" artifact={planArtifact} org="acme" />,
53
+ <PlanArtifactCard
54
+ executionId="aex_1"
55
+ artifact={planArtifact}
56
+ title="Refactor the auth flow"
57
+ org="acme"
58
+ />,
54
59
  );
55
60
 
56
- const region = screen.getByRole("region", { name: "Plan actions" });
57
- expect(region.textContent).toContain("Plan");
61
+ const region = screen.getByRole("region", { name: "Plan" });
62
+ expect(region.textContent).toContain("Refactor the auth flow");
63
+ expect(region.textContent).toContain("plan.md");
58
64
  expect(region.textContent).toContain("KB");
59
65
  });
60
66
 
61
- it("does NOT render the plan content (the message above is the document)", () => {
67
+ it("falls back to 'Plan' when the plan has no title", () => {
68
+ renderCard(
69
+ <PlanArtifactCard executionId="aex_1" artifact={planArtifact} org="acme" />,
70
+ );
71
+ const region = screen.getByRole("region", { name: "Plan" });
72
+ expect(region.textContent).toContain("Plan");
73
+ });
74
+
75
+ it("does NOT render the plan content (the document lives in the plan tab)", () => {
62
76
  const { stigmer, getArtifactContent } = createStigmerMock();
63
77
  render(
64
78
  withStigmer(
@@ -66,12 +80,12 @@ describe("PlanArtifactCard — action surface", () => {
66
80
  stigmer,
67
81
  ),
68
82
  );
69
- // The card is a pure action surface — it must not fetch the plan body until
70
- // the user explicitly opens the full preview.
83
+ // The card is the plan's compact stand-in — it must not fetch the plan
84
+ // body; that belongs to the plan tab (or the explicit preview modal).
71
85
  expect(getArtifactContent).not.toHaveBeenCalled();
72
86
  });
73
87
 
74
- it("offers exactly one primary 'Build from plan' action that calls onImplement", () => {
88
+ it("offers exactly one primary 'Build' action that calls onImplement", () => {
75
89
  const onImplement = vi.fn();
76
90
  renderCard(
77
91
  <PlanArtifactCard
@@ -82,18 +96,37 @@ describe("PlanArtifactCard — action surface", () => {
82
96
  />,
83
97
  );
84
98
 
85
- fireEvent.click(screen.getByText("Build from plan"));
99
+ fireEvent.click(screen.getByRole("button", { name: "Build" }));
86
100
  expect(onImplement).toHaveBeenCalledTimes(1);
87
101
  });
88
102
 
89
- it("hides 'Build from plan' when onImplement is not provided", () => {
103
+ it("hides 'Build' when onImplement is not provided", () => {
90
104
  renderCard(
91
105
  <PlanArtifactCard executionId="aex_1" artifact={planArtifact} org="acme" />,
92
106
  );
93
- expect(screen.queryByText("Build from plan")).toBeNull();
107
+ expect(screen.queryByRole("button", { name: "Build" })).toBeNull();
94
108
  });
95
109
 
96
- it("disables 'Build from plan' when disabled", () => {
110
+ it("shows the pending label while the approved plan uploads (buildPending)", () => {
111
+ renderCard(
112
+ <PlanArtifactCard
113
+ executionId="aex_1"
114
+ artifact={planArtifact}
115
+ org="acme"
116
+ onImplement={vi.fn()}
117
+ disabled
118
+ buildPending
119
+ />,
120
+ );
121
+
122
+ // The primary reads as in-progress and stays disabled — no double-submits
123
+ // while the upload precedes the implement turn.
124
+ expect(screen.queryByRole("button", { name: "Build" })).toBeNull();
125
+ const button = screen.getByText("Starting build…").closest("button")!;
126
+ expect(button.disabled).toBe(true);
127
+ });
128
+
129
+ it("disables 'Build' when disabled", () => {
97
130
  const onImplement = vi.fn();
98
131
  renderCard(
99
132
  <PlanArtifactCard
@@ -105,12 +138,44 @@ describe("PlanArtifactCard — action surface", () => {
105
138
  />,
106
139
  );
107
140
 
108
- const button = screen.getByText("Build from plan").closest("button")!;
141
+ const button = screen.getByRole("button", { name: "Build" }) as HTMLButtonElement;
109
142
  expect(button.disabled).toBe(true);
110
143
  fireEvent.click(button);
111
144
  expect(onImplement).not.toHaveBeenCalled();
112
145
  });
113
146
 
147
+ it("copies the plan text to the clipboard on demand", async () => {
148
+ const writeText = vi.fn().mockResolvedValue(undefined);
149
+ vi.stubGlobal("navigator", { clipboard: { writeText } });
150
+ const getArtifactContent = vi
151
+ .fn()
152
+ .mockResolvedValue({ content: new TextEncoder().encode("# Plan\n\nsteps") });
153
+ const getArtifactDownloadUrl = vi.fn();
154
+ const stigmer = {
155
+ agentExecution: { getArtifactContent, getArtifactDownloadUrl },
156
+ } as unknown as Stigmer;
157
+
158
+ render(
159
+ withStigmer(
160
+ <PlanArtifactCard executionId="aex_1" artifact={planArtifact} org="acme" />,
161
+ stigmer,
162
+ ),
163
+ );
164
+
165
+ fireEvent.click(screen.getByRole("button", { name: "Copy plan" }));
166
+
167
+ // Content is fetched at click time from the stable storage key, then
168
+ // written to the clipboard — the card never pre-fetches on mount.
169
+ expect(getArtifactContent).toHaveBeenCalledTimes(1);
170
+ const req = getArtifactContent.mock.calls[0][0];
171
+ expect(req.executionId).toBe("aex_1");
172
+ expect(req.storageKey).toBe("artifacts/aex_1/plan.md");
173
+ await screen.findByRole("button", { name: "Copied" });
174
+ expect(writeText).toHaveBeenCalledWith("# Plan\n\nsteps");
175
+
176
+ vi.unstubAllGlobals();
177
+ });
178
+
114
179
  it("downloads the artifact on demand via a freshly minted URL", async () => {
115
180
  const { stigmer, getArtifactDownloadUrl } = createStigmerMock();
116
181
  render(
@@ -119,7 +184,7 @@ describe("PlanArtifactCard — action surface", () => {
119
184
  stigmer,
120
185
  ),
121
186
  );
122
- fireEvent.click(screen.getByText("Download"));
187
+ fireEvent.click(screen.getByRole("button", { name: "Download plan.md" }));
123
188
  // The URL is resolved at click time from the stable storage key — never a
124
189
  // baked, expirable URL.
125
190
  expect(getArtifactDownloadUrl).toHaveBeenCalledTimes(1);
@@ -141,7 +206,7 @@ describe("PlanArtifactCard — Cmd/Ctrl+Enter accelerator (card-scoped)", () =>
141
206
  />,
142
207
  );
143
208
 
144
- const region = screen.getByRole("region", { name: "Plan actions" });
209
+ const region = screen.getByRole("region", { name: "Plan" });
145
210
  fireEvent.keyDown(region, { key: "Enter", metaKey: true });
146
211
  expect(onImplement).toHaveBeenCalledTimes(1);
147
212
  });
@@ -157,7 +222,7 @@ describe("PlanArtifactCard — Cmd/Ctrl+Enter accelerator (card-scoped)", () =>
157
222
  />,
158
223
  );
159
224
 
160
- const region = screen.getByRole("region", { name: "Plan actions" });
225
+ const region = screen.getByRole("region", { name: "Plan" });
161
226
  fireEvent.keyDown(region, { key: "Enter", ctrlKey: true });
162
227
  expect(onImplement).toHaveBeenCalledTimes(1);
163
228
  });
@@ -173,7 +238,7 @@ describe("PlanArtifactCard — Cmd/Ctrl+Enter accelerator (card-scoped)", () =>
173
238
  />,
174
239
  );
175
240
 
176
- const region = screen.getByRole("region", { name: "Plan actions" });
241
+ const region = screen.getByRole("region", { name: "Plan" });
177
242
  fireEvent.keyDown(region, { key: "Enter" });
178
243
  expect(onImplement).not.toHaveBeenCalled();
179
244
  });
@@ -190,14 +255,14 @@ describe("PlanArtifactCard — Cmd/Ctrl+Enter accelerator (card-scoped)", () =>
190
255
  />,
191
256
  );
192
257
 
193
- const region = screen.getByRole("region", { name: "Plan actions" });
258
+ const region = screen.getByRole("region", { name: "Plan" });
194
259
  fireEvent.keyDown(region, { key: "Enter", metaKey: true });
195
260
  expect(onImplement).not.toHaveBeenCalled();
196
261
  });
197
262
  });
198
263
 
199
- describe("PlanArtifactCard — Open full (org-gated preview)", () => {
200
- it("opens the shared preview modal when 'Open full' is clicked", () => {
264
+ describe("PlanArtifactCard — Open plan modal fallback (org-gated preview)", () => {
265
+ it("opens the shared preview modal when the open icon is clicked (no onOpenPlan)", () => {
201
266
  const { stigmer } = createStigmerMock();
202
267
  render(
203
268
  withStigmer(
@@ -209,14 +274,14 @@ describe("PlanArtifactCard — Open full (org-gated preview)", () => {
209
274
  // No dialog before the user opens it.
210
275
  expect(document.querySelector("dialog")).toBeNull();
211
276
 
212
- fireEvent.click(screen.getByText("Open full"));
277
+ fireEvent.click(screen.getByRole("button", { name: "Open plan" }));
213
278
 
214
279
  const dialog = document.querySelector("dialog");
215
280
  expect(dialog).toBeTruthy();
216
281
  expect(dialog!.getAttribute("aria-label")).toBe("Preview plan.md");
217
282
  });
218
283
 
219
- it("hides 'Open full' when org is absent (modal needs org), keeping Build + Download", () => {
284
+ it("hides the open action when org is absent (modal needs org), keeping Build + Download", () => {
220
285
  const onImplement = vi.fn();
221
286
  renderCard(
222
287
  <PlanArtifactCard
@@ -225,8 +290,31 @@ describe("PlanArtifactCard — Open full (org-gated preview)", () => {
225
290
  onImplement={onImplement}
226
291
  />,
227
292
  );
228
- expect(screen.queryByText("Open full")).toBeNull();
229
- expect(screen.queryByText("Build from plan")).not.toBeNull();
230
- expect(screen.queryByText("Download")).not.toBeNull();
293
+ expect(screen.queryByRole("button", { name: "Open plan" })).toBeNull();
294
+ expect(screen.queryByRole("button", { name: "Build" })).not.toBeNull();
295
+ expect(
296
+ screen.queryByRole("button", { name: "Download plan.md" }),
297
+ ).not.toBeNull();
298
+ });
299
+ });
300
+
301
+ describe("PlanArtifactCard — Open plan (panel-first review)", () => {
302
+ it("routes the open action to the panel when onOpenPlan is provided (no modal)", () => {
303
+ const onOpenPlan = vi.fn();
304
+ renderCard(
305
+ <PlanArtifactCard
306
+ executionId="aex_1"
307
+ artifact={planArtifact}
308
+ org="acme"
309
+ onOpenPlan={onOpenPlan}
310
+ />,
311
+ );
312
+
313
+ // One review affordance, not two: the facet supersedes the modal.
314
+ expect(screen.getAllByRole("button", { name: "Open plan" })).toHaveLength(1);
315
+
316
+ fireEvent.click(screen.getByRole("button", { name: "Open plan" }));
317
+ expect(onOpenPlan).toHaveBeenCalledTimes(1);
318
+ expect(document.querySelector("dialog")).toBeNull();
231
319
  });
232
320
  });
@@ -3,7 +3,7 @@ import { render, fireEvent, cleanup } from "@testing-library/react";
3
3
  import { PlanCompletionCard } from "../PlanCompletionCard";
4
4
 
5
5
  describe("PlanCompletionCard", () => {
6
- it("renders the card with status text and a 'Build from plan' button", () => {
6
+ it("renders the card with status text and a 'Build' button", () => {
7
7
  const { container } = render(<PlanCompletionCard onImplement={() => {}} />);
8
8
 
9
9
  const root = container.firstElementChild as HTMLElement;
@@ -13,7 +13,7 @@ describe("PlanCompletionCard", () => {
13
13
 
14
14
  const button = root.querySelector("button");
15
15
  expect(button).toBeTruthy();
16
- expect(button!.textContent).toContain("Build from plan");
16
+ expect(button!.textContent).toContain("Build");
17
17
 
18
18
  expect(root.textContent).toContain("Plan complete");
19
19
  cleanup();
@@ -0,0 +1,55 @@
1
+ import { describe, it, expect, afterEach } from "vitest";
2
+ import { render, screen, cleanup } from "@testing-library/react";
3
+ import { PlanDocumentMessage } from "../PlanDocumentMessage";
4
+
5
+ afterEach(cleanup);
6
+
7
+ describe("PlanDocumentMessage", () => {
8
+ it("lifts the leading H1 into the header and renders the body as markdown", () => {
9
+ render(
10
+ <PlanDocumentMessage
11
+ content={"# Migration Plan\n\n## Phase 1\n\n- step one"}
12
+ />,
13
+ );
14
+
15
+ const doc = screen.getByRole("article", { name: "Plan document" });
16
+ expect(doc).toBeTruthy();
17
+ expect(doc.querySelector("header")!.textContent).toContain(
18
+ "Migration Plan",
19
+ );
20
+ // The lifted title does not repeat inside the prose body.
21
+ expect(doc.querySelectorAll("h1")).toHaveLength(0);
22
+ });
23
+
24
+ it("falls back to a 'Plan' header when the document has no leading H1", () => {
25
+ render(<PlanDocumentMessage content="Just prose, no heading." />);
26
+
27
+ const doc = screen.getByRole("article", { name: "Plan document" });
28
+ expect(doc.querySelector("header")!.textContent).toContain("Plan");
29
+ expect(doc.textContent).toContain("Just prose, no heading.");
30
+ });
31
+
32
+ it("unwraps a whole-body BARE fence (plan-scoped fence handling)", () => {
33
+ render(
34
+ <PlanDocumentMessage content={"```\n# Fenced Plan\n\nBody text\n```"} />,
35
+ );
36
+
37
+ const doc = screen.getByRole("article", { name: "Plan document" });
38
+ // Unwrapped: the H1 became the header title, the body is prose (not a
39
+ // flat code block).
40
+ expect(doc.querySelector("header")!.textContent).toContain("Fenced Plan");
41
+ expect(doc.querySelector("pre")).toBeNull();
42
+ expect(doc.textContent).toContain("Body text");
43
+ });
44
+
45
+ it("keeps an inner code fence as a code block", () => {
46
+ render(
47
+ <PlanDocumentMessage
48
+ content={"# Plan\n\n```ts\nconst x = 1;\n```"}
49
+ />,
50
+ );
51
+
52
+ const doc = screen.getByRole("article", { name: "Plan document" });
53
+ expect(doc.querySelector("pre")).not.toBeNull();
54
+ });
55
+ });
@@ -0,0 +1,56 @@
1
+ import { describe, it, expect, vi, afterEach } from "vitest";
2
+ import { render, screen, fireEvent, cleanup } from "@testing-library/react";
3
+ import { PlanStreamingCard } from "../PlanStreamingCard";
4
+
5
+ afterEach(cleanup);
6
+
7
+ describe("PlanStreamingCard — live plan stand-in", () => {
8
+ it("is a busy region with the streaming title, status, and live size", () => {
9
+ render(
10
+ <PlanStreamingCard
11
+ title="Refactor the auth flow"
12
+ sizeBytes={2048}
13
+ onOpenPlan={vi.fn()}
14
+ />,
15
+ );
16
+
17
+ const region = screen.getByRole("region", { name: "Plan being written" });
18
+ expect(region.getAttribute("aria-busy")).toBe("true");
19
+ expect(region.textContent).toContain("Refactor the auth flow");
20
+ expect(region.textContent).toContain("Writing…");
21
+ expect(region.textContent).toContain("2.0 KB");
22
+ });
23
+
24
+ it("shows no filename mid-stream (the final name is not known yet)", () => {
25
+ render(
26
+ <PlanStreamingCard title="Refactor the auth flow" sizeBytes={2048} onOpenPlan={vi.fn()} />,
27
+ );
28
+ const region = screen.getByRole("region", { name: "Plan being written" });
29
+ expect(region.textContent).not.toContain("plan.md");
30
+ });
31
+
32
+ it("falls back to 'Writing plan…' until the title has streamed in", () => {
33
+ render(<PlanStreamingCard sizeBytes={12} onOpenPlan={vi.fn()} />);
34
+ expect(screen.getByText("Writing plan…")).toBeTruthy();
35
+ });
36
+
37
+ it("routes 'Open plan' to onOpenPlan", () => {
38
+ const onOpenPlan = vi.fn();
39
+ render(<PlanStreamingCard sizeBytes={64} onOpenPlan={onOpenPlan} />);
40
+
41
+ fireEvent.click(screen.getByText("Open plan"));
42
+ expect(onOpenPlan).toHaveBeenCalledTimes(1);
43
+ });
44
+
45
+ it("offers no Download or Build actions — nothing final exists yet", () => {
46
+ render(<PlanStreamingCard sizeBytes={64} onOpenPlan={vi.fn()} />);
47
+ expect(screen.queryByRole("button", { name: /download/i })).toBeNull();
48
+ expect(screen.queryByText("Build")).toBeNull();
49
+ });
50
+
51
+ it("renders without an action when onOpenPlan is absent", () => {
52
+ render(<PlanStreamingCard sizeBytes={64} />);
53
+ expect(screen.queryByText("Open plan")).toBeNull();
54
+ expect(screen.queryByRole("button")).toBeNull();
55
+ });
56
+ });