@ashlr/hub 3.11.3 → 3.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (558) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/README.md +44 -18
  3. package/dist/authority-surface.json +74 -59
  4. package/dist/build-identity.json +2 -2
  5. package/dist/cli/authority.d.ts +39 -0
  6. package/dist/cli/authority.js +222 -55
  7. package/dist/cli/authority.js.map +1 -1
  8. package/dist/cli/help.js +1 -1
  9. package/dist/cli/help.js.map +1 -1
  10. package/dist/cli/verse.d.ts +3 -0
  11. package/dist/cli/verse.js +10 -0
  12. package/dist/cli/verse.js.map +1 -1
  13. package/dist/core/authority/trust-roots.js +7 -1
  14. package/dist/core/authority/trust-roots.js.map +1 -1
  15. package/dist/core/authority/types.d.ts +2 -2
  16. package/dist/core/cloud/cloud-api.js +1 -1
  17. package/dist/core/cloud/cloud-api.js.map +1 -1
  18. package/dist/core/cloud/delivery-contract.d.ts +1 -1
  19. package/dist/core/cloud/delivery-contract.js +25 -15
  20. package/dist/core/cloud/delivery-contract.js.map +1 -1
  21. package/dist/core/cloud/store.js +6 -0
  22. package/dist/core/cloud/store.js.map +1 -1
  23. package/dist/core/cloud/tracker.d.ts +2 -0
  24. package/dist/core/cloud/tracker.js +140 -37
  25. package/dist/core/cloud/tracker.js.map +1 -1
  26. package/dist/core/cloud/types.d.ts +9 -1
  27. package/dist/core/cloud/types.js.map +1 -1
  28. package/dist/core/comms/dispatch.d.ts +5 -0
  29. package/dist/core/comms/dispatch.js +12 -1
  30. package/dist/core/comms/dispatch.js.map +1 -1
  31. package/dist/core/comms/requests.d.ts +27 -1
  32. package/dist/core/comms/requests.js +50 -1
  33. package/dist/core/comms/requests.js.map +1 -1
  34. package/dist/core/daemon/loop.d.ts +14 -0
  35. package/dist/core/daemon/loop.js +35 -0
  36. package/dist/core/daemon/loop.js.map +1 -1
  37. package/dist/core/fabric/claude-usage.js +23 -1
  38. package/dist/core/fabric/claude-usage.js.map +1 -1
  39. package/dist/core/fleet/dispatch-router.d.ts +7 -0
  40. package/dist/core/fleet/dispatch-router.js +4 -1
  41. package/dist/core/fleet/dispatch-router.js.map +1 -1
  42. package/dist/core/fleet/tick-hooks-live.d.ts +5 -1
  43. package/dist/core/fleet/tick-hooks-live.js +10 -1
  44. package/dist/core/fleet/tick-hooks-live.js.map +1 -1
  45. package/dist/core/local-runtime/llama/config.d.ts +14 -0
  46. package/dist/core/local-runtime/llama/config.js +20 -2
  47. package/dist/core/local-runtime/llama/config.js.map +1 -1
  48. package/dist/core/local-runtime/llama/process.d.ts +19 -0
  49. package/dist/core/local-runtime/llama/process.js +67 -17
  50. package/dist/core/local-runtime/llama/process.js.map +1 -1
  51. package/dist/core/local-runtime/llama/supervisor.js +14 -3
  52. package/dist/core/local-runtime/llama/supervisor.js.map +1 -1
  53. package/dist/core/observability/rollup.d.ts +12 -0
  54. package/dist/core/observability/rollup.js +37 -2
  55. package/dist/core/observability/rollup.js.map +1 -1
  56. package/dist/core/observability/usage-source.js +49 -1
  57. package/dist/core/observability/usage-source.js.map +1 -1
  58. package/dist/core/resources/connection-monitor.js +47 -4
  59. package/dist/core/resources/connection-monitor.js.map +1 -1
  60. package/dist/core/resources/engineering-mission-store.d.ts +1 -1
  61. package/dist/core/routing/headroom.js +7 -2
  62. package/dist/core/routing/headroom.js.map +1 -1
  63. package/dist/core/routing/router.d.ts +48 -0
  64. package/dist/core/routing/router.js +129 -13
  65. package/dist/core/routing/router.js.map +1 -1
  66. package/dist/core/run/best-of-n.d.ts +7 -0
  67. package/dist/core/run/best-of-n.js +3 -0
  68. package/dist/core/run/best-of-n.js.map +1 -1
  69. package/dist/core/run/harness-dispatch.d.ts +147 -0
  70. package/dist/core/run/harness-dispatch.js +234 -0
  71. package/dist/core/run/harness-dispatch.js.map +1 -0
  72. package/dist/core/run/orchestrator.js +3 -0
  73. package/dist/core/run/orchestrator.js.map +1 -1
  74. package/dist/core/run/provider-client.d.ts +8 -0
  75. package/dist/core/run/provider-client.js +4 -0
  76. package/dist/core/run/provider-client.js.map +1 -1
  77. package/dist/core/run/sandboxed-engine.d.ts +8 -0
  78. package/dist/core/run/sandboxed-engine.js +60 -7
  79. package/dist/core/run/sandboxed-engine.js.map +1 -1
  80. package/dist/core/types.d.ts +14 -0
  81. package/dist/core/types.js.map +1 -1
  82. package/dist/core/universe/builtins/preparation/manifest.json +1 -1
  83. package/dist/core/universe/builtins/preparation/preparation-bridge.mjs +188 -6
  84. package/dist/core/universe/builtins/preparation/preparation-verification-fixtures.mjs +187 -5
  85. package/dist/core/universe/firm-demo.d.ts +1 -1
  86. package/dist/core/universe/firm-graph.d.ts +2 -2
  87. package/dist/core/util/scrub.js +16 -3
  88. package/dist/core/util/scrub.js.map +1 -1
  89. package/dist/core/verse/accounts.d.ts +9 -1
  90. package/dist/core/verse/accounts.js +52 -11
  91. package/dist/core/verse/accounts.js.map +1 -1
  92. package/dist/core/verse/apps-api.d.ts +12 -0
  93. package/dist/core/verse/apps-api.js +22 -4
  94. package/dist/core/verse/apps-api.js.map +1 -1
  95. package/dist/core/verse/apps.js +22 -12
  96. package/dist/core/verse/apps.js.map +1 -1
  97. package/dist/core/verse/local-models.js +3 -7
  98. package/dist/core/verse/local-models.js.map +1 -1
  99. package/dist/core/verse/model-display-name.d.ts +34 -0
  100. package/dist/core/verse/model-display-name.js +125 -0
  101. package/dist/core/verse/model-display-name.js.map +1 -0
  102. package/dist/core/verse/seats.d.ts +11 -2
  103. package/dist/core/verse/seats.js +42 -18
  104. package/dist/core/verse/seats.js.map +1 -1
  105. package/dist/core/verse/transient-events.d.ts +21 -0
  106. package/dist/core/verse/transient-events.js +12 -0
  107. package/dist/core/verse/transient-events.js.map +1 -0
  108. package/dist/core/verse/types.d.ts +6 -13
  109. package/dist/core/verse/types.js +5 -36
  110. package/dist/core/verse/types.js.map +1 -1
  111. package/dist/core/web/public/next/assets/ActionMenu-B4-39f2S.js +2 -0
  112. package/dist/core/web/public/next/assets/{ActionMenu-FxXeRbPx.js.map → ActionMenu-B4-39f2S.js.map} +1 -1
  113. package/dist/core/web/public/next/assets/Advanced-B-LqYXvd.js +2 -0
  114. package/dist/core/web/public/next/assets/Advanced-B-LqYXvd.js.map +1 -0
  115. package/dist/core/web/public/next/assets/App-E2zCDRxm.js +7 -0
  116. package/dist/core/web/public/next/assets/App-E2zCDRxm.js.map +1 -0
  117. package/dist/core/web/public/next/assets/AppsSection-8wXPPhZb.js +2 -0
  118. package/dist/core/web/public/next/assets/AppsSection-8wXPPhZb.js.map +1 -0
  119. package/dist/core/web/public/next/assets/AreaTrend-BFimExYn.js +2 -0
  120. package/dist/core/web/public/next/assets/{AreaTrend-CDxrQU4b.js.map → AreaTrend-BFimExYn.js.map} +1 -1
  121. package/dist/core/web/public/next/assets/AutonomyOffState-B5eEkmiz.js +2 -0
  122. package/dist/core/web/public/next/assets/AutonomyOffState-B5eEkmiz.js.map +1 -0
  123. package/dist/core/web/public/next/assets/AutonomyOffState-DmbE71vI.css +1 -0
  124. package/dist/core/web/public/next/assets/AutonomySection-B46igJKR.js +2 -0
  125. package/dist/core/web/public/next/assets/{AutonomySection-DuQkHGD_.js.map → AutonomySection-B46igJKR.js.map} +1 -1
  126. package/dist/core/web/public/next/assets/BranchBar-BRkrEQGs.js +2 -0
  127. package/dist/core/web/public/next/assets/{BranchBar-CLsvOcyK.js.map → BranchBar-BRkrEQGs.js.map} +1 -1
  128. package/dist/core/web/public/next/assets/BudgetControl-T_RjPrw9.js +2 -0
  129. package/dist/core/web/public/next/assets/{BudgetControl-TL3FeZ1D.js.map → BudgetControl-T_RjPrw9.js.map} +1 -1
  130. package/dist/core/web/public/next/assets/{Button-HHXgoXGr.js → Button-BhO-WKPp.js} +2 -2
  131. package/dist/core/web/public/next/assets/{Button-HHXgoXGr.js.map → Button-BhO-WKPp.js.map} +1 -1
  132. package/dist/core/web/public/next/assets/CapacityStrip-CkFz5vq2.js +2 -0
  133. package/dist/core/web/public/next/assets/{CapacityStrip-qReu0RaF.js.map → CapacityStrip-CkFz5vq2.js.map} +1 -1
  134. package/dist/core/web/public/next/assets/{useChartWidth-BW6SwYIK.css → ChartFrame-BVuBe6RP.css} +1 -1
  135. package/dist/core/web/public/next/assets/ChartFrame-SygZ7B3x.js +2 -0
  136. package/dist/core/web/public/next/assets/ChartFrame-SygZ7B3x.js.map +1 -0
  137. package/dist/core/web/public/next/assets/ChatSection-D6WybBpB.js +3 -0
  138. package/dist/core/web/public/next/assets/ChatSection-D6WybBpB.js.map +1 -0
  139. package/dist/core/web/public/next/assets/CloudBudgetForm-Bd91iStN.js +2 -0
  140. package/dist/core/web/public/next/assets/CloudBudgetForm-Bd91iStN.js.map +1 -0
  141. package/dist/core/web/public/next/assets/CommandPalette-B6SgDJH-.js +2 -0
  142. package/dist/core/web/public/next/assets/CommandPalette-B6SgDJH-.js.map +1 -0
  143. package/dist/core/web/public/next/assets/CommandSection-CvAVd1w4.css +1 -0
  144. package/dist/core/web/public/next/assets/CommandSection-DgMGoepd.js +2 -0
  145. package/dist/core/web/public/next/assets/CommandSection-DgMGoepd.js.map +1 -0
  146. package/dist/core/web/public/next/assets/ConfirmDialog-Bv4hdK2T.js +2 -0
  147. package/dist/core/web/public/next/assets/{ConfirmDialog-DLrLKM0c.js.map → ConfirmDialog-Bv4hdK2T.js.map} +1 -1
  148. package/dist/core/web/public/next/assets/DeleteChatDialog-CH1Ix8Eh.js +2 -0
  149. package/dist/core/web/public/next/assets/DeleteChatDialog-CH1Ix8Eh.js.map +1 -0
  150. package/dist/core/web/public/next/assets/Dialog-BSsIFNqD.js +2 -0
  151. package/dist/core/web/public/next/assets/{Dialog-BS9Dxi3G.js.map → Dialog-BSsIFNqD.js.map} +1 -1
  152. package/dist/core/web/public/next/assets/DiffPane-BpNuJmth.js +2 -0
  153. package/dist/core/web/public/next/assets/{DiffPane-TOmUf3b2.js.map → DiffPane-BpNuJmth.js.map} +1 -1
  154. package/dist/core/web/public/next/assets/DiffViewer-CJarUvs0.js +2 -0
  155. package/dist/core/web/public/next/assets/{DiffViewer-BpH56302.js.map → DiffViewer-CJarUvs0.js.map} +1 -1
  156. package/dist/core/web/public/next/assets/DockHost-DW9q0NdR.js +2 -0
  157. package/dist/core/web/public/next/assets/DockHost-DW9q0NdR.js.map +1 -0
  158. package/dist/core/web/public/next/assets/{EmptyState-BqR5YAmf.js → EmptyState-DPrd2aak.js} +2 -2
  159. package/dist/core/web/public/next/assets/{EmptyState-BqR5YAmf.js.map → EmptyState-DPrd2aak.js.map} +1 -1
  160. package/dist/core/web/public/next/assets/{Epistemic-dhvDTwAZ.js → Epistemic-D7MxSmED.js} +2 -2
  161. package/dist/core/web/public/next/assets/{Epistemic-dhvDTwAZ.js.map → Epistemic-D7MxSmED.js.map} +1 -1
  162. package/dist/core/web/public/next/assets/FleetSection-BdZN6rGS.js +3 -0
  163. package/dist/core/web/public/next/assets/FleetSection-BdZN6rGS.js.map +1 -0
  164. package/dist/core/web/public/next/assets/Funnel-BeNQZWv2.js +2 -0
  165. package/dist/core/web/public/next/assets/{Funnel-D2u7Wlzc.js.map → Funnel-BeNQZWv2.js.map} +1 -1
  166. package/dist/core/web/public/next/assets/GearTray-CIPtzeIx.js +2 -0
  167. package/dist/core/web/public/next/assets/{GearTray-Cb2npoxM.js.map → GearTray-CIPtzeIx.js.map} +1 -1
  168. package/dist/core/web/public/next/assets/GrowthSection-iiQg6wvK.js +2 -0
  169. package/dist/core/web/public/next/assets/{GrowthSection-C5aDPs8B.js.map → GrowthSection-iiQg6wvK.js.map} +1 -1
  170. package/dist/core/web/public/next/assets/HandoffDialog-DrQ6ofuy.js +2 -0
  171. package/dist/core/web/public/next/assets/{HandoffDialog-BF3AYg-X.js.map → HandoffDialog-DrQ6ofuy.js.map} +1 -1
  172. package/dist/core/web/public/next/assets/Input-C0MQxEM6.js +2 -0
  173. package/dist/core/web/public/next/assets/{Input-B5dmGLZx.js.map → Input-C0MQxEM6.js.map} +1 -1
  174. package/dist/core/web/public/next/assets/LeaderCard-BRr3_yE-.js +2 -0
  175. package/dist/core/web/public/next/assets/LeaderCard-BRr3_yE-.js.map +1 -0
  176. package/dist/core/web/public/next/assets/MatrixHeatmap-DZvZeWXL.js +2 -0
  177. package/dist/core/web/public/next/assets/{MatrixHeatmap-BgEUs2Eu.js.map → MatrixHeatmap-DZvZeWXL.js.map} +1 -1
  178. package/dist/core/web/public/next/assets/McpSection-BRuCcTjT.js +2 -0
  179. package/dist/core/web/public/next/assets/{McpSection-DZkiOuoq.js.map → McpSection-BRuCcTjT.js.map} +1 -1
  180. package/dist/core/web/public/next/assets/MessageMarkdown-bRvD5nSc.js +3 -0
  181. package/dist/core/web/public/next/assets/{MessageMarkdown-BauY8ZTY.js.map → MessageMarkdown-bRvD5nSc.js.map} +1 -1
  182. package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-DLBNLfsn.js → MessageMarkdownRenderer-FjjkPKA2.js} +4 -4
  183. package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-DLBNLfsn.js.map → MessageMarkdownRenderer-FjjkPKA2.js.map} +1 -1
  184. package/dist/core/web/public/next/assets/{Meter-DNeocJnD.js → Meter-CFNLpwA-.js} +2 -2
  185. package/dist/core/web/public/next/assets/{Meter-DNeocJnD.js.map → Meter-CFNLpwA-.js.map} +1 -1
  186. package/dist/core/web/public/next/assets/MindSection-BTIiQS8P.js +2 -0
  187. package/dist/core/web/public/next/assets/MindSection-BTIiQS8P.js.map +1 -0
  188. package/dist/core/web/public/next/assets/MutationTokenDialog-T7gv3a9r.js +2 -0
  189. package/dist/core/web/public/next/assets/{MutationTokenDialog-mxrw0Yvy.js.map → MutationTokenDialog-T7gv3a9r.js.map} +1 -1
  190. package/dist/core/web/public/next/assets/NeedsYouDrawer-lYN4G_aM.js +2 -0
  191. package/dist/core/web/public/next/assets/{NeedsYouDrawer-CO-Balfp.js.map → NeedsYouDrawer-lYN4G_aM.js.map} +1 -1
  192. package/dist/core/web/public/next/assets/NeedsYouList-BgH8ezqf.js +2 -0
  193. package/dist/core/web/public/next/assets/{NeedsYouList-CzDZbzRD.js.map → NeedsYouList-BgH8ezqf.js.map} +1 -1
  194. package/dist/core/web/public/next/assets/NewChatDialog-Db5Xjrk8.js +3 -0
  195. package/dist/core/web/public/next/assets/NewChatDialog-Db5Xjrk8.js.map +1 -0
  196. package/dist/core/web/public/next/assets/OnboardingFlow-HUNQGQuU.css +1 -0
  197. package/dist/core/web/public/next/assets/OnboardingFlow-LoY-zuSe.js +2 -0
  198. package/dist/core/web/public/next/assets/OnboardingFlow-LoY-zuSe.js.map +1 -0
  199. package/dist/core/web/public/next/assets/OnboardingGate-C4VXn7BJ.js +3 -0
  200. package/dist/core/web/public/next/assets/OnboardingGate-C4VXn7BJ.js.map +1 -0
  201. package/dist/core/web/public/next/assets/PreviewPane-BPBbcROb.js +2 -0
  202. package/dist/core/web/public/next/assets/{PreviewPane-BS-CleCd.js.map → PreviewPane-BPBbcROb.js.map} +1 -1
  203. package/dist/core/web/public/next/assets/{ProviderLogo-C5mBg8i0.js → ProviderLogo-CT2cSfkg.js} +2 -2
  204. package/dist/core/web/public/next/assets/{ProviderLogo-C5mBg8i0.js.map → ProviderLogo-CT2cSfkg.js.map} +1 -1
  205. package/dist/core/web/public/next/assets/RailStatus-Vgl0GYtd.js +2 -0
  206. package/dist/core/web/public/next/assets/{RailStatus-cPRyOmrk.js.map → RailStatus-Vgl0GYtd.js.map} +1 -1
  207. package/dist/core/web/public/next/assets/{RefreshIndicator-CMwSCiz5.js → RefreshIndicator-CSyqpY_q.js} +2 -2
  208. package/dist/core/web/public/next/assets/{RefreshIndicator-CMwSCiz5.js.map → RefreshIndicator-CSyqpY_q.js.map} +1 -1
  209. package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-BFi1opsC.js → ResourcePoolConsoleApp-BX2nkdmZ.js} +4 -4
  210. package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-BFi1opsC.js.map → ResourcePoolConsoleApp-BX2nkdmZ.js.map} +1 -1
  211. package/dist/core/web/public/next/assets/ResourcesChrome-B2U2lO1H.js +3 -0
  212. package/dist/core/web/public/next/assets/ResourcesChrome-B2U2lO1H.js.map +1 -0
  213. package/dist/core/web/public/next/assets/ResourcesDrawer-BCFJ2Uq8.css +1 -0
  214. package/dist/core/web/public/next/assets/ResourcesDrawer-DlUKOjl9.js +2 -0
  215. package/dist/core/web/public/next/assets/ResourcesDrawer-DlUKOjl9.js.map +1 -0
  216. package/dist/core/web/public/next/assets/RouteErrorBoundary-BaC7YVzR.js +2 -0
  217. package/dist/core/web/public/next/assets/{RouteErrorBoundary-DYtwc2ja.js.map → RouteErrorBoundary-BaC7YVzR.js.map} +1 -1
  218. package/dist/core/web/public/next/assets/RunInCloudAction-D5PDHJPE.js +2 -0
  219. package/dist/core/web/public/next/assets/{RunInCloudAction-BEGEEM8O.js.map → RunInCloudAction-D5PDHJPE.js.map} +1 -1
  220. package/dist/core/web/public/next/assets/SeatSelector-Cg75LInq.js +3 -0
  221. package/dist/core/web/public/next/assets/{SeatSelector-CYHRR7Wp.js.map → SeatSelector-Cg75LInq.js.map} +1 -1
  222. package/dist/core/web/public/next/assets/Segmented-CametjLt.js +2 -0
  223. package/dist/core/web/public/next/assets/{Segmented-BE53BenI.js.map → Segmented-CametjLt.js.map} +1 -1
  224. package/dist/core/web/public/next/assets/Select-De52fghU.js +2 -0
  225. package/dist/core/web/public/next/assets/{Select-BwSGkHCS.js.map → Select-De52fghU.js.map} +1 -1
  226. package/dist/core/web/public/next/assets/SessionGate-CzlcNq3O.js +2 -0
  227. package/dist/core/web/public/next/assets/{SessionGate-e0dFJm9d.js.map → SessionGate-CzlcNq3O.js.map} +1 -1
  228. package/dist/core/web/public/next/assets/SessionInsightChip-Bk_Owa7u.js +2 -0
  229. package/dist/core/web/public/next/assets/{SessionInsightChip-CxlSyueJ.js.map → SessionInsightChip-Bk_Owa7u.js.map} +1 -1
  230. package/dist/core/web/public/next/assets/SessionSearch-C6C8DHN8.js +2 -0
  231. package/dist/core/web/public/next/assets/{SessionSearch-_yp7S2TP.js.map → SessionSearch-C6C8DHN8.js.map} +1 -1
  232. package/dist/core/web/public/next/assets/SettingsSection-mI9wQYZg.js +2 -0
  233. package/dist/core/web/public/next/assets/SettingsSection-mI9wQYZg.js.map +1 -0
  234. package/dist/core/web/public/next/assets/Sheet-CJhK9Dqv.js +2 -0
  235. package/dist/core/web/public/next/assets/{Sheet-DVP2Mgy6.js.map → Sheet-CJhK9Dqv.js.map} +1 -1
  236. package/dist/core/web/public/next/assets/ShortcutsOverlay-DDW-i9Fc.js +2 -0
  237. package/dist/core/web/public/next/assets/{ShortcutsOverlay-BcIcoClX.js.map → ShortcutsOverlay-DDW-i9Fc.js.map} +1 -1
  238. package/dist/core/web/public/next/assets/Sidebar-DT7ykaqS.js +3 -0
  239. package/dist/core/web/public/next/assets/Sidebar-DT7ykaqS.js.map +1 -0
  240. package/dist/core/web/public/next/assets/Slider-Bwd9HfXl.js +2 -0
  241. package/dist/core/web/public/next/assets/{Slider-BypUWjpH.js.map → Slider-Bwd9HfXl.js.map} +1 -1
  242. package/dist/core/web/public/next/assets/StatTile-DPZ5yyaU.js +2 -0
  243. package/dist/core/web/public/next/assets/StatTile-DPZ5yyaU.js.map +1 -0
  244. package/dist/core/web/public/next/assets/{StatusBadge-HCZp416_.js → StatusBadge-DHKRtttH.js} +2 -2
  245. package/dist/core/web/public/next/assets/{StatusBadge-HCZp416_.js.map → StatusBadge-DHKRtttH.js.map} +1 -1
  246. package/dist/core/web/public/next/assets/StepBand-DQykLkk_.js +2 -0
  247. package/dist/core/web/public/next/assets/{StepBand-Duz1PUes.js.map → StepBand-DQykLkk_.js.map} +1 -1
  248. package/dist/core/web/public/next/assets/Surface-D--LXgQm.js +2 -0
  249. package/dist/core/web/public/next/assets/Surface-D--LXgQm.js.map +1 -0
  250. package/dist/core/web/public/next/assets/Surface-e1z6GdZt.css +1 -0
  251. package/dist/core/web/public/next/assets/Swimlane-BzH6OCee.js +2 -0
  252. package/dist/core/web/public/next/assets/{Swimlane-DGcIcnNA.js.map → Swimlane-BzH6OCee.js.map} +1 -1
  253. package/dist/core/web/public/next/assets/{Switch-iveI-8NY.js → Switch-PMixU6b0.js} +2 -2
  254. package/dist/core/web/public/next/assets/{Switch-iveI-8NY.js.map → Switch-PMixU6b0.js.map} +1 -1
  255. package/dist/core/web/public/next/assets/{Tag-DH15CUJp.js → Tag-fordBsrJ.js} +2 -2
  256. package/dist/core/web/public/next/assets/{Tag-DH15CUJp.js.map → Tag-fordBsrJ.js.map} +1 -1
  257. package/dist/core/web/public/next/assets/TerminalPane-BSnGdUuF.js +7 -0
  258. package/dist/core/web/public/next/assets/TerminalPane-BSnGdUuF.js.map +1 -0
  259. package/dist/core/web/public/next/assets/UniverseConsoleApp-DtXFhAhw.js +2 -0
  260. package/dist/core/web/public/next/assets/{UniverseConsoleApp-C8yQ0AaR.js.map → UniverseConsoleApp-DtXFhAhw.js.map} +1 -1
  261. package/dist/core/web/public/next/assets/{UniverseView-_nPURPqe.js → UniverseView-sWm3pnTW.js} +3 -3
  262. package/dist/core/web/public/next/assets/{UniverseView-_nPURPqe.js.map → UniverseView-sWm3pnTW.js.map} +1 -1
  263. package/dist/core/web/public/next/assets/UsageSection-CiD1DbuF.js +3 -0
  264. package/dist/core/web/public/next/assets/UsageSection-CiD1DbuF.js.map +1 -0
  265. package/dist/core/web/public/next/assets/VerseConsoleApp-BCY5uSok.js +3 -0
  266. package/dist/core/web/public/next/assets/VerseConsoleApp-BCY5uSok.js.map +1 -0
  267. package/dist/core/web/public/next/assets/Workspace-BQSZFSeO.js +10 -0
  268. package/dist/core/web/public/next/assets/Workspace-BQSZFSeO.js.map +1 -0
  269. package/dist/core/web/public/next/assets/actions-BmIf9avl.css +1 -0
  270. package/dist/core/web/public/next/assets/actions-Ci6I4C0l.js +2 -0
  271. package/dist/core/web/public/next/assets/actions-Ci6I4C0l.js.map +1 -0
  272. package/dist/core/web/public/next/assets/apps-model-DlwnfqwJ.js +2 -0
  273. package/dist/core/web/public/next/assets/apps-model-DlwnfqwJ.js.map +1 -0
  274. package/dist/core/web/public/next/assets/authority-model-BFuPezSo.js +2 -0
  275. package/dist/core/web/public/next/assets/authority-model-BFuPezSo.js.map +1 -0
  276. package/dist/core/web/public/next/assets/binding-left-DZpq5sLf.js +2 -0
  277. package/dist/core/web/public/next/assets/binding-left-DZpq5sLf.js.map +1 -0
  278. package/dist/core/web/public/next/assets/{budget-queries-V3wcJVK_.js → budget-queries-DsAjH8ac.js} +2 -2
  279. package/dist/core/web/public/next/assets/{budget-queries-V3wcJVK_.js.map → budget-queries-DsAjH8ac.js.map} +1 -1
  280. package/dist/core/web/public/next/assets/capacity-strip-model-Dn1cNOhz.js +2 -0
  281. package/dist/core/web/public/next/assets/capacity-strip-model-Dn1cNOhz.js.map +1 -0
  282. package/dist/core/web/public/next/assets/charts-C_xJbJiw.js +2 -0
  283. package/dist/core/web/public/next/assets/charts-C_xJbJiw.js.map +1 -0
  284. package/dist/core/web/public/next/assets/charts-DhKTrQLw.css +1 -0
  285. package/dist/core/web/public/next/assets/clipboard-DkZdqlxf.js +2 -0
  286. package/dist/core/web/public/next/assets/clipboard-DkZdqlxf.js.map +1 -0
  287. package/dist/core/web/public/next/assets/cloud-D-HXms6q.css +1 -0
  288. package/dist/core/web/public/next/assets/cloud-model-CX407gPY.js +2 -0
  289. package/dist/core/web/public/next/assets/cloud-model-CX407gPY.js.map +1 -0
  290. package/dist/core/web/public/next/assets/cloud-queries-QAhpExlz.js +2 -0
  291. package/dist/core/web/public/next/assets/cloud-queries-QAhpExlz.js.map +1 -0
  292. package/dist/core/web/public/next/assets/cloud.module-DOP-N4Ch.js +2 -0
  293. package/dist/core/web/public/next/assets/cloud.module-DOP-N4Ch.js.map +1 -0
  294. package/dist/core/web/public/next/assets/command-catalog-CF0cQQac.js +2 -0
  295. package/dist/core/web/public/next/assets/command-catalog-CF0cQQac.js.map +1 -0
  296. package/dist/core/web/public/next/assets/context-model-Co4wh3SM.js +2 -0
  297. package/dist/core/web/public/next/assets/context-model-Co4wh3SM.js.map +1 -0
  298. package/dist/core/web/public/next/assets/context-model-DV1zCfAm.js +3 -0
  299. package/dist/core/web/public/next/assets/context-model-DV1zCfAm.js.map +1 -0
  300. package/dist/core/web/public/next/assets/{context-queries-CrPcHWTz.js → context-queries-CktFQqSS.js} +2 -2
  301. package/dist/core/web/public/next/assets/{context-queries-CrPcHWTz.js.map → context-queries-CktFQqSS.js.map} +1 -1
  302. package/dist/core/web/public/next/assets/{control-queries-CmgBgKV7.js → control-queries-DAvlh_YM.js} +2 -2
  303. package/dist/core/web/public/next/assets/{control-queries-CmgBgKV7.js.map → control-queries-DAvlh_YM.js.map} +1 -1
  304. package/dist/core/web/public/next/assets/copy-setup-CqRSfELB.js +2 -0
  305. package/dist/core/web/public/next/assets/copy-setup-CqRSfELB.js.map +1 -0
  306. package/dist/core/web/public/next/assets/dock-icons-BFuBbqJl.js +2 -0
  307. package/dist/core/web/public/next/assets/{dock-icons-CUh8dOxJ.js.map → dock-icons-BFuBbqJl.js.map} +1 -1
  308. package/dist/core/web/public/next/assets/fleet-model-Dfd5JyLR.js +2 -0
  309. package/dist/core/web/public/next/assets/fleet-model-Dfd5JyLR.js.map +1 -0
  310. package/dist/core/web/public/next/assets/fleet-queries-RtMTd5rR.js +2 -0
  311. package/dist/core/web/public/next/assets/fleet-queries-RtMTd5rR.js.map +1 -0
  312. package/dist/core/web/public/next/assets/{focus-trap-HtcoXeEq.js → focus-trap-BdrbWfC4.js} +2 -2
  313. package/dist/core/web/public/next/assets/{focus-trap-HtcoXeEq.js.map → focus-trap-BdrbWfC4.js.map} +1 -1
  314. package/dist/core/web/public/next/assets/format-Dk4Fmxax.js +2 -0
  315. package/dist/core/web/public/next/assets/format-Dk4Fmxax.js.map +1 -0
  316. package/dist/core/web/public/next/assets/{git-model-bk_RXh3y.js → git-model-_BnI_Ogh.js} +2 -2
  317. package/dist/core/web/public/next/assets/{git-model-bk_RXh3y.js.map → git-model-_BnI_Ogh.js.map} +1 -1
  318. package/dist/core/web/public/next/assets/global-CNNGMril.js +2 -0
  319. package/dist/core/web/public/next/assets/{global-oEl9Qj8u.js.map → global-CNNGMril.js.map} +1 -1
  320. package/dist/core/web/public/next/assets/{guarded-runners-LHLXmXIk.js → guarded-runners-DPh2d32e.js} +2 -2
  321. package/dist/core/web/public/next/assets/{guarded-runners-LHLXmXIk.js.map → guarded-runners-DPh2d32e.js.map} +1 -1
  322. package/dist/core/web/public/next/assets/icons-0haWy6nh.js +2 -0
  323. package/dist/core/web/public/next/assets/icons-0haWy6nh.js.map +1 -0
  324. package/dist/core/web/public/next/assets/{index-BVxOlseC.js → index-QesfXBsb.js} +3 -3
  325. package/dist/core/web/public/next/assets/{index-BVxOlseC.js.map → index-QesfXBsb.js.map} +1 -1
  326. package/dist/core/web/public/next/assets/live-model-De-q0ZFK.js +2 -0
  327. package/dist/core/web/public/next/assets/live-model-De-q0ZFK.js.map +1 -0
  328. package/dist/core/web/public/next/assets/local-model-C9xNi9fN.js +2 -0
  329. package/dist/core/web/public/next/assets/local-model-C9xNi9fN.js.map +1 -0
  330. package/dist/core/web/public/next/assets/mind.module-BrK2nFOL.js +2 -0
  331. package/dist/core/web/public/next/assets/{mind.module-gTGAuJt1.js.map → mind.module-BrK2nFOL.js.map} +1 -1
  332. package/dist/core/web/public/next/assets/mutations-DTCtKCn_.js +2 -0
  333. package/dist/core/web/public/next/assets/{mutations-C5S7okTW.js.map → mutations-DTCtKCn_.js.map} +1 -1
  334. package/dist/core/web/public/next/assets/nav-KmGX0CVz.js +2 -0
  335. package/dist/core/web/public/next/assets/{nav-NVtnuG7A.js.map → nav-KmGX0CVz.js.map} +1 -1
  336. package/dist/core/web/public/next/assets/{overnight-queries-DGm3qL1b.js → overnight-queries-mlO0xzsr.js} +2 -2
  337. package/dist/core/web/public/next/assets/{overnight-queries-DGm3qL1b.js.map → overnight-queries-mlO0xzsr.js.map} +1 -1
  338. package/dist/core/web/public/next/assets/primitives-D0Fb3TtS.js +1 -0
  339. package/dist/core/web/public/next/assets/{queries-CYisSAAB.js → queries-CyBE8nsW.js} +2 -2
  340. package/dist/core/web/public/next/assets/{queries-CYisSAAB.js.map → queries-CyBE8nsW.js.map} +1 -1
  341. package/dist/core/web/public/next/assets/reasoning-pref-CaoA4_Vl.js +2 -0
  342. package/dist/core/web/public/next/assets/{reasoning-pref-BUcFF_5G.js.map → reasoning-pref-CaoA4_Vl.js.map} +1 -1
  343. package/dist/core/web/public/next/assets/{reveal-anchor-D-tV8xau.js → reveal-anchor-BP1VqnPU.js} +2 -2
  344. package/dist/core/web/public/next/assets/{reveal-anchor-D-tV8xau.js.map → reveal-anchor-BP1VqnPU.js.map} +1 -1
  345. package/dist/core/web/public/next/assets/seat-subscription-C5Tvr0WQ.js +2 -0
  346. package/dist/core/web/public/next/assets/{seat-subscription-B-f9ViU2.js.map → seat-subscription-C5Tvr0WQ.js.map} +1 -1
  347. package/dist/core/web/public/next/assets/{sidebar-model-DQ-FyBHW.js → sidebar-model-B5Qk95k_.js} +2 -2
  348. package/dist/core/web/public/next/assets/{sidebar-model-DQ-FyBHW.js.map → sidebar-model-B5Qk95k_.js.map} +1 -1
  349. package/dist/core/web/public/next/assets/slots-DHKQDoE6.js +3 -0
  350. package/dist/core/web/public/next/assets/{slots-BhP8b8tf.js.map → slots-DHKQDoE6.js.map} +1 -1
  351. package/dist/core/web/public/next/assets/surface-data-CchClvHo.js +2 -0
  352. package/dist/core/web/public/next/assets/surface-data-CchClvHo.js.map +1 -0
  353. package/dist/core/web/public/next/assets/surface-prefetch-BWr0LBQn.js +2 -0
  354. package/dist/core/web/public/next/assets/surface-prefetch-BWr0LBQn.js.map +1 -0
  355. package/dist/core/web/public/next/assets/{tasks-model-BKDNqmmt.js → tasks-model-D6WFVULI.js} +2 -2
  356. package/dist/core/web/public/next/assets/{tasks-model-BKDNqmmt.js.map → tasks-model-D6WFVULI.js.map} +1 -1
  357. package/dist/core/web/public/next/assets/{terminal-icons-D2xe-aM1.js → terminal-icons-BvCvuXk2.js} +2 -2
  358. package/dist/core/web/public/next/assets/{terminal-icons-D2xe-aM1.js.map → terminal-icons-BvCvuXk2.js.map} +1 -1
  359. package/dist/core/web/public/next/assets/transient-events-nTLhMBND.js +2 -0
  360. package/dist/core/web/public/next/assets/transient-events-nTLhMBND.js.map +1 -0
  361. package/dist/core/web/public/next/assets/types-D5XOdyw8.js.map +1 -1
  362. package/dist/core/web/public/next/assets/{usage-queries-BZuAANlI.js → usage-queries-D1SU1t7r.js} +2 -2
  363. package/dist/core/web/public/next/assets/{usage-queries-BZuAANlI.js.map → usage-queries-D1SU1t7r.js.map} +1 -1
  364. package/dist/core/web/public/next/assets/{use-guarded-action-Cf4MeNBa.js → use-guarded-action-BZmBv7CJ.js} +2 -2
  365. package/dist/core/web/public/next/assets/{use-guarded-action-Cf4MeNBa.js.map → use-guarded-action-BZmBv7CJ.js.map} +1 -1
  366. package/dist/core/web/public/next/assets/{use-ticker-D9yi49my.js → use-ticker-CkJ4-0wU.js} +2 -2
  367. package/dist/core/web/public/next/assets/{use-ticker-D9yi49my.js.map → use-ticker-CkJ4-0wU.js.map} +1 -1
  368. package/dist/core/web/public/next/assets/{use-token-gate-DqrSXdX6.js → use-token-gate-CYcfk_GS.js} +2 -2
  369. package/dist/core/web/public/next/assets/{use-token-gate-DqrSXdX6.js.map → use-token-gate-CYcfk_GS.js.map} +1 -1
  370. package/dist/core/web/public/next/assets/useOnboarding-CujRS6PK.js +2 -0
  371. package/dist/core/web/public/next/assets/useOnboarding-CujRS6PK.js.map +1 -0
  372. package/dist/core/web/public/next/assets/useSeatsRefresh-BEaQdkZs.js +2 -0
  373. package/dist/core/web/public/next/assets/useSeatsRefresh-BEaQdkZs.js.map +1 -0
  374. package/dist/core/web/public/next/assets/useVerseTranscript-BQ0J6Xhx.js +2 -0
  375. package/dist/core/web/public/next/assets/{useVerseTranscript-CDYrrWOO.js.map → useVerseTranscript-BQ0J6Xhx.js.map} +1 -1
  376. package/dist/core/web/public/next/assets/verse-icons-DndgEgKS.js +2 -0
  377. package/dist/core/web/public/next/assets/verse-icons-DndgEgKS.js.map +1 -0
  378. package/dist/core/web/public/next/assets/verse-model-MMySehjj.js +2 -0
  379. package/dist/core/web/public/next/assets/verse-model-MMySehjj.js.map +1 -0
  380. package/dist/core/web/public/next/assets/verse-store-DNVRuiJL.js +2 -0
  381. package/dist/core/web/public/next/assets/verse-store-DNVRuiJL.js.map +1 -0
  382. package/dist/core/web/public/next/assets/warmup-CNEH_-be.js +3 -0
  383. package/dist/core/web/public/next/assets/{warmup-HG5vYbsN.js.map → warmup-CNEH_-be.js.map} +1 -1
  384. package/dist/core/web/public/next/assets/why-seat-model-jlDTwYSc.js +2 -0
  385. package/dist/core/web/public/next/assets/why-seat-model-jlDTwYSc.js.map +1 -0
  386. package/dist/core/web/public/next/assets/{workspace-model-CbhdPhei.js → workspace-model-Dukb2wwv.js} +2 -2
  387. package/dist/core/web/public/next/assets/{workspace-model-CbhdPhei.js.map → workspace-model-Dukb2wwv.js.map} +1 -1
  388. package/dist/core/web/public/next/index.html +1 -1
  389. package/dist/release-dependency-inventory.json +1 -1
  390. package/docs/README.md +2 -1
  391. package/package.json +1 -1
  392. package/dist/core/web/public/next/assets/ActionMenu-FxXeRbPx.js +0 -2
  393. package/dist/core/web/public/next/assets/Advanced-D_eS4472.js +0 -2
  394. package/dist/core/web/public/next/assets/Advanced-D_eS4472.js.map +0 -1
  395. package/dist/core/web/public/next/assets/App-Cj4zKbG3.js +0 -7
  396. package/dist/core/web/public/next/assets/App-Cj4zKbG3.js.map +0 -1
  397. package/dist/core/web/public/next/assets/AppsSection-Ddu_RCQE.js +0 -2
  398. package/dist/core/web/public/next/assets/AppsSection-Ddu_RCQE.js.map +0 -1
  399. package/dist/core/web/public/next/assets/AreaTrend-CDxrQU4b.js +0 -2
  400. package/dist/core/web/public/next/assets/AutonomySection-DuQkHGD_.js +0 -2
  401. package/dist/core/web/public/next/assets/BranchBar-CLsvOcyK.js +0 -2
  402. package/dist/core/web/public/next/assets/BudgetControl-TL3FeZ1D.js +0 -2
  403. package/dist/core/web/public/next/assets/BurnDown-sFXkUGdB.js +0 -2
  404. package/dist/core/web/public/next/assets/BurnDown-sFXkUGdB.js.map +0 -1
  405. package/dist/core/web/public/next/assets/CapacityStrip-qReu0RaF.js +0 -2
  406. package/dist/core/web/public/next/assets/ChatSection-DZuZfTaC.js +0 -3
  407. package/dist/core/web/public/next/assets/ChatSection-DZuZfTaC.js.map +0 -1
  408. package/dist/core/web/public/next/assets/CloudBudgetForm-DJbiT1wi.js +0 -2
  409. package/dist/core/web/public/next/assets/CloudBudgetForm-DJbiT1wi.js.map +0 -1
  410. package/dist/core/web/public/next/assets/CommandPalette-zYLFZRnj.js +0 -2
  411. package/dist/core/web/public/next/assets/CommandPalette-zYLFZRnj.js.map +0 -1
  412. package/dist/core/web/public/next/assets/CommandSection-rIeMK5Ch.js +0 -2
  413. package/dist/core/web/public/next/assets/CommandSection-rIeMK5Ch.js.map +0 -1
  414. package/dist/core/web/public/next/assets/ConfirmDialog-DLrLKM0c.js +0 -2
  415. package/dist/core/web/public/next/assets/Dialog-BS9Dxi3G.js +0 -2
  416. package/dist/core/web/public/next/assets/DiffPane-TOmUf3b2.js +0 -2
  417. package/dist/core/web/public/next/assets/DiffViewer-BpH56302.js +0 -2
  418. package/dist/core/web/public/next/assets/DockHost-DzkzR-HD.js +0 -2
  419. package/dist/core/web/public/next/assets/DockHost-DzkzR-HD.js.map +0 -1
  420. package/dist/core/web/public/next/assets/FleetSection-ViAb549H.js +0 -3
  421. package/dist/core/web/public/next/assets/FleetSection-ViAb549H.js.map +0 -1
  422. package/dist/core/web/public/next/assets/Funnel-D2u7Wlzc.js +0 -2
  423. package/dist/core/web/public/next/assets/GearTray-Cb2npoxM.js +0 -2
  424. package/dist/core/web/public/next/assets/GrowthSection-C5aDPs8B.js +0 -2
  425. package/dist/core/web/public/next/assets/HandoffDialog-BF3AYg-X.js +0 -2
  426. package/dist/core/web/public/next/assets/Input-B5dmGLZx.js +0 -2
  427. package/dist/core/web/public/next/assets/LeaderCard-DZrmjDbI.js +0 -2
  428. package/dist/core/web/public/next/assets/LeaderCard-DZrmjDbI.js.map +0 -1
  429. package/dist/core/web/public/next/assets/MatrixHeatmap-BgEUs2Eu.js +0 -2
  430. package/dist/core/web/public/next/assets/McpSection-DZkiOuoq.js +0 -2
  431. package/dist/core/web/public/next/assets/MessageMarkdown-BauY8ZTY.js +0 -3
  432. package/dist/core/web/public/next/assets/MindSection-BvJXFjyX.js +0 -2
  433. package/dist/core/web/public/next/assets/MindSection-BvJXFjyX.js.map +0 -1
  434. package/dist/core/web/public/next/assets/MutationTokenDialog-mxrw0Yvy.js +0 -2
  435. package/dist/core/web/public/next/assets/NeedsYouDrawer-CO-Balfp.js +0 -2
  436. package/dist/core/web/public/next/assets/NeedsYouList-CzDZbzRD.js +0 -2
  437. package/dist/core/web/public/next/assets/NewChatDialog-B8eJjlFf.js +0 -3
  438. package/dist/core/web/public/next/assets/NewChatDialog-B8eJjlFf.js.map +0 -1
  439. package/dist/core/web/public/next/assets/OnboardingFlow-Cij6KWat.js +0 -2
  440. package/dist/core/web/public/next/assets/OnboardingFlow-Cij6KWat.js.map +0 -1
  441. package/dist/core/web/public/next/assets/OnboardingFlow-DSpPj8UE.css +0 -1
  442. package/dist/core/web/public/next/assets/PreviewPane-BS-CleCd.js +0 -2
  443. package/dist/core/web/public/next/assets/RailStatus-cPRyOmrk.js +0 -2
  444. package/dist/core/web/public/next/assets/ResourcesChrome-BJCauW_t.js +0 -3
  445. package/dist/core/web/public/next/assets/ResourcesChrome-BJCauW_t.js.map +0 -1
  446. package/dist/core/web/public/next/assets/ResourcesDrawer-BDecg6nO.js +0 -2
  447. package/dist/core/web/public/next/assets/ResourcesDrawer-BDecg6nO.js.map +0 -1
  448. package/dist/core/web/public/next/assets/ResourcesDrawer-CSKIO_wZ.css +0 -1
  449. package/dist/core/web/public/next/assets/RouteErrorBoundary-DYtwc2ja.js +0 -2
  450. package/dist/core/web/public/next/assets/RunInCloudAction-BEGEEM8O.js +0 -2
  451. package/dist/core/web/public/next/assets/SeatSelector-CYHRR7Wp.js +0 -3
  452. package/dist/core/web/public/next/assets/Segmented-BE53BenI.js +0 -2
  453. package/dist/core/web/public/next/assets/Select-BwSGkHCS.js +0 -2
  454. package/dist/core/web/public/next/assets/SessionGate-e0dFJm9d.js +0 -2
  455. package/dist/core/web/public/next/assets/SessionInsightChip-CxlSyueJ.js +0 -2
  456. package/dist/core/web/public/next/assets/SessionSearch-_yp7S2TP.js +0 -2
  457. package/dist/core/web/public/next/assets/SettingsSection-wGnpWeGW.js +0 -2
  458. package/dist/core/web/public/next/assets/SettingsSection-wGnpWeGW.js.map +0 -1
  459. package/dist/core/web/public/next/assets/Sheet-DVP2Mgy6.js +0 -2
  460. package/dist/core/web/public/next/assets/ShortcutsOverlay-BcIcoClX.js +0 -2
  461. package/dist/core/web/public/next/assets/Sidebar-DjQOqPbm.js +0 -3
  462. package/dist/core/web/public/next/assets/Sidebar-DjQOqPbm.js.map +0 -1
  463. package/dist/core/web/public/next/assets/Slider-BypUWjpH.js +0 -2
  464. package/dist/core/web/public/next/assets/StepBand-Duz1PUes.js +0 -2
  465. package/dist/core/web/public/next/assets/Surface-B75lVfzm.js +0 -2
  466. package/dist/core/web/public/next/assets/Surface-B75lVfzm.js.map +0 -1
  467. package/dist/core/web/public/next/assets/Surface-DMca0gAe.css +0 -1
  468. package/dist/core/web/public/next/assets/Swimlane-DGcIcnNA.js +0 -2
  469. package/dist/core/web/public/next/assets/TerminalPane-MQT-veKZ.js +0 -7
  470. package/dist/core/web/public/next/assets/TerminalPane-MQT-veKZ.js.map +0 -1
  471. package/dist/core/web/public/next/assets/UniverseConsoleApp-C8yQ0AaR.js +0 -2
  472. package/dist/core/web/public/next/assets/UsageSection-CqxRGJ40.js +0 -2
  473. package/dist/core/web/public/next/assets/UsageSection-CqxRGJ40.js.map +0 -1
  474. package/dist/core/web/public/next/assets/VerseConsoleApp-DTjDpGCd.js +0 -3
  475. package/dist/core/web/public/next/assets/VerseConsoleApp-DTjDpGCd.js.map +0 -1
  476. package/dist/core/web/public/next/assets/Workspace-DfcFGzME.js +0 -10
  477. package/dist/core/web/public/next/assets/Workspace-DfcFGzME.js.map +0 -1
  478. package/dist/core/web/public/next/assets/actions-Ddfg2iLl.css +0 -1
  479. package/dist/core/web/public/next/assets/actions-tWevL9HV.js +0 -2
  480. package/dist/core/web/public/next/assets/actions-tWevL9HV.js.map +0 -1
  481. package/dist/core/web/public/next/assets/apps-model-CDFvmsQV.js +0 -2
  482. package/dist/core/web/public/next/assets/apps-model-CDFvmsQV.js.map +0 -1
  483. package/dist/core/web/public/next/assets/capacity-strip-model-BDbmQ3e3.js +0 -2
  484. package/dist/core/web/public/next/assets/capacity-strip-model-BDbmQ3e3.js.map +0 -1
  485. package/dist/core/web/public/next/assets/charts-CfAjuKMv.js +0 -2
  486. package/dist/core/web/public/next/assets/charts-CfAjuKMv.js.map +0 -1
  487. package/dist/core/web/public/next/assets/charts-uSX6xVYN.css +0 -1
  488. package/dist/core/web/public/next/assets/cloud-C1KPNRHC.css +0 -1
  489. package/dist/core/web/public/next/assets/cloud-queries-Br_r0UAz.js +0 -2
  490. package/dist/core/web/public/next/assets/cloud-queries-Br_r0UAz.js.map +0 -1
  491. package/dist/core/web/public/next/assets/cloud.module-ascz58c3.js +0 -2
  492. package/dist/core/web/public/next/assets/cloud.module-ascz58c3.js.map +0 -1
  493. package/dist/core/web/public/next/assets/command-bus-xYZoK9nQ.js +0 -2
  494. package/dist/core/web/public/next/assets/command-bus-xYZoK9nQ.js.map +0 -1
  495. package/dist/core/web/public/next/assets/command-catalog-Bb_PxC5w.js +0 -2
  496. package/dist/core/web/public/next/assets/command-catalog-Bb_PxC5w.js.map +0 -1
  497. package/dist/core/web/public/next/assets/composer-keys-su0g1h9o.js +0 -2
  498. package/dist/core/web/public/next/assets/composer-keys-su0g1h9o.js.map +0 -1
  499. package/dist/core/web/public/next/assets/context-model-BC-HOmPo.js +0 -2
  500. package/dist/core/web/public/next/assets/context-model-BC-HOmPo.js.map +0 -1
  501. package/dist/core/web/public/next/assets/context-model-CIBmSugV.js +0 -2
  502. package/dist/core/web/public/next/assets/context-model-CIBmSugV.js.map +0 -1
  503. package/dist/core/web/public/next/assets/dark-since-DOMvtB_G.js +0 -2
  504. package/dist/core/web/public/next/assets/dark-since-DOMvtB_G.js.map +0 -1
  505. package/dist/core/web/public/next/assets/dock-icons-CUh8dOxJ.js +0 -2
  506. package/dist/core/web/public/next/assets/dock-store-B2vlxqPu.js +0 -2
  507. package/dist/core/web/public/next/assets/dock-store-B2vlxqPu.js.map +0 -1
  508. package/dist/core/web/public/next/assets/fleet-model-7i-FbzKI.js +0 -2
  509. package/dist/core/web/public/next/assets/fleet-model-7i-FbzKI.js.map +0 -1
  510. package/dist/core/web/public/next/assets/fleet-queries-DzGoqq8X.js +0 -2
  511. package/dist/core/web/public/next/assets/fleet-queries-DzGoqq8X.js.map +0 -1
  512. package/dist/core/web/public/next/assets/format-BkWdOQDL.js +0 -2
  513. package/dist/core/web/public/next/assets/format-BkWdOQDL.js.map +0 -1
  514. package/dist/core/web/public/next/assets/global-oEl9Qj8u.js +0 -2
  515. package/dist/core/web/public/next/assets/guarded-action-OzqcPjmh.js +0 -3
  516. package/dist/core/web/public/next/assets/guarded-action-OzqcPjmh.js.map +0 -1
  517. package/dist/core/web/public/next/assets/icon-base-DvM1eI5V.js +0 -2
  518. package/dist/core/web/public/next/assets/icon-base-DvM1eI5V.js.map +0 -1
  519. package/dist/core/web/public/next/assets/icons-DEQa2rTx.js +0 -2
  520. package/dist/core/web/public/next/assets/icons-DEQa2rTx.js.map +0 -1
  521. package/dist/core/web/public/next/assets/live-model-bmsJgnYD.js +0 -2
  522. package/dist/core/web/public/next/assets/live-model-bmsJgnYD.js.map +0 -1
  523. package/dist/core/web/public/next/assets/local-model-DFyjKX0b.js +0 -2
  524. package/dist/core/web/public/next/assets/local-model-DFyjKX0b.js.map +0 -1
  525. package/dist/core/web/public/next/assets/mind.module-gTGAuJt1.js +0 -2
  526. package/dist/core/web/public/next/assets/mutations-C5S7okTW.js +0 -2
  527. package/dist/core/web/public/next/assets/nav-NVtnuG7A.js +0 -2
  528. package/dist/core/web/public/next/assets/preloaded-Cwf9rsnZ.js +0 -2
  529. package/dist/core/web/public/next/assets/preloaded-Cwf9rsnZ.js.map +0 -1
  530. package/dist/core/web/public/next/assets/primitives-DyCKYSBG.js +0 -1
  531. package/dist/core/web/public/next/assets/reasoning-pref-BUcFF_5G.js +0 -2
  532. package/dist/core/web/public/next/assets/seat-subscription-B-f9ViU2.js +0 -2
  533. package/dist/core/web/public/next/assets/section-visibility-Yctxu-if.js +0 -2
  534. package/dist/core/web/public/next/assets/section-visibility-Yctxu-if.js.map +0 -1
  535. package/dist/core/web/public/next/assets/slots-BhP8b8tf.js +0 -3
  536. package/dist/core/web/public/next/assets/surface-data-DTI7LjvH.js +0 -2
  537. package/dist/core/web/public/next/assets/surface-data-DTI7LjvH.js.map +0 -1
  538. package/dist/core/web/public/next/assets/surface-prefetch-CdUEBFrl.js +0 -2
  539. package/dist/core/web/public/next/assets/surface-prefetch-CdUEBFrl.js.map +0 -1
  540. package/dist/core/web/public/next/assets/useChartWidth-owwodNVz.js +0 -2
  541. package/dist/core/web/public/next/assets/useChartWidth-owwodNVz.js.map +0 -1
  542. package/dist/core/web/public/next/assets/useSeatsRefresh-DgFy-Ph4.js +0 -2
  543. package/dist/core/web/public/next/assets/useSeatsRefresh-DgFy-Ph4.js.map +0 -1
  544. package/dist/core/web/public/next/assets/useVerseTranscript-CDYrrWOO.js +0 -2
  545. package/dist/core/web/public/next/assets/verse-icons-F9VwX07_.js +0 -2
  546. package/dist/core/web/public/next/assets/verse-icons-F9VwX07_.js.map +0 -1
  547. package/dist/core/web/public/next/assets/verse-model-DyCwZF-M.js +0 -2
  548. package/dist/core/web/public/next/assets/verse-model-DyCwZF-M.js.map +0 -1
  549. package/dist/core/web/public/next/assets/verse-store-b_Lek_c5.js +0 -3
  550. package/dist/core/web/public/next/assets/verse-store-b_Lek_c5.js.map +0 -1
  551. package/dist/core/web/public/next/assets/verse-ui-store-62DxpVHS.js +0 -3
  552. package/dist/core/web/public/next/assets/verse-ui-store-62DxpVHS.js.map +0 -1
  553. package/dist/core/web/public/next/assets/viewport-nTubFCwf.js +0 -2
  554. package/dist/core/web/public/next/assets/viewport-nTubFCwf.js.map +0 -1
  555. package/dist/core/web/public/next/assets/warmup-HG5vYbsN.js +0 -3
  556. package/dist/core/web/public/next/assets/workbench-types-DzN-5trg.js +0 -2
  557. package/dist/core/web/public/next/assets/workbench-types-DzN-5trg.js.map +0 -1
  558. /package/dist/core/web/public/next/assets/{BurnDown-BuLMsJMx.css → StatTile-BuLMsJMx.css} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"NeedsYouList-CzDZbzRD.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/approvals/approvals-model.ts","../../../../../../src/web-ui/routes/verse/shell/needs-you-model.ts","../../../../../../src/web-ui/routes/verse/shell/NeedsYouDrawer.module.css","../../../../../../src/web-ui/routes/verse/shell/NeedsYouList.tsx"],"sourcesContent":["/**\n * routes/verse/approvals/approvals-model.ts — the pure decisions behind the\n * approvals queue: what order rows come in, and exactly what a human is\n * agreeing to when they press Approve.\n *\n * Kept framework-free and unit-tested because both are easy to get subtly\n * wrong: \"pending first\" must survive a status filter that also returns\n * decided rows, and the approve consequence sentence is the last thing\n * standing between a click and a real pull request against a real remote.\n */\nimport type { Proposal, ProposalKind } from '../../../data/api-types.js';\nimport { ENGINE_LABEL } from '../verse-model.js';\n\n/** Pending first, then newest first within each group. Stable and total. */\nexport function orderProposals(rows: readonly Proposal[]): Proposal[] {\n return [...rows].sort((a, b) => {\n const pendingA = a.status === 'pending' ? 0 : 1;\n const pendingB = b.status === 'pending' ? 0 : 1;\n if (pendingA !== pendingB) return pendingA - pendingB;\n const tsA = Date.parse(a.createdAt);\n const tsB = Date.parse(b.createdAt);\n const safeA = Number.isNaN(tsA) ? 0 : tsA;\n const safeB = Number.isNaN(tsB) ? 0 : tsB;\n if (safeA !== safeB) return safeB - safeA;\n return a.id.localeCompare(b.id);\n });\n}\n\nexport type RiskClass = NonNullable<Proposal['riskClass']>;\n\n/** high → medium → low → unstated. Used for the risk column's sort affordance. */\nexport function riskRank(risk: Proposal['riskClass']): number {\n switch (risk) {\n case 'high':\n return 0;\n case 'medium':\n return 1;\n case 'low':\n return 2;\n default:\n return 3;\n }\n}\n\n/** Client-side narrowing over whatever page the server returned. */\nexport function filterProposals(rows: readonly Proposal[], search: string, repo: string): Proposal[] {\n const s = search.trim().toLowerCase();\n const r = repo.trim().toLowerCase();\n if (!s && !r) return [...rows];\n return rows.filter((p) => {\n if (s && !p.title.toLowerCase().includes(s) && !(p.summary ?? '').toLowerCase().includes(s)) return false;\n if (r && !(p.repo ?? '').toLowerCase().includes(r)) return false;\n return true;\n });\n}\n\n/**\n * What approving this proposal actually does, in one sentence, naming the\n * repo. `pr` is the dangerous one: it pushes a branch to the remote and opens\n * a real pull request, which is visible to other people and cannot be undone\n * from the dialog. The confirm step MUST show this before the click.\n */\nexport function describeApproveConsequence(kind: ProposalKind | string, repo: string | null): string {\n // The project's NAME, not its absolute path: a sandbox checkout under\n // /private/tmp/claude-501/… is unreadable in a sentence. The confirm dialog\n // still prints the full path once, as the exact place the write lands.\n const where = repoName(repo) ?? 'the target repository';\n switch (kind) {\n case 'pr':\n return `Pushes a branch to ${where}'s remote and opens a real pull request. Other people can see it immediately, and this dialog cannot undo it.`;\n case 'patch':\n return `Writes the diff to ${where} on disk now. Nothing is pushed, but the working tree changes.`;\n default:\n return `Applies this ${String(kind)} proposal to ${where} now.`;\n }\n}\n\n/** True when approving reaches a remote — the loudest confirm wording. */\nexport function reachesRemote(kind: ProposalKind | string): boolean {\n return kind === 'pr';\n}\n\n/** The engine that produced the diff, as a short display string. */\nexport function engineOf(proposal: Pick<Proposal, 'engineModel' | 'engineTier'>): string | null {\n if (proposal.engineModel) return proposal.engineModel;\n if (proposal.engineTier) return proposal.engineTier;\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Readable detail\n// ---------------------------------------------------------------------------\n\n/** \"/Users/m/repos/binshield/\" → \"binshield\"; null for no repo. */\nexport function repoName(repo: string | null | undefined): string | null {\n if (typeof repo !== 'string') return null;\n const trimmed = repo.trim().replace(/\\/+$/, '');\n if (trimmed.length === 0) return null;\n const last = trimmed.slice(trimmed.lastIndexOf('/') + 1);\n return last.length > 0 ? last : trimmed;\n}\n\nconst KIND_LABEL: Record<string, string> = {\n patch: 'Patch',\n pr: 'Pull request',\n deploy: 'Deploy',\n note: 'Note',\n 'desktop-action': 'Desktop action',\n 'browser-action': 'Browser action',\n};\n\n/** \"patch\" → \"Patch\", \"pr\" → \"Pull request\"; an unknown kind is shown as sent. */\nexport function kindLabel(kind: ProposalKind | string): string {\n return KIND_LABEL[kind] ?? String(kind);\n}\n\n/**\n * The server builds a run proposal's title as `${engine} run: ${goal.slice(0, 80)}`\n * — cut at 80 characters, mid-word, sometimes mid-quote. This is the one\n * place that cut is made readable.\n */\nexport const RUN_TITLE_GOAL_CAP = 80;\n\nexport interface ReadableTitle {\n /** \"Claude run\" when the title carried an `engine run:` prefix; null otherwise. */\n eyebrow: string | null;\n /** The title to print: never ends mid-word; a cut one ends in \"…\". */\n text: string;\n /** True when the server's title was cut short (the full text we have rides in a tooltip). */\n truncated: boolean;\n}\n\nfunction capitalize(word: string): string {\n return word.length === 0 ? word : word.charAt(0).toUpperCase() + word.slice(1);\n}\n\n/** The app's own display name for an engine (\"Claude\", \"Codex\"); any other engine capitalized (\"Ollama\"). */\nfunction engineDisplayName(engine: string): string {\n const key = engine.toLowerCase();\n return Object.prototype.hasOwnProperty.call(ENGINE_LABEL, key)\n ? ENGINE_LABEL[key as keyof typeof ENGINE_LABEL]\n : capitalize(key);\n}\n\n/** Close a quote the cut left open, so the title does not read as a stray mark. */\nfunction closeQuotes(text: string): string {\n let out = text;\n if ((out.match(/\"/g) ?? []).length % 2 === 1) out += '\"';\n if ((out.match(/\\u201c/g) ?? []).length > (out.match(/\\u201d/g) ?? []).length) out += '\\u201d';\n return out;\n}\n\n/** Drop a trailing partial word and end on \"…\". */\nfunction cutAtWord(text: string): string {\n const body = text.replace(/(?:\\u2026|\\.\\.\\.)$/, '');\n const space = body.lastIndexOf(' ');\n const whole = space > 0 ? body.slice(0, space) : body;\n return `${whole.replace(/[\\s,;:\\-\\u2013\\u2014]+$/, '')}\\u2026`;\n}\n\nexport function readableTitle(title: string): ReadableTitle {\n const raw = typeof title === 'string' ? title.trim() : '';\n // Only the engines the sandboxed runner names — \"Dry run: …\" is a title, not an engine.\n const run = /^(\\[partial\\]\\s*)?(claude|codex|grok|local|ollama|gemini|api[\\w-]*) run:\\s*(.*)$/is.exec(raw);\n // \"Partial Claude run\", never \"Partial claude run\": the engine is a name either way.\n const eyebrow = run ? `${run[1] ? 'Partial ' : ''}${engineDisplayName(run[2]!)} run` : null;\n let text = run ? run[3]! : raw;\n // A title that already ends in an ellipsis right after a letter was cut mid-word upstream.\n const cutMidWord = /[\\p{L}\\p{N}](?:\\u2026|\\.\\.\\.)$/u.test(text);\n // A run goal at exactly the server's cap that does not end on a sentence boundary was sliced.\n const sliced = run !== null && text.length >= RUN_TITLE_GOAL_CAP && !/[.!?)\"'\\u201d\\u2026]$/.test(text);\n const truncated = cutMidWord || sliced;\n if (truncated) text = cutAtWord(text);\n text = closeQuotes(text);\n return { eyebrow, text: text.length > 0 ? text : raw, truncated };\n}\n\n/**\n * What a sandboxed run's summary line says, taken apart. The server writes\n * `[Partial ]<source> <engine:model> run produced N file(s) (+A/-D). <rest>`\n * (core/run/sandboxed-engine.ts); anything else parses to null and is shown\n * verbatim.\n */\nexport interface RunFacts {\n partial: boolean;\n /** The server's source label, verbatim (\"TITRR\", \"Best-of-N winner\"). */\n source: string;\n /** The source in plain words (\"Test-and-repair loop\"). */\n sourceLabel: string;\n /** What the source means, for a tooltip; null when the label says it already. */\n sourceHint: string | null;\n /** \"claude:claude-fable-5\". */\n model: string;\n files: number;\n insertions: number;\n deletions: number;\n /** Whatever the summary says after the run facts (\"Review before applying.\"), or null. */\n rest: string | null;\n}\n\nconst RUN_SUMMARY = /^(Partial )?(.+?) (\\S+) run produced (\\d+) file\\(s\\) \\(\\+(\\d+)\\/-(\\d+)\\)\\.?\\s*([\\s\\S]*)$/;\n\n/**\n * TITRR is internal shorthand (core/run/orchestrator.ts M78: Test → Iterate →\n * Test → Refine → Repeat). The operator sees the plain name; the acronym and\n * what it did ride in the tooltip.\n */\nconst TITRR_HINT =\n 'TITRR — Test, Iterate, Test, Refine, Repeat: after its change the run re-ran the repository\\u2019s tests and repaired the change until they passed or it ran out of attempts.';\n\nfunction describeSource(source: string): { label: string; hint: string | null } {\n if (/\\bTITRR\\b/.test(source)) {\n const rest = source.replace(/\\bTITRR\\b\\s*/, '').trim();\n const qualifier = rest === 'api-model' ? ' (API model)'\n : rest === 'api-model required-diff' ? ' (API model, retried for a missing diff)'\n : rest === 'api-model failed producer' ? ' (API model, producer failed)'\n : rest.length > 0 ? ` (${rest})` : '';\n return { label: `Test-and-repair loop${qualifier}`, hint: TITRR_HINT };\n }\n if (/^best-of-n/i.test(source)) {\n return { label: source, hint: 'Several models attempted this change in parallel; a judge compared them.' };\n }\n if (source === 'api-model') return { label: 'API model run', hint: null };\n if (source === 'Sandboxed') return { label: 'Sandboxed run', hint: 'Produced in an isolated sandbox checkout; nothing touched your working tree.' };\n return { label: source, hint: null };\n}\n\nexport function parseRunSummary(summary: string | null | undefined): RunFacts | null {\n if (typeof summary !== 'string') return null;\n const m = RUN_SUMMARY.exec(summary.trim());\n if (!m) return null;\n const { label, hint } = describeSource(m[2]!);\n const rest = m[7]!.trim();\n return {\n partial: m[1] !== undefined,\n source: m[2]!,\n sourceLabel: label,\n sourceHint: hint,\n model: m[3]!,\n files: Number(m[4]),\n insertions: Number(m[5]),\n deletions: Number(m[6]),\n rest: rest.length > 0 ? rest : null,\n };\n}\n\n/** \"2 files · +384 −0\" (a real minus sign, grouped thousands). */\nexport function formatDiffStats(facts: Pick<RunFacts, 'files' | 'insertions' | 'deletions'>): string {\n const n = (v: number) => v.toLocaleString('en-US');\n return `${n(facts.files)} ${facts.files === 1 ? 'file' : 'files'} \\u00b7 +${n(facts.insertions)} \\u2212${n(facts.deletions)}`;\n}\n\n/** The same stats as a sentence for assistive tech: \"2 files changed, 384 lines added, 0 removed\". */\nexport function describeDiffStats(facts: Pick<RunFacts, 'files' | 'insertions' | 'deletions'>): string {\n const n = (v: number) => v.toLocaleString('en-US');\n return `${n(facts.files)} ${facts.files === 1 ? 'file' : 'files'} changed, ${n(facts.insertions)} ${facts.insertions === 1 ? 'line' : 'lines'} added, ${n(facts.deletions)} removed`;\n}\n\n/**\n * \"just now\", \"5 minutes ago\", \"yesterday\", \"38 days ago\", then \"on Aug 17\"\n * past two months. Written out in full: the detail view has the room, and\n * \"38d\" is a sidebar abbreviation.\n */\nexport function longAgo(iso: string | null | undefined, now: number = Date.now()): string {\n if (typeof iso !== 'string') return 'at an unknown time';\n const then = Date.parse(iso);\n if (!Number.isFinite(then)) return 'at an unknown time';\n const seconds = Math.max(0, Math.round((now - then) / 1000));\n if (seconds < 45) return 'just now';\n const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });\n const minutes = Math.round(seconds / 60);\n if (minutes < 60) return rtf.format(-minutes, 'minute');\n const hours = Math.round(minutes / 60);\n if (hours < 24) return rtf.format(-hours, 'hour');\n const days = Math.round(hours / 24);\n if (days <= 60) return rtf.format(-days, 'day');\n return `on ${new Date(then).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })}`;\n}\n\n/** A local date and time for a tooltip: \"Mon, Aug 17, 3:12 PM\". */\nexport function localStamp(iso: string | null | undefined): string | undefined {\n if (typeof iso !== 'string') return undefined;\n const t = Date.parse(iso);\n if (!Number.isFinite(t)) return undefined;\n return new Date(t).toLocaleString([], { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit' });\n}\n","/**\n * routes/verse/shell/needs-you-model.ts — the Needs-you drawer as data (unit\n * C1): which items a split shows, how many each split has, whether the drawer\n * may say \"All clear\", and what a key press does to an item.\n *\n * Pure. The items come from GET /api/verse/activity (C1's own producers plus\n * Track B's, R1); each carries its own actions, so nothing here knows what a\n * grant or an owner-lane PR is.\n *\n * How a row READS (needsYouRowView) borrows the approvals detail view's text\n * helpers rather than growing a second copy: an approval item's title and\n * detail are the same proposal title and run summary that view already\n * untangles.\n */\nimport {\n NEEDS_YOU_KIND_CATEGORY,\n type NeedsYouAction,\n type NeedsYouActionKind,\n type NeedsYouItem,\n type NeedsYouSource,\n type VerseActivitySources,\n} from '../../../../core/verse/workbench-types.js';\nimport {\n describeDiffStats,\n formatDiffStats,\n kindLabel,\n localStamp,\n longAgo,\n parseRunSummary,\n readableTitle,\n repoName,\n} from '../approvals/approvals-model.js';\nimport type { VerseSeat } from '../../../data/api-types.js';\nimport { isVerseEngine, modelOptionFor, seatById } from '../verse-model.js';\nimport type { NeedsYouSplit } from '../verse-ui-store.js';\n\nexport const SPLIT_LABEL: Readonly<Record<NeedsYouSplit, string>> = {\n all: 'All',\n approvals: 'Approvals',\n fleet: 'Fleet',\n chats: 'Chats',\n accounts: 'Accounts',\n};\n\n/**\n * Which producers can put an item in each split. \"All clear\" is only\n * claimed for a split whose every producer answered: an owner-lane PR is in\n * Approvals but comes from the FLEET producer, so Approvals is only vouched\n * for when the fleet source answered too.\n */\nexport const SPLIT_SOURCES: Readonly<Record<NeedsYouSplit, readonly NeedsYouSource[]>> = {\n all: ['approvals', 'authority', 'fleet', 'leader', 'chats', 'accounts'],\n approvals: ['approvals', 'fleet', 'leader'],\n fleet: ['authority', 'fleet', 'leader'],\n chats: ['chats'],\n accounts: ['accounts'],\n};\n\nconst SOURCE_NAME: Readonly<Record<NeedsYouSource, string>> = {\n approvals: 'the approvals inbox',\n authority: 'the autonomy grant',\n fleet: 'the fleet',\n leader: 'the Leader',\n chats: 'chats',\n accounts: 'account health',\n};\n\nexport function itemsForSplit(items: readonly NeedsYouItem[], split: NeedsYouSplit): NeedsYouItem[] {\n if (split === 'all') return [...items];\n return items.filter((item) => NEEDS_YOU_KIND_CATEGORY[item.kind] === split);\n}\n\nexport function splitCounts(items: readonly NeedsYouItem[]): Record<NeedsYouSplit, number> {\n const counts: Record<NeedsYouSplit, number> = { all: items.length, approvals: 0, fleet: 0, chats: 0, accounts: 0 };\n for (const item of items) counts[NEEDS_YOU_KIND_CATEGORY[item.kind]] += 1;\n return counts;\n}\n\nexport interface SplitCoverage {\n /** Every producer feeding this split answered. */\n vouched: boolean;\n /** Operator-language names of the ones that did not, with why. */\n silent: Array<{ source: NeedsYouSource; name: string; state: 'unavailable' | 'error' }>;\n}\n\n/** Null sources (activity itself unavailable) vouch for nothing. */\nexport function splitCoverage(sources: VerseActivitySources | null, split: NeedsYouSplit): SplitCoverage {\n const silent: SplitCoverage['silent'] = [];\n for (const source of SPLIT_SOURCES[split]) {\n const state = sources?.[source] ?? 'unavailable';\n if (state !== 'ok') silent.push({ source, name: SOURCE_NAME[source], state });\n }\n return { vouched: silent.length === 0, silent };\n}\n\n/** \"the fleet isn't reporting yet and the Leader failed to answer\" — for the empty state. */\nexport function describeSilence(coverage: SplitCoverage): string {\n const phrases = coverage.silent.map((s) => (s.state === 'error' ? `${s.name} failed to answer` : `${s.name} isn't reporting in this build`));\n if (phrases.length === 0) return '';\n if (phrases.length === 1) return capitalise(phrases[0]!);\n return capitalise(`${phrases.slice(0, -1).join(', ')} and ${phrases[phrases.length - 1]}`);\n}\n\nfunction capitalise(text: string): string {\n return text.charAt(0).toUpperCase() + text.slice(1);\n}\n\n/** Approve / reject / veto ALWAYS confirm (SPEC-310C §1); other kinds only when the item says so. */\nexport const ALWAYS_CONFIRM: ReadonlySet<NeedsYouActionKind> = new Set(['approve', 'reject', 'veto']);\n\nexport function actionOf(item: NeedsYouItem, kind: NeedsYouActionKind): NeedsYouAction | null {\n return item.actions.find((a) => a.kind === kind) ?? null;\n}\n\nconst GENERIC_CONFIRM: Readonly<Record<'approve' | 'reject' | 'veto', { title: string; confirmLabel: string }>> = {\n approve: { title: 'Approve this?', confirmLabel: 'Approve' },\n reject: { title: 'Reject this?', confirmLabel: 'Reject' },\n veto: { title: 'Veto this action?', confirmLabel: 'Veto' },\n};\n\nexport interface ConfirmCopy {\n title: string;\n body: string;\n confirmLabel: string;\n}\n\n/** The dialog for `action` on `item`; null when the action runs without one. */\nexport function confirmCopy(item: NeedsYouItem, action: NeedsYouAction): ConfirmCopy | null {\n if (action.confirm) return action.confirm;\n if (action.kind === 'approve' || action.kind === 'reject' || action.kind === 'veto') {\n const generic = GENERIC_CONFIRM[action.kind];\n return { title: generic.title, body: readableItemTitle(item).text, confirmLabel: generic.confirmLabel };\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// How a row reads\n// ---------------------------------------------------------------------------\n\n/**\n * The approvals producer titles an item `${kind === 'pr' ? 'PR' : kind}: ${proposal.title}`\n * (core/verse/activity.ts approvalItem). Only an `approval` item is taken\n * apart this way — \"Failed: Migrate the store\" is a chat title, not a kind.\n */\nconst APPROVAL_KIND_PREFIX = /^(PR|[a-z][a-z-]*):\\s+([\\s\\S]+)$/;\n\nexport interface ReadableItemTitle {\n /** \"Patch · Claude run\": the proposal kind and the engine the title led with; null when neither. */\n kindLabel: string | null;\n /** The title to print. Never ends mid-word — a cut one ends in \"…\". */\n text: string;\n}\n\nexport function readableItemTitle(item: Pick<NeedsYouItem, 'kind' | 'title'>): ReadableItemTitle {\n let proposalKind: string | null = null;\n let rest = item.title;\n if (item.kind === 'approval') {\n const m = APPROVAL_KIND_PREFIX.exec(item.title.trim());\n if (m) {\n proposalKind = m[1] === 'PR' ? 'pr' : m[1]!;\n rest = m[2]!;\n }\n }\n const title = readableTitle(rest);\n const parts = [proposalKind === null ? null : kindLabel(proposalKind), title.eyebrow].filter((p): p is string => p !== null);\n return { kindLabel: parts.length > 0 ? parts.join(' · ') : null, text: title.text };\n}\n\n/** A sandboxed run's facts, lifted out of the item's detail line. */\nexport interface NeedsYouRunView {\n /** \"2 files · +384 −0\". */\n stats: string;\n /** \"2 files changed, 384 lines added, 0 removed\" — what a screen reader says instead. */\n statsSpoken: string;\n /** \"Test-and-repair loop\", never \"TITRR\". */\n source: string;\n /** What the source means, for a tooltip. */\n sourceHint: string | null;\n partial: boolean;\n /** \"claude:claude-fable-5\". */\n model: string;\n}\n\n/** Everything a Needs-you row prints, in operator language. The raw server text survives only in tooltips. */\nexport interface NeedsYouRowView {\n kindLabel: string | null;\n title: string;\n /** The title exactly as the server sent it — the row's tooltip. */\n fullTitle: string;\n run: NeedsYouRunView | null;\n /** What the detail says beyond the run facts (\"Review before applying.\"), or the detail verbatim; null when nothing. */\n detail: string | null;\n /** \"binshield\", never a path. */\n repo: string | null;\n /** The repo as sent, as a tooltip, when it was more than the name. */\n repoFull: string | undefined;\n /** \"38 days ago\". */\n age: string;\n /** The exact local time, for a tooltip. */\n ageStamp: string | undefined;\n}\n\nexport function needsYouRowView(item: NeedsYouItem, now: number = Date.now()): NeedsYouRowView {\n const title = readableItemTitle(item);\n const facts = parseRunSummary(item.detail);\n const repo = repoName(item.subject.repo);\n return {\n kindLabel: title.kindLabel,\n title: title.text,\n fullTitle: item.title,\n run: facts\n ? {\n stats: formatDiffStats(facts),\n statsSpoken: describeDiffStats(facts),\n source: facts.sourceLabel,\n sourceHint: facts.sourceHint,\n partial: facts.partial,\n model: facts.model,\n }\n : null,\n detail: facts ? facts.rest : item.detail,\n repo,\n repoFull: repo !== null && item.subject.repo !== null && item.subject.repo !== repo ? item.subject.repo : undefined,\n age: longAgo(item.since, now),\n ageStamp: localStamp(item.since),\n };\n}\n\n/** \"closes in 24m\" / \"expired\" — for veto windows and grants. */\nexport function until(iso: string, now: number = Date.now()): string {\n const t = Date.parse(iso);\n if (!Number.isFinite(t)) return '—';\n const s = Math.round((t - now) / 1000);\n if (s <= 0) return 'expired';\n if (s < 90) return `in ${s}s`;\n const m = Math.round(s / 60);\n if (m < 90) return `in ${m}m`;\n const h = Math.round(m / 60);\n if (h < 48) return `in ${h}h`;\n return `in ${Math.round(h / 24)}d`;\n}\n\n// ---------------------------------------------------------------------------\n// Seats and models, by name\n// ---------------------------------------------------------------------------\n\n/** A seat or model as the operator knows it; `raw` is the id as sent, for a tooltip, when the text differs. */\nexport interface DisplayName {\n text: string;\n raw: string | undefined;\n}\n\n/**\n * \"Claude Max\" for `claude-a`: the roster's label (bootstrap seats — the name\n * the seat picker and Apps & Accounts use). An id the roster does not know is\n * shown as sent: it is all there is.\n */\nexport function seatDisplayName(seats: readonly VerseSeat[], seatId: string): DisplayName {\n const label = seatById(seats, seatId)?.label;\n return label && label !== seatId ? { text: label, raw: seatId } : { text: seatId, raw: undefined };\n}\n\n/**\n * \"Fable 5.1\" for a run's `claude:claude-fable-5-1`: the catalog label (the\n * model picker's) on the item's own seat first, then on any seat of the run's\n * engine — exact id, then canonical (verse-model `modelOptionFor`, so a\n * pre-alias `claude-opus-5.5` still finds `claude-opus-5-5`). A model no\n * catalog lists is shown as sent.\n */\nexport function runModelDisplayName(seats: readonly VerseSeat[], model: string, seatId: string | null): DisplayName {\n const colon = model.indexOf(':');\n const prefix = colon > 0 ? model.slice(0, colon) : '';\n const engine = isVerseEngine(prefix) ? prefix : null;\n // `local:qwen3.8:27b` keeps its tag: only a known engine prefix is split off.\n const id = engine ? model.slice(colon + 1) : model;\n const order = [\n ...(seatId ? [seatId] : []),\n ...seats.filter((seat) => seat.id !== seatId && (engine === null || seat.engine === engine)).map((seat) => seat.id),\n ];\n for (const candidate of order) {\n const label = modelOptionFor(seats, { seatId: candidate, model: id })?.label;\n if (label && label !== model) return { text: label, raw: model };\n }\n return { text: model, raw: undefined };\n}\n","/* ⌘J — a right-hand sheet over the workbench; full screen on a phone.\n Hairlines, no cards. Severity is a word plus a 2px rule, never colour alone. */\n\n.backdrop {\n position: fixed;\n inset: 0;\n z-index: var(--z-dialog);\n display: flex;\n justify-content: flex-end;\n background: var(--bg-overlay);\n animation: fade var(--duration-fast) var(--ease-standard);\n}\n\n.panel {\n display: flex;\n flex-direction: column;\n width: min(480px, calc(100vw - var(--space-8)));\n height: 100%;\n background: var(--bg-surface);\n border-left: 1px solid var(--border-default);\n box-shadow: var(--shadow-dialog);\n outline: none;\n animation: slide var(--duration-base) var(--ease-decelerate);\n}\n\n/* Phone: the whole screen, sliding up. */\n.panel[data-presentation='full'] {\n width: 100%;\n border-left: 0;\n animation-name: rise;\n}\n\n.head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-3);\n min-height: var(--strip-height);\n padding: var(--space-2) var(--space-3) var(--space-2) var(--space-4);\n border-bottom: 1px solid var(--border-subtle);\n}\n\n.title {\n display: flex;\n align-items: baseline;\n gap: var(--space-2);\n font-family: var(--font-display);\n font-size: var(--text-md-size);\n line-height: var(--text-md-line);\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-display);\n}\n\n.titleCount {\n font-family: var(--font-ui);\n font-size: var(--text-sm-size);\n font-weight: var(--font-weight-regular);\n font-variant-numeric: tabular-nums;\n color: var(--text-tertiary);\n}\n\n.splits {\n display: flex;\n gap: var(--space-1);\n padding: var(--space-2) var(--space-3);\n border-bottom: 1px solid var(--border-subtle);\n overflow-x: auto;\n scrollbar-width: none;\n}\n\n.split {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n flex: none;\n min-height: var(--control-h-sm);\n padding: 0 var(--space-2);\n border-radius: var(--radius-sm);\n color: var(--text-secondary);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n.split:hover { background: var(--bg-hover); color: var(--text-primary); }\n.split[aria-selected='true'] { background: var(--bg-selected); color: var(--text-primary); font-weight: var(--font-weight-medium); }\n\n.splitCount {\n min-width: 18px;\n padding: 0 4px;\n border-radius: var(--radius-full);\n background: var(--bg-hover);\n font-size: var(--text-2xs-size);\n line-height: 18px;\n text-align: center;\n font-variant-numeric: tabular-nums;\n color: var(--text-secondary);\n}\n\n.body {\n position: relative;\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n}\n\n.rows { outline: none; }\n.rows:focus-visible { box-shadow: none; }\n/* The list holds focus (aria-activedescendant), so the focus ring is drawn on\n the ROW it points at — a ring around the whole list says nothing about\n which item A / R / V will act on. */\n.rows:focus-visible .row[aria-selected='true'] { box-shadow: inset 0 0 0 2px var(--border-focus); }\n\n.row {\n display: grid;\n grid-template-columns: 2px minmax(0, 1fr) auto;\n column-gap: var(--space-3);\n align-items: center;\n padding: var(--space-3) var(--space-4);\n border-bottom: 1px solid var(--border-subtle);\n cursor: pointer;\n}\n.row:hover { background: var(--bg-hover); }\n.row[aria-selected='true'] { background: var(--bg-selected); }\n\n.rule {\n align-self: stretch;\n border-radius: var(--radius-full);\n background: var(--border-strong);\n}\n.row[data-severity='high'] .rule { background: var(--status-danger-solid); }\n.row[data-severity='warn'] .rule { background: var(--status-warning-solid); }\n\n.rowMain { display: flex; flex-direction: column; min-width: 0; gap: 2px; }\n\n/* \"Patch · Claude run\" — the kind, above the title it no longer clutters.\n Secondary, not tertiary: tertiary falls under 4.5:1 on --bg-selected\n (approvals.module.css has the measurements). */\n.rowKind {\n margin: 0;\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n letter-spacing: var(--tracking-label);\n text-transform: uppercase;\n color: var(--text-secondary);\n}\n\n/* Two lines at most, wrapped at word boundaries. The text itself already\n ends on a whole word (approvals-model readableTitle); the full server\n title rides in `title`. */\n.rowTitle {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n line-clamp: 2;\n overflow: hidden;\n overflow-wrap: break-word;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-primary);\n}\n\n/* \"2 files · +384 −0 · Test-and-repair loop\". */\n.runFacts {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: 0 var(--space-2);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n}\n.diffStats { font-family: var(--font-display); font-variant-numeric: tabular-nums; color: var(--text-primary); }\n.runSource[title] { text-decoration: underline dotted; text-underline-offset: 3px; cursor: help; }\n\n.repo { font-weight: var(--font-weight-medium); }\n\n.rowMeta {\n display: flex;\n flex-wrap: wrap;\n gap: 0 var(--space-2);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n}\n\n.severity {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n letter-spacing: var(--tracking-label);\n text-transform: uppercase;\n}\n.severity[data-severity='high'] { color: var(--status-danger-fg); }\n.severity[data-severity='warn'] { color: var(--status-warning-fg); }\n\n.mono { font-family: var(--font-mono); font-size: var(--text-xs-size); }\n.deadline { color: var(--status-warning-fg); font-variant-numeric: tabular-nums; }\n\n.rowKeys { display: flex; gap: 2px; }\n\n.key,\n.inlineKey {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 4px;\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-xs);\n background: var(--bg-surface);\n font-family: var(--font-mono);\n font-size: var(--text-2xs-size);\n color: var(--text-secondary);\n}\n.inlineKey { margin-left: var(--space-2); background: transparent; }\n\n.loading { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-4); }\n\n.empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--space-2);\n padding: var(--space-16) var(--space-6);\n text-align: center;\n}\n.emptyTitle {\n font-family: var(--font-display);\n font-size: var(--text-md-size);\n line-height: var(--text-md-line);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n}\n.emptyBody {\n max-width: 44ch;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-secondary);\n}\n\n/* The reward for an empty inbox: a quiet check, not a confetti cannon. */\n.clearMark {\n position: relative;\n width: 40px;\n height: 40px;\n margin-bottom: var(--space-2);\n border-radius: var(--radius-full);\n background: var(--status-success-bg);\n}\n.clearMark::after {\n content: '';\n position: absolute;\n left: 14px;\n top: 10px;\n width: 10px;\n height: 16px;\n border: solid var(--status-success-solid);\n border-width: 0 2px 2px 0;\n transform: rotate(45deg);\n}\n\n.focusSink { position: absolute; width: 1px; height: 1px; overflow: hidden; outline: none; }\n\n.detail { outline: none; }\n\n.back {\n display: inline-flex;\n align-items: center;\n margin: var(--space-2) var(--space-3) 0;\n padding: var(--space-1) var(--space-2);\n border-radius: var(--radius-sm);\n font-size: var(--text-xs-size);\n color: var(--text-secondary);\n}\n.back:hover { background: var(--bg-hover); color: var(--text-primary); }\n\n/* ApprovalDetail was drawn for a wide pane: tighten its gutters in the sheet. */\n.approval > div { padding: var(--space-3) var(--space-4) var(--space-12); }\n\n.item { display: flex; flex-direction: column; gap: var(--space-4); padding: var(--space-3) var(--space-4) var(--space-8); }\n.itemHead { display: flex; flex-direction: column; gap: var(--space-1); }\n\n.itemTitle {\n font-family: var(--font-display);\n font-size: var(--text-lg-size);\n line-height: var(--text-lg-line);\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-display);\n}\n\n.itemDetail {\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line-relaxed);\n color: var(--text-secondary);\n overflow-wrap: anywhere;\n}\n\n.defs {\n display: grid;\n grid-template-columns: max-content minmax(0, 1fr);\n gap: var(--space-2) var(--space-4);\n margin: 0;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n.defs dt { color: var(--text-tertiary); }\n.defs dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }\n\n.itemActions { display: flex; flex-wrap: wrap; gap: var(--space-2); }\n\n.foot {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-1) var(--space-4);\n padding: var(--space-2) var(--space-4);\n border-top: 1px solid var(--border-subtle);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n color: var(--text-tertiary);\n}\n.foot span { display: inline-flex; align-items: center; gap: 2px; }\n\n.caveat {\n margin: 0;\n padding: var(--space-2) var(--space-4);\n border-top: 1px solid var(--border-subtle);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--status-warning-fg);\n background: var(--status-warning-bg);\n}\n\n@keyframes fade { from { opacity: 0; } }\n@keyframes slide { from { opacity: 0; transform: translateX(4px); } }\n@keyframes rise { from { opacity: 0; transform: translateY(4px); } }\n\n@media (prefers-reduced-motion: reduce) {\n :root:not([data-motion='full']) .backdrop,\n :root:not([data-motion='full']) .panel { animation: none; }\n}\n:root[data-motion='reduce'] .backdrop,\n:root[data-motion='reduce'] .panel { animation: none; }\n","/**\n * routes/verse/shell/NeedsYouList.tsx — the rows of the Needs-you drawer\n * (unit C1). A listbox with ONE tab stop and aria-activedescendant, so J / K\n * move the selection without moving focus (and without the page scrolling\n * under the drawer). Presentational: selection and keys belong to the drawer.\n *\n * Each row says what, where, and how urgent — severity is a word AND a colour\n * (never colour alone), and an item with a deadline shows it counting down.\n *\n * Rows print needsYouRowView, not the wire text: \"patch: claude run: Advance\n * goal \"… so a deg\" becomes a \"Patch · Claude run\" label over a title that\n * ends on a whole word (two lines at most; the server's text is the tooltip),\n * a run summary becomes \"2 files · +384 −0 · Test-and-repair loop\", and an age\n * is \"38 days ago\" with the exact local time on hover.\n */\nimport { forwardRef, useEffect, useRef } from 'react';\nimport type { NeedsYouItem } from '../../../../core/verse/workbench-types.js';\nimport { NEEDS_YOU_ACTION_KEYS } from '../../../../core/verse/workbench-types.js';\nimport { needsYouRowView, until, type NeedsYouRunView } from './needs-you-model.js';\nimport styles from './NeedsYouDrawer.module.css';\n\n/**\n * \"2 files · +384 −0 · Test-and-repair loop\". The stats are drawn for the eye\n * and spoken as a sentence; the source's meaning (what TITRR did) is its\n * tooltip. Shared with the drawer's item detail.\n */\nexport function NeedsYouRunFacts({ run }: { run: NeedsYouRunView }) {\n return (\n <span className={styles.runFacts}>\n <span className={styles.diffStats} aria-hidden=\"true\">{run.stats}</span>\n <span className=\"visually-hidden\">{run.statsSpoken}</span>\n <span aria-hidden=\"true\">·</span>\n <span className={styles.runSource} title={run.sourceHint ?? undefined}>\n {run.partial ? 'Partial · ' : ''}{run.source}\n </span>\n </span>\n );\n}\n\nconst SEVERITY_WORD: Readonly<Record<NeedsYouItem['severity'], string>> = { high: 'Urgent', warn: 'Soon', info: 'When you can' };\n\nconst SOURCE_WORD: Readonly<Record<NeedsYouItem['source'], string>> = {\n approvals: 'Approval',\n authority: 'Autonomy',\n fleet: 'Fleet',\n leader: 'Leader',\n chats: 'Chat',\n accounts: 'Account',\n};\n\nexport interface NeedsYouListProps {\n items: readonly NeedsYouItem[];\n selectedId: string | null;\n onSelect: (id: string) => void;\n onOpen: (id: string) => void;\n now: number;\n label: string;\n}\n\nexport const NeedsYouList = forwardRef<HTMLDivElement, NeedsYouListProps>(function NeedsYouList(\n { items, selectedId, onSelect, onOpen, now, label },\n ref,\n) {\n const listId = 'verse-needs-you-list';\n const rowsRef = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n if (!selectedId) return;\n // Matched by dataset, not a selector: ids come from other units' producers.\n const rows = rowsRef.current?.querySelectorAll<HTMLElement>('[data-item-id]') ?? [];\n const row = [...rows].find((el) => el.dataset['itemId'] === selectedId);\n row?.scrollIntoView?.({ block: 'nearest' });\n }, [selectedId]);\n\n return (\n <div\n ref={(node) => {\n rowsRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n }}\n id={listId}\n role=\"listbox\"\n aria-label={label}\n tabIndex={0}\n aria-activedescendant={selectedId ? `${listId}-${items.findIndex((i) => i.id === selectedId)}` : undefined}\n className={styles.rows}\n >\n {items.map((item, index) => {\n const keyed = item.actions\n .map((a) => NEEDS_YOU_ACTION_KEYS[a.kind])\n .filter((k): k is 'A' | 'R' | 'V' | 'E' => k !== undefined);\n const view = needsYouRowView(item, now);\n return (\n <div\n key={item.id}\n id={`${listId}-${index}`}\n data-item-id={item.id}\n role=\"option\"\n aria-selected={item.id === selectedId}\n className={styles.row}\n data-severity={item.severity}\n onClick={() => onOpen(item.id)}\n onMouseMove={() => item.id !== selectedId && onSelect(item.id)}\n >\n <span className={styles.rule} aria-hidden=\"true\" />\n <span className={styles.rowMain}>\n {view.kindLabel ? <span className={styles.rowKind}>{view.kindLabel}</span> : null}\n {/* Two lines at most, ending on a whole word; the server's title is the tooltip. */}\n <span className={styles.rowTitle} title={view.fullTitle}>{view.title}</span>\n {view.run ? <NeedsYouRunFacts run={view.run} /> : null}\n <span className={styles.rowMeta}>\n <span className={styles.severity} data-severity={item.severity}>{SEVERITY_WORD[item.severity]}</span>\n <span>{SOURCE_WORD[item.source]}</span>\n {view.repo ? <span className={styles.repo} title={view.repoFull}>{view.repo}</span> : null}\n {item.subject.pr ? <span>#{item.subject.pr}</span> : null}\n <span title={view.ageStamp}>{view.age}</span>\n {item.expiresAt ? <span className={styles.deadline}>closes {until(item.expiresAt, now)}</span> : null}\n </span>\n </span>\n {item.id === selectedId && keyed.length > 0 ? (\n <span className={styles.rowKeys} aria-hidden=\"true\">\n {keyed.map((k) => (\n <kbd key={k} className={styles.key}>{k}</kbd>\n ))}\n </span>\n ) : null}\n </div>\n );\n })}\n </div>\n );\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"NeedsYouList-BgH8ezqf.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/approvals/approvals-model.ts","../../../../../../src/web-ui/routes/verse/shell/needs-you-model.ts","../../../../../../src/web-ui/routes/verse/shell/NeedsYouDrawer.module.css","../../../../../../src/web-ui/routes/verse/shell/NeedsYouList.tsx"],"sourcesContent":["/**\n * routes/verse/approvals/approvals-model.ts — the pure decisions behind the\n * approvals queue: what order rows come in, and exactly what a human is\n * agreeing to when they press Approve.\n *\n * Kept framework-free and unit-tested because both are easy to get subtly\n * wrong: \"pending first\" must survive a status filter that also returns\n * decided rows, and the approve consequence sentence is the last thing\n * standing between a click and a real pull request against a real remote.\n */\nimport type { Proposal, ProposalKind } from '../../../data/api-types.js';\nimport { ENGINE_LABEL } from '../verse-model.js';\n\n/** Pending first, then newest first within each group. Stable and total. */\nexport function orderProposals(rows: readonly Proposal[]): Proposal[] {\n return [...rows].sort((a, b) => {\n const pendingA = a.status === 'pending' ? 0 : 1;\n const pendingB = b.status === 'pending' ? 0 : 1;\n if (pendingA !== pendingB) return pendingA - pendingB;\n const tsA = Date.parse(a.createdAt);\n const tsB = Date.parse(b.createdAt);\n const safeA = Number.isNaN(tsA) ? 0 : tsA;\n const safeB = Number.isNaN(tsB) ? 0 : tsB;\n if (safeA !== safeB) return safeB - safeA;\n return a.id.localeCompare(b.id);\n });\n}\n\nexport type RiskClass = NonNullable<Proposal['riskClass']>;\n\n/** high → medium → low → unstated. Used for the risk column's sort affordance. */\nexport function riskRank(risk: Proposal['riskClass']): number {\n switch (risk) {\n case 'high':\n return 0;\n case 'medium':\n return 1;\n case 'low':\n return 2;\n default:\n return 3;\n }\n}\n\n/** Client-side narrowing over whatever page the server returned. */\nexport function filterProposals(rows: readonly Proposal[], search: string, repo: string): Proposal[] {\n const s = search.trim().toLowerCase();\n const r = repo.trim().toLowerCase();\n if (!s && !r) return [...rows];\n return rows.filter((p) => {\n if (s && !p.title.toLowerCase().includes(s) && !(p.summary ?? '').toLowerCase().includes(s)) return false;\n if (r && !(p.repo ?? '').toLowerCase().includes(r)) return false;\n return true;\n });\n}\n\n/**\n * What approving this proposal actually does, in one sentence, naming the\n * repo. `pr` is the dangerous one: it pushes a branch to the remote and opens\n * a real pull request, which is visible to other people and cannot be undone\n * from the dialog. The confirm step MUST show this before the click.\n */\nexport function describeApproveConsequence(kind: ProposalKind | string, repo: string | null): string {\n // The project's NAME, not its absolute path: a sandbox checkout under\n // /private/tmp/claude-501/… is unreadable in a sentence. The confirm dialog\n // still prints the full path once, as the exact place the write lands.\n const where = repoName(repo) ?? 'the target repository';\n switch (kind) {\n case 'pr':\n return `Pushes a branch to ${where}'s remote and opens a real pull request. Other people can see it immediately, and this dialog cannot undo it.`;\n case 'patch':\n return `Writes the diff to ${where} on disk now. Nothing is pushed, but the working tree changes.`;\n default:\n return `Applies this ${String(kind)} proposal to ${where} now.`;\n }\n}\n\n/** True when approving reaches a remote — the loudest confirm wording. */\nexport function reachesRemote(kind: ProposalKind | string): boolean {\n return kind === 'pr';\n}\n\n/** The engine that produced the diff, as a short display string. */\nexport function engineOf(proposal: Pick<Proposal, 'engineModel' | 'engineTier'>): string | null {\n if (proposal.engineModel) return proposal.engineModel;\n if (proposal.engineTier) return proposal.engineTier;\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Readable detail\n// ---------------------------------------------------------------------------\n\n/** \"/Users/m/repos/binshield/\" → \"binshield\"; null for no repo. */\nexport function repoName(repo: string | null | undefined): string | null {\n if (typeof repo !== 'string') return null;\n const trimmed = repo.trim().replace(/\\/+$/, '');\n if (trimmed.length === 0) return null;\n const last = trimmed.slice(trimmed.lastIndexOf('/') + 1);\n return last.length > 0 ? last : trimmed;\n}\n\nconst KIND_LABEL: Record<string, string> = {\n patch: 'Patch',\n pr: 'Pull request',\n deploy: 'Deploy',\n note: 'Note',\n 'desktop-action': 'Desktop action',\n 'browser-action': 'Browser action',\n};\n\n/** \"patch\" → \"Patch\", \"pr\" → \"Pull request\"; an unknown kind is shown as sent. */\nexport function kindLabel(kind: ProposalKind | string): string {\n return KIND_LABEL[kind] ?? String(kind);\n}\n\n/**\n * The server builds a run proposal's title as `${engine} run: ${goal.slice(0, 80)}`\n * — cut at 80 characters, mid-word, sometimes mid-quote. This is the one\n * place that cut is made readable.\n */\nexport const RUN_TITLE_GOAL_CAP = 80;\n\nexport interface ReadableTitle {\n /** \"Claude run\" when the title carried an `engine run:` prefix; null otherwise. */\n eyebrow: string | null;\n /** The title to print: never ends mid-word; a cut one ends in \"…\". */\n text: string;\n /** True when the server's title was cut short (the full text we have rides in a tooltip). */\n truncated: boolean;\n}\n\nfunction capitalize(word: string): string {\n return word.length === 0 ? word : word.charAt(0).toUpperCase() + word.slice(1);\n}\n\n/** The app's own display name for an engine (\"Claude\", \"Codex\"); any other engine capitalized (\"Ollama\"). */\nfunction engineDisplayName(engine: string): string {\n const key = engine.toLowerCase();\n return Object.prototype.hasOwnProperty.call(ENGINE_LABEL, key)\n ? ENGINE_LABEL[key as keyof typeof ENGINE_LABEL]\n : capitalize(key);\n}\n\n/** Close a quote the cut left open, so the title does not read as a stray mark. */\nfunction closeQuotes(text: string): string {\n let out = text;\n if ((out.match(/\"/g) ?? []).length % 2 === 1) out += '\"';\n if ((out.match(/\\u201c/g) ?? []).length > (out.match(/\\u201d/g) ?? []).length) out += '\\u201d';\n return out;\n}\n\n/** Drop a trailing partial word and end on \"…\". */\nfunction cutAtWord(text: string): string {\n const body = text.replace(/(?:\\u2026|\\.\\.\\.)$/, '');\n const space = body.lastIndexOf(' ');\n const whole = space > 0 ? body.slice(0, space) : body;\n return `${whole.replace(/[\\s,;:\\-\\u2013\\u2014]+$/, '')}\\u2026`;\n}\n\nexport function readableTitle(title: string): ReadableTitle {\n const raw = typeof title === 'string' ? title.trim() : '';\n // Only the engines the sandboxed runner names — \"Dry run: …\" is a title, not an engine.\n const run = /^(\\[partial\\]\\s*)?(claude|codex|grok|local|ollama|gemini|api[\\w-]*) run:\\s*(.*)$/is.exec(raw);\n // \"Partial Claude run\", never \"Partial claude run\": the engine is a name either way.\n const eyebrow = run ? `${run[1] ? 'Partial ' : ''}${engineDisplayName(run[2]!)} run` : null;\n let text = run ? run[3]! : raw;\n // A title that already ends in an ellipsis right after a letter was cut mid-word upstream.\n const cutMidWord = /[\\p{L}\\p{N}](?:\\u2026|\\.\\.\\.)$/u.test(text);\n // A run goal at exactly the server's cap that does not end on a sentence boundary was sliced.\n const sliced = run !== null && text.length >= RUN_TITLE_GOAL_CAP && !/[.!?)\"'\\u201d\\u2026]$/.test(text);\n const truncated = cutMidWord || sliced;\n if (truncated) text = cutAtWord(text);\n text = closeQuotes(text);\n return { eyebrow, text: text.length > 0 ? text : raw, truncated };\n}\n\n/**\n * What a sandboxed run's summary line says, taken apart. The server writes\n * `[Partial ]<source> <engine:model> run produced N file(s) (+A/-D). <rest>`\n * (core/run/sandboxed-engine.ts); anything else parses to null and is shown\n * verbatim.\n */\nexport interface RunFacts {\n partial: boolean;\n /** The server's source label, verbatim (\"TITRR\", \"Best-of-N winner\"). */\n source: string;\n /** The source in plain words (\"Test-and-repair loop\"). */\n sourceLabel: string;\n /** What the source means, for a tooltip; null when the label says it already. */\n sourceHint: string | null;\n /** \"claude:claude-fable-5\". */\n model: string;\n files: number;\n insertions: number;\n deletions: number;\n /** Whatever the summary says after the run facts (\"Review before applying.\"), or null. */\n rest: string | null;\n}\n\nconst RUN_SUMMARY = /^(Partial )?(.+?) (\\S+) run produced (\\d+) file\\(s\\) \\(\\+(\\d+)\\/-(\\d+)\\)\\.?\\s*([\\s\\S]*)$/;\n\n/**\n * TITRR is internal shorthand (core/run/orchestrator.ts M78: Test → Iterate →\n * Test → Refine → Repeat). The operator sees the plain name; the acronym and\n * what it did ride in the tooltip.\n */\nconst TITRR_HINT =\n 'TITRR — Test, Iterate, Test, Refine, Repeat: after its change the run re-ran the repository\\u2019s tests and repaired the change until they passed or it ran out of attempts.';\n\nfunction describeSource(source: string): { label: string; hint: string | null } {\n if (/\\bTITRR\\b/.test(source)) {\n const rest = source.replace(/\\bTITRR\\b\\s*/, '').trim();\n const qualifier = rest === 'api-model' ? ' (API model)'\n : rest === 'api-model required-diff' ? ' (API model, retried for a missing diff)'\n : rest === 'api-model failed producer' ? ' (API model, producer failed)'\n : rest.length > 0 ? ` (${rest})` : '';\n return { label: `Test-and-repair loop${qualifier}`, hint: TITRR_HINT };\n }\n if (/^best-of-n/i.test(source)) {\n return { label: source, hint: 'Several models attempted this change in parallel; a judge compared them.' };\n }\n if (source === 'api-model') return { label: 'API model run', hint: null };\n if (source === 'Sandboxed') return { label: 'Sandboxed run', hint: 'Produced in an isolated sandbox checkout; nothing touched your working tree.' };\n return { label: source, hint: null };\n}\n\nexport function parseRunSummary(summary: string | null | undefined): RunFacts | null {\n if (typeof summary !== 'string') return null;\n const m = RUN_SUMMARY.exec(summary.trim());\n if (!m) return null;\n const { label, hint } = describeSource(m[2]!);\n const rest = m[7]!.trim();\n return {\n partial: m[1] !== undefined,\n source: m[2]!,\n sourceLabel: label,\n sourceHint: hint,\n model: m[3]!,\n files: Number(m[4]),\n insertions: Number(m[5]),\n deletions: Number(m[6]),\n rest: rest.length > 0 ? rest : null,\n };\n}\n\n/** \"2 files · +384 −0\" (a real minus sign, grouped thousands). */\nexport function formatDiffStats(facts: Pick<RunFacts, 'files' | 'insertions' | 'deletions'>): string {\n const n = (v: number) => v.toLocaleString('en-US');\n return `${n(facts.files)} ${facts.files === 1 ? 'file' : 'files'} \\u00b7 +${n(facts.insertions)} \\u2212${n(facts.deletions)}`;\n}\n\n/** The same stats as a sentence for assistive tech: \"2 files changed, 384 lines added, 0 removed\". */\nexport function describeDiffStats(facts: Pick<RunFacts, 'files' | 'insertions' | 'deletions'>): string {\n const n = (v: number) => v.toLocaleString('en-US');\n return `${n(facts.files)} ${facts.files === 1 ? 'file' : 'files'} changed, ${n(facts.insertions)} ${facts.insertions === 1 ? 'line' : 'lines'} added, ${n(facts.deletions)} removed`;\n}\n\n/**\n * \"just now\", \"5 minutes ago\", \"yesterday\", \"38 days ago\", then \"on Aug 17\"\n * past two months. Written out in full: the detail view has the room, and\n * \"38d\" is a sidebar abbreviation.\n */\nexport function longAgo(iso: string | null | undefined, now: number = Date.now()): string {\n if (typeof iso !== 'string') return 'at an unknown time';\n const then = Date.parse(iso);\n if (!Number.isFinite(then)) return 'at an unknown time';\n const seconds = Math.max(0, Math.round((now - then) / 1000));\n if (seconds < 45) return 'just now';\n const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });\n const minutes = Math.round(seconds / 60);\n if (minutes < 60) return rtf.format(-minutes, 'minute');\n const hours = Math.round(minutes / 60);\n if (hours < 24) return rtf.format(-hours, 'hour');\n const days = Math.round(hours / 24);\n if (days <= 60) return rtf.format(-days, 'day');\n return `on ${new Date(then).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })}`;\n}\n\n/** A local date and time for a tooltip: \"Mon, Aug 17, 3:12 PM\". */\nexport function localStamp(iso: string | null | undefined): string | undefined {\n if (typeof iso !== 'string') return undefined;\n const t = Date.parse(iso);\n if (!Number.isFinite(t)) return undefined;\n return new Date(t).toLocaleString([], { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit' });\n}\n","/**\n * routes/verse/shell/needs-you-model.ts — the Needs-you drawer as data (unit\n * C1): which items a split shows, how many each split has, whether the drawer\n * may say \"All clear\", and what a key press does to an item.\n *\n * Pure. The items come from GET /api/verse/activity (C1's own producers plus\n * Track B's, R1); each carries its own actions, so nothing here knows what a\n * grant or an owner-lane PR is.\n *\n * How a row READS (needsYouRowView) borrows the approvals detail view's text\n * helpers rather than growing a second copy: an approval item's title and\n * detail are the same proposal title and run summary that view already\n * untangles.\n */\nimport {\n NEEDS_YOU_KIND_CATEGORY,\n type NeedsYouAction,\n type NeedsYouActionKind,\n type NeedsYouItem,\n type NeedsYouSource,\n type VerseActivitySources,\n} from '../../../../core/verse/workbench-types.js';\nimport {\n describeDiffStats,\n formatDiffStats,\n kindLabel,\n localStamp,\n longAgo,\n parseRunSummary,\n readableTitle,\n repoName,\n} from '../approvals/approvals-model.js';\nimport type { VerseSeat } from '../../../data/api-types.js';\nimport { isVerseEngine, modelOptionFor, seatById } from '../verse-model.js';\nimport type { NeedsYouSplit } from '../verse-ui-store.js';\n\nexport const SPLIT_LABEL: Readonly<Record<NeedsYouSplit, string>> = {\n all: 'All',\n approvals: 'Approvals',\n fleet: 'Fleet',\n chats: 'Chats',\n accounts: 'Accounts',\n};\n\n/**\n * Which producers can put an item in each split. \"All clear\" is only\n * claimed for a split whose every producer answered: an owner-lane PR is in\n * Approvals but comes from the FLEET producer, so Approvals is only vouched\n * for when the fleet source answered too.\n */\nexport const SPLIT_SOURCES: Readonly<Record<NeedsYouSplit, readonly NeedsYouSource[]>> = {\n all: ['approvals', 'authority', 'fleet', 'leader', 'chats', 'accounts'],\n approvals: ['approvals', 'fleet', 'leader'],\n fleet: ['authority', 'fleet', 'leader'],\n chats: ['chats'],\n accounts: ['accounts'],\n};\n\nconst SOURCE_NAME: Readonly<Record<NeedsYouSource, string>> = {\n approvals: 'the approvals inbox',\n authority: 'the autonomy grant',\n fleet: 'the fleet',\n leader: 'the Leader',\n chats: 'chats',\n accounts: 'account health',\n};\n\nexport function itemsForSplit(items: readonly NeedsYouItem[], split: NeedsYouSplit): NeedsYouItem[] {\n if (split === 'all') return [...items];\n return items.filter((item) => NEEDS_YOU_KIND_CATEGORY[item.kind] === split);\n}\n\nexport function splitCounts(items: readonly NeedsYouItem[]): Record<NeedsYouSplit, number> {\n const counts: Record<NeedsYouSplit, number> = { all: items.length, approvals: 0, fleet: 0, chats: 0, accounts: 0 };\n for (const item of items) counts[NEEDS_YOU_KIND_CATEGORY[item.kind]] += 1;\n return counts;\n}\n\nexport interface SplitCoverage {\n /** Every producer feeding this split answered. */\n vouched: boolean;\n /** Operator-language names of the ones that did not, with why. */\n silent: Array<{ source: NeedsYouSource; name: string; state: 'unavailable' | 'error' }>;\n}\n\n/** Null sources (activity itself unavailable) vouch for nothing. */\nexport function splitCoverage(sources: VerseActivitySources | null, split: NeedsYouSplit): SplitCoverage {\n const silent: SplitCoverage['silent'] = [];\n for (const source of SPLIT_SOURCES[split]) {\n const state = sources?.[source] ?? 'unavailable';\n if (state !== 'ok') silent.push({ source, name: SOURCE_NAME[source], state });\n }\n return { vouched: silent.length === 0, silent };\n}\n\n/** \"the fleet isn't reporting yet and the Leader failed to answer\" — for the empty state. */\nexport function describeSilence(coverage: SplitCoverage): string {\n const phrases = coverage.silent.map((s) => (s.state === 'error' ? `${s.name} failed to answer` : `${s.name} isn't reporting in this build`));\n if (phrases.length === 0) return '';\n if (phrases.length === 1) return capitalise(phrases[0]!);\n return capitalise(`${phrases.slice(0, -1).join(', ')} and ${phrases[phrases.length - 1]}`);\n}\n\nfunction capitalise(text: string): string {\n return text.charAt(0).toUpperCase() + text.slice(1);\n}\n\n/** Approve / reject / veto ALWAYS confirm (SPEC-310C §1); other kinds only when the item says so. */\nexport const ALWAYS_CONFIRM: ReadonlySet<NeedsYouActionKind> = new Set(['approve', 'reject', 'veto']);\n\nexport function actionOf(item: NeedsYouItem, kind: NeedsYouActionKind): NeedsYouAction | null {\n return item.actions.find((a) => a.kind === kind) ?? null;\n}\n\nconst GENERIC_CONFIRM: Readonly<Record<'approve' | 'reject' | 'veto', { title: string; confirmLabel: string }>> = {\n approve: { title: 'Approve this?', confirmLabel: 'Approve' },\n reject: { title: 'Reject this?', confirmLabel: 'Reject' },\n veto: { title: 'Veto this action?', confirmLabel: 'Veto' },\n};\n\nexport interface ConfirmCopy {\n title: string;\n body: string;\n confirmLabel: string;\n}\n\n/** The dialog for `action` on `item`; null when the action runs without one. */\nexport function confirmCopy(item: NeedsYouItem, action: NeedsYouAction): ConfirmCopy | null {\n if (action.confirm) return action.confirm;\n if (action.kind === 'approve' || action.kind === 'reject' || action.kind === 'veto') {\n const generic = GENERIC_CONFIRM[action.kind];\n return { title: generic.title, body: readableItemTitle(item).text, confirmLabel: generic.confirmLabel };\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// How a row reads\n// ---------------------------------------------------------------------------\n\n/**\n * The approvals producer titles an item `${kind === 'pr' ? 'PR' : kind}: ${proposal.title}`\n * (core/verse/activity.ts approvalItem). Only an `approval` item is taken\n * apart this way — \"Failed: Migrate the store\" is a chat title, not a kind.\n */\nconst APPROVAL_KIND_PREFIX = /^(PR|[a-z][a-z-]*):\\s+([\\s\\S]+)$/;\n\nexport interface ReadableItemTitle {\n /** \"Patch · Claude run\": the proposal kind and the engine the title led with; null when neither. */\n kindLabel: string | null;\n /** The title to print. Never ends mid-word — a cut one ends in \"…\". */\n text: string;\n}\n\nexport function readableItemTitle(item: Pick<NeedsYouItem, 'kind' | 'title'>): ReadableItemTitle {\n let proposalKind: string | null = null;\n let rest = item.title;\n if (item.kind === 'approval') {\n const m = APPROVAL_KIND_PREFIX.exec(item.title.trim());\n if (m) {\n proposalKind = m[1] === 'PR' ? 'pr' : m[1]!;\n rest = m[2]!;\n }\n }\n const title = readableTitle(rest);\n const parts = [proposalKind === null ? null : kindLabel(proposalKind), title.eyebrow].filter((p): p is string => p !== null);\n return { kindLabel: parts.length > 0 ? parts.join(' · ') : null, text: title.text };\n}\n\n/** A sandboxed run's facts, lifted out of the item's detail line. */\nexport interface NeedsYouRunView {\n /** \"2 files · +384 −0\". */\n stats: string;\n /** \"2 files changed, 384 lines added, 0 removed\" — what a screen reader says instead. */\n statsSpoken: string;\n /** \"Test-and-repair loop\", never \"TITRR\". */\n source: string;\n /** What the source means, for a tooltip. */\n sourceHint: string | null;\n partial: boolean;\n /** \"claude:claude-fable-5\". */\n model: string;\n}\n\n/** Everything a Needs-you row prints, in operator language. The raw server text survives only in tooltips. */\nexport interface NeedsYouRowView {\n kindLabel: string | null;\n title: string;\n /** The title exactly as the server sent it — the row's tooltip. */\n fullTitle: string;\n run: NeedsYouRunView | null;\n /** What the detail says beyond the run facts (\"Review before applying.\"), or the detail verbatim; null when nothing. */\n detail: string | null;\n /** \"binshield\", never a path. */\n repo: string | null;\n /** The repo as sent, as a tooltip, when it was more than the name. */\n repoFull: string | undefined;\n /** \"38 days ago\". */\n age: string;\n /** The exact local time, for a tooltip. */\n ageStamp: string | undefined;\n}\n\nexport function needsYouRowView(item: NeedsYouItem, now: number = Date.now()): NeedsYouRowView {\n const title = readableItemTitle(item);\n const facts = parseRunSummary(item.detail);\n const repo = repoName(item.subject.repo);\n return {\n kindLabel: title.kindLabel,\n title: title.text,\n fullTitle: item.title,\n run: facts\n ? {\n stats: formatDiffStats(facts),\n statsSpoken: describeDiffStats(facts),\n source: facts.sourceLabel,\n sourceHint: facts.sourceHint,\n partial: facts.partial,\n model: facts.model,\n }\n : null,\n detail: facts ? facts.rest : item.detail,\n repo,\n repoFull: repo !== null && item.subject.repo !== null && item.subject.repo !== repo ? item.subject.repo : undefined,\n age: longAgo(item.since, now),\n ageStamp: localStamp(item.since),\n };\n}\n\n/** \"closes in 24m\" / \"expired\" — for veto windows and grants. */\nexport function until(iso: string, now: number = Date.now()): string {\n const t = Date.parse(iso);\n if (!Number.isFinite(t)) return '—';\n const s = Math.round((t - now) / 1000);\n if (s <= 0) return 'expired';\n if (s < 90) return `in ${s}s`;\n const m = Math.round(s / 60);\n if (m < 90) return `in ${m}m`;\n const h = Math.round(m / 60);\n if (h < 48) return `in ${h}h`;\n return `in ${Math.round(h / 24)}d`;\n}\n\n// ---------------------------------------------------------------------------\n// Seats and models, by name\n// ---------------------------------------------------------------------------\n\n/** A seat or model as the operator knows it; `raw` is the id as sent, for a tooltip, when the text differs. */\nexport interface DisplayName {\n text: string;\n raw: string | undefined;\n}\n\n/**\n * \"Claude Max\" for `claude-a`: the roster's label (bootstrap seats — the name\n * the seat picker and Apps & Accounts use). An id the roster does not know is\n * shown as sent: it is all there is.\n */\nexport function seatDisplayName(seats: readonly VerseSeat[], seatId: string): DisplayName {\n const label = seatById(seats, seatId)?.label;\n return label && label !== seatId ? { text: label, raw: seatId } : { text: seatId, raw: undefined };\n}\n\n/**\n * \"Fable 5.1\" for a run's `claude:claude-fable-5-1`: the catalog label (the\n * model picker's) on the item's own seat first, then on any seat of the run's\n * engine — exact id, then canonical (verse-model `modelOptionFor`, so a\n * pre-alias `claude-opus-5.5` still finds `claude-opus-5-5`). A model no\n * catalog lists is shown as sent.\n */\nexport function runModelDisplayName(seats: readonly VerseSeat[], model: string, seatId: string | null): DisplayName {\n const colon = model.indexOf(':');\n const prefix = colon > 0 ? model.slice(0, colon) : '';\n const engine = isVerseEngine(prefix) ? prefix : null;\n // `local:qwen3.8:27b` keeps its tag: only a known engine prefix is split off.\n const id = engine ? model.slice(colon + 1) : model;\n const order = [\n ...(seatId ? [seatId] : []),\n ...seats.filter((seat) => seat.id !== seatId && (engine === null || seat.engine === engine)).map((seat) => seat.id),\n ];\n for (const candidate of order) {\n const label = modelOptionFor(seats, { seatId: candidate, model: id })?.label;\n if (label && label !== model) return { text: label, raw: model };\n }\n return { text: model, raw: undefined };\n}\n","/* ⌘J — a right-hand sheet over the workbench; full screen on a phone.\n Hairlines, no cards. Severity is a word plus a 2px rule, never colour alone. */\n\n.backdrop {\n position: fixed;\n inset: 0;\n z-index: var(--z-dialog);\n display: flex;\n justify-content: flex-end;\n background: var(--bg-overlay);\n animation: fade var(--duration-fast) var(--ease-standard);\n}\n\n.panel {\n display: flex;\n flex-direction: column;\n width: min(480px, calc(100vw - var(--space-8)));\n height: 100%;\n background: var(--bg-surface);\n border-left: 1px solid var(--border-default);\n box-shadow: var(--shadow-dialog);\n outline: none;\n animation: slide var(--duration-base) var(--ease-decelerate);\n}\n\n/* Phone: the whole screen, sliding up. */\n.panel[data-presentation='full'] {\n width: 100%;\n border-left: 0;\n animation-name: rise;\n}\n\n.head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-3);\n min-height: var(--strip-height);\n padding: var(--space-2) var(--space-3) var(--space-2) var(--space-4);\n border-bottom: 1px solid var(--border-subtle);\n}\n\n.title {\n display: flex;\n align-items: baseline;\n gap: var(--space-2);\n font-family: var(--font-display);\n font-size: var(--text-md-size);\n line-height: var(--text-md-line);\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-display);\n}\n\n.titleCount {\n font-family: var(--font-ui);\n font-size: var(--text-sm-size);\n font-weight: var(--font-weight-regular);\n font-variant-numeric: tabular-nums;\n color: var(--text-tertiary);\n}\n\n.splits {\n display: flex;\n gap: var(--space-1);\n padding: var(--space-2) var(--space-3);\n border-bottom: 1px solid var(--border-subtle);\n overflow-x: auto;\n scrollbar-width: none;\n}\n\n.split {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n flex: none;\n min-height: var(--control-h-sm);\n padding: 0 var(--space-2);\n border-radius: var(--radius-sm);\n color: var(--text-secondary);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n.split:hover { background: var(--bg-hover); color: var(--text-primary); }\n.split[aria-selected='true'] { background: var(--bg-selected); color: var(--text-primary); font-weight: var(--font-weight-medium); }\n\n.splitCount {\n min-width: 18px;\n padding: 0 4px;\n border-radius: var(--radius-full);\n background: var(--bg-hover);\n font-size: var(--text-2xs-size);\n line-height: 18px;\n text-align: center;\n font-variant-numeric: tabular-nums;\n color: var(--text-secondary);\n}\n\n.body {\n position: relative;\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n}\n\n.rows { outline: none; }\n.rows:focus-visible { box-shadow: none; }\n/* The list holds focus (aria-activedescendant), so the focus ring is drawn on\n the ROW it points at — a ring around the whole list says nothing about\n which item A / R / V will act on. */\n.rows:focus-visible .row[aria-selected='true'] { box-shadow: inset 0 0 0 2px var(--border-focus); }\n\n.row {\n display: grid;\n grid-template-columns: 2px minmax(0, 1fr) auto;\n column-gap: var(--space-3);\n align-items: center;\n padding: var(--space-3) var(--space-4);\n border-bottom: 1px solid var(--border-subtle);\n cursor: pointer;\n}\n.row:hover { background: var(--bg-hover); }\n.row[aria-selected='true'] { background: var(--bg-selected); }\n\n.rule {\n align-self: stretch;\n border-radius: var(--radius-full);\n background: var(--border-strong);\n}\n.row[data-severity='high'] .rule { background: var(--status-danger-solid); }\n.row[data-severity='warn'] .rule { background: var(--status-warning-solid); }\n\n.rowMain { display: flex; flex-direction: column; min-width: 0; gap: 2px; }\n\n/* \"Patch · Claude run\" — the kind, above the title it no longer clutters.\n Secondary, not tertiary: tertiary falls under 4.5:1 on --bg-selected\n (approvals.module.css has the measurements). */\n.rowKind {\n margin: 0;\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n letter-spacing: var(--tracking-label);\n text-transform: uppercase;\n color: var(--text-secondary);\n}\n\n/* Two lines at most, wrapped at word boundaries. The text itself already\n ends on a whole word (approvals-model readableTitle); the full server\n title rides in `title`. */\n.rowTitle {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n line-clamp: 2;\n overflow: hidden;\n overflow-wrap: break-word;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-primary);\n}\n\n/* \"2 files · +384 −0 · Test-and-repair loop\". */\n.runFacts {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: 0 var(--space-2);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n}\n.diffStats { font-family: var(--font-display); font-variant-numeric: tabular-nums; color: var(--text-primary); }\n.runSource[title] { text-decoration: underline dotted; text-underline-offset: 3px; cursor: help; }\n\n.repo { font-weight: var(--font-weight-medium); }\n\n.rowMeta {\n display: flex;\n flex-wrap: wrap;\n gap: 0 var(--space-2);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n}\n\n.severity {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n letter-spacing: var(--tracking-label);\n text-transform: uppercase;\n}\n.severity[data-severity='high'] { color: var(--status-danger-fg); }\n.severity[data-severity='warn'] { color: var(--status-warning-fg); }\n\n.mono { font-family: var(--font-mono); font-size: var(--text-xs-size); }\n.deadline { color: var(--status-warning-fg); font-variant-numeric: tabular-nums; }\n\n.rowKeys { display: flex; gap: 2px; }\n\n.key,\n.inlineKey {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 4px;\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-xs);\n background: var(--bg-surface);\n font-family: var(--font-mono);\n font-size: var(--text-2xs-size);\n color: var(--text-secondary);\n}\n.inlineKey { margin-left: var(--space-2); background: transparent; }\n\n.loading { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-4); }\n\n.empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--space-2);\n padding: var(--space-16) var(--space-6);\n text-align: center;\n}\n.emptyTitle {\n font-family: var(--font-display);\n font-size: var(--text-md-size);\n line-height: var(--text-md-line);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n}\n.emptyBody {\n max-width: 44ch;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-secondary);\n}\n\n/* The reward for an empty inbox: a quiet check, not a confetti cannon. */\n.clearMark {\n position: relative;\n width: 40px;\n height: 40px;\n margin-bottom: var(--space-2);\n border-radius: var(--radius-full);\n background: var(--status-success-bg);\n}\n.clearMark::after {\n content: '';\n position: absolute;\n left: 14px;\n top: 10px;\n width: 10px;\n height: 16px;\n border: solid var(--status-success-solid);\n border-width: 0 2px 2px 0;\n transform: rotate(45deg);\n}\n\n.focusSink { position: absolute; width: 1px; height: 1px; overflow: hidden; outline: none; }\n\n.detail { outline: none; }\n\n.back {\n display: inline-flex;\n align-items: center;\n margin: var(--space-2) var(--space-3) 0;\n padding: var(--space-1) var(--space-2);\n border-radius: var(--radius-sm);\n font-size: var(--text-xs-size);\n color: var(--text-secondary);\n}\n.back:hover { background: var(--bg-hover); color: var(--text-primary); }\n\n/* ApprovalDetail was drawn for a wide pane: tighten its gutters in the sheet. */\n.approval > div { padding: var(--space-3) var(--space-4) var(--space-12); }\n\n.item { display: flex; flex-direction: column; gap: var(--space-4); padding: var(--space-3) var(--space-4) var(--space-8); }\n.itemHead { display: flex; flex-direction: column; gap: var(--space-1); }\n\n.itemTitle {\n font-family: var(--font-display);\n font-size: var(--text-lg-size);\n line-height: var(--text-lg-line);\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-display);\n}\n\n.itemDetail {\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line-relaxed);\n color: var(--text-secondary);\n overflow-wrap: anywhere;\n}\n\n.defs {\n display: grid;\n grid-template-columns: max-content minmax(0, 1fr);\n gap: var(--space-2) var(--space-4);\n margin: 0;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n.defs dt { color: var(--text-tertiary); }\n.defs dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }\n\n.itemActions { display: flex; flex-wrap: wrap; gap: var(--space-2); }\n\n.foot {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-1) var(--space-4);\n padding: var(--space-2) var(--space-4);\n border-top: 1px solid var(--border-subtle);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n color: var(--text-tertiary);\n}\n.foot span { display: inline-flex; align-items: center; gap: 2px; }\n\n.caveat {\n margin: 0;\n padding: var(--space-2) var(--space-4);\n border-top: 1px solid var(--border-subtle);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--status-warning-fg);\n background: var(--status-warning-bg);\n}\n\n@keyframes fade { from { opacity: 0; } }\n@keyframes slide { from { opacity: 0; transform: translateX(4px); } }\n@keyframes rise { from { opacity: 0; transform: translateY(4px); } }\n\n@media (prefers-reduced-motion: reduce) {\n :root:not([data-motion='full']) .backdrop,\n :root:not([data-motion='full']) .panel { animation: none; }\n}\n:root[data-motion='reduce'] .backdrop,\n:root[data-motion='reduce'] .panel { animation: none; }\n","/**\n * routes/verse/shell/NeedsYouList.tsx — the rows of the Needs-you drawer\n * (unit C1). A listbox with ONE tab stop and aria-activedescendant, so J / K\n * move the selection without moving focus (and without the page scrolling\n * under the drawer). Presentational: selection and keys belong to the drawer.\n *\n * Each row says what, where, and how urgent — severity is a word AND a colour\n * (never colour alone), and an item with a deadline shows it counting down.\n *\n * Rows print needsYouRowView, not the wire text: \"patch: claude run: Advance\n * goal \"… so a deg\" becomes a \"Patch · Claude run\" label over a title that\n * ends on a whole word (two lines at most; the server's text is the tooltip),\n * a run summary becomes \"2 files · +384 −0 · Test-and-repair loop\", and an age\n * is \"38 days ago\" with the exact local time on hover.\n */\nimport { forwardRef, useEffect, useRef } from 'react';\nimport type { NeedsYouItem } from '../../../../core/verse/workbench-types.js';\nimport { NEEDS_YOU_ACTION_KEYS } from '../../../../core/verse/workbench-types.js';\nimport { needsYouRowView, until, type NeedsYouRunView } from './needs-you-model.js';\nimport styles from './NeedsYouDrawer.module.css';\n\n/**\n * \"2 files · +384 −0 · Test-and-repair loop\". The stats are drawn for the eye\n * and spoken as a sentence; the source's meaning (what TITRR did) is its\n * tooltip. Shared with the drawer's item detail.\n */\nexport function NeedsYouRunFacts({ run }: { run: NeedsYouRunView }) {\n return (\n <span className={styles.runFacts}>\n <span className={styles.diffStats} aria-hidden=\"true\">{run.stats}</span>\n <span className=\"visually-hidden\">{run.statsSpoken}</span>\n <span aria-hidden=\"true\">·</span>\n <span className={styles.runSource} title={run.sourceHint ?? undefined}>\n {run.partial ? 'Partial · ' : ''}{run.source}\n </span>\n </span>\n );\n}\n\nconst SEVERITY_WORD: Readonly<Record<NeedsYouItem['severity'], string>> = { high: 'Urgent', warn: 'Soon', info: 'When you can' };\n\nconst SOURCE_WORD: Readonly<Record<NeedsYouItem['source'], string>> = {\n approvals: 'Approval',\n authority: 'Autonomy',\n fleet: 'Fleet',\n leader: 'Leader',\n chats: 'Chat',\n accounts: 'Account',\n};\n\nexport interface NeedsYouListProps {\n items: readonly NeedsYouItem[];\n selectedId: string | null;\n onSelect: (id: string) => void;\n onOpen: (id: string) => void;\n now: number;\n label: string;\n}\n\nexport const NeedsYouList = forwardRef<HTMLDivElement, NeedsYouListProps>(function NeedsYouList(\n { items, selectedId, onSelect, onOpen, now, label },\n ref,\n) {\n const listId = 'verse-needs-you-list';\n const rowsRef = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n if (!selectedId) return;\n // Matched by dataset, not a selector: ids come from other units' producers.\n const rows = rowsRef.current?.querySelectorAll<HTMLElement>('[data-item-id]') ?? [];\n const row = [...rows].find((el) => el.dataset['itemId'] === selectedId);\n row?.scrollIntoView?.({ block: 'nearest' });\n }, [selectedId]);\n\n return (\n <div\n ref={(node) => {\n rowsRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n }}\n id={listId}\n role=\"listbox\"\n aria-label={label}\n tabIndex={0}\n aria-activedescendant={selectedId ? `${listId}-${items.findIndex((i) => i.id === selectedId)}` : undefined}\n className={styles.rows}\n >\n {items.map((item, index) => {\n const keyed = item.actions\n .map((a) => NEEDS_YOU_ACTION_KEYS[a.kind])\n .filter((k): k is 'A' | 'R' | 'V' | 'E' => k !== undefined);\n const view = needsYouRowView(item, now);\n return (\n <div\n key={item.id}\n id={`${listId}-${index}`}\n data-item-id={item.id}\n role=\"option\"\n aria-selected={item.id === selectedId}\n className={styles.row}\n data-severity={item.severity}\n onClick={() => onOpen(item.id)}\n onMouseMove={() => item.id !== selectedId && onSelect(item.id)}\n >\n <span className={styles.rule} aria-hidden=\"true\" />\n <span className={styles.rowMain}>\n {view.kindLabel ? <span className={styles.rowKind}>{view.kindLabel}</span> : null}\n {/* Two lines at most, ending on a whole word; the server's title is the tooltip. */}\n <span className={styles.rowTitle} title={view.fullTitle}>{view.title}</span>\n {view.run ? <NeedsYouRunFacts run={view.run} /> : null}\n <span className={styles.rowMeta}>\n <span className={styles.severity} data-severity={item.severity}>{SEVERITY_WORD[item.severity]}</span>\n <span>{SOURCE_WORD[item.source]}</span>\n {view.repo ? <span className={styles.repo} title={view.repoFull}>{view.repo}</span> : null}\n {item.subject.pr ? <span>#{item.subject.pr}</span> : null}\n <span title={view.ageStamp}>{view.age}</span>\n {item.expiresAt ? <span className={styles.deadline}>closes {until(item.expiresAt, now)}</span> : null}\n </span>\n </span>\n {item.id === selectedId && keyed.length > 0 ? (\n <span className={styles.rowKeys} aria-hidden=\"true\">\n {keyed.map((k) => (\n <kbd key={k} className={styles.key}>{k}</kbd>\n ))}\n </span>\n ) : null}\n </div>\n );\n })}\n </div>\n );\n});\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import{a as e,c as t,n}from"./index-QesfXBsb.js";import{m as r,o as i}from"./global-CNNGMril.js";import{t as a}from"./Dialog-BSsIFNqD.js";import{S as o,i as s,s as ee}from"./VerseConsoleApp-BCY5uSok.js";import{B as c,D as l,M as u,i as d}from"./verse-model-MMySehjj.js";import{t as te}from"./Segmented-CametjLt.js";import{c as f,i as ne,n as p}from"./context-queries-CktFQqSS.js";import{a as m,v as h}from"./git-model-_BnI_Ogh.js";import{C as g,_ as re,a as ie,b as _,c as v,g as y,h as b,i as ae,l as x,n as S,t as C,u as w,x as oe,y as T}from"./context-model-Co4wh3SM.js";import{n as se,t as ce}from"./SeatSelector-Cg75LInq.js";import{r as le}from"./CapacityStrip-CkFz5vq2.js";import{a as ue,m as de,o as fe,s as pe,v as me}from"./workspace-model-Dukb2wwv.js";import{n as he,t as ge}from"./folder-picker-C8zo3A56.js";var E=t(e(),1),D={option:`_option_qkog4_1`,toggle:`_toggle_qkog4_12`,details:`_details_qkog4_24`,nameLabel:`_nameLabel_qkog4_30`,name:`_name_qkog4_30`,hint:`_hint_qkog4_46`},O=n(),k=/^[a-z0-9][a-z0-9._-]{0,62}$/i;function A(e){return k.test(e)&&!e.endsWith(`.lock`)&&!e.includes(`..`)}function _e(e=new Date){let t=e=>String(e).padStart(2,`0`);return`chat-${t(e.getMonth()+1)}${t(e.getDate())}-${t(e.getHours())}${t(e.getMinutes())}`}function j(e){return e.toLowerCase().replace(/[^a-z0-9._-]+/g,`-`).replace(/^[^a-z0-9]+/,``).replace(/-{2,}/g,`-`).slice(0,63)}function ve({repoName:e,value:t,onChange:n,disabled:r=!1}){let i=(0,E.useId)(),a=(0,E.useId)(),o=A(t.name);return(0,O.jsxs)(`fieldset`,{className:D.option,disabled:r,children:[(0,O.jsxs)(`label`,{className:D.toggle,children:[(0,O.jsx)(`input`,{type:`checkbox`,checked:t.enabled,onChange:e=>n({enabled:e.target.checked,name:t.name||_e()}),"aria-describedby":a}),`Isolate in a worktree`]}),t.enabled?(0,O.jsxs)(`div`,{className:D.details,children:[(0,O.jsx)(`label`,{className:D.nameLabel,htmlFor:i,children:`Name`}),(0,O.jsx)(`input`,{id:i,className:D.name,value:t.name,onChange:e=>n({...t,name:j(e.target.value)}),spellCheck:!1,autoCapitalize:`off`,autoCorrect:`off`,"aria-invalid":!o||void 0,"aria-describedby":a,maxLength:63})]}):null,(0,O.jsx)(`p`,{id:a,className:D.hint,children:t.enabled?o?(0,O.jsxs)(O.Fragment,{children:[`Creates `,(0,O.jsxs)(`code`,{children:[`~/.ashlr-worktrees/`,e,`/`,t.name]}),` on a new branch `,(0,O.jsxs)(`code`,{children:[`verse/`,t.name]}),`, from the current commit. Uncommitted changes stay in `,e,`.`]}):`Use letters, digits, dots, dashes or underscores.`:`The chat works on its own branch in its own folder, so your checkout is untouched.`})]})}async function ye(e,t){return t.enabled?(await h(e,t.name)).path:e}var M={width:`_width_stwix_1`,form:`_form_stwix_3`,field:`_field_stwix_4`,label:`_label_stwix_5`,optional:`_optional_stwix_13`,select:`_select_stwix_15`,input:`_input_stwix_16`,hint:`_hint_stwix_40`,error:`_error_stwix_41`,actions:`_actions_stwix_49`,cancel:`_cancel_stwix_50`,create:`_create_stwix_51`,capacity:`_capacity_stwix_72`,rootRow:`_rootRow_stwix_78`,removeRoot:`_removeRoot_stwix_87`,addRoot:`_addRoot_stwix_88`,context:`_context_stwix_108`,contextHead:`_contextHead_stwix_115`,contextBudget:`_contextBudget_stwix_122`,warn:`_warn_stwix_130`,fit:`_fit_stwix_137`,fitLine:`_fitLine_stwix_138`,fitBadge:`_fitBadge_stwix_147`,seatFacts:`_seatFacts_stwix_165`},N=`\0workspace:`,P=`\0other`,be=(e,t)=>t();function xe(e,t){return e?.seats[t]?.contextMode??`standard`}function Se(e,t,n){return e?c(e)?T(e,t):n!==`standard`&&u(e,`standard`)!==null?`standard`:null:null}function F(e){return e instanceof s?`Unlock actions with the mutation token to save a default.`:e instanceof i?e.detail??e.message:e instanceof Error?e.message:String(e)}function I({open:e,onClose:t,projects:n,seats:i,workspaces:s=[],initialProjectPath:l,initialSeat:u,busy:d=!1,error:te,onCreate:h,runMutation:re=be}){let ie=(0,E.useId)(),_=(0,E.useId)(),v=(0,E.useId)(),b=(0,E.useId)(),ae=(0,E.useId)(),x=(0,E.useRef)(null),[S,w]=(0,E.useState)(``),[oe,D]=(0,E.useState)(``),[k,j]=(0,E.useState)(null),[I,Ee]=(0,E.useState)(``),[De,L]=(0,E.useState)(null),[R,z]=(0,E.useState)([]),[Oe,ke]=(0,E.useState)([]),[Ae,je]=(0,E.useState)(!1),[Me,Ne]=(0,E.useState)(null),[B,Pe]=(0,E.useState)(null),[Fe,Ie]=(0,E.useState)(null),[Le,V]=(0,E.useState)(null),[Re,ze]=(0,E.useState)(!1),[Be,H]=(0,E.useState)(null),[Ve,U]=(0,E.useState)({status:`idle`}),[W,He]=(0,E.useState)({enabled:!1,name:``}),[Ue,We]=(0,E.useState)(!1),Ge=(0,E.useRef)(new Map),Ke=(0,E.useMemo)(()=>[...n].sort((e,t)=>Number(t.enrolled)-Number(e.enrolled)||e.name.localeCompare(t.name)),[n]),qe=(0,E.useRef)({initialProjectPath:l,initialSeat:u,projects:n,seats:i,sortedProjects:Ke});qe.current={initialProjectPath:l,initialSeat:u,projects:n,seats:i,sortedProjects:Ke},(0,E.useEffect)(()=>{if(!e)return;let{initialProjectPath:t,initialSeat:n,projects:r,seats:i,sortedProjects:a}=qe.current,o=t&&r.some(e=>e.path===t)?t:null;w(o??(t?P:a[0]?.path??P)),D(o?``:t??``),j(we(n??null,i)??se(i)),Ee(``),L(null),z([]),Ne(null),je(!1),ke([]),V(null),H(null),ze(!1),He({enabled:!1,name:_e()}),We(!1),Ge.current=new Map},[e]),(0,E.useEffect)(()=>{if(!e)return;let t=!1;return Ie(null),ne().then(e=>{t||Pe(e)}).catch(e=>{t||(Pe(null),Ie(F(e)))}),()=>{t=!0}},[e]),(0,E.useEffect)(()=>{e&&k===null&&i.length!==0&&j(we(u??null,i)??se(i))},[e,k,i,u]);let Je=r(o);(0,E.useEffect)(()=>{e&&Je()},[e,Je]);let Ye=(0,E.useMemo)(()=>{let e=new Map;for(let t of s)e.set(t.id,t);for(let t of Oe)e.has(t.id)||e.set(t.id,t);return[...e.values()]},[s,Oe]),G=S.startsWith(N),K=G?S.slice(11):null,q=G?``:S===P?oe.trim():S,J=k===null?null:i.find(e=>e.id===k.seatId)??null,Y=J===null||k===null?null:g(J,k.model),Xe=J?.health.state===`unavailable`,X=J!==null&&Y!==null?y(J,Y):null,Ze=!G&&q.length>0,Qe=Ze&&W.enabled,$e=!d&&!Ue&&(G||q.length>0)&&k!==null&&!Xe&&Y!==null&&X===null&&(!Qe||A(W.name)),et=K===null?null:Ye.find(e=>e.id===K)??null,Z=k===null?`standard`:xe(B,k.seatId),Q=T(Y,Le??Z),tt=c(Y),nt=T(Y,Z),rt=(0,E.useCallback)((e,t)=>k!==null&&e.id===k.seatId&&t.id===k.model?Q:T(t,xe(B,e.id)),[k,Q,B]);function it(e){j(e),V(null),H(null)}async function at(){if(k===null||J===null)return;let e=Q;ze(!0),H(null);try{let t=await re(`Saving ${C[e]} as the default context mode for ${J.label}.`,()=>f({seatId:k.seatId,contextMode:e}).then(e=>({ok:!0,prefs:e}),e=>({ok:!1,error:e})));if(t===null)return;if(!t.ok){H({ok:!1,text:F(t.error)});return}Pe(t.prefs),V(null),H({ok:!0,text:`New chats on ${J.label} now start in ${C[e]}.`})}catch(e){H({ok:!1,text:F(e)})}finally{ze(!1)}}let ot=(0,E.useMemo)(()=>{if(K!==null)return{key:`w:${K}`,query:{workspaceId:K}};if(G)return null;let e=de(q,R);if(!e.ok)return null;let[t,...n]=e.roots;return{key:`p:${e.roots.join(`
2
+ `)}`,query:n.length>0?{projectPath:t,extraRoots:n}:{projectPath:t}}},[K,G,q,R]),st=(0,E.useRef)(ot);st.current=ot;let $=ot?.key??null;(0,E.useEffect)(()=>{let t=st.current;if(!e||$===null||t===null){U({status:`idle`});return}let n=Ge.current.get($);if(n){U({status:`ready`,key:$,fit:n});return}let r=!1;U({status:`loading`,key:$});let i=setTimeout(()=>{p(t.query).then(e=>{Ge.current.set($,e),r||U({status:`ready`,key:$,fit:e})}).catch(e=>{r||U({status:`error`,key:$,message:F(e)})})},350);return()=>{r=!0,clearTimeout(i)}},[e,$]);let ct=$===null?{status:`idle`}:Ve.status!==`idle`&&Ve.key===$?Ve:{status:`loading`,key:$},lt=ct.status===`ready`?ct.fit:null,ut=pe(J?.engine??null,1+R.length),dt=fe(J?.engine??null,et?.roots.length??0),ft=ge();async function pt(){let e=await he();e!==null&&e.length>0&&(w(P),D(e))}async function mt(e){let t=await he();t!==null&&t.length>0&&z(R.map((n,r)=>r===e?t:n))}async function ht(){let e=de(q,R);if(!e.ok){L(e.error);return}je(!0),L(null),Ne(null);try{let t=ue(e.roots[0]),n=await ee({name:t,roots:e.roots});ke(e=>[...e,n]),w(`${N}${n.id}`),Ne(`Saved. “${n.name}” is in this list from now on.`)}catch(e){L(e instanceof Error?e.message:String(e))}finally{je(!1)}}function gt(e){if(e.preventDefault(),!k){L(`Pick a seat first.`);return}if(Y===null){L(`Pick a model this seat offers.`);return}if(X!==null){L(`${Y.label} cannot run on this seat: ${X}.`);return}if(K!==null){L(null);let e={workspaceId:K,seatId:k.seatId,model:k.model};delete e.projectPath;let t=I.trim();t&&(e.title=t);let n=Se(Y,Q,Z);n!==null&&(e.contextMode=n),h(e);return}let t=de(q,R);if(!t.ok){L(t.error);return}if(Qe&&!A(W.name)){L(`Name the worktree with letters, digits, dots, dashes or underscores.`);return}L(null);let[n,...r]=t.roots,i={projectPath:n,seatId:k.seatId,model:k.model};r.length>0&&(i.extraRoots=r);let a=I.trim();a&&(i.title=a);let o=Se(Y,Q,Z);if(o!==null&&(i.contextMode=o),!Qe){h(i);return}_t(n,i)}async function _t(e,t){We(!0);try{let n=await re(`Creating the worktree ${W.name} (a new branch verse/${W.name}) for this chat.`,()=>ye(e,W).then(e=>({ok:!0,folder:e}),e=>({ok:!1,error:e})));if(n===null)return;if(!n.ok){L(`The worktree could not be created: ${m(n.error)}`);return}await h({...t,projectPath:n.folder})}catch(e){L(m(e))}finally{We(!1)}}let vt=De??te??null;return(0,O.jsx)(a,{open:e,onClose:t,titleId:ie,title:`New chat`,initialFocusRef:x,widthClassName:M.width,children:(0,O.jsxs)(`form`,{className:M.form,onSubmit:gt,noValidate:!0,children:[(0,O.jsxs)(`label`,{className:M.field,htmlFor:_,children:[(0,O.jsx)(`span`,{className:M.label,children:`Project`}),(0,O.jsxs)(`select`,{id:_,ref:x,value:S,onChange:e=>w(e.target.value),className:M.select,children:[Ye.length>0?(0,O.jsx)(`optgroup`,{label:`Saved projects`,children:Ye.map(e=>(0,O.jsxs)(`option`,{value:`${N}${e.id}`,children:[e.name,` — `,me(e)]},e.id))}):null,Ke.map(e=>(0,O.jsxs)(`option`,{value:e.path,children:[e.name,e.enrolled?``:` (recent)`,` — `,e.path]},e.path)),(0,O.jsx)(`option`,{value:P,children:`Other folder…`})]})]}),S===P&&!G?(0,O.jsxs)(`label`,{className:M.field,htmlFor:v,children:[(0,O.jsx)(`span`,{className:M.label,children:`Folder path`}),(0,O.jsxs)(`div`,{className:M.rootRow,children:[(0,O.jsx)(`input`,{id:v,className:M.input,value:oe,onChange:e=>D(e.target.value),placeholder:`/absolute/path/to/project`,autoComplete:`off`,spellCheck:!1}),ft?(0,O.jsx)(`button`,{type:`button`,className:M.addRoot,onClick:()=>void pt(),children:`Choose folder…`}):null]})]}):null,dt?(0,O.jsx)(`p`,{className:M.hint,children:dt}):null,G?null:(0,O.jsxs)(`div`,{className:M.field,children:[(0,O.jsxs)(`span`,{className:M.label,children:[`Also include `,(0,O.jsx)(`span`,{className:M.optional,children:`optional`})]}),R.map((e,t)=>(0,O.jsxs)(`div`,{className:M.rootRow,children:[(0,O.jsx)(`input`,{className:M.input,value:e,onChange:e=>z(R.map((n,r)=>r===t?e.target.value:n)),placeholder:`/absolute/path/to/another/folder`,"aria-label":`Additional folder ${t+1}`,autoComplete:`off`,spellCheck:!1}),ft?(0,O.jsx)(`button`,{type:`button`,className:M.removeRoot,onClick:()=>void mt(t),"aria-label":`Choose additional folder ${t+1}`,children:`Choose folder…`}):null,(0,O.jsx)(`button`,{type:`button`,className:M.removeRoot,onClick:()=>z(R.filter((e,n)=>n!==t)),"aria-label":`Remove additional folder ${t+1}`,children:`Remove`})]},t)),R.length+1<8?(0,O.jsx)(`button`,{type:`button`,className:M.addRoot,onClick:()=>z([...R,``]),children:`Add a folder`}):null,ut?(0,O.jsx)(`p`,{className:M.hint,children:ut}):null,(0,O.jsxs)(`div`,{className:M.rootRow,children:[(0,O.jsx)(`button`,{type:`button`,className:M.addRoot,onClick:()=>void ht(),disabled:Ae||q.length===0,children:Ae?`Saving…`:`Save as a project`}),(0,O.jsx)(`span`,{className:M.hint,children:`Keeps these folders in the list above. No chat needed first.`})]})]}),Me?(0,O.jsx)(`p`,{role:`status`,className:M.hint,children:Me}):null,Ze?(0,O.jsx)(ve,{repoName:Ce(q),value:W,onChange:He,disabled:Ue||d}):null,(0,O.jsx)(ce,{id:ae,seats:i,value:k,onChange:it,workingSetTokens:lt?.totalEstTokens??null,modeFor:rt}),J===null?null:(0,O.jsx)(`div`,{className:M.capacity,children:(0,O.jsx)(le,{seats:i,seatIds:[J.id],local:`each`,headline:!1,title:`${J.label} capacity`})}),J===null||Y===null?null:(0,O.jsx)(Te,{seat:J,option:Y,unavailableReason:X,mode:Q,offersModes:tt,savedDefault:nt,prefsLoaded:B!==null,prefsError:Fe,onMode:e=>{V(e),H(null)},savingDefault:Re,defaultNote:Be,onMakeDefault:()=>void at(),fitState:ct}),i.length===0?(0,O.jsx)(`p`,{className:M.hint,children:`No seats yet — connect an account or start Ollama, then reload.`}):null,(0,O.jsxs)(`label`,{className:M.field,htmlFor:b,children:[(0,O.jsxs)(`span`,{className:M.label,children:[`Title `,(0,O.jsx)(`span`,{className:M.optional,children:`optional`})]}),(0,O.jsx)(`input`,{id:b,className:M.input,value:I,onChange:e=>Ee(e.target.value),placeholder:`Defaults to your first message`,maxLength:120})]}),vt?(0,O.jsx)(`p`,{role:`alert`,className:M.error,children:vt}):null,(0,O.jsxs)(`div`,{className:M.actions,children:[(0,O.jsx)(`button`,{type:`button`,className:M.cancel,onClick:t,children:`Cancel`}),(0,O.jsx)(`button`,{type:`submit`,className:M.create,disabled:!$e,children:Ue?`Creating worktree…`:d?`Creating…`:`Start chat`})]})]})})}function Ce(e){let t=e.replace(/[\\/]+$/,``).split(/[\\/]/);return t[t.length-1]||e}function we(e,t){if(e===null)return null;let n=t.find(t=>t.id===e.seatId),r=g(n,e.model);return r===null?e:{seatId:e.seatId,model:r.id}}function Te({seat:e,option:t,unavailableReason:n,mode:r,offersModes:i,savedDefault:a,prefsLoaded:o,prefsError:s,onMode:ee,savingDefault:c,defaultNote:f,onMakeDefault:ne,fitState:p}){let m=(0,E.useId)(),h=ie(t,r),g=_(e),y=oe(e),T=p.status===`ready`?b(p.fit.totalEstTokens,t,r,e.engine):null;return(0,O.jsxs)(`div`,{className:M.context,role:`group`,"aria-labelledby":m,children:[(0,O.jsxs)(`div`,{className:M.contextHead,children:[(0,O.jsx)(`span`,{id:m,className:M.label,children:`Context`}),(0,O.jsx)(`span`,{className:M.contextBudget,children:h===null?`Window unknown`:`${l(h.contextWindow)} window${h.autoCompactAt===null?``:` · compacts ≈${l(h.autoCompactAt)}`}`})]}),h!==null&&t.windowSource?(0,O.jsxs)(`p`,{className:M.hint,children:[`Window `,d[t.windowSource],`.`]}):null,n===null?null:(0,O.jsxs)(`p`,{className:M.warn,children:[t.label,` cannot run on this seat: `,n,`. Pick another model.`]}),i?(0,O.jsxs)(O.Fragment,{children:[(0,O.jsx)(te,{"aria-label":`Context mode`,size:`sm`,value:r,onChange:ee,options:[`standard`,`expansive`].map(e=>{let n=u(t,e);return{value:e,label:n===null?C[e]:`${C[e]} · ≈${l(n.autoCompactAt??n.contextWindow)}`,ariaLabel:C[e]}})}),(0,O.jsx)(`p`,{className:M.hint,children:ae(e.engine,t,r)}),o&&r!==a?(0,O.jsx)(`div`,{className:M.rootRow,children:(0,O.jsx)(`button`,{type:`button`,className:M.addRoot,onClick:ne,disabled:c,children:c?`Saving…`:`Make ${C[r]} the default for ${e.label}`})}):null,f===null?null:(0,O.jsx)(`p`,{role:f.ok?`status`:`alert`,className:f.ok?M.hint:M.error,children:f.text}),s===null?null:(0,O.jsxs)(`p`,{className:M.hint,children:[`Saved defaults could not be read (`,s,`); this chat starts in `,C[r],` unless you pick otherwise.`]})]}):(0,O.jsx)(`p`,{className:M.hint,children:re(e.engine,t)}),(0,O.jsx)(`div`,{className:M.fit,"aria-live":`polite`,children:p.status===`idle`?null:p.status===`loading`?(0,O.jsx)(`p`,{className:M.hint,children:`Sizing the chosen folders…`}):p.status===`error`?(0,O.jsxs)(`p`,{className:M.hint,children:[`Could not size the chosen folders: `,p.message]}):T===null?(0,O.jsxs)(`p`,{className:M.hint,children:[`~`,l(p.fit.totalEstTokens),` tokens of tracked code; this model’s budget is unknown, so no fit is claimed.`]}):(0,O.jsxs)(O.Fragment,{children:[(0,O.jsxs)(`p`,{className:M.fitLine,children:[(0,O.jsx)(`span`,{className:M.fitBadge,"data-fit":T,children:S[T]}),(0,O.jsx)(`span`,{children:v({verdict:T,tokens:p.fit.totalEstTokens,option:t,mode:r,floor:x(p.fit)})})]}),(0,O.jsx)(`p`,{className:M.hint,children:w(e.engine)})]})}),g===null&&y.length===0?null:(0,O.jsxs)(`ul`,{className:M.seatFacts,"aria-label":`${e.label} facts`,children:[g===null?null:(0,O.jsxs)(`li`,{children:[`Runs `,g,`.`]}),y.map(e=>(0,O.jsx)(`li`,{children:e},e))]})]})}export{I as NewChatDialog};
3
+ //# sourceMappingURL=NewChatDialog-Db5Xjrk8.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NewChatDialog-Db5Xjrk8.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/git/WorktreeOption.module.css","../../../../../../src/web-ui/routes/verse/git/WorktreeOption.tsx","../../../../../../src/web-ui/routes/verse/NewChatDialog.module.css","../../../../../../src/web-ui/routes/verse/NewChatDialog.tsx"],"sourcesContent":[".option {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n margin: 0;\n padding: 0;\n border: 0;\n min-width: 0;\n}\n.option:disabled { opacity: 0.6; }\n\n.toggle {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n min-height: var(--control-h-sm);\n font-size: var(--text-sm-size);\n font-weight: var(--font-weight-medium);\n color: var(--text-primary);\n cursor: pointer;\n}\n.toggle input { width: 16px; height: 16px; accent-color: var(--accent-600); }\n\n.details {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n padding-left: calc(16px + var(--space-2));\n}\n.nameLabel { font-size: var(--text-sm-size); color: var(--text-secondary); }\n.name {\n flex: 1 1 auto;\n min-width: 0;\n min-height: var(--control-h-sm);\n padding: 0 var(--space-3);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n background: var(--bg-input);\n color: var(--text-primary);\n font-family: var(--font-mono);\n font-size: var(--text-sm-size);\n}\n.name:focus-visible { outline: none; border-color: var(--border-focus); box-shadow: var(--shadow-focus-ring); }\n.name[aria-invalid='true'] { border-color: var(--status-danger-solid); }\n\n.hint {\n margin: 0;\n padding-left: calc(16px + var(--space-2));\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-tertiary);\n overflow-wrap: anywhere;\n}\n.hint code {\n font-family: var(--font-mono);\n color: var(--text-secondary);\n}\n","/**\n * routes/verse/git/WorktreeOption.tsx — \"Isolate in worktree\" for the New\n * chat dialog (unit C5; SPEC-310C §2 \"Worktrees\", P1).\n *\n * NewChatDialog is C2's; this is the piece it mounts (CROSS-UNIT request in\n * the C5 report): a checkbox, a name, and one sentence saying exactly what\n * will be created. On submit C2 calls `resolveChatFolder(root, value)` and\n * starts the chat in the folder it returns — the worktree when isolation is\n * on, the project itself when it is off.\n *\n * The name is a slug (the server enforces the same rule); a default is\n * offered so isolation is one click, not a naming exercise.\n */\nimport { useId } from 'react';\nimport { createGitWorktree } from './git-queries.js';\nimport styles from './WorktreeOption.module.css';\n\nexport interface WorktreeValue {\n enabled: boolean;\n name: string;\n}\n\n/** Same rule as core/verse/worktrees.ts WORKTREE_NAME_RE. */\nexport const WORKTREE_NAME_PATTERN = /^[a-z0-9][a-z0-9._-]{0,62}$/i;\n\nexport function isValidWorktreeName(name: string): boolean {\n return WORKTREE_NAME_PATTERN.test(name) && !name.endsWith('.lock') && !name.includes('..');\n}\n\n/** A readable default: `chat-0924-1432` (month, day, hour, minute). */\nexport function defaultWorktreeName(now: Date = new Date()): string {\n const pad = (n: number) => String(n).padStart(2, '0');\n return `chat-${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}`;\n}\n\n/** Turn free typing into a valid slug as the operator types (\"Fix login!\" → \"fix-login\"). */\nexport function slugifyWorktreeName(raw: string): string {\n return raw\n .toLowerCase()\n .replace(/[^a-z0-9._-]+/g, '-')\n .replace(/^[^a-z0-9]+/, '')\n .replace(/-{2,}/g, '-')\n .slice(0, 63);\n}\n\nexport interface WorktreeOptionProps {\n /** The project folder the chat would start in (its repository name is shown). */\n repoName: string;\n value: WorktreeValue;\n onChange: (next: WorktreeValue) => void;\n disabled?: boolean;\n}\n\nexport function WorktreeOption({ repoName, value, onChange, disabled = false }: WorktreeOptionProps) {\n const nameId = useId();\n const hintId = useId();\n const valid = isValidWorktreeName(value.name);\n return (\n <fieldset className={styles.option} disabled={disabled}>\n <label className={styles.toggle}>\n <input\n type=\"checkbox\"\n checked={value.enabled}\n onChange={(e) => onChange({ enabled: e.target.checked, name: value.name || defaultWorktreeName() })}\n aria-describedby={hintId}\n />\n Isolate in a worktree\n </label>\n {value.enabled ? (\n <div className={styles.details}>\n <label className={styles.nameLabel} htmlFor={nameId}>\n Name\n </label>\n <input\n id={nameId}\n className={styles.name}\n value={value.name}\n onChange={(e) => onChange({ ...value, name: slugifyWorktreeName(e.target.value) })}\n spellCheck={false}\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n aria-invalid={!valid || undefined}\n aria-describedby={hintId}\n maxLength={63}\n />\n </div>\n ) : null}\n <p id={hintId} className={styles.hint}>\n {value.enabled ? (\n valid ? (\n <>\n Creates <code>~/.ashlr-worktrees/{repoName}/{value.name}</code> on a new branch <code>verse/{value.name}</code>, from the current commit.\n Uncommitted changes stay in {repoName}.\n </>\n ) : (\n 'Use letters, digits, dots, dashes or underscores.'\n )\n ) : (\n 'The chat works on its own branch in its own folder, so your checkout is untouched.'\n )}\n </p>\n </fieldset>\n );\n}\n\n/**\n * The folder a new chat should start in: the new worktree when isolation is\n * on (created now, through the mutation token like every git write), the\n * project itself when it is off. Throws the server's refusal (a taken name, a\n * repository with no commits) for the dialog to show.\n */\nexport async function resolveChatFolder(root: string, value: WorktreeValue): Promise<string> {\n if (!value.enabled) return root;\n const created = await createGitWorktree(root, value.name);\n return created.path;\n}\n",".width { width: min(520px, calc(100vw - 32px)); }\n\n.form { display: grid; gap: var(--space-4); }\n.field { display: grid; gap: var(--space-1); min-width: 0; }\n.label {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n.optional { font-weight: var(--font-weight-regular); letter-spacing: 0; text-transform: none; opacity: 0.8; }\n\n.select,\n.input {\n width: 100%;\n min-height: var(--control-h);\n padding: 0 var(--space-2);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n background: var(--bg-input);\n color: var(--text-primary);\n font-size: var(--text-sm-size);\n text-overflow: ellipsis;\n}\n.input::placeholder { color: var(--text-tertiary); }\n.select,\n.input {\n transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);\n}\n.select:hover:not(:disabled),\n.input:hover:not(:disabled) { border-color: var(--border-strong); }\n/* Same focus treatment as the Input/Select primitives: accent edge plus the\n system ring, so a field in this dialog and a field in Settings read\n identically — and both are actually visible (see Input.module.css). */\n.select:focus-visible,\n.input:focus-visible { border-color: var(--border-focus); box-shadow: var(--shadow-focus-ring); }\n\n.hint { font-size: var(--text-xs-size); line-height: var(--text-xs-line); color: var(--text-tertiary); }\n.error {\n padding-left: var(--space-3);\n border-left: 2px solid var(--status-danger-solid);\n color: var(--status-danger-fg);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n\n.actions { display: flex; justify-content: flex-end; gap: var(--space-2); }\n.cancel,\n.create {\n min-height: var(--control-h);\n padding: 0 var(--space-4);\n border: 1px solid transparent;\n border-radius: var(--radius-sm);\n font-size: var(--text-sm-size);\n font-weight: var(--font-weight-medium);\n transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);\n}\n.cancel { color: var(--text-secondary); }\n.cancel:hover { background: var(--bg-hover); color: var(--text-primary); }\n.cancel:active { background: var(--bg-active); }\n.create { background: var(--accent-600); color: var(--accent-contrast); }\n.create:hover:not(:disabled) { background: var(--accent-700); }\n.create:active:not(:disabled) { background: var(--accent-700); }\n.create:disabled { opacity: 0.4; cursor: not-allowed; }\n\n/* The chosen seat's capacity, directly under the picker: this is where the\n choice is made, so the cost of making it belongs here and not one section\n away. Indented on the engine-neutral hairline the error state also uses, so\n it reads as commentary on the field above rather than a new field. */\n.capacity {\n padding-left: var(--space-3);\n border-left: 1px solid var(--border-default);\n}\n\n/* Extra workspace folders: one row per folder, with its own Remove. */\n.rootRow {\n display: flex;\n gap: var(--space-2);\n align-items: center;\n margin-top: var(--space-2);\n}\n\n.rootRow .input { flex: 1 1 auto; min-width: 0; }\n\n.removeRoot,\n.addRoot {\n flex: none;\n padding: var(--space-1) var(--space-2);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-sm);\n background: var(--surface-raised);\n color: var(--text-default);\n font-size: var(--text-xs);\n cursor: pointer;\n}\n\n.addRoot { margin-top: var(--space-2); align-self: flex-start; }\n\n.removeRoot:hover,\n.addRoot:hover { border-color: var(--border-strong, var(--border-subtle)); }\n\n/* ---- V3.9 context --------------------------------------------------------\n The chosen model's context budget, mode, fit and seat facts. Hung off the\n same hairline as the capacity note above it: both are commentary on the\n seat field, not new fields of their own. */\n.context {\n display: grid;\n gap: var(--space-2);\n min-width: 0;\n padding-left: var(--space-3);\n border-left: 1px solid var(--border-default);\n}\n.contextHead {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--space-2);\n}\n.contextBudget {\n font-family: var(--font-display);\n font-size: var(--text-sm-size);\n font-variant-numeric: tabular-nums;\n color: var(--text-primary);\n}\n/* A model the pinned CLI cannot run: it blocks \"Start chat\", so it reads as a\n warning, in words — the disabled button alone would not say why. */\n.warn {\n padding-left: var(--space-3);\n border-left: 2px solid var(--status-warning-solid);\n color: var(--status-warning-fg);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n.fit { display: grid; gap: var(--space-1); min-width: 0; }\n.fitLine {\n display: flex;\n align-items: baseline;\n gap: var(--space-2);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n}\n/* The verdict is a WORD first; the tint only repeats it (DESIGN-V2 §6). */\n.fitBadge {\n flex: none;\n padding: 0 var(--space-2);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-full);\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n font-weight: var(--font-weight-semibold);\n line-height: 18px;\n white-space: nowrap;\n color: var(--text-secondary);\n}\n.fitBadge[data-fit='fits'] { border-color: var(--status-success-solid); color: var(--status-success-fg); background: var(--status-success-bg); }\n.fitBadge[data-fit='tight'] { border-color: var(--status-warning-solid); color: var(--status-warning-fg); background: var(--status-warning-bg); }\n.fitBadge[data-fit='expansive'] { border-color: var(--status-info-solid); color: var(--status-info-fg); background: var(--status-info-bg); }\n.fitBadge[data-fit='split'] { border-color: var(--status-danger-solid); color: var(--status-danger-fg); background: var(--status-danger-bg); }\n/* The seat's own facts: its pinned CLI and any note it carries (binary skew,\n catalog not fetched yet). Same quiet treatment as the resources panel. */\n.seatFacts {\n list-style: none;\n margin: 0;\n padding: 0;\n display: grid;\n gap: var(--space-1);\n}\n.seatFacts li {\n font-size: var(--text-2xs-size, 11px);\n line-height: var(--text-2xs-line, 14px);\n color: var(--text-tertiary);\n overflow-wrap: anywhere;\n}\n","/**\n * routes/verse/NewChatDialog.tsx — start a chat: pick a project (saved\n * projects + enrolled repos + any project a previous chat used, or \"Other\n * folder…\" with an absolute path), pick a seat + model, optionally title it.\n * Built on the shared Dialog primitive so focus trap / Escape / return-focus\n * come free.\n *\n * A folder typed here can be KEPT: \"Save as a project\" writes it to the\n * workspace registry and it is in this picker from then on. Before that\n * button existed the only folders that came back were ones a chat had already\n * been created on (core/verse/projects.ts remembers those), so a folder\n * opened and not chatted on was gone by the next launch.\n *\n * The native directory chooser is offered ALONGSIDE the text input, never\n * instead of it — the same console runs in a plain browser, where there is no\n * chooser at all.\n *\n * The seat list is where the choice actually GETS MADE, so the picked seat's\n * capacity is shown here too, under the picker: plan, the binding window as a\n * meter, its reset verbatim, and any credit balance — the same projection the\n * resources panel renders, so the two can never describe one seat differently.\n *\n * Opening the dialog also re-reads the roster. `bootstrap` has no SSE\n * invalidation and the account collector needs ~75s to warm, so a dialog\n * opened early in a session would otherwise show the cold, empty reading\n * taken at mount and present it as the state of the world.\n *\n * V3.9 — THE CONTEXT A CHAT WILL HAVE IS DECIDED HERE TOO (docs/VERSE-CONTEXT.md):\n *\n * - CONTEXT MODE. For a model with a real expansive budget (1M Claude\n * models, GPT-6 / GPT-5.6 on Codex) the operator picks Standard or\n * Expansive, defaulting to the seat's saved preference, and can make the\n * choice that seat's default. The mode is sent explicitly whenever there\n * was a choice, so the chat is created in exactly the mode on screen — even\n * if the preference changed underneath the open dialog.\n * - CONTEXT FIT. The chosen folders (or saved project) are sized by\n * GET /context-fit — git ls-files, bytes ÷ 4, zero spend — and every model\n * row says whether that code would fit, with the chosen model's verdict\n * explained in words (\"split\" says how: fan out, or narrow the folders).\n * Suggests, never switches: nothing here changes the mode on its own.\n * - SEAT FACTS. The chosen seat's pinned CLI version and its own notes\n * (binary skew, catalog not fetched yet) are shown in visible text; a\n * model the pinned CLI cannot run is refused here, with the reason, rather\n * than at turn time.\n */\nimport { useCallback, useEffect, useId, useMemo, useRef, useState, type FormEvent } from 'react';\nimport type { VerseCreateSessionRequest, VerseModelOption, VerseProject, VerseSeat, VerseWorkspace } from '../../data/api-types.js';\nimport type { VerseContextFit, VerseContextMode, VersePreferences } from '../../../core/verse/types.js';\nimport { budgetFor, hasExpansiveMode } from '../../../core/verse/context-math.js';\nimport { Dialog } from '../../components/primitives/Dialog.js';\nimport { Segmented } from '../../components/primitives/Segmented.js';\nimport { ApiError } from '../../data/client.js';\nimport { useRefetch } from '../../data/hooks.js';\nimport { fetchContextFit, fetchPreferences, updatePreferences } from './context/context-queries.js';\nimport { defaultWorktreeName, isValidWorktreeName, resolveChatFolder, WorktreeOption, type WorktreeValue } from './git/WorktreeOption.js';\nimport { describeGitError } from './git/git-model.js';\nimport { defaultSeatChoice, SeatSelector, type SeatChoice } from './SeatSelector.js';\nimport { LiveCapacityStrip } from './usage/CapacityStrip.js';\nimport {\n CONTEXT_MODE_LABEL,\n FIT_LABEL,\n fitMethodNote,\n contextModeDescription,\n effectiveBudget,\n fitExplanation,\n fitIsFloor,\n modelFit,\n modelUnavailableReason,\n noModeReason,\n resolveContextMode,\n seatCliLine,\n seatContextNotes,\n seatModelOption,\n} from './usage/context-model.js';\nimport { WINDOW_SOURCE_TEXT } from './verse-model.js';\nimport {\n defaultWorkspaceName,\n extraRootsCaveat,\n extraRootsNote,\n MAX_WORKSPACE_ROOTS,\n validateRootSet,\n workspaceSummary,\n} from './workspace-model.js';\nimport { createVerseWorkspace, verseBootstrapQuery, VerseMutationLockedError } from './verse-queries.js';\nimport { formatTokens } from './verse-readouts.js';\nimport { nativePickerAvailable, pickDirectory } from './folder-picker.js';\nimport styles from './NewChatDialog.module.css';\n\n/**\n * Prefix marking a select value as a WORKSPACE id rather than a folder path.\n * Safe for the same reason `OTHER` is: it starts with a NUL, and a filesystem\n * path can never contain one.\n */\nconst WORKSPACE_PREFIX = '\\0workspace:';\n\nconst OTHER = '\u0000other';\n\n/**\n * How long a typed path must sit still before it is sized. Sizing is cheap\n * and cached server-side (60 s), but a request per keystroke would still\n * spawn `git ls-files` for every prefix of a path being typed.\n */\nexport const FIT_DEBOUNCE_MS = 350;\n\n/**\n * Runs a write that needs the mutation token. ChatSection passes its own guard\n * (which opens the token dialog and resumes); resolving `null` means the\n * operator dismissed that dialog and nothing was written.\n */\nexport type RunMutation = <T>(reason: string, action: () => Promise<T>) => Promise<T | null>;\n\nconst runDirectly: RunMutation = (_reason, action) => action();\n\n/** How a \"make this the default\" write ended — carried as a value so no guard can swallow a failure. */\ntype DefaultSave = { ok: true; prefs: VersePreferences } | { ok: false; error: unknown };\n\ntype FitState =\n | { status: 'idle' }\n | { status: 'loading'; key: string }\n | { status: 'ready'; key: string; fit: VerseContextFit }\n | { status: 'error'; key: string; message: string };\n\n/** The seat's saved default mode for new chats; `standard` when none, or when preferences are unread. */\nexport function seatPreferredMode(prefs: VersePreferences | null, seatId: string): VerseContextMode {\n return prefs?.seats[seatId]?.contextMode ?? 'standard';\n}\n\n/**\n * Whether the create request carries `contextMode`, and which.\n *\n * Sent whenever the operator HAD a choice (the model has an expansive budget),\n * so the chat starts in exactly the mode on screen. Also sent — as `standard` —\n * when the seat's saved default is a mode this model does not have, so the\n * server's default resolution can never reject a model the operator was\n * allowed to pick. Otherwise omitted: the server's own default is the only\n * possible answer, and a model with no known window has no budget to name.\n */\nexport function requestContextMode(option: VerseModelOption | null, mode: VerseContextMode, preferred: VerseContextMode): VerseContextMode | null {\n if (!option) return null;\n if (hasExpansiveMode(option)) return resolveContextMode(option, mode);\n if (preferred !== 'standard' && budgetFor(option, 'standard') !== null) return 'standard';\n return null;\n}\n\n/** The operator-facing sentence for a failed read or write: the server's own words first. */\nfunction describeError(err: unknown): string {\n if (err instanceof VerseMutationLockedError) return 'Unlock actions with the mutation token to save a default.';\n if (err instanceof ApiError) return err.detail ?? err.message;\n return err instanceof Error ? err.message : String(err);\n}\n\nexport interface NewChatDialogProps {\n open: boolean;\n onClose: () => void;\n projects: readonly VerseProject[];\n seats: readonly VerseSeat[];\n /** Named multi-folder workspaces. Absent on an older server. */\n workspaces?: readonly VerseWorkspace[];\n /** Pre-fill (e.g. \"same project, different seat\" from the composer). */\n initialProjectPath?: string | null;\n initialSeat?: SeatChoice | null;\n busy?: boolean;\n error?: string | null;\n onCreate: (req: VerseCreateSessionRequest) => Promise<void> | void;\n /** Guard for the one write this dialog makes itself (a seat's default mode). */\n runMutation?: RunMutation;\n}\n\nexport function NewChatDialog({ open, onClose, projects, seats, workspaces = [], initialProjectPath, initialSeat, busy = false, error, onCreate, runMutation = runDirectly }: NewChatDialogProps) {\n const titleId = useId();\n const projectId = useId();\n const pathId = useId();\n const nameId = useId();\n const seatId = useId();\n const firstField = useRef<HTMLSelectElement>(null);\n const [projectChoice, setProjectChoice] = useState<string>('');\n const [customPath, setCustomPath] = useState('');\n const [seat, setSeat] = useState<SeatChoice | null>(null);\n const [title, setTitle] = useState('');\n const [localError, setLocalError] = useState<string | null>(null);\n /** Ad-hoc folders beyond the primary, when not binding to a workspace. */\n const [extraRoots, setExtraRoots] = useState<string[]>([]);\n /**\n * Projects saved from THIS dialog, held locally as well as sent.\n *\n * `workspaces` is refreshed by the cache invalidation the mutation triggers,\n * but that is a round trip. Keeping the created record here means the option\n * the operator just saved is in the picker on the very next paint — the\n * whole promise of the button is that the folder is now kept, so a second of\n * \"did that work?\" would undo it.\n */\n const [saved, setSaved] = useState<VerseWorkspace[]>([]);\n const [savingProject, setSavingProject] = useState(false);\n const [savedNote, setSavedNote] = useState<string | null>(null);\n /** The operator's standing choices; null until read (or when the read failed — then every seat defaults to Standard). */\n const [prefs, setPrefs] = useState<VersePreferences | null>(null);\n const [prefsError, setPrefsError] = useState<string | null>(null);\n /** An explicit mode pick for the chosen model; null = follow the seat's saved default. */\n const [modeChoice, setModeChoice] = useState<VerseContextMode | null>(null);\n const [savingDefault, setSavingDefault] = useState(false);\n const [defaultNote, setDefaultNote] = useState<{ ok: boolean; text: string } | null>(null);\n const [fitState, setFitState] = useState<FitState>({ status: 'idle' });\n /** \"Isolate in a worktree\" (C5): off by default; a name is offered once it is turned on. */\n const [worktree, setWorktree] = useState<WorktreeValue>({ enabled: false, name: '' });\n /** True while the worktree is being created, before the chat is. */\n const [isolating, setIsolating] = useState(false);\n /** Readings taken while this dialog is open, so flipping between folders does not re-ask. */\n const fitCache = useRef(new Map<string, VerseContextFit>());\n\n const sortedProjects = useMemo(() => [...projects].sort((a, b) => Number(b.enrolled) - Number(a.enrolled) || a.name.localeCompare(b.name)), [projects]);\n\n // Reset to the caller's pre-fill ONLY on the open transition. The pre-fill\n // inputs are read through a ref: `projects`/`seats` are fresh arrays on\n // every bootstrap refetch (which any turn finishing elsewhere triggers),\n // and re-running the reset on those would wipe a half-typed path or title.\n const prefill = useRef({ initialProjectPath, initialSeat, projects, seats, sortedProjects });\n prefill.current = { initialProjectPath, initialSeat, projects, seats, sortedProjects };\n useEffect(() => {\n if (!open) return;\n const { initialProjectPath: path, initialSeat: seatChoice, projects: known, seats: available, sortedProjects: sorted } = prefill.current;\n const knownPath = path && known.some((p) => p.path === path) ? path : null;\n setProjectChoice(knownPath ?? (path ? OTHER : sorted[0]?.path ?? OTHER));\n setCustomPath(knownPath ? '' : path ?? '');\n setSeat(normalizeChoice(seatChoice ?? null, available) ?? defaultSeatChoice(available));\n setTitle('');\n setLocalError(null);\n setExtraRoots([]);\n setSavedNote(null);\n setSavingProject(false);\n setSaved([]);\n setModeChoice(null);\n setDefaultNote(null);\n setSavingDefault(false);\n setWorktree({ enabled: false, name: defaultWorktreeName() });\n setIsolating(false);\n fitCache.current = new Map();\n }, [open]);\n\n // Preferences are re-read on every open: a default saved from another tab\n // (or by the CLI) must be what this dialog starts from.\n useEffect(() => {\n if (!open) return undefined;\n let cancelled = false;\n setPrefsError(null);\n fetchPreferences()\n .then((next) => {\n if (!cancelled) setPrefs(next);\n })\n .catch((err: unknown) => {\n if (cancelled) return;\n setPrefs(null);\n setPrefsError(describeError(err));\n });\n return () => {\n cancelled = true;\n };\n }, [open]);\n\n // Seats that arrive after the dialog opened (slow bootstrap) fill an empty\n // seat once, without touching anything the operator has typed.\n useEffect(() => {\n if (!open || seat !== null || seats.length === 0) return;\n setSeat(normalizeChoice(initialSeat ?? null, seats) ?? defaultSeatChoice(seats));\n }, [open, seat, seats, initialSeat]);\n\n // One re-read per open, not per render: the roster is worth a fresh look at\n // the moment a seat is about to be chosen, and worth nothing after that.\n const refetchBootstrap = useRefetch(verseBootstrapQuery);\n useEffect(() => {\n if (open) refetchBootstrap();\n }, [open, refetchBootstrap]);\n\n // The picker's saved-project list: what the server has, plus anything saved\n // in this dialog that the refreshed list has not caught up with yet.\n const savedProjects = useMemo(() => {\n const byId = new Map<string, VerseWorkspace>();\n for (const w of workspaces) byId.set(w.id, w);\n for (const w of saved) if (!byId.has(w.id)) byId.set(w.id, w);\n return [...byId.values()];\n }, [workspaces, saved]);\n\n const usingWorkspace = projectChoice.startsWith(WORKSPACE_PREFIX);\n const workspaceId = usingWorkspace ? projectChoice.slice(WORKSPACE_PREFIX.length) : null;\n const projectPath = usingWorkspace ? '' : projectChoice === OTHER ? customPath.trim() : projectChoice;\n const chosenSeat = seat === null ? null : seats.find((s) => s.id === seat.seatId) ?? null;\n const chosenOption = chosenSeat === null || seat === null ? null : seatModelOption(chosenSeat, seat.model);\n const disabledSeat = chosenSeat?.health.state === 'unavailable';\n // A model the pinned CLI cannot run is refused HERE, with its reason, not at\n // turn time — and a model the seat no longer lists is not a choice at all.\n const modelReason = chosenSeat !== null && chosenOption !== null ? modelUnavailableReason(chosenSeat, chosenOption) : null;\n // Isolation applies to an ad-hoc folder only: a saved project's roots are\n // fixed in the registry (the same reason extra folders are hidden for one).\n const offersWorktree = !usingWorkspace && projectPath.length > 0;\n const isolate = offersWorktree && worktree.enabled;\n const canCreate = !busy && !isolating && (usingWorkspace || projectPath.length > 0) && seat !== null && !disabledSeat\n && chosenOption !== null && modelReason === null && (!isolate || isValidWorktreeName(worktree.name));\n const chosenWorkspace = workspaceId === null ? null : savedProjects.find((w) => w.id === workspaceId) ?? null;\n\n // ---- context mode ------------------------------------------------------\n const preferredMode = seat === null ? 'standard' : seatPreferredMode(prefs, seat.seatId);\n const chatMode = resolveContextMode(chosenOption, modeChoice ?? preferredMode);\n const offersModes = hasExpansiveMode(chosenOption);\n const savedDefault = resolveContextMode(chosenOption, preferredMode);\n\n /** Every OTHER row shows its seat's default mode; the chosen row shows the mode picked for it. */\n const modeFor = useCallback((rowSeat: VerseSeat, model: VerseModelOption): VerseContextMode => {\n if (seat !== null && rowSeat.id === seat.seatId && model.id === seat.model) return chatMode;\n return resolveContextMode(model, seatPreferredMode(prefs, rowSeat.id));\n }, [seat, chatMode, prefs]);\n\n function chooseSeat(choice: SeatChoice) {\n setSeat(choice);\n // A mode picked for one model says nothing about another: follow the new\n // seat's saved default until the operator picks again.\n setModeChoice(null);\n setDefaultNote(null);\n }\n\n async function makeSeatDefault() {\n if (seat === null || chosenSeat === null) return;\n const mode = chatMode;\n setSavingDefault(true);\n setDefaultNote(null);\n try {\n // The action SETTLES as a value, never as a rejection. A guard that parks\n // the action behind the token prompt and runs it after the unlock may not\n // forward a rejection (ChatSection's `withToken` resolves only), and then\n // this function's catch/finally would never run: the button would sit on\n // \"Saving…\" for the rest of the dialog with no error shown. Catching\n // here makes both outcomes reach the code below whichever guard runs it.\n const outcome = await runMutation(`Saving ${CONTEXT_MODE_LABEL[mode]} as the default context mode for ${chosenSeat.label}.`,\n () => updatePreferences({ seatId: seat.seatId, contextMode: mode }).then(\n (saved): DefaultSave => ({ ok: true, prefs: saved }),\n (error: unknown): DefaultSave => ({ ok: false, error }),\n ));\n if (outcome === null) return; // the operator closed the token prompt: nothing was sent\n if (!outcome.ok) {\n setDefaultNote({ ok: false, text: describeError(outcome.error) });\n return;\n }\n setPrefs(outcome.prefs);\n setModeChoice(null);\n setDefaultNote({ ok: true, text: `New chats on ${chosenSeat.label} now start in ${CONTEXT_MODE_LABEL[mode]}.` });\n } catch (err) {\n // Only the guard itself can still throw here (e.g. a direct run with no token held).\n setDefaultNote({ ok: false, text: describeError(err) });\n } finally {\n setSavingDefault(false);\n }\n }\n\n // ---- context fit -------------------------------------------------------\n // What to size: the saved project by id (the server reads its roots), or\n // the ad-hoc folder set once it validates. Nothing is sized for a path that\n // is still being typed into something invalid.\n const fitRequest = useMemo((): { key: string; query: { workspaceId?: string; projectPath?: string; extraRoots?: string[] } } | null => {\n if (workspaceId !== null) return { key: `w:${workspaceId}`, query: { workspaceId } };\n if (usingWorkspace) return null;\n const validation = validateRootSet(projectPath, extraRoots);\n if (!validation.ok) return null;\n const [primary, ...rest] = validation.roots;\n return {\n key: `p:${validation.roots.join('\\n')}`,\n query: rest.length > 0 ? { projectPath: primary!, extraRoots: rest } : { projectPath: primary! },\n };\n }, [workspaceId, usingWorkspace, projectPath, extraRoots]);\n const fitRequestRef = useRef(fitRequest);\n fitRequestRef.current = fitRequest;\n const fitKey = fitRequest?.key ?? null;\n\n useEffect(() => {\n const request = fitRequestRef.current;\n if (!open || fitKey === null || request === null) {\n setFitState({ status: 'idle' });\n return undefined;\n }\n const cached = fitCache.current.get(fitKey);\n if (cached) {\n setFitState({ status: 'ready', key: fitKey, fit: cached });\n return undefined;\n }\n let cancelled = false;\n setFitState({ status: 'loading', key: fitKey });\n const timer = setTimeout(() => {\n fetchContextFit(request.query)\n .then((fit) => {\n fitCache.current.set(fitKey, fit);\n if (!cancelled) setFitState({ status: 'ready', key: fitKey, fit });\n })\n .catch((err: unknown) => {\n if (!cancelled) setFitState({ status: 'error', key: fitKey, message: describeError(err) });\n });\n }, FIT_DEBOUNCE_MS);\n return () => {\n cancelled = true;\n clearTimeout(timer);\n };\n }, [open, fitKey]);\n\n // The reading for the folders on screen NOW. Between a change and the\n // effect that re-reads, the held state belongs to the previous folders, so\n // it is shown as \"sizing\" rather than attributed to the new ones.\n const currentFit: FitState = fitKey === null\n ? { status: 'idle' }\n : fitState.status !== 'idle' && fitState.key === fitKey ? fitState : { status: 'loading', key: fitKey };\n const fit = currentFit.status === 'ready' ? currentFit.fit : null;\n\n // A seat whose CLI takes no additional-directory flag reaches only the\n // primary folder. Say that at the point the extra folders are chosen, rather\n // than letting the operator discover it from a diff that will not apply.\n // This holds for a SAVED project too — a project saved with three folders\n // still reaches one of them on a Grok seat, and the picker is the only place\n // that knows both facts at once.\n const adHocNote = extraRootsNote(chosenSeat?.engine ?? null, 1 + extraRoots.length);\n const workspaceCaveat = extraRootsCaveat(chosenSeat?.engine ?? null, chosenWorkspace?.roots.length ?? 0);\n\n /** The native chooser, where there is one. The text input never goes away. */\n const showPicker = nativePickerAvailable();\n async function choosePrimary() {\n const picked = await pickDirectory();\n if (picked !== null && picked.length > 0) {\n setProjectChoice(OTHER);\n setCustomPath(picked);\n }\n }\n async function chooseExtra(index: number) {\n const picked = await pickDirectory();\n if (picked !== null && picked.length > 0) {\n setExtraRoots(extraRoots.map((r, i) => (i === index ? picked : r)));\n }\n }\n\n /**\n * Keep the folder set that is on screen, so it is in this picker next time.\n *\n * Deliberately one press with no naming step: the folder's own name is very\n * nearly always the right one, and the project can be renamed from the\n * sidebar. A dialog inside a dialog to collect a name would cost more than\n * it is worth at the moment someone just wants to keep a folder.\n */\n async function saveProject() {\n const validation = validateRootSet(projectPath, extraRoots);\n if (!validation.ok) {\n setLocalError(validation.error);\n return;\n }\n setSavingProject(true);\n setLocalError(null);\n setSavedNote(null);\n try {\n const name = defaultWorkspaceName(validation.roots[0]!);\n const workspace = await createVerseWorkspace({ name, roots: validation.roots });\n setSaved((prev) => [...prev, workspace]);\n setProjectChoice(`${WORKSPACE_PREFIX}${workspace.id}`);\n setSavedNote(`Saved. “${workspace.name}” is in this list from now on.`);\n } catch (err) {\n setLocalError(err instanceof Error ? err.message : String(err));\n } finally {\n setSavingProject(false);\n }\n }\n\n function submit(event: FormEvent) {\n event.preventDefault();\n if (!seat) {\n setLocalError('Pick a seat first.');\n return;\n }\n if (chosenOption === null) {\n setLocalError('Pick a model this seat offers.');\n return;\n }\n if (modelReason !== null) {\n setLocalError(`${chosenOption.label} cannot run on this seat: ${modelReason}.`);\n return;\n }\n // Bound to a named workspace: the server reads the roots from the\n // registry, so no path is sent at all and the two cannot disagree.\n if (workspaceId !== null) {\n setLocalError(null);\n const req: VerseCreateSessionRequest = {\n // `projectPath` is filled in by the server from the workspace primary;\n // the field is required by the type, and the server rejects the pair.\n workspaceId,\n seatId: seat.seatId,\n model: seat.model,\n } as VerseCreateSessionRequest;\n delete (req as Partial<VerseCreateSessionRequest>).projectPath;\n const named = title.trim();\n if (named) req.title = named;\n const wsMode = requestContextMode(chosenOption, chatMode, preferredMode);\n if (wsMode !== null) req.contextMode = wsMode;\n void onCreate(req);\n return;\n }\n\n const validation = validateRootSet(projectPath, extraRoots);\n if (!validation.ok) {\n setLocalError(validation.error);\n return;\n }\n if (isolate && !isValidWorktreeName(worktree.name)) {\n setLocalError('Name the worktree with letters, digits, dots, dashes or underscores.');\n return;\n }\n setLocalError(null);\n const [primary, ...rest] = validation.roots;\n const req: VerseCreateSessionRequest = { projectPath: primary!, seatId: seat.seatId, model: seat.model };\n if (rest.length > 0) req.extraRoots = rest;\n const trimmed = title.trim();\n if (trimmed) req.title = trimmed;\n const mode = requestContextMode(chosenOption, chatMode, preferredMode);\n if (mode !== null) req.contextMode = mode;\n if (!isolate) {\n void onCreate(req);\n return;\n }\n void createIsolated(primary!, req);\n }\n\n /**\n * \"Isolate in a worktree\": create `~/.ashlr-worktrees/<repo>/<name>` on\n * `verse/<name>` FIRST (a git write — through the same token guard as every\n * other write this dialog makes), then start the chat in it. Only the\n * primary folder moves; extra folders stay where they are. A refusal (a\n * taken name, a folder that is not a repository, a repo with no commits)\n * is shown here and no chat is created.\n */\n async function createIsolated(primary: string, req: VerseCreateSessionRequest) {\n setIsolating(true);\n try {\n const outcome = await runMutation(`Creating the worktree ${worktree.name} (a new branch verse/${worktree.name}) for this chat.`,\n () => resolveChatFolder(primary, worktree).then(\n (folder): { ok: true; folder: string } | { ok: false; error: unknown } => ({ ok: true, folder }),\n (error: unknown): { ok: false; error: unknown } => ({ ok: false, error }),\n ));\n if (outcome === null) return; // the token prompt was dismissed: nothing was created\n if (!outcome.ok) {\n setLocalError(`The worktree could not be created: ${describeGitError(outcome.error)}`);\n return;\n }\n await onCreate({ ...req, projectPath: outcome.folder });\n } catch (err) {\n setLocalError(describeGitError(err));\n } finally {\n setIsolating(false);\n }\n }\n\n const message = localError ?? error ?? null;\n\n return (\n <Dialog open={open} onClose={onClose} titleId={titleId} title=\"New chat\" initialFocusRef={firstField} widthClassName={styles.width}>\n <form className={styles.form} onSubmit={submit} noValidate>\n <label className={styles.field} htmlFor={projectId}>\n <span className={styles.label}>Project</span>\n <select id={projectId} ref={firstField} value={projectChoice} onChange={(event) => setProjectChoice(event.target.value)} className={styles.select}>\n {/* The group exists only when there is something in it. An empty\n \"Saved projects\" heading is a promise the console cannot keep,\n and until this dialog could create one it was exactly that. */}\n {savedProjects.length > 0 ? (\n <optgroup label=\"Saved projects\">\n {savedProjects.map((w) => (\n <option key={w.id} value={`${WORKSPACE_PREFIX}${w.id}`}>\n {w.name} — {workspaceSummary(w)}\n </option>\n ))}\n </optgroup>\n ) : null}\n {sortedProjects.map((p) => (\n <option key={p.path} value={p.path}>{p.name}{p.enrolled ? '' : ' (recent)'} — {p.path}</option>\n ))}\n <option value={OTHER}>Other folder…</option>\n </select>\n </label>\n {projectChoice === OTHER && !usingWorkspace ? (\n <label className={styles.field} htmlFor={pathId}>\n <span className={styles.label}>Folder path</span>\n {/* The text input is unconditional: the console also runs in a\n plain browser, which has no directory chooser at all. The\n native button is an ADDITION where a shell can provide one. */}\n <div className={styles.rootRow}>\n <input id={pathId} className={styles.input} value={customPath} onChange={(event) => setCustomPath(event.target.value)}\n placeholder=\"/absolute/path/to/project\" autoComplete=\"off\" spellCheck={false} />\n {showPicker ? (\n <button type=\"button\" className={styles.addRoot} onClick={() => void choosePrimary()}>Choose folder…</button>\n ) : null}\n </div>\n </label>\n ) : null}\n {workspaceCaveat ? <p className={styles.hint}>{workspaceCaveat}</p> : null}\n {/* Extra folders, for the very common \"this service plus the shared\n library it depends on\". Hidden for a workspace, whose roots are\n defined once in the registry and must not be edited per chat —\n that is the difference between a workspace and an ad-hoc set. */}\n {usingWorkspace ? null : (\n <div className={styles.field}>\n <span className={styles.label}>\n Also include <span className={styles.optional}>optional</span>\n </span>\n {extraRoots.map((root, index) => (\n <div key={index} className={styles.rootRow}>\n <input\n className={styles.input}\n value={root}\n onChange={(event) => setExtraRoots(extraRoots.map((r, i) => (i === index ? event.target.value : r)))}\n placeholder=\"/absolute/path/to/another/folder\"\n aria-label={`Additional folder ${index + 1}`}\n autoComplete=\"off\"\n spellCheck={false}\n />\n {showPicker ? (\n <button\n type=\"button\"\n className={styles.removeRoot}\n onClick={() => void chooseExtra(index)}\n aria-label={`Choose additional folder ${index + 1}`}\n >Choose folder…</button>\n ) : null}\n <button\n type=\"button\"\n className={styles.removeRoot}\n onClick={() => setExtraRoots(extraRoots.filter((_, i) => i !== index))}\n aria-label={`Remove additional folder ${index + 1}`}\n >Remove</button>\n </div>\n ))}\n {extraRoots.length + 1 < MAX_WORKSPACE_ROOTS ? (\n <button type=\"button\" className={styles.addRoot} onClick={() => setExtraRoots([...extraRoots, ''])}>\n Add a folder\n </button>\n ) : null}\n {adHocNote ? <p className={styles.hint}>{adHocNote}</p> : null}\n {/* Keep this folder set. Nothing about a SAVED project can be\n edited per chat — that is the difference between a project and\n an ad-hoc set — so the offer appears only on the ad-hoc path. */}\n <div className={styles.rootRow}>\n <button type=\"button\" className={styles.addRoot} onClick={() => void saveProject()}\n disabled={savingProject || projectPath.length === 0}>\n {savingProject ? 'Saving…' : 'Save as a project'}\n </button>\n <span className={styles.hint}>Keeps these folders in the list above. No chat needed first.</span>\n </div>\n </div>\n )}\n {/* OUTSIDE the ad-hoc block on purpose: saving switches the picker to\n the project it just created, which unmounts that block — and the\n confirmation that the folder was kept is exactly what must not\n disappear at that moment. */}\n {savedNote ? <p role=\"status\" className={styles.hint}>{savedNote}</p> : null}\n\n {offersWorktree ? (\n <WorktreeOption repoName={folderName(projectPath)} value={worktree} onChange={setWorktree} disabled={isolating || busy} />\n ) : null}\n\n <SeatSelector id={seatId} seats={seats} value={seat} onChange={chooseSeat}\n workingSetTokens={fit?.totalEstTokens ?? null} modeFor={modeFor} />\n {/* THE shared capacity view (usage/CapacityStrip, SPEC-310C §4), for\n the chosen seat. Full density on purpose: the verbatim reset and\n any credit balance are what decide \"can I start this now\", and\n the compact row drops both. */}\n {chosenSeat === null ? null : (\n <div className={styles.capacity}>\n <LiveCapacityStrip seats={seats} seatIds={[chosenSeat.id]} local=\"each\" headline={false}\n title={`${chosenSeat.label} capacity`} />\n </div>\n )}\n {chosenSeat === null || chosenOption === null ? null : (\n <ContextChoice\n seat={chosenSeat}\n option={chosenOption}\n unavailableReason={modelReason}\n mode={chatMode}\n offersModes={offersModes}\n savedDefault={savedDefault}\n prefsLoaded={prefs !== null}\n prefsError={prefsError}\n onMode={(mode) => {\n setModeChoice(mode);\n setDefaultNote(null);\n }}\n savingDefault={savingDefault}\n defaultNote={defaultNote}\n onMakeDefault={() => void makeSeatDefault()}\n fitState={currentFit}\n />\n )}\n {seats.length === 0 ? <p className={styles.hint}>No seats yet — connect an account or start Ollama, then reload.</p> : null}\n <label className={styles.field} htmlFor={nameId}>\n <span className={styles.label}>Title <span className={styles.optional}>optional</span></span>\n <input id={nameId} className={styles.input} value={title} onChange={(event) => setTitle(event.target.value)}\n placeholder=\"Defaults to your first message\" maxLength={120} />\n </label>\n {message ? <p role=\"alert\" className={styles.error}>{message}</p> : null}\n <div className={styles.actions}>\n <button type=\"button\" className={styles.cancel} onClick={onClose}>Cancel</button>\n <button type=\"submit\" className={styles.create} disabled={!canCreate}>\n {isolating ? 'Creating worktree…' : busy ? 'Creating…' : 'Start chat'}\n </button>\n </div>\n </form>\n </Dialog>\n );\n}\n\n/** The last segment of a folder path — the repository name the worktree hint shows. */\nfunction folderName(path: string): string {\n const parts = path.replace(/[\\\\/]+$/, '').split(/[\\\\/]/);\n return parts[parts.length - 1] || path;\n}\n\n/**\n * A pre-fill resolved against the CURRENT roster: an aliased model id (a chat\n * remembered on `claude-opus-5.5`) becomes the seat's own spelling, so the\n * picker shows the choice instead of \"Choose a seat…\". Nothing else changes —\n * a remembered model the pinned CLI cannot run stays chosen, so its reason is\n * shown rather than the choice being silently swapped for another.\n */\nexport function normalizeChoice(choice: SeatChoice | null, seats: readonly VerseSeat[]): SeatChoice | null {\n if (choice === null) return null;\n const seat = seats.find((s) => s.id === choice.seatId);\n const option = seatModelOption(seat, choice.model);\n return option === null ? choice : { seatId: choice.seatId, model: option.id };\n}\n\ninterface ContextChoiceProps {\n seat: VerseSeat;\n option: VerseModelOption;\n unavailableReason: string | null;\n mode: VerseContextMode;\n offersModes: boolean;\n /** The seat's saved default, resolved for this model. */\n savedDefault: VerseContextMode;\n prefsLoaded: boolean;\n prefsError: string | null;\n onMode: (mode: VerseContextMode) => void;\n savingDefault: boolean;\n defaultNote: { ok: boolean; text: string } | null;\n onMakeDefault: () => void;\n fitState: FitState;\n}\n\n/**\n * The chosen model's context, under the picker: its budget and provenance,\n * the mode selector (only where a real second budget exists), the fit verdict\n * for the chosen folders, and the seat's pinned CLI and notes.\n */\nfunction ContextChoice({\n seat,\n option,\n unavailableReason,\n mode,\n offersModes,\n savedDefault,\n prefsLoaded,\n prefsError,\n onMode,\n savingDefault,\n defaultNote,\n onMakeDefault,\n fitState,\n}: ContextChoiceProps) {\n const labelId = useId();\n const budget = effectiveBudget(option, mode);\n const cli = seatCliLine(seat);\n const notes = seatContextNotes(seat);\n const verdict = fitState.status === 'ready' ? modelFit(fitState.fit.totalEstTokens, option, mode, seat.engine) : null;\n\n return (\n <div className={styles.context} role=\"group\" aria-labelledby={labelId}>\n <div className={styles.contextHead}>\n <span id={labelId} className={styles.label}>Context</span>\n <span className={styles.contextBudget}>\n {budget === null\n ? 'Window unknown'\n : `${formatTokens(budget.contextWindow)} window${budget.autoCompactAt === null ? '' : ` · compacts ≈${formatTokens(budget.autoCompactAt)}`}`}\n </span>\n </div>\n {budget !== null && option.windowSource ? (\n <p className={styles.hint}>Window {WINDOW_SOURCE_TEXT[option.windowSource]}.</p>\n ) : null}\n\n {unavailableReason !== null ? (\n <p className={styles.warn}>{option.label} cannot run on this seat: {unavailableReason}. Pick another model.</p>\n ) : null}\n\n {offersModes ? (\n <>\n <Segmented<VerseContextMode>\n aria-label=\"Context mode\"\n size=\"sm\"\n value={mode}\n onChange={onMode}\n options={(['standard', 'expansive'] as const).map((m) => {\n const b = budgetFor(option, m);\n return {\n value: m,\n label: b === null ? CONTEXT_MODE_LABEL[m] : `${CONTEXT_MODE_LABEL[m]} · ≈${formatTokens(b.autoCompactAt ?? b.contextWindow)}`,\n ariaLabel: CONTEXT_MODE_LABEL[m],\n };\n })}\n />\n <p className={styles.hint}>{contextModeDescription(seat.engine, option, mode)}</p>\n {prefsLoaded && mode !== savedDefault ? (\n <div className={styles.rootRow}>\n <button type=\"button\" className={styles.addRoot} onClick={onMakeDefault} disabled={savingDefault}>\n {savingDefault ? 'Saving…' : `Make ${CONTEXT_MODE_LABEL[mode]} the default for ${seat.label}`}\n </button>\n </div>\n ) : null}\n {defaultNote !== null ? (\n <p role={defaultNote.ok ? 'status' : 'alert'} className={defaultNote.ok ? styles.hint : styles.error}>{defaultNote.text}</p>\n ) : null}\n {prefsError !== null ? (\n <p className={styles.hint}>Saved defaults could not be read ({prefsError}); this chat starts in {CONTEXT_MODE_LABEL[mode]} unless you pick otherwise.</p>\n ) : null}\n </>\n ) : (\n <p className={styles.hint}>{noModeReason(seat.engine, option)}</p>\n )}\n\n <div className={styles.fit} aria-live=\"polite\">\n {fitState.status === 'idle' ? null\n : fitState.status === 'loading' ? <p className={styles.hint}>Sizing the chosen folders…</p>\n : fitState.status === 'error' ? <p className={styles.hint}>Could not size the chosen folders: {fitState.message}</p>\n : verdict === null ? (\n <p className={styles.hint}>\n ~{formatTokens(fitState.fit.totalEstTokens)} tokens of tracked code; this model&rsquo;s budget is unknown, so no fit is claimed.\n </p>\n ) : (\n <>\n <p className={styles.fitLine}>\n <span className={styles.fitBadge} data-fit={verdict}>{FIT_LABEL[verdict]}</span>\n <span>{fitExplanation({ verdict, tokens: fitState.fit.totalEstTokens, option, mode, floor: fitIsFloor(fitState.fit) })}</span>\n </p>\n <p className={styles.hint}>{fitMethodNote(seat.engine)}</p>\n </>\n )}\n </div>\n\n {cli === null && notes.length === 0 ? null : (\n <ul className={styles.seatFacts} aria-label={`${seat.label} facts`}>\n {cli === null ? null : <li>Runs {cli}.</li>}\n {notes.map((note) => <li key={note}>{note}</li>)}\n </ul>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ ._card_10xpw_14{z-index:var(--z-dialog);left:calc(var(--rail-width) + var(--space-5));right:auto;bottom:calc(var(--space-5) + env(safe-area-inset-bottom,0px));width:min(420px, calc(100vw - var(--rail-width) - var(--space-5) * 2));max-height:min(640px, calc(100vh - var(--space-8)));background:var(--bg-surface-raised);border:1px solid var(--border-default);border-radius:var(--radius-lg);box-shadow:var(--shadow-dialog);animation:_onboarding-in_10xpw_1 var(--duration-base) var(--ease-decelerate);flex-direction:column;display:flex;position:fixed;overflow:hidden}@keyframes _onboarding-in_10xpw_1{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}._head_10xpw_56{align-items:flex-start;gap:var(--space-2);padding:var(--space-4) var(--space-4) var(--space-3);border-bottom:1px solid var(--border-subtle);display:flex}._headText_10xpw_64{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}._eyebrow_10xpw_72{font-family:var(--font-display);font-size:var(--text-2xs-size);letter-spacing:var(--tracking-label);text-transform:uppercase;color:var(--text-tertiary)}._title_10xpw_80{font-family:var(--font-display);font-size:var(--text-md-size);font-weight:var(--font-weight-semibold);letter-spacing:var(--tracking-display);color:var(--text-primary)}._subtitle_10xpw_88{font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);color:var(--text-secondary)}._body_10xpw_96{min-height:0;padding:var(--space-4);gap:var(--space-3);flex-direction:column;flex:1;align-items:flex-start;display:flex;overflow-y:auto}._lead_10xpw_107{font-size:var(--text-sm-size);line-height:var(--text-sm-line-relaxed);color:var(--text-primary)}._aside_10xpw_113,._caveat_10xpw_114{font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);color:var(--text-tertiary)}._caveat_10xpw_114{border-left:2px solid var(--border-strong);padding-left:var(--space-3)}._kbd_10xpw_125{font-family:var(--font-mono);font-size:var(--text-2xs-size);border:1px solid var(--border-default);border-radius:var(--radius-xs);background:var(--bg-surface);color:var(--text-secondary);white-space:nowrap;padding:1px 5px}._sections_10xpw_138,._findings_10xpw_139{flex-direction:column;width:100%;margin:0;padding:0;list-style:none;display:flex}._sectionRow_10xpw_148{align-items:flex-start;gap:var(--space-3);padding:var(--space-2) 0;border-top:1px solid var(--border-subtle);display:flex}._sectionRow_10xpw_148:first-child{border-top:none}._sectionIcon_10xpw_160,._localIcon_10xpw_161{width:var(--control-h-xs);height:var(--control-h-xs);color:var(--text-tertiary);flex:none;justify-content:center;align-items:center;display:inline-flex}._sectionText_10xpw_173{flex-direction:column;gap:2px;min-width:0;display:flex}._sectionName_10xpw_180{font-family:var(--font-display);font-size:var(--text-xs-size);font-weight:var(--font-weight-semibold);color:var(--text-primary);align-items:center;gap:var(--space-2);display:inline-flex}._sectionBlurb_10xpw_190{font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);color:var(--text-secondary)}._finding_10xpw_139{gap:var(--space-1);padding:var(--space-3) 0;border-top:1px solid var(--border-subtle);flex-direction:column;display:flex}._finding_10xpw_139:first-child{border-top:none}._findingHead_10xpw_210{justify-content:space-between;align-items:center;gap:var(--space-2);flex-wrap:wrap;display:flex}._stopName_10xpw_218{font-family:var(--font-display);font-size:var(--text-sm-size);font-weight:var(--font-weight-semibold);color:var(--text-primary)}._findingDetail_10xpw_225{font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);color:var(--text-secondary)}._findingNote_10xpw_231{font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);color:var(--text-tertiary)}._findingFix_10xpw_237{align-items:baseline;gap:var(--space-2);flex-wrap:wrap;margin-top:2px;display:flex}._fixLabel_10xpw_245{font-family:var(--font-display);font-size:var(--text-2xs-size);letter-spacing:var(--tracking-label);text-transform:uppercase;color:var(--text-tertiary);flex:none}._fixText_10xpw_254{font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);color:var(--text-secondary)}._code_10xpw_260{font-family:var(--font-mono);font-size:var(--text-xs-size);border:1px solid var(--border-subtle);border-radius:var(--radius-xs);background:var(--bg-code,var(--bg-surface));color:var(--text-primary);overflow-wrap:anywhere;padding:2px 6px}._tone_10xpw_276{flex:none;align-items:center;gap:5px;display:inline-flex}._toneLabel_10xpw_283{font-family:var(--font-display);font-size:var(--text-2xs-size);letter-spacing:var(--tracking-label);text-transform:uppercase;color:var(--text-secondary)}._tone_10xpw_276[data-tone=ok]{color:var(--status-success-fg,var(--text-secondary))}._tone_10xpw_276[data-tone=attention]{color:var(--status-warning-fg,var(--text-secondary))}._tone_10xpw_276[data-tone=unknown]{color:var(--text-tertiary)}._foot_10xpw_305{justify-content:space-between;align-items:center;gap:var(--space-3);padding:var(--space-3) var(--space-4);border-top:1px solid var(--border-subtle);background:var(--bg-surface);display:flex}._pips_10xpw_315{gap:5px;margin:0;padding:0;list-style:none;display:flex}._pip_10xpw_315{background:var(--border-default);border-radius:1px;width:14px;height:2px}._pip_10xpw_315[data-state=current]{background:var(--accent-500)}._pip_10xpw_315[data-state=done]{background:var(--border-strong)}._actions_10xpw_338{align-items:center;gap:var(--space-2);display:flex}@media (max-width:900px){._card_10xpw_14{left:calc(var(--rail-width) + var(--space-3));width:min(420px, calc(100vw - var(--rail-width) - var(--space-3) * 2));right:auto}}._chip_10xpw_362{z-index:var(--z-dialog);left:calc(var(--rail-width) + var(--space-5));bottom:calc(var(--space-5) + env(safe-area-inset-bottom,0px));max-width:calc(100vw - var(--rail-width) - var(--space-5) * 2);height:var(--control-h-sm);background:var(--bg-surface-raised);border:1px solid var(--border-default);border-radius:var(--radius-full);box-shadow:var(--shadow-sm);animation:_onboarding-in_10xpw_1 var(--duration-base) var(--ease-decelerate);align-items:center;display:inline-flex;position:fixed}._chipOpen_10xpw_378,._chipDismiss_10xpw_379{height:100%;color:var(--text-secondary);cursor:pointer;font:inherit;background:0 0;border:none;align-items:center;display:inline-flex}._chipOpen_10xpw_378{gap:var(--space-2);min-width:0;padding:0 var(--space-2) 0 var(--space-3);border-radius:var(--radius-full) 0 0 var(--radius-full);font-size:var(--text-xs-size);white-space:nowrap}._chipLabel_10xpw_399{font-family:var(--font-display);font-weight:var(--font-weight-semibold);color:var(--text-primary);text-overflow:ellipsis;overflow:hidden}._chipCount_10xpw_407{font-family:var(--font-mono);font-size:var(--text-2xs-size);color:var(--text-tertiary);font-variant-numeric:tabular-nums}._chipDismiss_10xpw_379{width:var(--control-h-sm);border-left:1px solid var(--border-subtle);border-radius:0 var(--radius-full) var(--radius-full) 0;color:var(--text-tertiary);flex:none;justify-content:center}._chipOpen_10xpw_378:hover,._chipDismiss_10xpw_379:hover{background:var(--bg-hover);color:var(--text-primary)}._card_10xpw_14:focus:not(:focus-visible){outline:none}@media (max-width:900px){._chip_10xpw_362{left:calc(var(--rail-width) + var(--space-3));max-width:calc(100vw - var(--rail-width) - var(--space-3) * 2)}}
@@ -0,0 +1,2 @@
1
+ import{a as e,c as t,n}from"./index-QesfXBsb.js";import{p as r}from"./global-CNNGMril.js";import{M as i,at as a,lt as o,q as s,z as c}from"./VerseConsoleApp-BCY5uSok.js";import{y as l}from"./format-Dk4Fmxax.js";import{r as u}from"./CapacityStrip-CkFz5vq2.js";import{t as d}from"./Button-BhO-WKPp.js";import{C as f,a as p,b as m,f as h,i as g,o as _,r as v,s as y,t as b,u as x}from"./icons-0haWy6nh.js";import{s as S}from"./verse-icons-DndgEgKS.js";import{t as C}from"./command-catalog-CF0cQQac.js";import{n as w}from"./surface-data-CchClvHo.js";import"./primitives-D0Fb3TtS.js";import{a as T,s as E}from"./usage-queries-D1SU1t7r.js";import{r as D}from"./AutonomyOffState-B5eEkmiz.js";import{a as O,o as k}from"./authority-model-BFuPezSo.js";import{copyAutonomySetupCommand as A}from"./copy-setup-CqRSfELB.js";import{a as j,i as M,n as N,r as P,s as F,t as I}from"./useOnboarding-CujRS6PK.js";var L=t(e(),1),R=[{id:`welcome`,title:`Welcome to Verse`,subtitle:`Five sections, one rail.`},{id:`accounts`,title:`Your seats`,subtitle:`Which provider accounts this machine can actually dispatch to right now.`},{id:`local`,title:`Local runtime`,subtitle:`Whether there is a model on this machine, and what that changes.`},{id:`autonomy`,title:`Turn on autonomy`,subtitle:`It stays off until you set it up. Turning it down is always one click.`},{id:`stops`,title:`Three ways to stop`,subtitle:`They do not have the same blast radius. This is the one screen that says so.`},{id:`finish`,title:`Make it yours`,subtitle:`Theme, accent, density and font live in Settings. Then start a chat.`}];function z(e){return Number.isFinite(e)?Math.min(R.length-1,Math.max(0,Math.trunc(e))):0}var B=`Local seats cost nothing and consume no provider quota, so the autonomous loop can keep working after a cloud window is used up.`,V=`Without one, every turn and every autonomous tick spends a provider account, and a used-up window stops the work.`;function H(e){if(e.loading)return{tone:`unknown`,state:`checking`,summary:`Probing the local runtimes on this machine…`,meaning:B,fix:null,modelCount:0,toolCapableCount:0,stale:!1};if(!e.snapshot)return{tone:`unknown`,state:`not reported`,summary:`This server does not report local runtimes, so Verse cannot say whether one is available here.`,meaning:V,fix:e.unavailableReason,modelCount:0,toolCapableCount:0,stale:!1};let t=e.snapshot.models,n=t.filter(e=>e.supportsTools===!0).length,r=e.snapshot.runtimes.some(e=>e.stale);return e.snapshot.reachable?t.length===0?{tone:`attention`,state:`no models`,summary:`A local runtime answered, but it has no models installed.`,meaning:V,fix:`Pull a model into the runtime, then press Refresh in Usage.`,modelCount:0,toolCapableCount:0,stale:r}:{tone:`ok`,state:r?`available (retained reading)`:`available`,summary:`${t.length} local ${t.length===1?`model`:`models`} available`+(n>0?`, ${n} of them tool-capable.`:`, none of them tool-capable.`)+(r?` Last known reading.`:``),meaning:n>0?B:`${B} A model that cannot call tools can answer, but cannot run an agentic turn.`,fix:null,modelCount:t.length,toolCapableCount:n,stale:r}:{tone:`attention`,state:`unreachable`,summary:`No local runtime answered. Verse cannot tell whether one is not running or not installed — the probe only knows it got no answer.`,meaning:V,fix:`Start Ollama (or LM Studio) and press Refresh in Usage. If neither is installed, everything still works — it all runs on the cloud seats.`,modelCount:0,toolCapableCount:0,stale:r}}var U=[{name:`Pause`,scope:`Halts autonomous dispatch only. A running loop parks instead of exiting.`,limit:`Your own chats and the agent’s write tools keep working.`,reversible:`Reversible in one click, with no restart and no confirmation.`,tone:`ok`},{name:`Stop loop`,scope:`Stops the daemon — and engages the GLOBAL kill switch while doing it.`,limit:`That means it also refuses the agent’s own write tools, exactly like the emergency control.`,reversible:`Reversible, but confirm-guarded. For an ordinary halt, use Pause.`,tone:`attention`},{name:`Emergency stop`,scope:`Engages the global kill switch (~/.ashlr/KILL) directly.`,limit:`Every mutating path refuses: the loop, dispatch, and the agent’s own write tools.`,reversible:`Reversible, confirm-guarded, and deliberately separated from the other two.`,tone:`attention`}],W={card:`_card_10xpw_14`,"onboarding-in":`_onboarding-in_10xpw_1`,head:`_head_10xpw_56`,headText:`_headText_10xpw_64`,eyebrow:`_eyebrow_10xpw_72`,title:`_title_10xpw_80`,subtitle:`_subtitle_10xpw_88`,body:`_body_10xpw_96`,lead:`_lead_10xpw_107`,aside:`_aside_10xpw_113`,caveat:`_caveat_10xpw_114`,kbd:`_kbd_10xpw_125`,sections:`_sections_10xpw_138`,findings:`_findings_10xpw_139`,sectionRow:`_sectionRow_10xpw_148`,sectionIcon:`_sectionIcon_10xpw_160`,localIcon:`_localIcon_10xpw_161`,sectionText:`_sectionText_10xpw_173`,sectionName:`_sectionName_10xpw_180`,sectionBlurb:`_sectionBlurb_10xpw_190`,finding:`_finding_10xpw_139`,findingHead:`_findingHead_10xpw_210`,stopName:`_stopName_10xpw_218`,findingDetail:`_findingDetail_10xpw_225`,findingNote:`_findingNote_10xpw_231`,findingFix:`_findingFix_10xpw_237`,fixLabel:`_fixLabel_10xpw_245`,fixText:`_fixText_10xpw_254`,code:`_code_10xpw_260`,tone:`_tone_10xpw_276`,toneLabel:`_toneLabel_10xpw_283`,foot:`_foot_10xpw_305`,pips:`_pips_10xpw_315`,pip:`_pip_10xpw_315`,actions:`_actions_10xpw_338`,chip:`_chip_10xpw_362`,chipOpen:`_chipOpen_10xpw_378`,chipDismiss:`_chipDismiss_10xpw_379`,chipLabel:`_chipLabel_10xpw_399`,chipCount:`_chipCount_10xpw_407`},G=n();function K({tone:e,label:t}){let n=e===`ok`?v:e===`attention`?b:x;return(0,G.jsxs)(`span`,{className:W.tone,"data-tone":e,children:[(0,G.jsx)(n,{size:13,"aria-hidden":`true`,focusable:`false`}),(0,G.jsx)(`span`,{className:W.toneLabel,children:t})]})}function q({children:e}){return(0,G.jsx)(`div`,{className:W.body,children:e})}function J(){return(0,G.jsxs)(q,{children:[(0,G.jsx)(`p`,{className:W.lead,children:`Verse runs your chats and this machine’s agent fleet from one local server.`}),(0,G.jsx)(`ul`,{className:W.sections,children:s.map((e,t)=>{let n=S[e.id];return(0,G.jsxs)(`li`,{className:W.sectionRow,children:[(0,G.jsx)(`span`,{className:W.sectionIcon,"aria-hidden":`true`,children:(0,G.jsx)(n,{})}),(0,G.jsxs)(`span`,{className:W.sectionText,children:[(0,G.jsxs)(`span`,{className:W.sectionName,children:[e.label,` `,(0,G.jsxs)(`kbd`,{className:W.kbd,children:[`⌘`,t+1]})]}),(0,G.jsx)(`span`,{className:W.sectionBlurb,children:e.blurb})]})]},e.id)})}),(0,G.jsxs)(`p`,{className:W.sectionBlurb,children:[(0,G.jsx)(`kbd`,{className:W.kbd,children:`⌘K`}),` runs anything by name · `,(0,G.jsx)(`kbd`,{className:W.kbd,children:`⌘J`}),` is everything waiting on you · Settings, Apps & Accounts and Usage are under the gear.`]})]})}function Y(){return(0,G.jsxs)(q,{children:[(0,G.jsx)(u,{density:`compact`,headline:!0,local:`collapse`,labelledBy:`verse-onboarding-title`,emptyText:`No seats reported yet. Connect an account in Apps & Accounts, or start Ollama for local models.`,renderActions:e=>e.connection?.fixCommand?(0,G.jsxs)(`p`,{className:W.findingFix,children:[(0,G.jsx)(`span`,{className:W.fixLabel,children:`Fix`}),(0,G.jsx)(`code`,{className:W.code,children:e.connection.fixCommand.join(` `)})]}):null}),(0,G.jsx)(`p`,{className:W.aside,children:`Every window, reset and reserve lives in Apps & Accounts, under the gear.`})]})}function X(){let e=r(T),t=(0,L.useMemo)(()=>{let t=e.data?.reason??e.error?.message??null;return H({snapshot:e.data?.available?E(e.data.raw):null,loading:e.data===void 0&&e.status!==`error`,unavailableReason:t===null?null:l(t)})},[e.data,e.status,e.error]);return(0,G.jsxs)(q,{children:[(0,G.jsxs)(`div`,{className:W.findingHead,children:[(0,G.jsx)(`span`,{className:W.localIcon,"aria-hidden":`true`,children:(0,G.jsx)(y,{size:15})}),(0,G.jsx)(K,{tone:t.tone,label:t.state})]}),(0,G.jsx)(`p`,{className:W.lead,children:t.summary}),(0,G.jsx)(`p`,{className:W.findingDetail,children:t.meaning}),t.fix?(0,G.jsxs)(`p`,{className:W.findingFix,children:[(0,G.jsx)(`span`,{className:W.fixLabel,children:`Fix`}),(0,G.jsx)(`span`,{className:W.fixText,children:t.fix})]}):null]})}function Z(e){return e===`success`?`ok`:e===`warning`||e===`danger`?`attention`:`unknown`}function Q(){let e=r(w),[t,n]=(0,L.useState)(null),i=e.data?.value??null,a=e.data===void 0&&e.status!==`error`,s=k(i),l=O(i,Date.now()),u=D(i?.grant.state===`none`),f=!i||i.grant.state===`none`&&u!==`ready`,p=a?`Reading the autonomy state…`:i?l.detail:e.data?.reason??e.error?.message??`The autonomy state could not be read.`;return(0,G.jsxs)(q,{children:[(0,G.jsxs)(`div`,{className:W.findingHead,children:[(0,G.jsx)(`span`,{className:W.stopName,children:`Right now`}),(0,G.jsx)(K,{tone:a?`unknown`:Z(s.tone),label:a?`checking`:i?s.text:`not reported`})]}),(0,G.jsx)(`p`,{className:W.findingDetail,children:p}),(0,G.jsxs)(`p`,{className:W.lead,children:[`The switch on Command `,(0,G.jsx)(`kbd`,{className:W.kbd,children:`⌘1`}),` — Off, Propose, Autonomous — decides what the fleet may do on its own. Raising it past your grant asks for Touch ID; lowering it never does.`]}),f?(0,G.jsxs)(G.Fragment,{children:[(0,G.jsxs)(`div`,{className:W.findingFix,children:[(0,G.jsx)(`span`,{className:W.fixLabel,children:`Set up`}),(0,G.jsx)(`code`,{className:W.code,children:C}),(0,G.jsx)(d,{variant:`subtle`,size:`sm`,icon:(0,G.jsx)(_,{size:13}),onClick:()=>{A().then(n)},children:t?`Copied`:`Copy`})]}),(0,G.jsx)(`p`,{className:W.aside,role:t===!1?`alert`:void 0,children:t===!1?`The clipboard is not available here — select the command and copy it by hand.`:`Run it in a terminal. It stops for what only you can do — sudo, Touch ID, GitHub — and --dry-run prints every step first.`})]}):l.action?(0,G.jsx)(d,{variant:`subtle`,icon:(0,G.jsx)(h,{size:14}),onClick:()=>c(`autonomy.grant`,{via:`button`}),children:l.action===`re-approve`?`Re-approve grant…`:`Approve grant…`}):(0,G.jsx)(d,{variant:`subtle`,icon:(0,G.jsx)(h,{size:14}),onClick:()=>o(`command`),children:`Open Command`}),(0,G.jsxs)(`p`,{className:W.aside,children:[(0,G.jsx)(`kbd`,{className:W.kbd,children:`⌘K`}),` “Autonomy: …” and “Approve grant…” work from any surface.`]})]})}function $(){return(0,G.jsxs)(q,{children:[(0,G.jsxs)(`p`,{className:W.lead,children:[`Fleet `,(0,G.jsx)(`kbd`,{className:W.kbd,children:`⌘2`}),` has three stop controls. They are not interchangeable, and the difference is the most important thing on this screen.`]}),(0,G.jsx)(`ul`,{className:W.findings,children:U.map(e=>(0,G.jsxs)(`li`,{className:W.finding,children:[(0,G.jsxs)(`div`,{className:W.findingHead,children:[(0,G.jsx)(`span`,{className:W.stopName,children:e.name}),(0,G.jsx)(K,{tone:e.tone,label:e.tone===`ok`?`narrow`:`global`})]}),(0,G.jsx)(`p`,{className:W.findingDetail,children:e.scope}),(0,G.jsx)(`p`,{className:W.findingDetail,children:e.limit}),(0,G.jsx)(`p`,{className:W.findingNote,children:e.reversible})]},e.name))})]})}function ee(){return(0,G.jsxs)(q,{children:[(0,G.jsxs)(`p`,{className:W.lead,children:[`Settings `,(0,G.jsx)(`kbd`,{className:W.kbd,children:`⌘,`}),` carries theme, accent hue, density, display font, corner radius and reduced motion. Every change applies as you make it — there is no save button.`]}),(0,G.jsx)(d,{variant:`subtle`,icon:(0,G.jsx)(m,{size:14}),onClick:()=>o(`settings`),children:`Open Settings`}),(0,G.jsx)(`p`,{className:W.aside,children:`You can replay this tour any time from Settings → Onboarding.`})]})}var te=[J,Y,X,Q,$,ee];function ne(){let{open:e,expanded:t,step:n}=I(),r=z(n),o=R[r],s=te[r],c=r===R.length-1,l=R.length,u=(0,L.useCallback)(()=>M(),[]),m=(0,L.useRef)(null),h=(0,L.useRef)(null),_=(0,L.useRef)(!1),v=(0,L.useCallback)(()=>{_.current=!0,j()},[]),y=(0,L.useCallback)(()=>{_.current=!0,N()},[]);return(0,L.useEffect)(()=>{_.current&&(_.current=!1,t?m.current?.focus():h.current?.focus())},[t]),(0,L.useEffect)(()=>{if(!e||!t)return;function n(e){if(e.key!==`Escape`)return;let t=m.current;t&&e.target instanceof Node&&t.contains(e.target)&&(e.preventDefault(),y())}return document.addEventListener(`keydown`,n),()=>document.removeEventListener(`keydown`,n)},[e,t,y]),e?t?(0,G.jsxs)(`aside`,{ref:m,tabIndex:-1,className:W.card,"aria-labelledby":`verse-onboarding-title`,role:`region`,children:[(0,G.jsxs)(`header`,{className:W.head,children:[(0,G.jsxs)(`div`,{className:W.headText,children:[(0,G.jsxs)(`p`,{className:W.eyebrow,children:[`Getting started · `,r+1,` of `,l]}),(0,G.jsx)(`h2`,{id:`verse-onboarding-title`,className:W.title,children:o.title}),(0,G.jsx)(`p`,{className:W.subtitle,children:o.subtitle})]}),(0,G.jsx)(d,{iconOnly:!0,variant:`ghost`,size:`sm`,"aria-label":`Minimize getting started`,title:`Minimize getting started`,"aria-expanded":`true`,icon:(0,G.jsx)(g,{size:14}),onClick:y})]}),(0,G.jsx)(s,{}),(0,G.jsxs)(`footer`,{className:W.foot,children:[(0,G.jsx)(`ol`,{className:W.pips,"aria-hidden":`true`,children:R.map((e,t)=>(0,G.jsx)(`li`,{className:W.pip,"data-state":t===r?`current`:t<r?`done`:`todo`},e.id))}),(0,G.jsxs)(`div`,{className:W.actions,children:[(0,G.jsx)(d,{variant:`ghost`,size:`sm`,onClick:u,children:`Skip setup`}),r>0?(0,G.jsx)(d,{variant:`subtle`,size:`sm`,onClick:()=>F(r-1),children:`Back`}):null,c?(0,G.jsx)(d,{variant:`primary`,size:`sm`,icon:(0,G.jsx)(i,{size:14}),onClick:()=>{P(),a(`new-chat`)},children:`Start a first chat`}):(0,G.jsx)(d,{variant:`primary`,size:`sm`,onClick:()=>F(r+1),children:`Next`})]})]})]}):(0,G.jsxs)(`div`,{className:W.chip,role:`region`,"aria-label":`Getting started`,children:[(0,G.jsxs)(`button`,{ref:h,type:`button`,className:W.chipOpen,"aria-expanded":`false`,title:`Getting started: ${o.title}`,onClick:v,children:[(0,G.jsx)(`span`,{className:W.chipLabel,children:`Getting started`}),(0,G.jsxs)(`span`,{className:W.chipCount,children:[r+1,`/`,l]}),(0,G.jsx)(p,{size:13,"aria-hidden":`true`,focusable:`false`})]}),(0,G.jsx)(`button`,{type:`button`,className:W.chipDismiss,"aria-label":`Dismiss getting started`,title:`Dismiss getting started — replay it any time from Settings`,onClick:u,children:(0,G.jsx)(f,{size:12,"aria-hidden":`true`,focusable:`false`})})]}):null}export{ne as OnboardingFlow};
2
+ //# sourceMappingURL=OnboardingFlow-LoY-zuSe.js.map