@ashlr/hub 3.10.0 → 3.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (448) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/dist/authority-surface.json +43 -23
  3. package/dist/build-identity.json +2 -2
  4. package/dist/core/daemon/capacity-publisher.d.ts +19 -0
  5. package/dist/core/daemon/capacity-publisher.js +49 -2
  6. package/dist/core/daemon/capacity-publisher.js.map +1 -1
  7. package/dist/core/daemon/overnight-status.d.ts +13 -0
  8. package/dist/core/daemon/overnight-status.js +93 -8
  9. package/dist/core/daemon/overnight-status.js.map +1 -1
  10. package/dist/core/fleet/dispatch-router.js +26 -9
  11. package/dist/core/fleet/dispatch-router.js.map +1 -1
  12. package/dist/core/fleet/fleet-runtime-journal.js +12 -5
  13. package/dist/core/fleet/fleet-runtime-journal.js.map +1 -1
  14. package/dist/core/fleet/fleet-types.d.ts +13 -0
  15. package/dist/core/routing/budget-store.js +11 -5
  16. package/dist/core/routing/budget-store.js.map +1 -1
  17. package/dist/core/routing/capacity-history-api.d.ts +30 -0
  18. package/dist/core/routing/capacity-history-api.js +147 -0
  19. package/dist/core/routing/capacity-history-api.js.map +1 -0
  20. package/dist/core/routing/capacity-history-types.d.ts +63 -0
  21. package/dist/core/routing/capacity-history-types.js +18 -0
  22. package/dist/core/routing/capacity-history-types.js.map +1 -0
  23. package/dist/core/routing/capacity-history.d.ts +130 -0
  24. package/dist/core/routing/capacity-history.js +654 -0
  25. package/dist/core/routing/capacity-history.js.map +1 -0
  26. package/dist/core/routing/headroom.d.ts +5 -1
  27. package/dist/core/routing/headroom.js +82 -41
  28. package/dist/core/routing/headroom.js.map +1 -1
  29. package/dist/core/routing/router.d.ts +8 -1
  30. package/dist/core/routing/router.js +49 -16
  31. package/dist/core/routing/router.js.map +1 -1
  32. package/dist/core/routing/seat-reasons.d.ts +35 -0
  33. package/dist/core/routing/seat-reasons.js +48 -0
  34. package/dist/core/routing/seat-reasons.js.map +1 -0
  35. package/dist/core/routing/types.d.ts +37 -0
  36. package/dist/core/routing/types.js.map +1 -1
  37. package/dist/core/verse/fleet-history-types.d.ts +12 -4
  38. package/dist/core/verse/fleet-history-types.js +4 -2
  39. package/dist/core/verse/fleet-history-types.js.map +1 -1
  40. package/dist/core/verse/fleet-live-api.d.ts +14 -1
  41. package/dist/core/verse/fleet-live-api.js +31 -11
  42. package/dist/core/verse/fleet-live-api.js.map +1 -1
  43. package/dist/core/verse/preferences.d.ts +3 -1
  44. package/dist/core/verse/preferences.js +5 -2
  45. package/dist/core/verse/preferences.js.map +1 -1
  46. package/dist/core/verse/types.d.ts +5 -1
  47. package/dist/core/verse/types.js.map +1 -1
  48. package/dist/core/verse/verse-api.js +2 -1
  49. package/dist/core/verse/verse-api.js.map +1 -1
  50. package/dist/core/web/public/next/assets/{ActionMenu-DhbNne-M.js → ActionMenu-BBB7VYjz.js} +2 -2
  51. package/dist/core/web/public/next/assets/{ActionMenu-DhbNne-M.js.map → ActionMenu-BBB7VYjz.js.map} +1 -1
  52. package/dist/core/web/public/next/assets/Advanced-Bywv_iYR.css +1 -0
  53. package/dist/core/web/public/next/assets/Advanced-xVYFAeA8.js +2 -0
  54. package/dist/core/web/public/next/assets/Advanced-xVYFAeA8.js.map +1 -0
  55. package/dist/core/web/public/next/assets/{App-DyBg1v_q.js → App-CbDCLAxn.js} +5 -5
  56. package/dist/core/web/public/next/assets/{App-DyBg1v_q.js.map → App-CbDCLAxn.js.map} +1 -1
  57. package/dist/core/web/public/next/assets/AppsSection-B5HWJi9I.js +2 -0
  58. package/dist/core/web/public/next/assets/AppsSection-B5HWJi9I.js.map +1 -0
  59. package/dist/core/web/public/next/assets/AreaTrend-BgnK0wAy.js +2 -0
  60. package/dist/core/web/public/next/assets/AreaTrend-BgnK0wAy.js.map +1 -0
  61. package/dist/core/web/public/next/assets/AutonomySection-BF5UCsMv.js +2 -0
  62. package/dist/core/web/public/next/assets/{AutonomySection-CoMngwNB.js.map → AutonomySection-BF5UCsMv.js.map} +1 -1
  63. package/dist/core/web/public/next/assets/BranchBar-BZNQ50YE.css +1 -0
  64. package/dist/core/web/public/next/assets/BranchBar-nfSb59Kv.js +2 -0
  65. package/dist/core/web/public/next/assets/BranchBar-nfSb59Kv.js.map +1 -0
  66. package/dist/core/web/public/next/assets/BudgetControl-BESM12dO.js +2 -0
  67. package/dist/core/web/public/next/assets/BudgetControl-BESM12dO.js.map +1 -0
  68. package/dist/core/web/public/next/assets/BurnDown-D1AfskPT.js +2 -0
  69. package/dist/core/web/public/next/assets/BurnDown-D1AfskPT.js.map +1 -0
  70. package/dist/core/web/public/next/assets/{Button-0-nNbv1h.js → Button-Cr_qkQEc.js} +2 -2
  71. package/dist/core/web/public/next/assets/{Button-0-nNbv1h.js.map → Button-Cr_qkQEc.js.map} +1 -1
  72. package/dist/core/web/public/next/assets/CapacityStrip-Cc28CyWk.css +1 -0
  73. package/dist/core/web/public/next/assets/CapacityStrip-DqqYnLek.js +2 -0
  74. package/dist/core/web/public/next/assets/CapacityStrip-DqqYnLek.js.map +1 -0
  75. package/dist/core/web/public/next/assets/ChatSection-DoqjyVoj.js +3 -0
  76. package/dist/core/web/public/next/assets/{ChatSection-B9cdRKUh.js.map → ChatSection-DoqjyVoj.js.map} +1 -1
  77. package/dist/core/web/public/next/assets/{CommandPalette-GpeCSrPy.js → CommandPalette-lLV-OR63.js} +2 -2
  78. package/dist/core/web/public/next/assets/{CommandPalette-GpeCSrPy.js.map → CommandPalette-lLV-OR63.js.map} +1 -1
  79. package/dist/core/web/public/next/assets/CommandSection-fiZ4DJpM.js +2 -0
  80. package/dist/core/web/public/next/assets/CommandSection-fiZ4DJpM.js.map +1 -0
  81. package/dist/core/web/public/next/assets/Composer-ByzxOJK6.css +1 -0
  82. package/dist/core/web/public/next/assets/Composer.module-C8U73KdQ.js +2 -0
  83. package/dist/core/web/public/next/assets/{Composer.module-DJMdrqNt.js.map → Composer.module-C8U73KdQ.js.map} +1 -1
  84. package/dist/core/web/public/next/assets/DiffPane-BAvvbBsf.css +1 -0
  85. package/dist/core/web/public/next/assets/DiffPane-BVxhK-cy.js +2 -0
  86. package/dist/core/web/public/next/assets/DiffPane-BVxhK-cy.js.map +1 -0
  87. package/dist/core/web/public/next/assets/{DiffViewer-tOGWk0CA.js → DiffViewer-yCdw9J-Y.js} +2 -2
  88. package/dist/core/web/public/next/assets/{DiffViewer-tOGWk0CA.js.map → DiffViewer-yCdw9J-Y.js.map} +1 -1
  89. package/dist/core/web/public/next/assets/DockHost-B4RaYOET.css +1 -0
  90. package/dist/core/web/public/next/assets/DockHost-BZReKwos.js +2 -0
  91. package/dist/core/web/public/next/assets/DockHost-BZReKwos.js.map +1 -0
  92. package/dist/core/web/public/next/assets/{EmptyState-DdJ4CxtO.js → EmptyState-D1GDxVZy.js} +2 -2
  93. package/dist/core/web/public/next/assets/{EmptyState-DdJ4CxtO.js.map → EmptyState-D1GDxVZy.js.map} +1 -1
  94. package/dist/core/web/public/next/assets/{Epistemic-BLjM5y_y.js → Epistemic-DRp4dBfB.js} +2 -2
  95. package/dist/core/web/public/next/assets/{Epistemic-BLjM5y_y.js.map → Epistemic-DRp4dBfB.js.map} +1 -1
  96. package/dist/core/web/public/next/assets/FleetSection-CFiWeOEs.css +1 -0
  97. package/dist/core/web/public/next/assets/FleetSection-rPLy_NPo.js +3 -0
  98. package/dist/core/web/public/next/assets/FleetSection-rPLy_NPo.js.map +1 -0
  99. package/dist/core/web/public/next/assets/Funnel-zvDj3He4.js +2 -0
  100. package/dist/core/web/public/next/assets/Funnel-zvDj3He4.js.map +1 -0
  101. package/dist/core/web/public/next/assets/GearTray-CkviqjYr.js +2 -0
  102. package/dist/core/web/public/next/assets/GearTray-CkviqjYr.js.map +1 -0
  103. package/dist/core/web/public/next/assets/GrowthSection-Bg5sW0jI.js +2 -0
  104. package/dist/core/web/public/next/assets/GrowthSection-Bg5sW0jI.js.map +1 -0
  105. package/dist/core/web/public/next/assets/HandoffDialog-DcPj1ri9.js +2 -0
  106. package/dist/core/web/public/next/assets/HandoffDialog-DcPj1ri9.js.map +1 -0
  107. package/dist/core/web/public/next/assets/{Input-CTu0CycC.js → Input-Ci7TD96x.js} +2 -2
  108. package/dist/core/web/public/next/assets/{Input-CTu0CycC.js.map → Input-Ci7TD96x.js.map} +1 -1
  109. package/dist/core/web/public/next/assets/{LeaderCard-BuSDeATv.js → LeaderCard-BSFTlMRF.js} +2 -2
  110. package/dist/core/web/public/next/assets/{LeaderCard-BuSDeATv.js.map → LeaderCard-BSFTlMRF.js.map} +1 -1
  111. package/dist/core/web/public/next/assets/{MatrixHeatmap-9dKgJ_pT.css → MatrixHeatmap-Bmnvo1l1.css} +1 -1
  112. package/dist/core/web/public/next/assets/MatrixHeatmap-DojKZe9L.js +2 -0
  113. package/dist/core/web/public/next/assets/MatrixHeatmap-DojKZe9L.js.map +1 -0
  114. package/dist/core/web/public/next/assets/McpSection-CvcYu1X_.js +2 -0
  115. package/dist/core/web/public/next/assets/{McpSection-1UncWBpW.js.map → McpSection-CvcYu1X_.js.map} +1 -1
  116. package/dist/core/web/public/next/assets/MessageMarkdown-BrLCrb73.js +3 -0
  117. package/dist/core/web/public/next/assets/{MessageMarkdown-C4pl9LI5.js.map → MessageMarkdown-BrLCrb73.js.map} +1 -1
  118. package/dist/core/web/public/next/assets/MessageMarkdown-Cgh5f1-Q.css +1 -0
  119. package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-CZsF77ZM.js → MessageMarkdownRenderer-CjmdBw2p.js} +2 -2
  120. package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-CZsF77ZM.js.map → MessageMarkdownRenderer-CjmdBw2p.js.map} +1 -1
  121. package/dist/core/web/public/next/assets/{Meter-C18ciKz4.js → Meter-DTHbmhQg.js} +2 -2
  122. package/dist/core/web/public/next/assets/{Meter-C18ciKz4.js.map → Meter-DTHbmhQg.js.map} +1 -1
  123. package/dist/core/web/public/next/assets/MindSection-DcO9fmYe.js +2 -0
  124. package/dist/core/web/public/next/assets/MindSection-DcO9fmYe.js.map +1 -0
  125. package/dist/core/web/public/next/assets/MutationTokenDialog-Cqn2uPV6.js +2 -0
  126. package/dist/core/web/public/next/assets/MutationTokenDialog-Cqn2uPV6.js.map +1 -0
  127. package/dist/core/web/public/next/assets/NeedsYouDrawer-BpvidnM2.css +1 -0
  128. package/dist/core/web/public/next/assets/NeedsYouDrawer-hiTINupk.js +2 -0
  129. package/dist/core/web/public/next/assets/NeedsYouDrawer-hiTINupk.js.map +1 -0
  130. package/dist/core/web/public/next/assets/NeedsYouList-B4Z37Phx.js +2 -0
  131. package/dist/core/web/public/next/assets/NeedsYouList-B4Z37Phx.js.map +1 -0
  132. package/dist/core/web/public/next/assets/NeedsYouList-CruOt4JT.css +1 -0
  133. package/dist/core/web/public/next/assets/NewChatDialog-utSckh7C.js +3 -0
  134. package/dist/core/web/public/next/assets/{NewChatDialog-B_BsS9pr.js.map → NewChatDialog-utSckh7C.js.map} +1 -1
  135. package/dist/core/web/public/next/assets/OnboardingFlow-7N3YSUHN.js +2 -0
  136. package/dist/core/web/public/next/assets/{OnboardingFlow-CtCPpgoX.js.map → OnboardingFlow-7N3YSUHN.js.map} +1 -1
  137. package/dist/core/web/public/next/assets/PreviewPane-CqzkaAjG.js +2 -0
  138. package/dist/core/web/public/next/assets/PreviewPane-CqzkaAjG.js.map +1 -0
  139. package/dist/core/web/public/next/assets/PreviewPane-DoMsJSG3.css +1 -0
  140. package/dist/core/web/public/next/assets/RailStatus-sZhApA8k.js +2 -0
  141. package/dist/core/web/public/next/assets/RailStatus-sZhApA8k.js.map +1 -0
  142. package/dist/core/web/public/next/assets/{RefreshIndicator-CnhEovMZ.js → RefreshIndicator-C1uQIegT.js} +2 -2
  143. package/dist/core/web/public/next/assets/{RefreshIndicator-CnhEovMZ.js.map → RefreshIndicator-C1uQIegT.js.map} +1 -1
  144. package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-28gLwmwV.js → ResourcePoolConsoleApp-DXjjV6Sh.js} +4 -4
  145. package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-28gLwmwV.js.map → ResourcePoolConsoleApp-DXjjV6Sh.js.map} +1 -1
  146. package/dist/core/web/public/next/assets/{RouteErrorBoundary-AyUPCIb3.js → RouteErrorBoundary-D1LZxQjN.js} +2 -2
  147. package/dist/core/web/public/next/assets/{RouteErrorBoundary-AyUPCIb3.js.map → RouteErrorBoundary-D1LZxQjN.js.map} +1 -1
  148. package/dist/core/web/public/next/assets/SeatSelector-CT92PqM_.js +3 -0
  149. package/dist/core/web/public/next/assets/{SeatSelector-DaUO-zoK.js.map → SeatSelector-CT92PqM_.js.map} +1 -1
  150. package/dist/core/web/public/next/assets/{Segmented-B_8c_83S.js → Segmented-BMvq-FfD.js} +2 -2
  151. package/dist/core/web/public/next/assets/{Segmented-B_8c_83S.js.map → Segmented-BMvq-FfD.js.map} +1 -1
  152. package/dist/core/web/public/next/assets/{Select-Bl5g5Dt_.js → Select-DkdeoSQn.js} +2 -2
  153. package/dist/core/web/public/next/assets/{Select-Bl5g5Dt_.js.map → Select-DkdeoSQn.js.map} +1 -1
  154. package/dist/core/web/public/next/assets/{SessionInsightChip-w0I21q0c.js → SessionInsightChip-CwlakUYU.js} +2 -2
  155. package/dist/core/web/public/next/assets/{SessionInsightChip-w0I21q0c.js.map → SessionInsightChip-CwlakUYU.js.map} +1 -1
  156. package/dist/core/web/public/next/assets/SessionSearch-DFByh2NZ.js +2 -0
  157. package/dist/core/web/public/next/assets/{SessionSearch-B5aQ0BCM.js.map → SessionSearch-DFByh2NZ.js.map} +1 -1
  158. package/dist/core/web/public/next/assets/SettingsSection-DgSaHFK4.js +2 -0
  159. package/dist/core/web/public/next/assets/SettingsSection-DgSaHFK4.js.map +1 -0
  160. package/dist/core/web/public/next/assets/{Sheet-CVjk-cLI.js → Sheet-C7APkGPt.js} +2 -2
  161. package/dist/core/web/public/next/assets/{Sheet-CVjk-cLI.js.map → Sheet-C7APkGPt.js.map} +1 -1
  162. package/dist/core/web/public/next/assets/{ShortcutsOverlay-BiBjnBcc.js → ShortcutsOverlay-ZPyXUS_I.js} +2 -2
  163. package/dist/core/web/public/next/assets/{ShortcutsOverlay-BiBjnBcc.js.map → ShortcutsOverlay-ZPyXUS_I.js.map} +1 -1
  164. package/dist/core/web/public/next/assets/Sidebar-BRc1vGDF.css +1 -0
  165. package/dist/core/web/public/next/assets/Sidebar-Chsgazmk.js +3 -0
  166. package/dist/core/web/public/next/assets/Sidebar-Chsgazmk.js.map +1 -0
  167. package/dist/core/web/public/next/assets/{Slider-BS9MU5ZV.js → Slider-B0kjW7cd.js} +2 -2
  168. package/dist/core/web/public/next/assets/{Slider-BS9MU5ZV.js.map → Slider-B0kjW7cd.js.map} +1 -1
  169. package/dist/core/web/public/next/assets/{StatusBadge-DAf-ArKE.js → StatusBadge-wv4e6f8b.js} +2 -2
  170. package/dist/core/web/public/next/assets/{StatusBadge-DAf-ArKE.js.map → StatusBadge-wv4e6f8b.js.map} +1 -1
  171. package/dist/core/web/public/next/assets/StepBand-Db8WPw8J.js +2 -0
  172. package/dist/core/web/public/next/assets/StepBand-Db8WPw8J.js.map +1 -0
  173. package/dist/core/web/public/next/assets/{Surface-CiYOdNKQ.js → Surface-BkDrQ4t3.js} +2 -2
  174. package/dist/core/web/public/next/assets/{Surface-CiYOdNKQ.js.map → Surface-BkDrQ4t3.js.map} +1 -1
  175. package/dist/core/web/public/next/assets/Swimlane-Dcve56cP.js +2 -0
  176. package/dist/core/web/public/next/assets/Swimlane-Dcve56cP.js.map +1 -0
  177. package/dist/core/web/public/next/assets/{Switch-BzRXtNPt.js → Switch-DamlpSMY.js} +2 -2
  178. package/dist/core/web/public/next/assets/{Switch-BzRXtNPt.js.map → Switch-DamlpSMY.js.map} +1 -1
  179. package/dist/core/web/public/next/assets/{Tag-DEEbDz7T.js → Tag-Cs4tudBN.js} +2 -2
  180. package/dist/core/web/public/next/assets/{Tag-DEEbDz7T.js.map → Tag-Cs4tudBN.js.map} +1 -1
  181. package/dist/core/web/public/next/assets/TerminalPane-BDkKFych.js +7 -0
  182. package/dist/core/web/public/next/assets/TerminalPane-BDkKFych.js.map +1 -0
  183. package/dist/core/web/public/next/assets/TerminalPane-BwfMbnJz.css +1 -0
  184. package/dist/core/web/public/next/assets/UniverseConsoleApp-BE72VyBL.js +2 -0
  185. package/dist/core/web/public/next/assets/{UniverseConsoleApp-DKqAf-eD.js.map → UniverseConsoleApp-BE72VyBL.js.map} +1 -1
  186. package/dist/core/web/public/next/assets/{UniverseView-D6081LQL.js → UniverseView-BbmYY2P4.js} +2 -2
  187. package/dist/core/web/public/next/assets/{UniverseView-D6081LQL.js.map → UniverseView-BbmYY2P4.js.map} +1 -1
  188. package/dist/core/web/public/next/assets/UsageSection-DsB-Jqyl.css +1 -0
  189. package/dist/core/web/public/next/assets/UsageSection-DsC5WmLk.js +2 -0
  190. package/dist/core/web/public/next/assets/UsageSection-DsC5WmLk.js.map +1 -0
  191. package/dist/core/web/public/next/assets/VerseConsoleApp-CXJWDiEM.css +1 -0
  192. package/dist/core/web/public/next/assets/VerseConsoleApp-Dq_hREXs.js +3 -0
  193. package/dist/core/web/public/next/assets/VerseConsoleApp-Dq_hREXs.js.map +1 -0
  194. package/dist/core/web/public/next/assets/Workspace-BYW9dm90.css +1 -0
  195. package/dist/core/web/public/next/assets/Workspace-CKvVEPFq.js +10 -0
  196. package/dist/core/web/public/next/assets/Workspace-CKvVEPFq.js.map +1 -0
  197. package/dist/core/web/public/next/assets/actions-BnjZy8a-.js +2 -0
  198. package/dist/core/web/public/next/assets/actions-BnjZy8a-.js.map +1 -0
  199. package/dist/core/web/public/next/assets/actions-Ddfg2iLl.css +1 -0
  200. package/dist/core/web/public/next/assets/{budget-queries-Dacv1VYP.js → budget-queries-Cp6vO7FH.js} +2 -2
  201. package/dist/core/web/public/next/assets/{budget-queries-Dacv1VYP.js.map → budget-queries-Cp6vO7FH.js.map} +1 -1
  202. package/dist/core/web/public/next/assets/calendar-day-BxBYHfX1.js +2 -0
  203. package/dist/core/web/public/next/assets/calendar-day-BxBYHfX1.js.map +1 -0
  204. package/dist/core/web/public/next/assets/capacity-strip-model-9-Yb211u.js +2 -0
  205. package/dist/core/web/public/next/assets/capacity-strip-model-9-Yb211u.js.map +1 -0
  206. package/dist/core/web/public/next/assets/charts-BmbKhjqw.js +2 -0
  207. package/dist/core/web/public/next/assets/charts-BmbKhjqw.js.map +1 -0
  208. package/dist/core/web/public/next/assets/colors-BZ3a9wFf.js +2 -0
  209. package/dist/core/web/public/next/assets/colors-BZ3a9wFf.js.map +1 -0
  210. package/dist/core/web/public/next/assets/{command-bus-CpYuam1F.js → command-bus-DHJJLWh8.js} +2 -2
  211. package/dist/core/web/public/next/assets/{command-bus-CpYuam1F.js.map → command-bus-DHJJLWh8.js.map} +1 -1
  212. package/dist/core/web/public/next/assets/context-model-BGznyHNQ.js +2 -0
  213. package/dist/core/web/public/next/assets/context-model-BGznyHNQ.js.map +1 -0
  214. package/dist/core/web/public/next/assets/context-model-DeJ28uSZ.js +2 -0
  215. package/dist/core/web/public/next/assets/context-model-DeJ28uSZ.js.map +1 -0
  216. package/dist/core/web/public/next/assets/context-queries-_mEgy4eg.js +2 -0
  217. package/dist/core/web/public/next/assets/context-queries-_mEgy4eg.js.map +1 -0
  218. package/dist/core/web/public/next/assets/context.module-BijAfoJw.js +2 -0
  219. package/dist/core/web/public/next/assets/context.module-BijAfoJw.js.map +1 -0
  220. package/dist/core/web/public/next/assets/{control-queries-BGjarMm9.js → control-queries-C4TG8blN.js} +2 -2
  221. package/dist/core/web/public/next/assets/{control-queries-BGjarMm9.js.map → control-queries-C4TG8blN.js.map} +1 -1
  222. package/dist/core/web/public/next/assets/dark-since-DOMvtB_G.js +2 -0
  223. package/dist/core/web/public/next/assets/dark-since-DOMvtB_G.js.map +1 -0
  224. package/dist/core/web/public/next/assets/dock-icons-BB7Fi6hT.js +2 -0
  225. package/dist/core/web/public/next/assets/dock-icons-BB7Fi6hT.js.map +1 -0
  226. package/dist/core/web/public/next/assets/dock-panes-mnIwSpRp.js +2 -0
  227. package/dist/core/web/public/next/assets/{dock-panes-BNTLvX7G.js.map → dock-panes-mnIwSpRp.js.map} +1 -1
  228. package/dist/core/web/public/next/assets/{dock-store-_E5h6TEq.js → dock-store-CdHQRP8s.js} +2 -2
  229. package/dist/core/web/public/next/assets/{dock-store-_E5h6TEq.js.map → dock-store-CdHQRP8s.js.map} +1 -1
  230. package/dist/core/web/public/next/assets/fleet-model-B4FKC7fH.js +2 -0
  231. package/dist/core/web/public/next/assets/fleet-model-B4FKC7fH.js.map +1 -0
  232. package/dist/core/web/public/next/assets/format-DKrNjdwD.js +2 -0
  233. package/dist/core/web/public/next/assets/format-DKrNjdwD.js.map +1 -0
  234. package/dist/core/web/public/next/assets/format-lW58rL2y.js +2 -0
  235. package/dist/core/web/public/next/assets/format-lW58rL2y.js.map +1 -0
  236. package/dist/core/web/public/next/assets/{git-model-5v5xGobf.js → git-model-DaGw1SzS.js} +2 -2
  237. package/dist/core/web/public/next/assets/{git-model-5v5xGobf.js.map → git-model-DaGw1SzS.js.map} +1 -1
  238. package/dist/core/web/public/next/assets/global-DG1fmn4y.js +2 -0
  239. package/dist/core/web/public/next/assets/global-DG1fmn4y.js.map +1 -0
  240. package/dist/core/web/public/next/assets/{guarded-action-vOPc8v75.js → guarded-action--lguLXfz.js} +2 -2
  241. package/dist/core/web/public/next/assets/{guarded-action-vOPc8v75.js.map → guarded-action--lguLXfz.js.map} +1 -1
  242. package/dist/core/web/public/next/assets/{icons-DWb24OA6.js → icons-YPgbel-I.js} +2 -2
  243. package/dist/core/web/public/next/assets/{icons-DWb24OA6.js.map → icons-YPgbel-I.js.map} +1 -1
  244. package/dist/core/web/public/next/assets/{index-afDA8cwW.js → index-Dk8R-3a7.js} +3 -3
  245. package/dist/core/web/public/next/assets/{index-afDA8cwW.js.map → index-Dk8R-3a7.js.map} +1 -1
  246. package/dist/core/web/public/next/assets/live-model-44wEU6I8.js +2 -0
  247. package/dist/core/web/public/next/assets/live-model-44wEU6I8.js.map +1 -0
  248. package/dist/core/web/public/next/assets/mind-B9PzLcl0.css +1 -0
  249. package/dist/core/web/public/next/assets/mind.module-BOABBdi_.js +2 -0
  250. package/dist/core/web/public/next/assets/mind.module-BOABBdi_.js.map +1 -0
  251. package/dist/core/web/public/next/assets/mutations-DjXM3IDg.js +2 -0
  252. package/dist/core/web/public/next/assets/{mutations-C6E10SPX.js.map → mutations-DjXM3IDg.js.map} +1 -1
  253. package/dist/core/web/public/next/assets/{overnight-queries-CCGfiS-g.js → overnight-queries-Be_eossf.js} +2 -2
  254. package/dist/core/web/public/next/assets/{overnight-queries-CCGfiS-g.js.map → overnight-queries-Be_eossf.js.map} +1 -1
  255. package/dist/core/web/public/next/assets/pane-chrome-8JmEhHVD.css +1 -0
  256. package/dist/core/web/public/next/assets/pane-chrome.module-D7o-fVd0.js +2 -0
  257. package/dist/core/web/public/next/assets/pane-chrome.module-D7o-fVd0.js.map +1 -0
  258. package/dist/core/web/public/next/assets/primitives-Dl3SEQvh.js +1 -0
  259. package/dist/core/web/public/next/assets/{queries-BuYIEHst.js → queries-CYEVCq5r.js} +2 -2
  260. package/dist/core/web/public/next/assets/{queries-BuYIEHst.js.map → queries-CYEVCq5r.js.map} +1 -1
  261. package/dist/core/web/public/next/assets/{reasoning-pref-BVzGczV7.js → reasoning-pref-a_ZP6GzU.js} +2 -2
  262. package/dist/core/web/public/next/assets/{reasoning-pref-BVzGczV7.js.map → reasoning-pref-a_ZP6GzU.js.map} +1 -1
  263. package/dist/core/web/public/next/assets/seat-subscription-CRigL-GE.js +2 -0
  264. package/dist/core/web/public/next/assets/seat-subscription-CRigL-GE.js.map +1 -0
  265. package/dist/core/web/public/next/assets/{section-visibility-CSrsTcwK.js → section-visibility-u7q-Q9AA.js} +2 -2
  266. package/dist/core/web/public/next/assets/{section-visibility-CSrsTcwK.js.map → section-visibility-u7q-Q9AA.js.map} +1 -1
  267. package/dist/core/web/public/next/assets/{sidebar-model-C8fyqSQY.js → sidebar-model-i4WRuQ6j.js} +2 -2
  268. package/dist/core/web/public/next/assets/{sidebar-model-C8fyqSQY.js.map → sidebar-model-i4WRuQ6j.js.map} +1 -1
  269. package/dist/core/web/public/next/assets/slots-CV9ZuLQU.js +3 -0
  270. package/dist/core/web/public/next/assets/{slots-W8gkmdfE.js.map → slots-CV9ZuLQU.js.map} +1 -1
  271. package/dist/core/web/public/next/assets/surface-data-DLvmUX9z.js +2 -0
  272. package/dist/core/web/public/next/assets/surface-data-DLvmUX9z.js.map +1 -0
  273. package/dist/core/web/public/next/assets/surface-prefetch-Ct2JwXvL.js +2 -0
  274. package/dist/core/web/public/next/assets/surface-prefetch-Ct2JwXvL.js.map +1 -0
  275. package/dist/core/web/public/next/assets/tasks-model-DWs5u9RO.js +2 -0
  276. package/dist/core/web/public/next/assets/{tasks-model-CnYQzgxk.js.map → tasks-model-DWs5u9RO.js.map} +1 -1
  277. package/dist/core/web/public/next/assets/{terminal-icons-CxUYaWX9.js → terminal-icons-Ct9cZsEK.js} +2 -2
  278. package/dist/core/web/public/next/assets/{terminal-icons-CxUYaWX9.js.map → terminal-icons-Ct9cZsEK.js.map} +1 -1
  279. package/dist/core/web/public/next/assets/{tool-semantics-CTRuLF5j.js → tool-semantics-GX8ScuSH.js} +2 -2
  280. package/dist/core/web/public/next/assets/{tool-semantics-CTRuLF5j.js.map → tool-semantics-GX8ScuSH.js.map} +1 -1
  281. package/dist/core/web/public/next/assets/{turn-files-BvB5LLNw.js → turn-files-BPHQzYuH.js} +2 -2
  282. package/dist/core/web/public/next/assets/{turn-files-BvB5LLNw.js.map → turn-files-BPHQzYuH.js.map} +1 -1
  283. package/dist/core/web/public/next/assets/{usage-queries-CQOpeE1H.js → usage-queries-CI_y9oWZ.js} +2 -2
  284. package/dist/core/web/public/next/assets/{usage-queries-CQOpeE1H.js.map → usage-queries-CI_y9oWZ.js.map} +1 -1
  285. package/dist/core/web/public/next/assets/use-guarded-action-DVCtLzSo.js +2 -0
  286. package/dist/core/web/public/next/assets/use-guarded-action-DVCtLzSo.js.map +1 -0
  287. package/dist/core/web/public/next/assets/{use-ticker-hryPXnyp.js → use-ticker-C3LQ2IYs.js} +2 -2
  288. package/dist/core/web/public/next/assets/{use-ticker-hryPXnyp.js.map → use-ticker-C3LQ2IYs.js.map} +1 -1
  289. package/dist/core/web/public/next/assets/use-token-gate-B5gOFkeH.js +2 -0
  290. package/dist/core/web/public/next/assets/use-token-gate-B5gOFkeH.js.map +1 -0
  291. package/dist/core/web/public/next/assets/{useActivity-Cg_9-7nt.js → useActivity-C3R1Sudh.js} +2 -2
  292. package/dist/core/web/public/next/assets/{useActivity-Cg_9-7nt.js.map → useActivity-C3R1Sudh.js.map} +1 -1
  293. package/dist/core/web/public/next/assets/useChartWidth-0APW0BR3.js +2 -0
  294. package/dist/core/web/public/next/assets/useChartWidth-0APW0BR3.js.map +1 -0
  295. package/dist/core/web/public/next/assets/useChartWidth-BAtVgn2n.css +1 -0
  296. package/dist/core/web/public/next/assets/{useSeatsRefresh-4Ov9eT1F.js → useSeatsRefresh-BN8bso-n.js} +2 -2
  297. package/dist/core/web/public/next/assets/{useSeatsRefresh-4Ov9eT1F.js.map → useSeatsRefresh-BN8bso-n.js.map} +1 -1
  298. package/dist/core/web/public/next/assets/verse-model-yHPwjf-7.js +2 -0
  299. package/dist/core/web/public/next/assets/verse-model-yHPwjf-7.js.map +1 -0
  300. package/dist/core/web/public/next/assets/{verse-queries-BjQoOTwv.js → verse-queries-2PxoBISm.js} +2 -2
  301. package/dist/core/web/public/next/assets/{verse-queries-BjQoOTwv.js.map → verse-queries-2PxoBISm.js.map} +1 -1
  302. package/dist/core/web/public/next/assets/verse-store-DHTuZpYa.js +3 -0
  303. package/dist/core/web/public/next/assets/verse-store-DHTuZpYa.js.map +1 -0
  304. package/dist/core/web/public/next/assets/verse-ui-store-Dy4HuDBV.js +3 -0
  305. package/dist/core/web/public/next/assets/{verse-ui-store-KTTKfv-T.js.map → verse-ui-store-Dy4HuDBV.js.map} +1 -1
  306. package/dist/core/web/public/next/assets/{viewport-ZB86jdES.js → viewport-DDoJ_xVq.js} +2 -2
  307. package/dist/core/web/public/next/assets/{viewport-ZB86jdES.js.map → viewport-DDoJ_xVq.js.map} +1 -1
  308. package/dist/core/web/public/next/assets/warmup-BsL2LdR-.js +3 -0
  309. package/dist/core/web/public/next/assets/warmup-BsL2LdR-.js.map +1 -0
  310. package/dist/core/web/public/next/assets/{workspace-model-4hq_Mv3N.js → workspace-model-Dd3LmIym.js} +2 -2
  311. package/dist/core/web/public/next/assets/{workspace-model-4hq_Mv3N.js.map → workspace-model-Dd3LmIym.js.map} +1 -1
  312. package/dist/core/web/public/next/index.html +1 -1
  313. package/dist/release-dependency-inventory.json +1 -1
  314. package/package.json +1 -1
  315. package/dist/core/web/public/next/assets/Advanced-CHjxJt2z.css +0 -1
  316. package/dist/core/web/public/next/assets/Advanced-DM0DYibH.js +0 -2
  317. package/dist/core/web/public/next/assets/Advanced-DM0DYibH.js.map +0 -1
  318. package/dist/core/web/public/next/assets/AppsSection-CXxbfPJQ.js +0 -2
  319. package/dist/core/web/public/next/assets/AppsSection-CXxbfPJQ.js.map +0 -1
  320. package/dist/core/web/public/next/assets/AreaTrend-gUVXkfhf.js +0 -2
  321. package/dist/core/web/public/next/assets/AreaTrend-gUVXkfhf.js.map +0 -1
  322. package/dist/core/web/public/next/assets/AutonomySection-CoMngwNB.js +0 -2
  323. package/dist/core/web/public/next/assets/BranchBar-C-NovaXr.js +0 -2
  324. package/dist/core/web/public/next/assets/BranchBar-C-NovaXr.js.map +0 -1
  325. package/dist/core/web/public/next/assets/BranchBar-C9BpPVLr.css +0 -1
  326. package/dist/core/web/public/next/assets/BudgetControl-P5lMxHvQ.js +0 -2
  327. package/dist/core/web/public/next/assets/BudgetControl-P5lMxHvQ.js.map +0 -1
  328. package/dist/core/web/public/next/assets/BurnDown-4P1LDoCL.js +0 -2
  329. package/dist/core/web/public/next/assets/BurnDown-4P1LDoCL.js.map +0 -1
  330. package/dist/core/web/public/next/assets/CapacityStrip-D6Yyg4a1.js +0 -2
  331. package/dist/core/web/public/next/assets/CapacityStrip-D6Yyg4a1.js.map +0 -1
  332. package/dist/core/web/public/next/assets/CapacityStrip-wgFP9MUA.css +0 -1
  333. package/dist/core/web/public/next/assets/ChatSection-B9cdRKUh.js +0 -3
  334. package/dist/core/web/public/next/assets/CommandSection-BC0uXim_.js +0 -2
  335. package/dist/core/web/public/next/assets/CommandSection-BC0uXim_.js.map +0 -1
  336. package/dist/core/web/public/next/assets/Composer-CkcwbQhG.css +0 -1
  337. package/dist/core/web/public/next/assets/Composer.module-DJMdrqNt.js +0 -2
  338. package/dist/core/web/public/next/assets/DiffPane-5uLKa0au.js +0 -2
  339. package/dist/core/web/public/next/assets/DiffPane-5uLKa0au.js.map +0 -1
  340. package/dist/core/web/public/next/assets/DiffPane-Csboxnn0.css +0 -1
  341. package/dist/core/web/public/next/assets/DockHost-BGnTgdIb.css +0 -1
  342. package/dist/core/web/public/next/assets/DockHost-CBV_6Ehi.js +0 -2
  343. package/dist/core/web/public/next/assets/DockHost-CBV_6Ehi.js.map +0 -1
  344. package/dist/core/web/public/next/assets/FleetSection-DuJcQCGg.js +0 -3
  345. package/dist/core/web/public/next/assets/FleetSection-DuJcQCGg.js.map +0 -1
  346. package/dist/core/web/public/next/assets/FleetSection-w9AjqfTR.css +0 -1
  347. package/dist/core/web/public/next/assets/Funnel-qX3Hlbce.js +0 -2
  348. package/dist/core/web/public/next/assets/Funnel-qX3Hlbce.js.map +0 -1
  349. package/dist/core/web/public/next/assets/GearTray-kVGP1coG.js +0 -2
  350. package/dist/core/web/public/next/assets/GearTray-kVGP1coG.js.map +0 -1
  351. package/dist/core/web/public/next/assets/GrowthSection-CYxJ9MH5.js +0 -2
  352. package/dist/core/web/public/next/assets/GrowthSection-CYxJ9MH5.js.map +0 -1
  353. package/dist/core/web/public/next/assets/HandoffDialog-DHZo3Ev0.js +0 -2
  354. package/dist/core/web/public/next/assets/HandoffDialog-DHZo3Ev0.js.map +0 -1
  355. package/dist/core/web/public/next/assets/MatrixHeatmap-B_JWCjZx.js +0 -2
  356. package/dist/core/web/public/next/assets/MatrixHeatmap-B_JWCjZx.js.map +0 -1
  357. package/dist/core/web/public/next/assets/McpSection-1UncWBpW.js +0 -2
  358. package/dist/core/web/public/next/assets/MessageMarkdown-C4pl9LI5.js +0 -3
  359. package/dist/core/web/public/next/assets/MessageMarkdown-Czcl3L_Q.css +0 -1
  360. package/dist/core/web/public/next/assets/MindSection-C3fCw_fD.js +0 -2
  361. package/dist/core/web/public/next/assets/MindSection-C3fCw_fD.js.map +0 -1
  362. package/dist/core/web/public/next/assets/MutationTokenDialog-Dn0tzCrh.js +0 -2
  363. package/dist/core/web/public/next/assets/MutationTokenDialog-Dn0tzCrh.js.map +0 -1
  364. package/dist/core/web/public/next/assets/NeedsYouDrawer-CuNYJCJ0.js +0 -2
  365. package/dist/core/web/public/next/assets/NeedsYouDrawer-CuNYJCJ0.js.map +0 -1
  366. package/dist/core/web/public/next/assets/NeedsYouDrawer-SkhvvdLb.css +0 -1
  367. package/dist/core/web/public/next/assets/NewChatDialog-B_BsS9pr.js +0 -3
  368. package/dist/core/web/public/next/assets/OnboardingFlow-CtCPpgoX.js +0 -2
  369. package/dist/core/web/public/next/assets/PreviewPane-Cx6RRwzM.js +0 -2
  370. package/dist/core/web/public/next/assets/PreviewPane-Cx6RRwzM.js.map +0 -1
  371. package/dist/core/web/public/next/assets/PreviewPane-WQJFjSXe.css +0 -1
  372. package/dist/core/web/public/next/assets/RailStatus-BWs6xevj.js +0 -2
  373. package/dist/core/web/public/next/assets/RailStatus-BWs6xevj.js.map +0 -1
  374. package/dist/core/web/public/next/assets/SeatSelector-DaUO-zoK.js +0 -3
  375. package/dist/core/web/public/next/assets/SessionSearch-B5aQ0BCM.js +0 -2
  376. package/dist/core/web/public/next/assets/SettingsSection-CuESA30a.js +0 -2
  377. package/dist/core/web/public/next/assets/SettingsSection-CuESA30a.js.map +0 -1
  378. package/dist/core/web/public/next/assets/Sidebar-DfD8MNZt.css +0 -1
  379. package/dist/core/web/public/next/assets/Sidebar-q11dtYZf.js +0 -3
  380. package/dist/core/web/public/next/assets/Sidebar-q11dtYZf.js.map +0 -1
  381. package/dist/core/web/public/next/assets/StepBand-B1W7rU70.js +0 -2
  382. package/dist/core/web/public/next/assets/StepBand-B1W7rU70.js.map +0 -1
  383. package/dist/core/web/public/next/assets/Swimlane-BR40WVcj.js +0 -2
  384. package/dist/core/web/public/next/assets/Swimlane-BR40WVcj.js.map +0 -1
  385. package/dist/core/web/public/next/assets/TerminalPane-CPKUTD9K.js +0 -7
  386. package/dist/core/web/public/next/assets/TerminalPane-CPKUTD9K.js.map +0 -1
  387. package/dist/core/web/public/next/assets/TerminalPane-CmE2QL-Q.css +0 -1
  388. package/dist/core/web/public/next/assets/UniverseConsoleApp-DKqAf-eD.js +0 -2
  389. package/dist/core/web/public/next/assets/UsageSection-B6fR3cru.js +0 -2
  390. package/dist/core/web/public/next/assets/UsageSection-B6fR3cru.js.map +0 -1
  391. package/dist/core/web/public/next/assets/UsageSection-DwgNOYvi.css +0 -1
  392. package/dist/core/web/public/next/assets/VerseConsoleApp-C0V221WL.css +0 -1
  393. package/dist/core/web/public/next/assets/VerseConsoleApp-bjARLPwN.js +0 -3
  394. package/dist/core/web/public/next/assets/VerseConsoleApp-bjARLPwN.js.map +0 -1
  395. package/dist/core/web/public/next/assets/Workspace-DQXMVDf7.css +0 -1
  396. package/dist/core/web/public/next/assets/Workspace-DtJb5tiM.js +0 -10
  397. package/dist/core/web/public/next/assets/Workspace-DtJb5tiM.js.map +0 -1
  398. package/dist/core/web/public/next/assets/actions-Bszsdpms.js +0 -2
  399. package/dist/core/web/public/next/assets/actions-Bszsdpms.js.map +0 -1
  400. package/dist/core/web/public/next/assets/actions-Dug8YIf0.css +0 -1
  401. package/dist/core/web/public/next/assets/capacity-strip-model-BR539Ci8.js +0 -2
  402. package/dist/core/web/public/next/assets/capacity-strip-model-BR539Ci8.js.map +0 -1
  403. package/dist/core/web/public/next/assets/charts-D4NaLaXA.js +0 -2
  404. package/dist/core/web/public/next/assets/charts-D4NaLaXA.js.map +0 -1
  405. package/dist/core/web/public/next/assets/colors-B-vHsX1S.js +0 -2
  406. package/dist/core/web/public/next/assets/colors-B-vHsX1S.js.map +0 -1
  407. package/dist/core/web/public/next/assets/context-model-Bto3LZn2.js +0 -2
  408. package/dist/core/web/public/next/assets/context-model-Bto3LZn2.js.map +0 -1
  409. package/dist/core/web/public/next/assets/context-queries-DVdSLrYy.js +0 -2
  410. package/dist/core/web/public/next/assets/context-queries-DVdSLrYy.js.map +0 -1
  411. package/dist/core/web/public/next/assets/context.module-B_k02HNU.js +0 -2
  412. package/dist/core/web/public/next/assets/context.module-B_k02HNU.js.map +0 -1
  413. package/dist/core/web/public/next/assets/dock-icons-oG8d7mNZ.js +0 -2
  414. package/dist/core/web/public/next/assets/dock-icons-oG8d7mNZ.js.map +0 -1
  415. package/dist/core/web/public/next/assets/dock-panes-BNTLvX7G.js +0 -2
  416. package/dist/core/web/public/next/assets/fleet-model-ClBbQ0Uj.js +0 -2
  417. package/dist/core/web/public/next/assets/fleet-model-ClBbQ0Uj.js.map +0 -1
  418. package/dist/core/web/public/next/assets/format-BNYWGJat.js +0 -2
  419. package/dist/core/web/public/next/assets/format-BNYWGJat.js.map +0 -1
  420. package/dist/core/web/public/next/assets/global-DVgMguLr.js +0 -2
  421. package/dist/core/web/public/next/assets/global-DVgMguLr.js.map +0 -1
  422. package/dist/core/web/public/next/assets/live-model-Dm6ITHvX.js +0 -2
  423. package/dist/core/web/public/next/assets/live-model-Dm6ITHvX.js.map +0 -1
  424. package/dist/core/web/public/next/assets/mind-B-lYfSUJ.css +0 -1
  425. package/dist/core/web/public/next/assets/mind.module-BzhAlg3e.js +0 -2
  426. package/dist/core/web/public/next/assets/mind.module-BzhAlg3e.js.map +0 -1
  427. package/dist/core/web/public/next/assets/mutations-C6E10SPX.js +0 -2
  428. package/dist/core/web/public/next/assets/primitives-DQvYikjm.js +0 -1
  429. package/dist/core/web/public/next/assets/seat-subscription-CrWOV4Qc.js +0 -2
  430. package/dist/core/web/public/next/assets/seat-subscription-CrWOV4Qc.js.map +0 -1
  431. package/dist/core/web/public/next/assets/slots-W8gkmdfE.js +0 -3
  432. package/dist/core/web/public/next/assets/surface-data-ZtCegYMQ.js +0 -2
  433. package/dist/core/web/public/next/assets/surface-data-ZtCegYMQ.js.map +0 -1
  434. package/dist/core/web/public/next/assets/tasks-model-CnYQzgxk.js +0 -2
  435. package/dist/core/web/public/next/assets/types-Dypu22dp.js +0 -3
  436. package/dist/core/web/public/next/assets/types-Dypu22dp.js.map +0 -1
  437. package/dist/core/web/public/next/assets/use-guarded-action-CO_aAsed.js +0 -2
  438. package/dist/core/web/public/next/assets/use-guarded-action-CO_aAsed.js.map +0 -1
  439. package/dist/core/web/public/next/assets/use-token-gate-DYA2-ALC.js +0 -2
  440. package/dist/core/web/public/next/assets/use-token-gate-DYA2-ALC.js.map +0 -1
  441. package/dist/core/web/public/next/assets/useChartWidth-B8E5mJgM.css +0 -1
  442. package/dist/core/web/public/next/assets/useChartWidth-MEXvDxDL.js +0 -2
  443. package/dist/core/web/public/next/assets/useChartWidth-MEXvDxDL.js.map +0 -1
  444. package/dist/core/web/public/next/assets/verse-model-E98kXngO.js +0 -2
  445. package/dist/core/web/public/next/assets/verse-model-E98kXngO.js.map +0 -1
  446. package/dist/core/web/public/next/assets/verse-store-BgKx_YGs.js +0 -2
  447. package/dist/core/web/public/next/assets/verse-store-BgKx_YGs.js.map +0 -1
  448. package/dist/core/web/public/next/assets/verse-ui-store-KTTKfv-T.js +0 -3
@@ -1 +0,0 @@
1
- {"version":3,"file":"surface-data-ZtCegYMQ.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/command/surface-data.ts"],"sourcesContent":["/**\n * routes/verse/command/surface-data.ts — every read and write behind the\n * four 3.10 surfaces (Command, Fleet, Growth, Mind), in one place (unit C7).\n *\n * GET /api/verse/authority AuthorityStatusV1 (B-U1)\n * GET /api/verse/authority/draft AuthorityGrantDraft (B-U1)\n * POST /api/verse/authority AuthorityActionRequest\n * GET /api/verse/fleet/live FleetLiveSnapshotV1 (B-U5)\n * POST /api/verse/fleet/live FleetLiveActionRequest\n * GET /api/verse/leader LeaderStateV1 (B-U8)\n * POST /api/verse/leader LeaderActionRequest\n * GET /api/verse/learning LearningStateV1 (B-U9)\n * GET /api/verse/activity VerseActivityResponse (C1 — read through\n * the shell's ONE useActivity poll, never a\n * second loop from here)\n * GET /api/verse/fleet/history FleetHistoryResponse (A8)\n * GET /api/reasoning/digest ReasoningDigest (A7)\n * GET /api/verse/budget BudgetView (A9 — budget-queries.ts)\n * GET /api/models per-model ROI (data/queries.ts)\n *\n * WHY every read is OPTIONAL: Track B's modules land in parallel with these\n * surfaces (SPEC-310BC-COORD), and C0's mount answers 404 for a family that\n * has not landed. A 404 is \"this card has no source yet\", never \"Command is\n * broken\" — so a read resolves to `{ value: null, available: false, reason }`\n * and the card renders a designed not-available state from `reason`. A body\n * this client cannot narrow is treated the same way (available, but nothing\n * shown rather than guessed). 401 and aborts still propagate: an expired\n * read session is the whole app's state, not one card's.\n *\n * Writes pull the held mutation token (VerseControlLockedError without one —\n * the surfaces route every write through useGuardedAction, which opens the\n * token dialog first) and invalidate exactly the keys they change.\n */\nimport { ApiError, apiGet, apiPost } from '../../../data/client.js';\nimport { getMutationToken, touchMutationHold } from '../../../data/auth-store.js';\nimport { invalidate } from '../../../data/cache.js';\nimport type { QueryDef } from '../../../data/queries.js';\nimport { VerseControlLockedError } from '../autonomy/control-queries.js';\nimport { refreshActivity } from '../shell/useActivity.js';\nimport type { OptionalFleetRead } from '../autonomy/fleet-contract.js';\nimport type {\n AuthorityActionRequest,\n AuthorityGrantDraft,\n AuthorityStatusV1,\n} from '../../../../core/authority/types.js';\nimport type { FleetLiveActionRequest, FleetLiveSnapshotV1 } from '../../../../core/fleet/fleet-types.js';\nimport type { LeaderActionRequest, LeaderStateV1 } from '../../../../core/vision/leader-types.js';\nimport type { LearningStateV1 } from '../../../../core/learn/harness-types.js';\nimport type { VerseActivityResponse } from '../../../../core/verse/workbench-types.js';\nimport type { FleetHistoryResponse } from '../../../../core/verse/fleet-history-types.js';\nimport type { ReasoningDigest } from '../../../../core/reasoning/types.js';\n\n/** A read that is allowed to be absent (the autonomy folder's shape, reused). */\nexport type OptionalRead<T> = OptionalFleetRead<T>;\n\nexport const AUTHORITY_PATH = '/api/verse/authority';\nexport const AUTHORITY_DRAFT_PATH = '/api/verse/authority/draft';\nexport const FLEET_LIVE_PATH = '/api/verse/fleet/live';\nexport const LEADER_PATH = '/api/verse/leader';\nexport const LEARNING_PATH = '/api/verse/learning';\nexport const FLEET_HISTORY_PATH = '/api/verse/fleet/history?days=90';\nexport const REASONING_DIGEST_PATH = '/api/reasoning/digest?days=30';\n\nexport const SURFACE_KEYS = Object.freeze({\n authority: 'verse-authority',\n authorityDraft: 'verse-authority-draft',\n fleetLive: 'verse-fleet-live',\n leader: 'verse-leader',\n learning: 'verse-learning',\n fleetHistory: 'verse-fleet-history-90d',\n reasoningDigest: 'verse-reasoning-digest-30d',\n});\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\n/**\n * Structural guards: just enough to know the body is the contract's shape\n * (version tag + the arrays the cards iterate), so a mismatched server can\n * never crash a render with `undefined.map`. Field-level honesty (null =\n * unknown) is the cards' job.\n */\nexport const narrow = {\n authority(raw: unknown): AuthorityStatusV1 | null {\n return isRecord(raw) && raw['v'] === 1 && typeof raw['switch'] === 'string' && isRecord(raw['grant']) ? (raw as unknown as AuthorityStatusV1) : null;\n },\n draft(raw: unknown): AuthorityGrantDraft | null {\n return isRecord(raw) && isRecord(raw['payload']) && typeof raw['digest'] === 'string' ? (raw as unknown as AuthorityGrantDraft) : null;\n },\n fleetLive(raw: unknown): FleetLiveSnapshotV1 | null {\n return isRecord(raw) && raw['v'] === 1 && Array.isArray(raw['runs']) && Array.isArray(raw['repos']) && Array.isArray(raw['lanes']) && isRecord(raw['summary'])\n ? (raw as unknown as FleetLiveSnapshotV1)\n : null;\n },\n leader(raw: unknown): LeaderStateV1 | null {\n return isRecord(raw) && raw['v'] === 1 && Array.isArray(raw['timeline']) && Array.isArray(raw['actions']) && isRecord(raw['hitRate'])\n ? (raw as unknown as LeaderStateV1)\n : null;\n },\n learning(raw: unknown): LearningStateV1 | null {\n return isRecord(raw) && raw['v'] === 1 && Array.isArray(raw['versions']) && Array.isArray(raw['experiments']) ? (raw as unknown as LearningStateV1) : null;\n },\n activity(raw: unknown): VerseActivityResponse | null {\n return isRecord(raw) && Array.isArray(raw['needsYou']) && Array.isArray(raw['running']) && isRecord(raw['sources']) ? (raw as unknown as VerseActivityResponse) : null;\n },\n fleetHistory(raw: unknown): FleetHistoryResponse | null {\n return isRecord(raw) && Array.isArray(raw['days']) && isRecord(raw['sources']) && isRecord(raw['funnel']) ? (raw as unknown as FleetHistoryResponse) : null;\n },\n reasoningDigest(raw: unknown): ReasoningDigest | null {\n return isRecord(raw) && Array.isArray(raw['insights']) && Array.isArray(raw['trends']) && isRecord(raw['totals']) ? (raw as unknown as ReasoningDigest) : null;\n },\n};\n\n/** Operator words for a source that did not answer (never a path, never a trace). */\nfunction absence(what: string, err: unknown): string {\n if (err instanceof ApiError) {\n if (err.status === 404) return `${what} is not in this build yet, so this card has no source.`;\n if (err.status === 503) return `${what} failed to load on the server.`;\n return `${what} answered HTTP ${err.status}.`;\n }\n return `${what} could not be reached.`;\n}\n\n/** A QueryDef whose value is an OptionalRead: 404 / unreachable / unrecognised all resolve, never throw. */\nexport function optionalQuery<T>(key: string, path: string, what: string, guard: (raw: unknown) => T | null): QueryDef<OptionalRead<T>> {\n return {\n key,\n fetch: async (signal) => {\n try {\n const raw = await apiGet<unknown>(path, signal);\n const value = guard(raw);\n if (value === null) {\n return { value: null, available: true, reason: `${what} answered in a shape this version does not recognise, so nothing is shown rather than guessed.` };\n }\n return { value, available: true, reason: null };\n } catch (err) {\n if (err instanceof ApiError && err.status === 401) throw err;\n if (err instanceof DOMException && err.name === 'AbortError') throw err;\n return { value: null, available: false, reason: absence(what, err) };\n }\n },\n };\n}\n\nexport const authorityQuery = optionalQuery(SURFACE_KEYS.authority, AUTHORITY_PATH, 'The authority service', narrow.authority);\nexport const authorityDraftQuery = optionalQuery(SURFACE_KEYS.authorityDraft, AUTHORITY_DRAFT_PATH, 'The grant draft', narrow.draft);\nexport const fleetLiveQuery = optionalQuery(SURFACE_KEYS.fleetLive, FLEET_LIVE_PATH, 'The live fleet view', narrow.fleetLive);\nexport const leaderQuery = optionalQuery(SURFACE_KEYS.leader, LEADER_PATH, 'The Leader', narrow.leader);\nexport const learningQuery = optionalQuery(SURFACE_KEYS.learning, LEARNING_PATH, 'Self-improvement', narrow.learning);\nexport const fleetHistoryQuery = optionalQuery(SURFACE_KEYS.fleetHistory, FLEET_HISTORY_PATH, 'Fleet history', narrow.fleetHistory);\nexport const reasoningDigestQuery = optionalQuery(SURFACE_KEYS.reasoningDigest, REASONING_DIGEST_PATH, 'The reasoning digest', narrow.reasoningDigest);\n\n// ---------------------------------------------------------------------------\n// Writes\n// ---------------------------------------------------------------------------\n\nasync function post<T>(path: string, body: unknown): Promise<T> {\n const token = getMutationToken();\n if (!token) throw new VerseControlLockedError();\n const result = await apiPost<T>(path, body, token);\n touchMutationHold();\n return result;\n}\n\n/**\n * One authority action. The server answers the new AuthorityStatusV1 for\n * every form; raising past the grant is its 409 `grant-required` (the page\n * opens the Touch ID sheet BEFORE ever sending that, but the server is the\n * authority — a stale page gets the refusal, not a raise).\n */\nexport async function postAuthority(action: AuthorityActionRequest): Promise<AuthorityStatusV1 | null> {\n const result = await post<unknown>(AUTHORITY_PATH, action);\n invalidate(SURFACE_KEYS.authority);\n invalidate(SURFACE_KEYS.fleetLive);\n void refreshActivity();\n if (action.action === 'grant' || action.action === 're-approve') invalidate(SURFACE_KEYS.authorityDraft);\n return narrow.authority(result);\n}\n\nexport async function postFleetLive(action: FleetLiveActionRequest): Promise<unknown> {\n const result = await post<unknown>(FLEET_LIVE_PATH, action);\n invalidate(SURFACE_KEYS.fleetLive);\n void refreshActivity();\n return result;\n}\n\nexport async function postLeader(action: LeaderActionRequest): Promise<unknown> {\n const result = await post<unknown>(LEADER_PATH, action);\n invalidate(SURFACE_KEYS.leader);\n void refreshActivity();\n return result;\n}\n\n/**\n * A Needs-you item's own action. `path` was validated by the producer\n * (isNeedsYouItem → isSafeApiRoute) and is re-checked here: the mutation\n * token must never be aimed anywhere but this origin's /api/.\n */\nexport async function postNeedsYouAction(path: string, body: Record<string, unknown>): Promise<unknown> {\n if (!/^\\/api\\/[^\\s\\\\]*$/.test(path) || path.startsWith('//') || path.includes('..')) {\n throw new Error('That action points outside this app, so it was not sent.');\n }\n const result = await post<unknown>(path, body);\n void refreshActivity();\n invalidate(SURFACE_KEYS.fleetLive);\n invalidate(SURFACE_KEYS.leader);\n invalidate(SURFACE_KEYS.authority);\n return result;\n}\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{x as e}from"./verse-model-E98kXngO.js";import{i as t}from"./sidebar-model-C8fyqSQY.js";import{n}from"./tool-semantics-CTRuLF5j.js";function r(t){let r=0;for(let e=t.length-1;e>=0;--e)if(t[e].kind===`user`){r=e;break}let i=[],a=[];for(let o=r;o<t.length;o+=1){let r=t[o];if(r.kind!==`tool`)continue;let s={toolUseId:r.toolUseId,kind:n(r.name)===`task`?`subagent`:`tool`,name:r.name,detail:e(r.input)||r.name,startedAt:r.at,status:r.result===null?`running`:r.result.isError?`failed`:`done`,durationMs:r.durationMs};(s.status===`running`?i:a).push(s)}return[...i,...a.reverse()]}function i(e,n,r){let i=new Map;for(let e of n?.running??[])e.sessionId!==r&&i.set(e.sessionId,{sessionId:e.sessionId,title:e.title,engine:e.engine,startedAt:e.startedAt,live:t(e.live)});for(let t of e)t.id===r||t.status!==`running`||i.has(t.id)||i.set(t.id,{sessionId:t.id,title:t.title,engine:t.engine,startedAt:null,live:null});return[...i.values()]}function a(e,t){let n=e.filter(e=>e.status===`running`);return{turn:n.length,subagents:n.filter(e=>e.kind===`subagent`).length,chats:t.length,total:n.length+t.length}}function o(e){let t=`${e.total} running task${e.total===1?``:`s`}`,n=[];return e.turn>0&&n.push(`${e.turn} in this chat`),e.chats>0&&n.push(`${e.chats} other chat${e.chats===1?``:`s`}`),n.length>0?`${t}: ${n.join(`, `)}`:t}export{a as countTasks,r as currentTurnTasks,o as describeTaskCounts,i as otherRunningChats};
2
- //# sourceMappingURL=tasks-model-CnYQzgxk.js.map
@@ -1,3 +0,0 @@
1
- var e=[`minimal`,`low`,`medium`,`high`,`xhigh`,`max`],t=new Set([`thinking-delta`,`thinking-progress`,`progress`,`status`]);function n(e){return t.has(e.type)}var r=65536,i=12e3,a=[`This conversation is about to continue in a fresh session that has none of its context.`,`Write the handoff note that new session should start from. Do not edit files or run commands for this — only write the note.`,``,`Cover, concretely:`,`- The goal, and what "done" looks like.`,`- Decisions made so far, each with the reason it was made.`,`- Current state: what is finished, what is half-done, what is untested.`,`- Files changed and anything not yet committed.`,`- How to verify the work (exact commands).`,`- Open questions, risks, and approaches already tried that did not work.`,``,`Keep it under 600 words. Prefer file paths and commands over prose.`].join(`
2
- `),o=65536,s=139264,c=6144;export{c as a,n as c,r as i,i as n,s as o,a as r,o as s,e as t};
3
- //# sourceMappingURL=types-Dypu22dp.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types-Dypu22dp.js","names":[],"sources":["../../../../../../src/core/verse/types.ts"],"sourcesContent":["/**\n * Ashlr Verse — interactive multi-turn session contract (V1).\n *\n * A Verse session binds one project directory to one execution seat\n * (engine + account + model). Each user turn spawns ONE vendor CLI process\n * that resumes the vendor-native conversation by id, streams normalized\n * events, and exits. No long-lived stdin is held between turns.\n *\n * Seats:\n * claude -> `claude -p ... --output-format stream-json` via a native-profile launcher (account pinned by CLAUDE_CONFIG_DIR)\n * local -> the plain `claude` binary with ANTHROPIC_BASE_URL pointed at Ollama (Anthropic-compatible API); model = Ollama tag\n * codex -> `codex exec --json` / `codex exec resume <threadId> --json` via a native-profile launcher (CODEX_HOME pinned)\n * grok -> `grok -p ... --output-format streaming-messages-json` via a native-profile launcher (GROK_HOME pinned)\n *\n * Nothing in this module reads secrets. Account identity is pinned by the\n * launcher command recorded in ~/.ashlr/account-connections/connections.json.\n */\n\nexport type VerseEngine = 'claude' | 'codex' | 'grok' | 'local';\n\nexport type VerseSessionStatus = 'idle' | 'running' | 'error';\n\n/** One selectable execution seat shown in the model/account picker. */\nexport interface VerseSeat {\n /** Stable id, e.g. `claude`, `codex-personal`, `grok`, `local:qwen3-coder-next:ctx64k`. */\n id: string;\n engine: VerseEngine;\n /** Human label, e.g. \"Claude Code\", \"Personal Codex\", \"Grok\", \"Qwen3-Coder-Next (local)\". */\n label: string;\n /** Account id from connections.json for native seats; `local` for Ollama seats. */\n accountId: string;\n /** Models this seat can run. First entry is the default. */\n models: VerseModelOption[];\n /** Best-known context window in tokens for the default model (null when unknown). */\n contextWindow: number | null;\n /** Latest health/usage evidence, if any. Never an admission input in V1. */\n health: VerseSeatHealth;\n /**\n * V2.1 ADDITIVE. The subscription capacity behind this seat, so the seat\n * list can render a meter without a second request.\n *\n * Absent (`undefined`) for LOCAL seats: an Ollama tag has no subscription\n * and no provider window. Its real constraint is machine memory, which is\n * reported by `VerseBootstrap.localRuntime`, not by a quota. Absent on a\n * native seat means the server could not build a record for that account\n * at all — `health.state` says what it does know.\n */\n capacity?: VerseSeatCapacity;\n /**\n * V3.9 ADDITIVE. The version of the CLI binary this seat is PINNED to (its\n * native-profile launcher execs one exact file). Absent when unknown and on\n * local seats. A pinned binary never updates itself, so a model that needs a\n * newer CLI is listed with `unavailableReason` rather than silently failing.\n */\n cliVersion?: string;\n /**\n * V3.9 ADDITIVE. Plain-language facts about this seat's context setup the UI\n * must show rather than imply (binary skew, catalog not yet fetched, …).\n * Absent when there is nothing to say, so ordinary seats keep their shape.\n */\n notes?: string[];\n}\n\n/**\n * Where a context-window figure came from, so nothing on screen implies more\n * certainty than it has (docs/VERSE-CONTEXT.md §1).\n *\n * - `runtime` — the CLI reported it for THIS turn (claude/grok\n * `result.modelUsage.<m>.contextWindow`, codex rollout\n * `token_count.info.model_context_window`, Ollama\n * `/api/ps`). Wins over everything else.\n * - `provider-catalog` — the seat's own served catalog on disk (codex/grok\n * `native-state/models_cache.json`).\n * - `cli-catalog` — read out of the pinned CLI binary's embedded catalog\n * and recorded here with the version it was read from.\n * - `documented` — the provider's published model table.\n * - `fallback` — a named default; the UI marks it as an estimate.\n */\nexport type VerseWindowSource = 'runtime' | 'provider-catalog' | 'cli-catalog' | 'documented' | 'fallback';\n\n/**\n * How much context a session is allowed to accumulate before the CLI compacts.\n *\n * - `standard` — the default. Evidence-based budget per engine: Claude 1M\n * models compact near 400k instead of ~967k; Codex, Grok and\n * local run their native windows.\n * - `expansive` — opt-in. Claude runs its full native window (CLI `auto`),\n * Codex raises `model_context_window` to the model's catalog\n * maximum (872k on GPT-6 / GPT-5.6). Costs more usage per turn,\n * buys simultaneous visibility for coupled, cross-cutting work.\n *\n * A mode that does not exist for a model (Grok, local, 200k Claude models,\n * GPT-5.5) is simply absent from that model's option — never faked.\n */\nexport type VerseContextMode = 'standard' | 'expansive';\n\nexport const VERSE_CONTEXT_MODES: readonly VerseContextMode[] = ['standard', 'expansive'];\n\n/** One mode's budget for a model on a seat. */\nexport interface VerseContextBudget {\n /** The window the CLI measures against in this mode (the meter's denominator). */\n contextWindow: number;\n /** Token count at which the CLI auto-compacts in this mode; null when unknown. */\n autoCompactAt: number | null;\n /**\n * The RAW window value the CLI must be TOLD to reach this budget, when that\n * differs from `contextWindow` — codex measures against 95% of the window it\n * is configured with, so expansive GPT-6 is `providerWindow: 872_000`\n * (`-c model_context_window=872000`) but `contextWindow: 828_400`.\n */\n providerWindow?: number | null;\n}\n\nexport interface VerseModelOption {\n id: string;\n label: string;\n /** Standard-mode window the CLI measures against (codex: the 95% effective window). */\n contextWindow: number | null;\n /**\n * V3.9 ADDITIVE — every field below is optional so records and fixtures\n * written before it keep validating. Absent means \"not known\", never zero.\n */\n /** Standard-mode auto-compaction point. */\n autoCompactAt?: number | null;\n /** Present ONLY when this model on this seat has a real expansive mode. */\n expansive?: VerseContextBudget | null;\n /** The CLI's default max output for this model, when known. */\n maxOutputTokens?: number | null;\n windowSource?: VerseWindowSource;\n /** Minimum CLI version that knows this model id (e.g. '2.1.280'); null when any. */\n minCliVersion?: string | null;\n /**\n * Why this model cannot run on this seat right now, in plain language (e.g.\n * \"needs Claude Code 2.1.280; this seat runs 2.1.257\"). Null/absent = runnable.\n * Listed rather than hidden so the operator learns WHY a model is missing.\n */\n unavailableReason?: string | null;\n}\n\nexport interface VerseSeatHealth {\n state: 'ready' | 'degraded' | 'unavailable' | 'unknown';\n /** e.g. \"5h window 72% used, resets 14:00\" — plain text, already sanitized. */\n summary: string | null;\n windows: Array<{ id: string; usedPercent: number | null; resetsAt: string | null }>;\n observedAt: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Seat capacity (V2.1, additive) — see docs/VERSE-TELEMETRY-V2.md, which is\n// the authority for every honesty rule encoded in these shapes.\n//\n// This file is imported by the BROWSER bundle, so it may not import\n// `core/verse/accounts.ts` (node:fs). The shapes below therefore restate the\n// provider-record shapes structurally. `seats.ts` assigns the account record's\n// values straight into them, so a divergence in `core/verse/accounts.ts` stops\n// `seats.ts` compiling — that assignment is the drift guard.\n// ---------------------------------------------------------------------------\n\n/** One provider-reported quota window, as carried on a seat. */\nexport interface VerseSeatWindow {\n id: string;\n /** Provider-reported percent, or null for NO SIGNAL — which is not zero. */\n usedPercent: number | null;\n /**\n * Machine-readable reset instant. STRUCTURALLY ALWAYS NULL for Claude: that\n * provider publishes only a sentence, which lives in `resetDescription` and\n * is rendered verbatim. Never synthesize a countdown from a description.\n */\n resetsAt: string | null;\n /** The provider's own reset wording, verbatim (\"resets Sep 25 at 7pm (America/New_York)\"). */\n resetDescription: string | null;\n /**\n * TRUE only when the provider explicitly FLAGGED the limit. Such a window's\n * `usedPercent` is the SENTINEL 100 — a denial, not a measurement — and must\n * be labelled \"limit reached\", never \"100% used\".\n */\n limitReached: boolean;\n /** False when `usedPercent` is a flagged sentinel rather than a reading. */\n measured: boolean;\n}\n\n/**\n * Codex credits, INDEPENDENT of the window: a fully used weekly window with a\n * spendable balance is not blocked. `null` is \"no signal\", never \"no credits\".\n */\nexport interface VerseSeatCredits {\n hasCredits: boolean;\n unlimited: boolean;\n /** Provider-reported decimal string, kept verbatim — never rounded. */\n balance: string | null;\n}\n\n/**\n * The coarse \"can I use this seat right now\" verdict. Deliberately coarse: the\n * exact numbers are in `windows`, and a verdict that pretended to more\n * precision than the providers give would be a lie.\n *\n * - `ready` — a reading exists and the binding window has headroom.\n * - `tight` — the binding window is at/above the warn threshold, OR it is\n * spent while Codex credits remain spendable (not blocked).\n * - `exhausted` — the binding window is spent and nothing else is left.\n * - `signed-out` — the account is not authenticated; reconnect it.\n * - `unknown` — NO window carried a percent. Not zero, not healthy.\n */\nexport type VerseSeatUsability = 'ready' | 'tight' | 'exhausted' | 'signed-out' | 'unknown';\n\n/**\n * Where a seat's windows came from, so nothing implies freshness it lacks.\n * Mirrors `VerseEvidenceSource` in `core/verse/accounts.ts`.\n */\nexport type VerseSeatEvidenceSource = 'collector' | 'shared-evidence' | 'baseline' | 'none';\n\n/** Everything the seat list needs to draw a capacity meter honestly. */\nexport interface VerseSeatCapacity {\n /** e.g. \"max\", \"pro\", \"SuperGrok\". Null when the provider gave none. */\n planType: string | null;\n /**\n * THE CONSTRAINT THAT ACTUALLY BLOCKS WORK: the window with the highest\n * `usedPercent`. Null when no window carried a percent at all.\n */\n binding: VerseSeatWindow | null;\n /** Every window the provider reported, in provider order. */\n windows: VerseSeatWindow[];\n /** Codex only; null for every other provider and when no signal exists. */\n credits: VerseSeatCredits | null;\n usability: VerseSeatUsability;\n observedAt: string | null;\n evidenceSource: VerseSeatEvidenceSource;\n /** Plain-language provider facts the UI must show instead of implying a fault. */\n notes: string[];\n}\n\nexport interface VerseProject {\n path: string;\n name: string;\n /** From ~/.ashlr/enrollment.json when present. */\n enrolled: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Workspaces (V2.2, ADDITIVE) — see docs/VERSE-WORKSPACES.md §1.\n//\n// A session bound to ONE directory cannot express \"this service plus the\n// shared library it depends on\", which is most real work. A workspace is a\n// NAMED set of roots with exactly one marked primary.\n//\n// `VerseSession.projectPath` keeps its meaning — it IS the primary root — so\n// every session record, adapter and test written before workspaces existed\n// still loads and still runs. Nothing rewrites saved chat history.\n//\n// ENROLLMENT IS NOT PART OF THIS SHAPE ON PURPOSE. A workspace says what a\n// session may REACH; `~/.ashlr/enrollment.json` says what the AUTONOMOUS lane\n// may mutate, and the two are deliberately separate registries. Membership in\n// a workspace grants no enrollment: `enrolled` below is READ from the\n// registry per root and is never written by anything in this feature.\n// ---------------------------------------------------------------------------\n\n/** One directory in a workspace. Exactly one root in a workspace is primary. */\nexport interface VerseWorkspaceRoot {\n /** Absolute, physically resolved path (symlinks followed). */\n path: string;\n /** Display name; defaults to the basename. */\n name: string;\n /**\n * The session's cwd and the value `projectPath` carries. Exactly one root\n * per workspace has this set.\n */\n primary: boolean;\n}\n\n/**\n * A named set of roots.\n *\n * ONE TYPE, TWO USES, DELIBERATELY. An interactive session binds to a\n * workspace to decide what it can reach; the autonomous lane reads the same\n * workspace as a SECTION — \"these repositories collaborate, work on them\n * together\" — when `section` is true. They were not split because the thing\n * being named is identical in both: a set of directories that belong to one\n * piece of work. Two registries of named repo groups would drift.\n *\n * What is NOT on this type is priority. A repo may belong to several\n * workspaces, so a per-membership rank would give one repo several\n * contradictory ranks. Priority is therefore an attribute OF THE REPO, held\n * once per path in the same registry — see `VerseRootPriority`.\n */\nexport interface VerseWorkspace {\n id: string;\n name: string;\n /** Primary first, then the extras in the order they were added. */\n roots: VerseWorkspaceRoot[];\n /**\n * Offer this workspace to the autonomous lane as a section.\n *\n * GRANTS NOTHING. The fleet still reaches only what\n * `~/.ashlr/enrollment.json` permits; a section can group and order those\n * repos and nothing else. A member that is not enrolled stays unreachable.\n */\n section: boolean;\n createdAt: string;\n updatedAt: string;\n}\n\n/**\n * Relative standing of one repository in the autonomous lane's attention.\n *\n * ORDERING ONLY, NEVER ADMISSION. `critical` on an unenrolled repo is still\n * refused by `assertMayMutate`; `low` on an enrolled one is still permitted.\n * An ordinal rather than a number because the operator's judgement here is\n * \"this matters more than that\", and a 0-100 score would invent a precision\n * nobody holds.\n *\n * Absent means `normal`, which is how every repo already behaves — so a\n * registry with no priorities at all reproduces today's flat list exactly.\n */\nexport type VerseRootPriority = 'critical' | 'high' | 'normal' | 'low';\n\nexport const VERSE_ROOT_PRIORITIES: readonly VerseRootPriority[] =\n ['critical', 'high', 'normal', 'low'];\n\nexport const VERSE_DEFAULT_ROOT_PRIORITY: VerseRootPriority = 'normal';\n\n/** Sort weight; lower sorts first. Never a budget, never a multiplier. */\nexport const VERSE_ROOT_PRIORITY_RANK: Record<VerseRootPriority, number> = {\n critical: 0,\n high: 1,\n normal: 2,\n low: 3,\n};\n\n/** One enrolled repository as the autonomy scope view ranks it. */\nexport interface VerseAutonomyScopeEntry {\n path: string;\n name: string;\n priority: VerseRootPriority;\n /** Sections (workspaces with `section: true`) this repo belongs to. */\n sections: Array<{ id: string; name: string }>;\n /** True when a focus section is set and this repo is outside it. */\n outsideFocus: boolean;\n}\n\n/**\n * The autonomous lane's scope, ORDERED.\n *\n * Built by INTERSECTING section membership with the enrollment registry, so\n * it can only ever be a subset of what enrollment already allows. Sections\n * add ordering and grouping; they never add reach.\n */\nexport interface VerseAutonomyScopeView {\n focusSectionId: string | null;\n focusSectionName: string | null;\n /** Enrolled repos, most important first. */\n entries: VerseAutonomyScopeEntry[];\n /**\n * Paths a section names that are NOT enrolled. Listed so the blast radius\n * is legible in both directions — these are exactly the repos a section\n * does NOT give the fleet.\n */\n unenrolledSectionRoots: string[];\n}\n\n/**\n * Per-root git identity. A turn that edits two repos produces two diffs, so\n * the transcript has to be able to attribute each file to the right one.\n *\n * `remote` is the canonical `owner/repo` for a GitHub origin and null for\n * anything else — deliberately NOT the raw remote URL, which can carry a\n * token in its userinfo and would then reach an API response.\n */\nexport interface VerseRootGit {\n branch: string;\n /** Count of porcelain entries; 0 is clean. */\n dirty: number;\n ahead: number;\n behind: number;\n remote: string | null;\n}\n\n/** A root as the client sees it: identity, reachability and honest scope. */\nexport interface VerseRootStatus {\n path: string;\n name: string;\n primary: boolean;\n exists: boolean;\n /**\n * Read live from the enrollment registry. FALSE means the interactive lane\n * still works on this root while the autonomous lane refuses it — being in\n * a workspace never changes this.\n */\n enrolled: boolean;\n /** Null when the root is not a git repository, or git is unavailable. */\n git: VerseRootGit | null;\n /**\n * False when the session's engine has no way to be granted this root (Grok's\n * CLI exposes `--cwd` and nothing else). The root is still listed, because\n * hiding it would misrepresent what the workspace is.\n */\n reachable: boolean;\n}\n\n/** GET /api/verse/sessions/:id/roots */\nexport interface VerseSessionRootsResponse {\n sessionId: string;\n workspaceId: string | null;\n workspaceName: string | null;\n roots: VerseRootStatus[];\n /**\n * Plain-language facts the UI must show rather than imply: an unreachable\n * root on a Grok seat, or a root the autonomous lane will refuse.\n */\n notes: string[];\n}\n\n/** GET /api/verse/workspaces */\nexport interface VerseWorkspacesResponse {\n workspaces: VerseWorkspace[];\n /** Live per-root facts, keyed by workspace id, so one read draws the list. */\n status: Record<string, VerseRootStatus[]>;\n /** Per-repo priority, keyed by canonical path. Absent key means `normal`. */\n priorities: Record<string, VerseRootPriority>;\n focusSectionId: string | null;\n}\n\n/** POST /api/verse/workspaces */\nexport interface VerseWorkspaceCreateRequest {\n name: string;\n /** Absolute paths. The first is the primary. */\n roots: string[];\n /** Also offer this set to the autonomous lane as a section. Default false. */\n section?: boolean;\n}\n\n/** POST /api/verse/workspaces/:id/update */\nexport interface VerseWorkspaceUpdateRequest {\n name?: string;\n /** When present, replaces the root set wholesale. First entry is primary. */\n roots?: string[];\n section?: boolean;\n}\n\n/** POST /api/verse/workspaces/priority */\nexport interface VerseRootPriorityRequest {\n path: string;\n priority: VerseRootPriority;\n}\n\n/** POST /api/verse/workspaces/focus — `sectionId: null` clears the focus. */\nexport interface VerseFocusSectionRequest {\n sectionId: string | null;\n}\n\n/** Hard cap on roots per workspace — a blast radius, not a UI limit. */\nexport const VERSE_MAX_WORKSPACE_ROOTS = 8;\n\n/**\n * Every root a session can reach, primary first.\n *\n * Pure and total: a record written before workspaces existed has no\n * `extraRoots` and yields exactly `[projectPath]`, which is what every caller\n * assumed before this existed.\n */\nexport function verseSessionRoots(\n session: Pick<VerseSession, 'projectPath' | 'extraRoots'>,\n): string[] {\n const out = [session.projectPath];\n for (const root of session.extraRoots ?? []) {\n if (typeof root === 'string' && root.length > 0 && !out.includes(root)) out.push(root);\n }\n return out;\n}\n\nexport interface VerseUsage {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheCreationTokens: number;\n /**\n * Prompt size of the most recent assistant call = live context occupancy.\n * Stored UNCLAMPED: a reading above the window is information (the CLI is\n * about to compact or overflow), and only the UI decides how to draw it.\n */\n contextTokens: number;\n contextWindow: number | null;\n /** V3.9 ADDITIVE. Where `contextWindow` came from; absent on old records. */\n contextWindowSource?: VerseWindowSource;\n /** V3.9 ADDITIVE. Auto-compaction point for the session's current mode. */\n autoCompactAt?: number | null;\n /**\n * V3.9 ADDITIVE. False when `contextTokens` is an UPPER BOUND rather than a\n * measurement (codex before its rollout is readable: the turn total sums\n * every model call). Absent means exact.\n */\n contextTokensExact?: boolean;\n}\n\nexport interface VerseSession {\n id: string;\n title: string;\n /**\n * The PRIMARY root: the process cwd and the folder every pre-workspace\n * client already reads. Unchanged in meaning, which is why no session\n * record ever has to be rewritten.\n */\n projectPath: string;\n /**\n * V2.2 ADDITIVE. Roots BEYOND the primary, pinned at creation time.\n *\n * Absent on every record written before workspaces existed, and absent on\n * a single-root session today — so the on-disk shape of an ordinary chat\n * does not change at all.\n *\n * PINNED, not referenced: a session keeps the roots it was created with\n * even if the named workspace is later edited or deleted, for the same\n * reason `launch.anthropicBaseUrl` is pinned — a conversation must not\n * silently gain reach because config moved underneath it.\n */\n extraRoots?: string[];\n /** V2.2 ADDITIVE. Provenance of the pinned roots; absent for an ad-hoc set. */\n workspaceId?: string;\n workspaceName?: string;\n engine: VerseEngine;\n accountId: string;\n seatId: string;\n model: string;\n /** Vendor conversation id used for resume (claude/grok: our uuid; codex: thread id from output). */\n nativeSessionId: string | null;\n createdAt: string;\n updatedAt: string;\n status: VerseSessionStatus;\n turnCount: number;\n usage: VerseUsage;\n lastError: string | null;\n /**\n * V3.9 ADDITIVE. The session's context budget. Every record written by 3.9+\n * carries it explicitly, so ABSENT means a pre-3.9 record: the engine\n * materializes it on first touch — `expansive` for a Claude 1M model (that\n * is the native ~967k compaction those chats always ran with, so upgrading\n * never forces a paid compaction), `standard` otherwise (= native).\n * Changeable mid-session (POST /sessions/:id/context-mode): it changes CLI\n * flags, not prompt content — but switching DOWN below the current\n * occupancy makes the CLI compact on its next turn.\n */\n contextMode?: VerseContextMode;\n /** V3.9 ADDITIVE. Native compactions observed so far (claude/grok compact_boundary, codex rollout `compacted`). */\n compactionCount?: number;\n /** V3.9 ADDITIVE. Set when this session was started as a handoff from another. */\n handoffFrom?: { sessionId: string; title: string };\n /**\n * V3.9 ADDITIVE. Shared project memory was offered to this session's CLI at\n * creation. Pinned, like the roots: a conversation must not silently gain a\n * writable directory because a preference moved underneath it.\n */\n memoryEnabled?: boolean;\n /**\n * V3.10 ADDITIVE (contract: unit C0; written by C3's engine). The operator's\n * per-chat effort and permission choices, applied from the NEXT turn — a\n * running turn keeps the argv it was launched with. Absent (every record\n * before 3.10, and any key never set) = the engine default: permission mode\n * `accept-edits`, effort = the CLI's own default.\n *\n * A MODEL change is deliberately NOT stored here: it rewrites `model` above,\n * which every launch already reads — one field, one truth.\n */\n controls?: VerseSessionControls;\n}\n\n/**\n * V3.10. Permission modes a chat can run in (SPEC-310C §0.6), in picker order.\n * - `plan` — the CLI plans and edits nothing.\n * - `accept-edits` — the default: edits applied without asking.\n * - `auto` — the CLI's own auto mode.\n * - `bypass` — every check skipped. Shown red and confirmed PER CHAT:\n * never a default, never inherited by a new chat.\n * Adapters map these to each CLI's spelling (claude `acceptEdits` /\n * `bypassPermissions`, grok `dontAsk`, …). An engine that cannot honour one\n * reports it unavailable WITH a reason rather than approximating it. The\n * in-page \"Ask\" mode (answering permission prompts in the UI) is 3.11.\n */\nexport const VERSE_PERMISSION_MODES = ['plan', 'accept-edits', 'auto', 'bypass'] as const;\nexport type VersePermissionMode = (typeof VERSE_PERMISSION_MODES)[number];\nexport const VERSE_DEFAULT_PERMISSION_MODE: VersePermissionMode = 'accept-edits';\n\n/**\n * V3.10. Reasoning effort, the union across engines — claude `--effort`\n * (low · medium · high · xhigh · max) and codex `model_reasoning_effort`\n * (minimal · low · medium · high · xhigh). Each seat offers only the subset\n * its CLI accepts; the rest come back unavailable with a reason.\n */\nexport const VERSE_EFFORTS = ['minimal', 'low', 'medium', 'high', 'xhigh', 'max'] as const;\nexport type VerseEffort = (typeof VERSE_EFFORTS)[number];\n\n/** V3.10. `VerseSession.controls` — absent key = engine default (see there). */\nexport interface VerseSessionControls {\n effort?: VerseEffort;\n permissionMode?: VersePermissionMode;\n}\n\n/** Normalized event stream. `seq` is monotonic per session and is the SSE id. */\nexport type VerseEvent =\n | { seq: number; at: string; type: 'user-message'; turnId: string; text: string }\n | { seq: number; at: string; type: 'turn-started'; turnId: string; pid: number | null }\n | { seq: number; at: string; type: 'text-delta'; turnId: string; text: string }\n | { seq: number; at: string; type: 'assistant-message'; turnId: string; text: string }\n /**\n * Reasoning the CLI chose to show. V3.10 ADDITIVE optional fields (absent on\n * older records = unknown, never \"false\"/\"0\"):\n * - `redacted` the CLI sent a signature-only / redacted block, so `text` is\n * empty but the model DID think (the UI says \"Thought 12s\").\n * - `durationMs` wall time the block took to stream, when measured.\n * - `kind` see VerseThinkingKind.\n */\n | {\n seq: number;\n at: string;\n type: 'thinking';\n turnId: string;\n text: string;\n redacted?: boolean;\n durationMs?: number;\n kind?: VerseThinkingKind;\n }\n | { seq: number; at: string; type: 'tool-use'; turnId: string; toolUseId: string; name: string; input: unknown }\n | { seq: number; at: string; type: 'tool-result'; turnId: string; toolUseId: string; output: string; isError: boolean }\n | { seq: number; at: string; type: 'usage'; turnId: string; usage: VerseUsage }\n | { seq: number; at: string; type: 'turn-done'; turnId: string; ok: boolean; nativeSessionId: string | null; durationMs: number }\n /**\n * `code` (V3.10 ADDITIVE, optional) is a stable machine key for errors the UI\n * or engine acts on — see VERSE_ERROR_CODES. Absent = uncategorised.\n */\n | { seq: number; at: string; type: 'error'; turnId: string | null; message: string; code?: string }\n | { seq: number; at: string; type: 'cancelled'; turnId: string }\n /**\n * V3.9. The CLI compacted its own conversation. Token counts are the CLI's\n * own (`compact_metadata.pre_tokens/post_tokens` on claude/grok). Codex\n * rollouts mark only THAT a compaction happened, so its counts are the last\n * `token_count` reading before the marker and the first one after it —\n * measured, but by Verse, not stated by the CLI; its `durationMs` is null.\n * Any count may be null when no reading brackets the compaction.\n */\n | {\n seq: number;\n at: string;\n type: 'compaction';\n turnId: string | null;\n trigger: 'auto' | 'manual';\n preTokens: number | null;\n postTokens: number | null;\n durationMs: number | null;\n }\n /**\n * V3.9. A context-occupancy READING that is not a usage delta — e.g. codex's\n * rollout `token_count` (exact last-call prompt size and the window the CLI\n * measured it against), polled mid-turn and read again after it. Replaces\n * the session's `contextTokens`; never summed. The engine fills\n * `autoCompactAt` for the window in force.\n */\n | {\n seq: number;\n at: string;\n type: 'context';\n turnId: string | null;\n contextTokens: number;\n contextWindow: number | null;\n exact: boolean;\n autoCompactAt?: number | null;\n /**\n * Where `contextWindow` came from. A CLI reading is `runtime`; the event\n * the engine writes after a MODE SWITCH carries the new budget's catalog\n * source, so a client never relabels a catalog figure as a measurement.\n * Absent on events from before this field existed (treat as `runtime`).\n */\n contextWindowSource?: VerseWindowSource;\n }\n // ── V3.10 TRANSIENT events ────────────────────────────────────────────────\n // Never written to the session log; fanned out to live SSE listeners only\n // (see VERSE_TRANSIENT_EVENT_TYPES for the wire rules). A reload therefore\n // never shows them — everything they convey is either ephemeral (a spinner)\n // or re-stated by a persisted event at turn end (`thinking`, `usage`).\n /** A chunk of streamed reasoning text for the in-flight thinking block. */\n | { seq: number; at: string; type: 'thinking-delta'; turnId: string; text: string }\n /**\n * The CLI reports reasoning volume without text (claude\n * `system/thinking_tokens`). An ESTIMATE, rate-limited by the adapter.\n */\n | { seq: number; at: string; type: 'thinking-progress'; turnId: string; estimatedTokens: number }\n /**\n * What the running turn is doing right now. `tool` names the running tool\n * when phase is `tool`. `outTokens`/`tokPerSec` are absent when unmeasured.\n */\n | {\n seq: number;\n at: string;\n type: 'progress';\n turnId: string;\n phase: VerseProgressPhase;\n tool?: string;\n elapsedMs: number;\n outTokens?: number;\n tokPerSec?: number;\n }\n /** A human-readable notice about the turn's plumbing (API retry, preflight, no-output watchdog). */\n | { seq: number; at: string; type: 'status'; turnId: string | null; kind: VerseStatusKind; message: string }\n // ── V3.10 PERSISTED events ────────────────────────────────────────────────\n /**\n * The engine recovered from a lost native conversation (e.g. the vendor\n * thread vanished) by starting a new native session seeded with the handoff\n * note (`how: 'handoff'`) or a bare new session (`new-native-session`).\n */\n | { seq: number; at: string; type: 'recovered'; turnId: string | null; how: VerseRecoveryHow; message: string }\n /**\n * The log hit its cap and events with `seq < droppedBefore` were dropped at\n * a TURN boundary (never mid-turn). `turnId` is always null — it is present\n * only so code reading `event.turnId` across the union keeps typechecking.\n */\n | { seq: number; at: string; type: 'history-truncated'; turnId: null; droppedBefore: number };\n\nexport type VerseEventType = VerseEvent['type'];\n\n/** V3.10. `summary` = vendor-summarised reasoning, `raw` = verbatim, `progress` = a heading/placeholder only. */\nexport type VerseThinkingKind = 'summary' | 'raw' | 'progress';\n\n/** V3.10. Phase of a running turn, carried by the transient `progress` event. */\nexport type VerseProgressPhase = 'thinking' | 'tool' | 'writing' | 'waiting';\n\n/** V3.10. What a transient `status` notice is about. */\nexport type VerseStatusKind = 'retry' | 'preflight' | 'watchdog';\n\n/** V3.10. How a `recovered` event restored the conversation. */\nexport type VerseRecoveryHow = 'new-native-session' | 'handoff';\n\n/**\n * V3.10. Known `error.code` values. `code` stays `string` on the wire so an\n * older client never rejects a newer code; these are the ones Verse acts on.\n * - `native-thread-missing` — the vendor conversation to resume no longer exists.\n * - `session-in-use` — the CLI refused because the native session id is locked.\n */\nexport const VERSE_ERROR_CODES = ['native-thread-missing', 'session-in-use'] as const;\nexport type VerseErrorCode = (typeof VERSE_ERROR_CODES)[number];\n\n/**\n * V3.10. Event types that are NEVER persisted — emitted to live SSE listeners\n * only. Wire rules (A5 server, A6 client):\n * - a transient event carries `seq` = the session's LAST PERSISTED seq (the\n * counter does not advance), so the stored log stays gap-free and a server\n * restart can never reissue a seq a client already saw;\n * - its SSE frame has NO `id:` line, so the browser's Last-Event-ID resume\n * cursor only ever points at persisted events;\n * - clients must not dedupe, store or resume by a transient event's seq.\n * Browser-safe (plain Set), imported by the web bundle.\n */\nconst TRANSIENT_EVENT_TYPE_LIST = [\n 'thinking-delta',\n 'thinking-progress',\n 'progress',\n 'status',\n] as const satisfies readonly VerseEventType[];\n\nexport const VERSE_TRANSIENT_EVENT_TYPES: ReadonlySet<VerseEventType> = new Set<VerseEventType>(TRANSIENT_EVENT_TYPE_LIST);\n\nexport type VerseTransientEventType = (typeof TRANSIENT_EVENT_TYPE_LIST)[number];\nexport type VerseTransientEvent = Extract<VerseEvent, { type: VerseTransientEventType }>;\nexport type VersePersistedEvent = Exclude<VerseEvent, { type: VerseTransientEventType }>;\n\n/** V3.10. Type guard over VERSE_TRANSIENT_EVENT_TYPES. */\nexport function isTransientVerseEvent(event: VerseEvent): event is VerseTransientEvent {\n return VERSE_TRANSIENT_EVENT_TYPES.has(event.type);\n}\n\n/**\n * Which endpoint a LOCAL seat sends its turns to.\n *\n * - `ollama` — the historical lane: the plain `claude` binary with\n * ANTHROPIC_BASE_URL pointed straight at Ollama's\n * Anthropic-compatible endpoint on :11434. Ollama\n * serialises this model architecture, so a fleet of local\n * agents on this lane is a queue (docs/LOCAL-FLEET.md).\n * - `llama-server` — the same binary pointed at the local Anthropic\n * normalising proxy that fronts llama-server. That proxy\n * is the ONLY way to reach llama-server's parallel slots\n * and the prompt-cache fix, because Qwen3.8's chat\n * template rejects Claude Code's request shape unless the\n * proxy rewrites it on the way through.\n *\n * DISPATCH ONLY. Model DISCOVERY stays on Ollama in both lanes — llama-server\n * implements neither `/api/tags` nor `/api/show`, which is where every local\n * seat's identity, context window and `tools` capability comes from.\n */\nexport type VerseLocalDispatch = 'ollama' | 'llama-server';\n\n/** What a client is told about this machine's local serving situation. */\nexport interface VerseLocalRuntimeSummary {\n /** Ollama reachable? Drives the local seats and an inline hint when false. */\n ollama: { reachable: boolean; baseUrl: string; models: string[] };\n /**\n * Where local seats DISPATCH turns, reported only when that is NOT the\n * default Ollama lane.\n *\n * Absent means `ollama`, i.e. exactly what every existing client already\n * assumes — so opting in is visible on the wire and NOT opting in changes no\n * payload at all.\n */\n dispatch?: { lane: VerseLocalDispatch; baseUrl: string };\n}\n\n/** GET /api/verse/bootstrap */\nexport interface VerseBootstrap {\n seats: VerseSeat[];\n projects: VerseProject[];\n sessions: VerseSession[];\n /** Whether POST routes are enabled on this server (`ashlr serve --allow-dispatch` / `ashlr verse`). */\n dispatchEnabled: boolean;\n localRuntime: VerseLocalRuntimeSummary;\n}\n\n/**\n * GET /api/verse/seats (V2.1)\n *\n * WHY THIS ROUTE EXISTS: `bootstrap` is a MOUNT-TIME snapshot. A client that\n * opened the app before the collector's first cycle finished would show\n * \"unknown\" forever. This is the same seat list, cheap enough to poll, and it\n * always reflects the collector's CURRENT state rather than a cached one.\n */\nexport interface VerseSeatsResponse {\n /** When this body was built. */\n sampledAt: string;\n seats: VerseSeat[];\n localRuntime: VerseBootstrap['localRuntime'];\n}\n\n/**\n * POST /api/verse/sessions\n *\n * Two spellings, never mixed (the API rejects the mix rather than silently\n * preferring one):\n * - `workspaceId` alone — the named workspace supplies primary and extras.\n * - `projectPath` (+ optional `extraRoots`) — an ad-hoc set, which is also\n * exactly the pre-workspace request shape.\n */\nexport interface VerseCreateSessionRequest {\n projectPath: string;\n seatId: string;\n model?: string;\n title?: string;\n /** V2.2 ADDITIVE. Absolute paths beyond the primary. */\n extraRoots?: string[];\n /** V2.2 ADDITIVE. Bind to a named workspace instead of naming paths. */\n workspaceId?: string;\n /**\n * SERVER-FILLED. The API resolves this from the registry once `workspaceId`\n * is validated, and never reads it off the request body — so a session can\n * not be labelled with a workspace name that is not the one it was built\n * from.\n */\n workspaceName?: string;\n /**\n * V3.9 ADDITIVE. Absent → the seat's preferred mode (preferences.json), else\n * `standard`. `expansive` on a model with no expansive budget is rejected.\n */\n contextMode?: VerseContextMode;\n /**\n * V3.9 ADDITIVE. Start this session as a handoff from an existing one. The\n * server resolves the source's title itself (never from the body) and pins\n * `handoffFrom`; the handoff TEXT is sent by the client as turn 1, after the\n * operator has read it — nothing is spent on their behalf.\n */\n handoffFromSessionId?: string;\n}\n\n/** POST /api/verse/sessions/:id/turns */\nexport interface VerseTurnRequest {\n text: string;\n}\nexport interface VerseTurnResponse {\n turnId: string;\n session: VerseSession;\n}\n\n/** GET /api/verse/sessions/:id */\nexport interface VerseSessionDetail {\n session: VerseSession;\n events: VerseEvent[];\n}\n\n/** Adapter input: how to launch one turn. Pure data, produced by the engine, consumed by the spawner. */\nexport interface VerseTurnLaunch {\n argv: string[];\n cwd: string;\n /** Extra env layered over a minimal base (PATH/HOME/TMPDIR/LANG). Never contains secrets. */\n env: Record<string, string>;\n /** Text written to stdin (codex); null when the prompt is in argv. */\n stdin: string | null;\n}\n\nexport const VERSE_MAX_TURN_TEXT_BYTES = 64 * 1024;\nexport const VERSE_MAX_EVENTS_PER_SESSION = 20_000;\nexport const VERSE_TURN_TIMEOUT_MS = 30 * 60 * 1000;\n/**\n * LAST-RESORT fallbacks, used only when neither the runtime, the seat's own\n * catalog, nor the verified per-model table (core/verse/model-windows.ts) knows\n * the model. Each mirrors what the CLI ITSELF assumes for an unknown id, so the\n * meter never claims more than the CLI will allow:\n *\n * - claude 200_000 — Claude Code's `Mg()` default for an unrecognized model.\n * Every KNOWN Claude id carries its real window (1M for the 5.x family,\n * Opus 4.8 and Sonnet 5) in the per-model table instead.\n * - codex 258_400 — 272_000 × the 95% `effective_context_window_percent`\n * every codex catalog entry carries; the figure codex's own rollouts report\n * as `model_context_window` (65,440 of 65,440 observed events).\n * - grok 500_000 — `context_window` for every grok-4.x id in the seat catalog.\n * - local 65_536 — the num_ctx the default local tag pins.\n */\nexport const VERSE_DEFAULT_CONTEXT_WINDOWS: Record<string, number> = {\n claude: 200_000,\n codex: 258_400,\n grok: 500_000,\n local: 65_536,\n};\n\n// ---------------------------------------------------------------------------\n// V3.9 context orchestration — request/response shapes (docs/VERSE-CONTEXT.md)\n// ---------------------------------------------------------------------------\n\n/** GET /api/verse/preferences — the operator's standing context choices. */\nexport interface VersePreferences {\n version: 1;\n /** Per-seat default context mode for NEW sessions. Absent = `standard`. */\n seats: Record<string, { contextMode?: VerseContextMode }>;\n /** Shared project memory. On by default; listed canonical paths opt out. */\n memory: { enabled: boolean; disabledProjects: string[] };\n /**\n * V3.10 ADDITIVE. Stream vendor-summarised reasoning on non-local seats\n * (claude `--thinking-display summarized`). Absent = on (Mason's default).\n */\n thinkingDisplay?: boolean;\n}\n\n/**\n * POST /api/verse/preferences — exactly ONE of the three forms per request, so\n * a body can never change more than the operator clicked.\n */\nexport type VersePreferencesUpdate =\n | { seatId: string; contextMode: VerseContextMode }\n | { memoryEnabled: boolean }\n | { projectPath: string; memoryEnabled: boolean };\n\n/** POST /api/verse/sessions/:id/context-mode */\nexport interface VerseContextModeRequest {\n mode: VerseContextMode;\n}\n\n/** POST /api/verse/sessions/:id/handoff-preview */\nexport interface VerseHandoffPreviewRequest {\n /**\n * Include the latest assistant message verbatim (capped) as the agent's own\n * summary — used after \"Ask this seat to summarize\" produced one.\n */\n includeLastAssistant?: boolean;\n /** Optional operator focus line, e.g. \"finish the migration of X\". ≤ 500 chars. */\n focus?: string;\n}\n\n/** Deterministic, zero-spend handoff note built from the session's event log. */\nexport interface VerseHandoffPreview {\n sourceSessionId: string;\n sourceTitle: string;\n /** The exact text to send as turn 1 of the new session. ≤ VERSE_HANDOFF_MAX_CHARS. */\n text: string;\n stats: {\n chars: number;\n /** chars / 4, rounded up — the same estimator the fit badges use. */\n estTokens: number;\n turnsCovered: number;\n filesTouched: number;\n /** Sections dropped to respect the cap, by name; empty when nothing was cut. */\n truncated: string[];\n };\n}\n\nexport const VERSE_HANDOFF_MAX_CHARS = 12_000;\n\n/**\n * The canned turn behind \"Ask this seat to summarize first\". Shared by the UI\n * (which sends it as an ordinary turn through the normal spend chokepoint) and\n * the handoff builder (which must NOT carry it into the new session as the\n * operator's \"latest ask\" — the new chat would otherwise be told to write a\n * handoff note instead of continuing the work).\n *\n * Written so the reply is useful as turn 1 of a session that has NONE of this\n * context. It asks for no tool use on purpose: a summary that starts editing\n * files is not a summary, and a read-only turn is also the cheapest one.\n */\nexport const VERSE_HANDOFF_SUMMARY_REQUEST = [\n 'This conversation is about to continue in a fresh session that has none of its context.',\n 'Write the handoff note that new session should start from. Do not edit files or run commands for this — only write the note.',\n '',\n 'Cover, concretely:',\n '- The goal, and what \"done\" looks like.',\n '- Decisions made so far, each with the reason it was made.',\n '- Current state: what is finished, what is half-done, what is untested.',\n '- Files changed and anything not yet committed.',\n '- How to verify the work (exact commands).',\n '- Open questions, risks, and approaches already tried that did not work.',\n '',\n 'Keep it under 600 words. Prefer file paths and commands over prose.',\n].join('\\n');\n\n/** GET /api/verse/context-fit — how big the reachable code is, in tokens. */\nexport interface VerseContextFitRoot {\n path: string;\n /** Tracked text files counted (git ls-files, binaries and >1 MB files skipped). */\n files: number;\n bytes: number;\n estTokens: number;\n /** True when the scan hit its file or time cap; estTokens is then a floor. */\n truncated: boolean;\n}\n\nexport interface VerseContextFit {\n roots: VerseContextFitRoot[];\n totalEstTokens: number;\n /** Always 'bytes/4' today; named so a better estimator can be introduced honestly. */\n estimator: 'bytes/4';\n sampledAt: string;\n}\n\n/**\n * Per-model verdict for a working set (see context-math.ts `fitVerdict`):\n * fits in standard, tight in standard, fits only in expansive, or too big for\n * any single context (split the work).\n */\nexport type VerseFitVerdict = 'fits' | 'tight' | 'expansive' | 'split';\n\n/** GET /api/verse/search?q=&limit= — keyword search over past sessions. Zero spend. */\nexport interface VerseSearchHit {\n sessionId: string;\n title: string;\n projectPath: string;\n engine: VerseEngine;\n seq: number;\n at: string;\n kind: 'user' | 'assistant';\n /** ≤ 240 chars around the first match, whitespace-collapsed. */\n snippet: string;\n score: number;\n}\n\nexport interface VerseSearchResponse {\n query: string;\n hits: VerseSearchHit[];\n /** Sessions actually scanned (the scan is bounded; see session-search.ts). */\n scannedSessions: number;\n truncated: boolean;\n}\n\n/** GET/POST /api/verse/memory — shared project memory for one project. */\nexport interface VerseProjectMemory {\n projectPath: string;\n enabled: boolean;\n /** Contents of MEMORY.md ('' when absent). */\n content: string;\n bytes: number;\n updatedAt: string | null;\n /** Other files the agents created in the memory directory (names only). */\n files: string[];\n /**\n * Present (true) only when `content` as SENT differs from the bytes on disk:\n * the public-JSON sanitizer rewrote the home path to `~` or replaced a\n * secret-looking value with `[REDACTED]`. The file itself is untouched; a\n * save that would write placeholders over real values is refused (409\n * VERSE_MEMORY_REDACTED), so the editor must say so before the operator types.\n */\n contentSanitized?: boolean;\n}\n\n/** POST /api/verse/memory */\nexport interface VerseProjectMemoryWrite {\n projectPath: string;\n content: string;\n}\n\nexport const VERSE_MEMORY_MAX_BYTES = 64 * 1024;\n\n/**\n * POST /api/verse/memory's own JSON body cap: JSON escaping can double the\n * content (every newline becomes `\\\\n`), plus room for the other fields. Every\n * other route keeps the 64 KiB default. Shared so the browser's pre-check can\n * never refuse a save the server would accept.\n */\nexport const VERSE_MEMORY_BODY_MAX_BYTES = 2 * VERSE_MEMORY_MAX_BYTES + 8 * 1024;\n\n/** Cap on the memory block appended to each session's system prompt. */\nexport const VERSE_MEMORY_BLOCK_MAX_BYTES = 6 * 1024;\n"],"mappings":"AA2kBA,IAAa,EAAgB,CAAC,UAAW,MAAO,SAAU,OAAQ,QAAS,KAAK,EAyKnE,EAA2D,IAAI,IAAoB,CAN9F,iBACA,oBACA,WACA,QAG8F,CAAyB,EAOzH,SAAgB,EAAsB,EAAiD,CACrF,OAAO,EAA4B,IAAI,EAAM,IAAI,CACnD,CA+HA,IAAa,EAA4B,MAqF5B,EAA0B,KAa1B,EAAgC,CAC3C,0FACA,+HACA,GACA,qBACA,0CACA,6DACA,0EACA,kDACA,6CACA,2EACA,GACA,qEACF,CAAC,CAAC,KAAK;CAAI,EA4EE,EAAyB,MAQzB,EAA8B,OAG9B,EAA+B"}
@@ -1,2 +0,0 @@
1
- import{a as e,s as t}from"./index-afDA8cwW.js";import{c as n,k as r,s as i}from"./global-DVgMguLr.js";import{n as a}from"./control-queries-BGjarMm9.js";var o=t(e(),1);function s(e){return e instanceof n?`This server runs without dispatch, so that action is unavailable.`:e instanceof a?e.message:e instanceof i?e.status===401?"The mutation token was rejected. Unlock again with the token `ashlr verse` printed.":e.detail?e.detail:e.status===400?e.message:e.status===409?`The server refused the action, and sent no reason.`:e.message:e instanceof Error?e.message:`That action failed. Try again.`}function c(){let[e,t]=(0,o.useState)(!1),[i,a]=(0,o.useState)(null),[c,l]=(0,o.useState)(!1),[u,d]=(0,o.useState)(!1),[f,p]=(0,o.useState)(``),m=(0,o.useRef)(null),h=(0,o.useCallback)(async(e,r)=>{t(!0),a(null);try{let t=await e();r?.(t)}catch(e){e instanceof n?l(!0):a(s(e))}finally{t(!1)}},[]),g=(0,o.useCallback)((e,t,n)=>{a(null);let i=n;if(r()){h(e,i);return}m.current={fn:e,onResult:i},p(t),d(!0)},[h]),_=(0,o.useCallback)(()=>{d(!1);let e=m.current;m.current=null,e&&r()&&h(e.fn,e.onResult)},[h]);return{request:g,busy:e,error:i,clearError:(0,o.useCallback)(()=>a(null),[]),readOnly:c,tokenOpen:u,tokenReason:f,closeToken:_}}export{c as t};
2
- //# sourceMappingURL=use-guarded-action-CO_aAsed.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-guarded-action-CO_aAsed.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/autonomy/use-guarded-action.ts"],"sourcesContent":["/**\n * routes/verse/autonomy/use-guarded-action.ts — the one place a Verse control\n * surface turns \"the operator clicked something destructive\" into an actual\n * request. Shared by the Autonomy cockpit and the Approvals surface.\n *\n * It folds together the three things every mutating click in this app has to\n * do, which were previously re-implemented per call site:\n *\n * - **Token hand-off.** No mutation hold yet → remember the action, open\n * MutationTokenDialog, and run it once the token lands. The hold is read\n * LIVE on dialog close, never from a render-time snapshot, because\n * MutationTokenDialog's onClose fires before this component re-renders.\n * - **Read-only sessions.** Every POST 404s when the server was started\n * without dispatch. That is a session mode, not a failure, so it flips a\n * `readOnly` flag the surface renders as an explanation — never as an error\n * toast and never as a crash.\n * - **Busy + error state** for exactly one in-flight action at a time.\n */\nimport { useCallback, useRef, useState } from 'react';\nimport { hasMutationHold } from '../../../data/auth-store.js';\nimport { ApiError, DispatchDisabledError } from '../../../data/client.js';\nimport { VerseControlLockedError } from './control-queries.js';\n\nexport function describeControlError(err: unknown): string {\n if (err instanceof DispatchDisabledError) return 'This server runs without dispatch, so that action is unavailable.';\n if (err instanceof VerseControlLockedError) return err.message;\n if (err instanceof ApiError) {\n if (err.status === 401) return 'The mutation token was rejected. Unlock again with the token `ashlr verse` printed.';\n // The control plane writes a careful refusal ladder — \"no repositories are\n // enrolled, so the loop would do nothing. Add scope first.\" — and returns\n // it as `note` on the 409 body. A blanket \"something else is already\n // running\" replaced every one of those with a sentence that was usually\n // false and never actionable. Show the server's own words whenever it\n // sent any; the generic line is now only the last resort.\n if (err.detail) return err.detail;\n if (err.status === 400) return err.message;\n if (err.status === 409) return 'The server refused the action, and sent no reason.';\n return err.message;\n }\n return err instanceof Error ? err.message : 'That action failed. Try again.';\n}\n\nexport interface GuardedAction {\n /**\n * Run `fn`, prompting for the mutation token first when none is held.\n *\n * `onResult` receives `fn`'s resolved value when it succeeds. It exists\n * because the value was previously dropped on the floor, and for the daemon\n * routes that value carries the server's own account of what just happened\n * (`VerseDaemonActionResult.note` — e.g. that an ordinary stop also engaged\n * the global kill switch). It is not called when `fn` throws.\n */\n request: <T>(fn: () => Promise<T>, reason: string, onResult?: (result: T) => void) => void;\n busy: boolean;\n error: string | null;\n clearError: () => void;\n /** True once a POST 404'd — the server has no dispatch enabled. */\n readOnly: boolean;\n /** Bind these three to <MutationTokenDialog/>. */\n tokenOpen: boolean;\n tokenReason: string;\n closeToken: () => void;\n}\n\nexport function useGuardedAction(): GuardedAction {\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [readOnly, setReadOnly] = useState(false);\n const [tokenOpen, setTokenOpen] = useState(false);\n const [tokenReason, setTokenReason] = useState('');\n // The deferred action and the callback that wants its result travel together\n // — the token dialog may run it a render later, long after `request` returned.\n const pending = useRef<{ fn: () => Promise<unknown>; onResult?: (result: never) => void } | null>(null);\n\n const perform = useCallback(\n async (fn: () => Promise<unknown>, onResult?: (result: never) => void) => {\n setBusy(true);\n setError(null);\n try {\n const result = await fn();\n onResult?.(result as never);\n } catch (err) {\n if (err instanceof DispatchDisabledError) setReadOnly(true);\n else setError(describeControlError(err));\n } finally {\n setBusy(false);\n }\n },\n [],\n );\n\n const request = useCallback(\n <T,>(fn: () => Promise<T>, reason: string, onResult?: (result: T) => void) => {\n setError(null);\n const handler = onResult as ((result: never) => void) | undefined;\n if (hasMutationHold()) {\n void perform(fn, handler);\n return;\n }\n pending.current = { fn, onResult: handler };\n setTokenReason(reason);\n setTokenOpen(true);\n },\n [perform],\n );\n\n const closeToken = useCallback(() => {\n setTokenOpen(false);\n const next = pending.current;\n pending.current = null;\n // Live read: the dialog closes synchronously after setToken().\n if (next && hasMutationHold()) void perform(next.fn, next.onResult);\n }, [perform]);\n\n const clearError = useCallback(() => setError(null), []);\n\n return { request, busy, error, clearError, readOnly, tokenOpen, tokenReason, closeToken };\n}\n"],"mappings":"uKAuBA,SAAgB,EAAqB,EAAsB,CAgBzD,OAfI,aAAe,EAA8B,oEAC7C,aAAe,EAAgC,EAAI,QACnD,aAAe,EACb,EAAI,SAAW,IAAY,sFAO3B,EAAI,OAAe,EAAI,OACvB,EAAI,SAAW,IAAY,EAAI,QAC/B,EAAI,SAAW,IAAY,qDACxB,EAAI,QAEN,aAAe,MAAQ,EAAI,QAAU,gCAC9C,CAwBA,SAAgB,GAAkC,CAChD,GAAM,CAAC,EAAM,IAAA,EAAW,EAAA,SAAA,CAAS,EAAK,EAChC,CAAC,EAAO,IAAA,EAAY,EAAA,SAAA,CAAwB,IAAI,EAChD,CAAC,EAAU,IAAA,EAAe,EAAA,SAAA,CAAS,EAAK,EACxC,CAAC,EAAW,IAAA,EAAgB,EAAA,SAAA,CAAS,EAAK,EAC1C,CAAC,EAAa,IAAA,EAAkB,EAAA,SAAA,CAAS,EAAE,EAG3C,GAAA,EAAU,EAAA,OAAA,CAAkF,IAAI,EAEhG,GAAA,EAAU,EAAA,YAAA,CACd,MAAO,EAA4B,IAAuC,CACxE,EAAQ,EAAI,EACZ,EAAS,IAAI,EACb,GAAI,CACF,IAAM,EAAS,MAAM,EAAG,EACxB,IAAW,CAAe,CAC5B,OAAS,EAAK,CACR,aAAe,EAAuB,EAAY,EAAI,EACrD,EAAS,EAAqB,CAAG,CAAC,CACzC,QAAU,CACR,EAAQ,EAAK,CACf,CACF,EACA,CAAC,CACH,EAEM,GAAA,EAAU,EAAA,YAAA,EACT,EAAsB,EAAgB,IAAmC,CAC5E,EAAS,IAAI,EACb,IAAM,EAAU,EAChB,GAAI,EAAgB,EAAG,CACrB,EAAa,EAAI,CAAO,EACxB,MACF,CACA,EAAQ,QAAU,CAAE,KAAI,SAAU,CAAQ,EAC1C,EAAe,CAAM,EACrB,EAAa,EAAI,CACnB,EACA,CAAC,CAAO,CACV,EAEM,GAAA,EAAa,EAAA,YAAA,KAAkB,CACnC,EAAa,EAAK,EAClB,IAAM,EAAO,EAAQ,QACrB,EAAQ,QAAU,KAEd,GAAQ,EAAgB,GAAG,EAAa,EAAK,GAAI,EAAK,QAAQ,CACpE,EAAG,CAAC,CAAO,CAAC,EAIZ,MAAO,CAAE,UAAS,OAAM,QAAO,YAAA,EAFZ,EAAA,YAAA,KAAkB,EAAS,IAAI,EAAG,CAAC,CAEvB,EAAY,WAAU,YAAW,cAAa,YAAW,CAC1F"}
@@ -1,2 +0,0 @@
1
- import{a as e,s as t}from"./index-afDA8cwW.js";import{c as n,k as r,s as i}from"./global-DVgMguLr.js";import{r as a}from"./verse-queries-BjQoOTwv.js";var o=t(e(),1);function s(){let[e,t]=(0,o.useState)({open:!1,reason:``}),n=(0,o.useRef)(null),i=(0,o.useCallback)((e,i)=>r()?i():(n.current?.cancel(),new Promise((r,a)=>{n.current={run:()=>{i().then(r,a)},cancel:()=>r(null)},t({open:!0,reason:e})})),[]),a=(0,o.useCallback)(()=>{t({open:!1,reason:``});let e=n.current;e&&setTimeout(()=>{n.current===e&&(n.current=null,e.cancel())},0)},[]),s=(0,o.useCallback)(()=>{let e=n.current;n.current=null,e?.run()},[]);return{run:i,dialog:{open:e.open,reason:e.reason,onClose:a,onUnlocked:s}}}function c(e){return e instanceof n?"This server is read-only (started without dispatch — run `ashlr verse`), or older than this console.":e instanceof a?`Unlock actions with the mutation token first.`:e instanceof i?e.status===401?"The mutation token was rejected. Unlock again with the token `ashlr verse` printed.":e.code===`VERSE_SESSION_NOT_FOUND`?`This chat no longer exists on the server — it may have been deleted. Refresh the chat list.`:e.detail?e.detail:e.status===404?"This server does not have that route yet — update Ashlr and restart `ashlr verse`.":e.status===409?`A turn is already running in this chat. Wait for it or stop it first.`:e.message:e instanceof Error&&e.message?e.message:`Something went wrong.`}export{s as n,c as t};
2
- //# sourceMappingURL=use-token-gate-DYA2-ALC.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-token-gate-DYA2-ALC.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/context/use-token-gate.ts"],"sourcesContent":["/**\n * routes/verse/context/use-token-gate.ts — the mutation-token hand-off for\n * the self-contained context surfaces (handoff dialog, memory panel).\n *\n * Same contract as ChatSection's `withToken`, extracted because these\n * components are mounted by OTHER owners (the workspace header, the resources\n * panel) that cannot thread a guard down to them:\n *\n * - a held token → the action runs now;\n * - no token → the action is parked, MutationTokenDialog opens with a reason\n * saying what the click will do, and the action runs once unlocked;\n * - the dialog dismissed → the promise resolves `null`, so the caller can\n * tell \"not done\" from \"done\" without an exception.\n *\n * The hold is read LIVE (`hasMutationHold()`), never from a render snapshot:\n * MutationTokenDialog calls `onClose` before `onUnlocked` in the same tick,\n * so a snapshot taken at render time is always one step behind.\n */\nimport { useCallback, useRef, useState } from 'react';\nimport { hasMutationHold } from '../../../data/auth-store.js';\nimport { ApiError, DispatchDisabledError } from '../../../data/client.js';\nimport { VerseMutationLockedError } from '../verse-queries.js';\n\nexport interface TokenGateDialogProps {\n open: boolean;\n reason: string;\n onClose: () => void;\n onUnlocked: () => void;\n}\n\nexport interface TokenGate {\n run<T>(reason: string, action: () => Promise<T>): Promise<T | null>;\n /** Spread onto <MutationTokenDialog />. */\n dialog: TokenGateDialogProps;\n}\n\nexport function useTokenGate(): TokenGate {\n const [prompt, setPrompt] = useState<{ open: boolean; reason: string }>({ open: false, reason: '' });\n const pending = useRef<{ run: () => void; cancel: () => void } | null>(null);\n\n const run = useCallback(<T,>(reason: string, action: () => Promise<T>): Promise<T | null> => {\n if (hasMutationHold()) return action();\n // A second click while the prompt is up supersedes the first: the earlier\n // caller is told \"not done\" rather than left waiting forever.\n pending.current?.cancel();\n return new Promise<T | null>((resolve, reject) => {\n pending.current = {\n run: () => { action().then(resolve, reject); },\n cancel: () => resolve(null),\n };\n setPrompt({ open: true, reason });\n });\n }, []);\n\n const onClose = useCallback(() => {\n setPrompt({ open: false, reason: '' });\n // onClose fires BEFORE onUnlocked on a successful submit, so only treat\n // this as a dismissal if nothing claimed the parked action by next tick.\n const parked = pending.current;\n if (!parked) return;\n setTimeout(() => {\n if (pending.current === parked) {\n pending.current = null;\n parked.cancel();\n }\n }, 0);\n }, []);\n\n const onUnlocked = useCallback(() => {\n const parked = pending.current;\n pending.current = null;\n parked?.run();\n }, []);\n\n return { run, dialog: { open: prompt.open, reason: prompt.reason, onClose, onUnlocked } };\n}\n\n/**\n * One sentence for a failed context action. Prefers the server's own words\n * (`ApiError.detail`), which the context routes write for a person.\n */\nexport function describeContextError(err: unknown): string {\n if (err instanceof DispatchDisabledError) {\n // A CODELESS 404 on a write: the dispatch gate, or a server that predates\n // this route — the two answer the same bare body by design (client.ts).\n // A missing chat is NOT this: it carries VERSE_SESSION_NOT_FOUND below.\n return 'This server is read-only (started without dispatch — run `ashlr verse`), or older than this console.';\n }\n if (err instanceof VerseMutationLockedError) return 'Unlock actions with the mutation token first.';\n if (err instanceof ApiError) {\n if (err.status === 401) return 'The mutation token was rejected. Unlock again with the token `ashlr verse` printed.';\n if (err.code === 'VERSE_SESSION_NOT_FOUND') return 'This chat no longer exists on the server — it may have been deleted. Refresh the chat list.';\n if (err.detail) return err.detail;\n if (err.status === 404) return 'This server does not have that route yet — update Ashlr and restart `ashlr verse`.';\n if (err.status === 409) return 'A turn is already running in this chat. Wait for it or stop it first.';\n return err.message;\n }\n return err instanceof Error && err.message ? err.message : 'Something went wrong.';\n}\n"],"mappings":"qKAoCA,SAAgB,GAA0B,CACxC,GAAM,CAAC,EAAQ,IAAA,EAAa,EAAA,SAAA,CAA4C,CAAE,KAAM,GAAO,OAAQ,EAAG,CAAC,EAC7F,GAAA,EAAU,EAAA,OAAA,CAAuD,IAAI,EAErE,GAAA,EAAM,EAAA,YAAA,EAAiB,EAAgB,IACvC,EAAgB,EAAU,EAAO,GAGrC,EAAQ,SAAS,OAAO,EACjB,IAAI,SAAmB,EAAS,IAAW,CAChD,EAAQ,QAAU,CAChB,QAAW,CAAE,EAAO,CAAC,CAAC,KAAK,EAAS,CAAM,CAAG,EAC7C,WAAc,EAAQ,IAAI,CAC5B,EACA,EAAU,CAAE,KAAM,GAAM,QAAO,CAAC,CAClC,CAAC,GACA,CAAC,CAAC,EAEC,GAAA,EAAU,EAAA,YAAA,KAAkB,CAChC,EAAU,CAAE,KAAM,GAAO,OAAQ,EAAG,CAAC,EAGrC,IAAM,EAAS,EAAQ,QAClB,GACL,eAAiB,CACX,EAAQ,UAAY,IACtB,EAAQ,QAAU,KAClB,EAAO,OAAO,EAElB,EAAG,CAAC,CACN,EAAG,CAAC,CAAC,EAEC,GAAA,EAAa,EAAA,YAAA,KAAkB,CACnC,IAAM,EAAS,EAAQ,QACvB,EAAQ,QAAU,KAClB,GAAQ,IAAI,CACd,EAAG,CAAC,CAAC,EAEL,MAAO,CAAE,MAAK,OAAQ,CAAE,KAAM,EAAO,KAAM,OAAQ,EAAO,OAAQ,UAAS,YAAW,CAAE,CAC1F,CAMA,SAAgB,EAAqB,EAAsB,CAgBzD,OAfI,aAAe,EAIV,uGAEL,aAAe,EAAiC,gDAChD,aAAe,EACb,EAAI,SAAW,IAAY,sFAC3B,EAAI,OAAS,0BAAkC,8FAC/C,EAAI,OAAe,EAAI,OACvB,EAAI,SAAW,IAAY,qFAC3B,EAAI,SAAW,IAAY,wEACxB,EAAI,QAEN,aAAe,OAAS,EAAI,QAAU,EAAI,QAAU,uBAC7D"}
@@ -1 +0,0 @@
1
- :root{--chart-series-1:var(--data-cat-1);--chart-series-2:var(--data-cat-2);--chart-series-3:var(--data-cat-3);--chart-series-4:var(--data-cat-4);--chart-series-5:var(--data-cat-5);--chart-series-6:var(--data-cat-6);--chart-neutral:var(--status-neutral-solid);--chart-seq-1:var(--data-seq-1);--chart-seq-2:var(--data-seq-2);--chart-seq-3:var(--data-seq-3);--chart-seq-4:var(--data-seq-4);--chart-seq-5:var(--data-seq-5);--chart-seq-6:var(--data-seq-6);--chart-seq-7:var(--data-seq-7);--chart-sequential:var(--chart-seq-5);--chart-sequential-soft:var(--chart-seq-3);--chart-diverging-pos:var(--chart-seq-5);--chart-diverging-neg:var(--status-danger-solid);--chart-diverging-mid:var(--border-strong);--chart-unknown:var(--status-unknown-solid);--chart-unknown-hatch:repeating-linear-gradient(135deg, var(--chart-unknown) 0 1px, transparent 1px 5px);--chart-queued-outline:var(--status-neutral-solid);--chart-grid:var(--border-subtle);--chart-axis:var(--border-strong);--chart-surface:var(--bg-surface);--chart-tooltip-bg:var(--bg-surface-raised);--chart-tooltip-border:var(--border-default);--chart-heat-0:var(--chart-grid);--chart-heat-1:var(--chart-seq-2);--chart-heat-2:var(--chart-seq-3);--chart-heat-3:var(--chart-seq-5);--chart-heat-4:var(--chart-seq-7);--chart-track:var(--chart-seq-1)}._table_x2yvy_1{border-collapse:collapse;width:100%;font-size:var(--text-xs-size)}._table_x2yvy_1 th,._table_x2yvy_1 td{text-align:left;padding:var(--space-1) var(--space-2);border-bottom:1px solid var(--border-subtle)}._table_x2yvy_1 th{color:var(--text-tertiary);font-weight:var(--font-weight-medium);text-transform:uppercase;letter-spacing:.04em;font-size:var(--text-xs-size)}._numeric_x2yvy_22{text-align:right;font-variant-numeric:tabular-nums}._empty_x2yvy_27{color:var(--text-tertiary);text-align:center}._plotWrap_1pkd1_3{width:100%;min-width:0;position:relative}._svg_1pkd1_9{max-width:100%;display:block;overflow:visible}._grid_1pkd1_15{stroke:var(--chart-grid);stroke-width:1px;shape-rendering:crispedges}._axis_1pkd1_21{stroke:var(--chart-axis);stroke-width:1px;shape-rendering:crispedges}._tick_1pkd1_27{font-family:var(--font-ui);font-size:var(--text-xs-size);fill:var(--text-tertiary);font-variant-numeric:tabular-nums}._label_1pkd1_34{font-family:var(--font-ui);font-size:var(--text-xs-size);fill:var(--text-secondary)}._labelStrong_1pkd1_40{font-family:var(--font-ui);font-size:var(--text-xs-size);font-weight:var(--font-weight-medium);fill:var(--text-primary)}._line_1pkd1_47{fill:none;stroke-width:2px;stroke-linecap:round;stroke-linejoin:round}._wash_1pkd1_54{stroke:none;opacity:.1}._reference_1pkd1_59{fill:none;stroke:var(--text-tertiary);stroke-width:1px;stroke-dasharray:4 3}._projection_1pkd1_66{fill:none;stroke-width:2px;stroke-dasharray:5 4;stroke-linecap:round}._marker_1pkd1_73{stroke:var(--chart-surface);stroke-width:2px}._crosshair_1pkd1_78{stroke:var(--chart-axis);stroke-width:1px;pointer-events:none}._hit_1pkd1_84{fill:#0000;cursor:default}._hit_1pkd1_84:focus{outline:none}._hit_1pkd1_84:focus-visible{stroke:var(--border-focus);stroke-width:2px}._focusable_1pkd1_98:focus{outline:none}._focusable_1pkd1_98:focus-visible{outline:2px solid var(--border-focus);outline-offset:2px;border-radius:var(--radius-sm)}._track_1pkd1_108{fill:var(--chart-track)}._noData_1pkd1_112{fill:none;stroke:var(--chart-grid);stroke-width:1px;stroke-dasharray:2 2}._tooltip_1pkd1_119{z-index:var(--z-dropdown);pointer-events:none;padding:var(--space-2);border:1px solid var(--chart-tooltip-border);border-radius:var(--radius-sm);background:var(--chart-tooltip-bg);box-shadow:var(--shadow-md);color:var(--text-primary);font-size:var(--text-xs-size);white-space:nowrap;position:absolute;transform:translate(-50%,calc(-100% - 8px))}._tooltipTitle_1pkd1_134{color:var(--text-tertiary);margin-bottom:var(--space-1)}._tooltipRow_1pkd1_139{align-items:center;gap:var(--space-2);display:flex}._tooltipKey_1pkd1_145{border-radius:2px;flex:none;width:8px;height:8px}._tooltipValue_1pkd1_152{padding-left:var(--space-3);font-weight:var(--font-weight-semibold);font-variant-numeric:tabular-nums;margin-left:auto}._tooltipMuted_1pkd1_159{color:var(--text-tertiary);font-style:italic}._legend_1pkd1_164{gap:var(--space-1) var(--space-3);margin:var(--space-2) 0 0;font-size:var(--text-xs-size);color:var(--text-secondary);flex-wrap:wrap;padding:0;list-style:none;display:flex}._legendItem_1pkd1_175{align-items:center;gap:var(--space-1);display:inline-flex}._swatch_1pkd1_181{border-radius:2px;flex:none;width:10px;height:10px}._swatchLine_1pkd1_188{flex:none;width:12px;height:2px}._swatchEmpty_1pkd1_194{border:1px dashed var(--chart-axis);border-radius:2px;flex:none;width:10px;height:10px}._note_1pkd1_202{margin:var(--space-2) 0 0;font-size:var(--text-xs-size);color:var(--text-tertiary)}._srOnly_1pkd1_208{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}@media (prefers-reduced-motion:no-preference){._animated_1pkd1_221{transition:opacity .12s}}._monogram_1pkd1_227{font-family:var(--font-display);font-size:var(--text-2xs-size);font-weight:var(--font-weight-semibold);fill:var(--text-secondary)}._unknownMark_1pkd1_235{stroke:var(--chart-unknown);stroke-width:1px}._swatchHatch_1pkd1_241{border:1px solid var(--chart-unknown);background:var(--chart-unknown-hatch);border-radius:2px;flex:none;width:10px;height:10px}._halo_1pkd1_252{paint-order:stroke;stroke:var(--chart-surface);stroke-width:3px;stroke-linejoin:round}._frame_it6x9_1{border:1px solid var(--border-subtle);border-radius:var(--radius-lg);background:var(--bg-surface);min-width:0;padding:var(--card-pad,var(--space-4));margin:0}._header_it6x9_11{justify-content:space-between;align-items:flex-start;gap:var(--space-3);margin-bottom:var(--space-3);flex-wrap:wrap;display:flex}._actions_it6x9_20{align-items:center;gap:var(--space-2);flex:none;margin-left:auto;display:inline-flex}._menuWrap_it6x9_28{display:inline-flex;position:relative}._more_it6x9_34{width:calc(var(--control-h-xs,20px) + 4px);height:calc(var(--control-h-xs,20px) + 4px);border-radius:var(--radius-sm);color:var(--text-tertiary);cursor:pointer;transition:background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);background:0 0;border:1px solid #0000;justify-content:center;align-items:center;padding:0;display:inline-flex}._more_it6x9_34:hover,._more_it6x9_34[aria-expanded=true]{background:var(--bg-hover);color:var(--text-primary)}._more_it6x9_34:focus-visible{outline:2px solid var(--border-focus);outline-offset:1px}._menu_it6x9_28{top:calc(100% + var(--space-1));z-index:var(--z-dropdown);min-width:176px;padding:var(--space-1);border:1px solid var(--border-default);border-radius:var(--radius-md);background:var(--bg-surface-raised);box-shadow:var(--shadow-menu);flex-direction:column;display:flex;position:absolute;right:0}._menuItem_it6x9_75{align-items:center;gap:var(--space-2);padding:var(--space-1) var(--space-2);border-radius:var(--radius-sm);color:var(--text-primary);font:inherit;font-size:var(--text-xs-size);line-height:var(--text-xs-line);text-align:left;cursor:pointer;background:0 0;border:0;display:flex}._menuItem_it6x9_75:hover,._menuItem_it6x9_75:focus-visible{background:var(--bg-hover);outline:none}._check_it6x9_97{width:1em;color:var(--text-secondary)}._hint_it6x9_102{padding:0 var(--space-1);border:1px solid var(--border-subtle);border-radius:var(--radius-xs,3px);color:var(--text-tertiary);font-family:var(--font-mono);font-size:var(--text-2xs-size);margin-left:auto}._heading_it6x9_112{flex-direction:column;gap:2px;min-width:0;display:flex}._title_it6x9_119{font-size:var(--text-sm-size);font-weight:var(--font-weight-semibold);color:var(--text-primary)}._description_it6x9_125{font-size:var(--text-xs-size);color:var(--text-tertiary)}._plot_it6x9_130{width:100%;min-width:0;position:relative}._table_it6x9_136{max-height:360px;overflow:auto}._caveat_it6x9_141{margin:0 0 var(--space-3);padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);background:var(--status-unknown-bg);color:var(--status-unknown-fg);font-size:var(--text-xs-size);line-height:var(--text-sm-line)}._state_it6x9_151{padding:var(--space-6) var(--space-3);text-align:center;color:var(--text-tertiary);font-size:var(--text-sm-size);margin:0}._dark_it6x9_159{gap:var(--space-1);flex-direction:column;align-items:center;display:flex}._darkTitle_it6x9_166{color:var(--text-secondary);font-weight:var(--font-weight-semibold);margin:0}._darkBody_it6x9_172{font-size:var(--text-xs-size);max-width:44ch;margin:0}._unknown_it6x9_178{color:var(--status-unknown-fg)}
@@ -1,2 +0,0 @@
1
- import{a as e,n as t,s as n}from"./index-afDA8cwW.js";import{d as r,f as i}from"./colors-B-vHsX1S.js";var a=n(e(),1),o=t();function s(e){if(!Number.isFinite(e))return`—`;let t=Math.abs(e);return t>=1e6?`${(e/1e6).toFixed(t>=1e7?0:1)}M`:t>=1e4?`${Math.round(e/1e3)}K`:t>=1e3?e.toLocaleString(`en-US`):Number.isInteger(e)?String(e):e.toFixed(1)}function c(e){if(!Number.isFinite(e))return`—`;let t=Math.abs(e),n=e<0?`-`:``;return t>=1e6?`${n}$${(t/1e6).toFixed(1)}M`:t>=1e3?`${n}$${(t/1e3).toFixed(1)}K`:`${n}$${t.toFixed(2)}`}function l(e,t=0){return Number.isFinite(e)?`${(e*100).toFixed(t)}%`:`—`}function u(e){if(!Number.isFinite(e))return`—`;let t=s(Math.abs(e));return e>0?`+${t}`:e<0?`-${t}`:t}function d(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return e;let t=new Date(`${e}T00:00:00Z`);return Number.isNaN(t.getTime())||t.toISOString().slice(0,10)!==e?e:t.toLocaleDateString(`en-US`,{month:`short`,day:`numeric`,timeZone:`UTC`})}function f(e){let t=new Date(e);return Number.isNaN(t.getTime())?``:t.toLocaleDateString(`en-US`,{month:`short`,day:`numeric`})}var p={table:`_table_x2yvy_1`,numeric:`_numeric_x2yvy_22`,empty:`_empty_x2yvy_27`};function m({caption:e,columns:t,rows:n,rowKey:r,emptyMessage:i=`No rows.`}){return(0,o.jsxs)(`table`,{className:p.table,children:[(0,o.jsx)(`caption`,{className:`visually-hidden`,children:e}),(0,o.jsx)(`thead`,{children:(0,o.jsx)(`tr`,{children:t.map(e=>(0,o.jsx)(`th`,{scope:`col`,className:e.numeric?p.numeric:void 0,children:e.label},e.key))})}),(0,o.jsxs)(`tbody`,{children:[n.length===0?(0,o.jsx)(`tr`,{children:(0,o.jsx)(`td`,{colSpan:Math.max(1,t.length),className:p.empty,children:i})}):null,n.map((e,n)=>(0,o.jsx)(`tr`,{children:t.map(t=>(0,o.jsx)(`td`,{className:t.numeric?p.numeric:void 0,children:t.render(e)},t.key))},r(e,n)))]})]})}var h={plotWrap:`_plotWrap_1pkd1_3`,svg:`_svg_1pkd1_9`,grid:`_grid_1pkd1_15`,axis:`_axis_1pkd1_21`,tick:`_tick_1pkd1_27`,label:`_label_1pkd1_34`,labelStrong:`_labelStrong_1pkd1_40`,line:`_line_1pkd1_47`,wash:`_wash_1pkd1_54`,reference:`_reference_1pkd1_59`,projection:`_projection_1pkd1_66`,marker:`_marker_1pkd1_73`,crosshair:`_crosshair_1pkd1_78`,hit:`_hit_1pkd1_84`,focusable:`_focusable_1pkd1_98`,track:`_track_1pkd1_108`,noData:`_noData_1pkd1_112`,tooltip:`_tooltip_1pkd1_119`,tooltipTitle:`_tooltipTitle_1pkd1_134`,tooltipRow:`_tooltipRow_1pkd1_139`,tooltipKey:`_tooltipKey_1pkd1_145`,tooltipValue:`_tooltipValue_1pkd1_152`,tooltipMuted:`_tooltipMuted_1pkd1_159`,legend:`_legend_1pkd1_164`,legendItem:`_legendItem_1pkd1_175`,swatch:`_swatch_1pkd1_181`,swatchLine:`_swatchLine_1pkd1_188`,swatchEmpty:`_swatchEmpty_1pkd1_194`,note:`_note_1pkd1_202`,srOnly:`_srOnly_1pkd1_208`,animated:`_animated_1pkd1_221`,monogram:`_monogram_1pkd1_227`,unknownMark:`_unknownMark_1pkd1_235`,swatchHatch:`_swatchHatch_1pkd1_241`,halo:`_halo_1pkd1_252`};function g({items:e,min:t=2}){return e.length<t?null:(0,o.jsx)(`ul`,{className:h.legend,children:e.map(e=>(0,o.jsxs)(`li`,{className:h.legendItem,children:[(0,o.jsx)(`span`,{"aria-hidden":`true`,className:e.kind===`line`?h.swatchLine:e.kind===`empty`?h.swatchEmpty:e.kind===`hatch`?h.swatchHatch:h.swatch,style:e.kind===`empty`||e.kind===`hatch`?void 0:{background:e.color}}),e.label]},e.label))})}function _({left:e,top:t,title:n,rows:r}){return(0,o.jsxs)(`div`,{className:h.tooltip,style:{left:e,top:t},role:`presentation`,children:[(0,o.jsx)(`div`,{className:h.tooltipTitle,children:n}),r.map(e=>(0,o.jsxs)(`div`,{className:h.tooltipRow,children:[e.color?(0,o.jsx)(`span`,{className:h.tooltipKey,style:{background:e.color},"aria-hidden":`true`}):null,(0,o.jsx)(`span`,{children:e.label}),e.value===null?(0,o.jsx)(`span`,{className:`${h.tooltipValue} ${h.tooltipMuted}`,children:`no data`}):(0,o.jsx)(`span`,{className:h.tooltipValue,children:e.value})]},e.key))]})}function v(e,t,n=70){return Math.min(Math.max(e,Math.min(n,t/2)),Math.max(t-n,t/2))}function y({id:e}){let{size:t,angle:n,strokeWidth:i,stroke:a}=r;return(0,o.jsx)(`pattern`,{id:e,width:t,height:t,patternUnits:`userSpaceOnUse`,patternTransform:`rotate(${n})`,children:(0,o.jsx)(`line`,{x1:0,y1:0,x2:0,y2:t,stroke:a,strokeWidth:i})})}var b={claude:`C`,codex:`X`,grok:`G`,local:`L`};function x({engine:e,x:t,y:n,height:r}){return(0,o.jsxs)(`g`,{"data-engine":e,"aria-hidden":`true`,children:[(0,o.jsx)(`rect`,{x:t,y:n,width:2,height:r,rx:1,fill:i(e)}),(0,o.jsx)(`text`,{className:h.monogram,x:t+6,y:n+r/2,dy:`0.34em`,children:b[e]})]})}function S(){return(0,o.jsxs)(`svg`,{width:16,height:16,viewBox:`0 0 16 16`,"aria-hidden":`true`,focusable:`false`,children:[(0,o.jsx)(`circle`,{cx:3.5,cy:8,r:1.4,fill:`currentColor`}),(0,o.jsx)(`circle`,{cx:8,cy:8,r:1.4,fill:`currentColor`}),(0,o.jsx)(`circle`,{cx:12.5,cy:8,r:1.4,fill:`currentColor`})]})}var C={frame:`_frame_it6x9_1`,header:`_header_it6x9_11`,actions:`_actions_it6x9_20`,menuWrap:`_menuWrap_it6x9_28`,more:`_more_it6x9_34`,menu:`_menu_it6x9_28`,menuItem:`_menuItem_it6x9_75`,check:`_check_it6x9_97`,hint:`_hint_it6x9_102`,heading:`_heading_it6x9_112`,title:`_title_it6x9_119`,description:`_description_it6x9_125`,plot:`_plot_it6x9_130`,table:`_table_it6x9_136`,caveat:`_caveat_it6x9_141`,state:`_state_it6x9_151`,dark:`_dark_it6x9_159`,darkTitle:`_darkTitle_it6x9_166`,darkBody:`_darkBody_it6x9_172`,unknown:`_unknown_it6x9_178`};function w(e){return d(e.slice(0,10))}function T({status:e}){switch(e.kind){case`loading`:return(0,o.jsx)(`p`,{className:C.state,"aria-busy":`true`,children:`Loading…`});case`empty`:return(0,o.jsx)(`p`,{className:C.state,children:e.message??`Nothing happened in this window.`});case`dark`:return(0,o.jsxs)(`div`,{className:`${C.state} ${C.dark}`,children:[(0,o.jsxs)(`p`,{className:C.darkTitle,children:[e.subject??`Fleet`,` dark since `,w(e.since)]}),(0,o.jsx)(`p`,{className:C.darkBody,children:e.detail??`No runs or proposals have been recorded since then.`})]});case`unknown`:return(0,o.jsxs)(`p`,{className:`${C.state} ${C.unknown}`,role:`note`,children:[`Unknown — `,e.reason??`the data source could not be read.`,` Nothing is shown rather than a guess.`]})}}function E(e){if(!(e instanceof HTMLElement))return!1;let t=e.tagName;return t===`INPUT`||t===`TEXTAREA`||t===`SELECT`||e.isContentEditable}var D=[{view:`chart`,label:`Show as chart`,hint:null},{view:`table`,label:`Show as table`,hint:`T`}];function O({title:e,view:t,onPick:n}){let[r,i]=(0,a.useState)(!1),[s,c]=(0,a.useState)(0),l=(0,a.useRef)(null),u=(0,a.useRef)(null),d=(0,a.useId)(),f=(0,a.useCallback)(e=>{i(!1),e&&l.current?.focus()},[]);(0,a.useEffect)(()=>{if(!r)return;let e=e=>{let t=e.target;t&&(u.current?.contains(t)||l.current?.contains(t))||i(!1)};return document.addEventListener(`pointerdown`,e),()=>document.removeEventListener(`pointerdown`,e)},[r]),(0,a.useEffect)(()=>{r&&u.current?.querySelectorAll(`[role="menuitemradio"]`)[s]?.focus()},[r,s]);function p(e){c(e),i(!0)}function m(e){(e.key===`ArrowDown`||e.key===`ArrowUp`)&&(e.preventDefault(),p(e.key===`ArrowUp`?D.length-1:0))}function h(e){e.key===`ArrowDown`?(e.preventDefault(),c(e=>(e+1)%D.length)):e.key===`ArrowUp`?(e.preventDefault(),c(e=>(e-1+D.length)%D.length)):e.key===`Home`?(e.preventDefault(),c(0)):e.key===`End`?(e.preventDefault(),c(D.length-1)):e.key===`Escape`?(e.preventDefault(),e.stopPropagation(),f(!0)):e.key===`Tab`&&f(!1)}return(0,o.jsxs)(`span`,{className:C.menuWrap,children:[(0,o.jsx)(`button`,{ref:l,type:`button`,className:C.more,"aria-label":`${e}: view options`,"aria-haspopup":`menu`,"aria-expanded":r,"aria-controls":r?d:void 0,title:`View options (T toggles the table)`,onClick:()=>r?f(!1):p(Math.max(0,D.findIndex(e=>e.view===t))),onKeyDown:m,children:(0,o.jsx)(S,{})}),r?(0,o.jsx)(`div`,{ref:u,id:d,role:`menu`,"aria-label":`${e} view`,className:C.menu,onKeyDown:h,children:D.map((e,r)=>(0,o.jsxs)(`button`,{type:`button`,role:`menuitemradio`,"aria-checked":t===e.view,tabIndex:r===s?0:-1,className:C.menuItem,onClick:()=>{n(e.view),f(!0)},children:[(0,o.jsx)(`span`,{className:C.check,"aria-hidden":`true`,children:t===e.view?`✓`:``}),(0,o.jsx)(`span`,{children:e.label}),e.hint?(0,o.jsx)(`kbd`,{className:C.hint,children:e.hint}):null]},e.view))}):null]})}function k({title:e,description:t,caveat:n,status:r={kind:`ready`},defaultView:i=`chart`,hideToggle:s=!1,actions:c,children:l,table:u,footer:d}){let[f,p]=(0,a.useState)(i),m=(0,a.useId)(),h=r.kind===`ready`,g=h&&!s;function _(e){g&&!e.defaultPrevented&&(e.metaKey||e.ctrlKey||e.altKey||e.shiftKey||e.key.toLowerCase()!==`t`||E(e.target)||(e.preventDefault(),p(e=>e===`chart`?`table`:`chart`)))}return(0,o.jsxs)(`figure`,{className:C.frame,"aria-labelledby":m,"data-chart-card":``,"data-view":f,onKeyDown:_,children:[(0,o.jsxs)(`figcaption`,{className:C.header,children:[(0,o.jsxs)(`span`,{className:C.heading,children:[(0,o.jsx)(`span`,{id:m,className:C.title,children:e}),t?(0,o.jsx)(`span`,{className:C.description,children:t}):null]}),c||g?(0,o.jsxs)(`span`,{className:C.actions,children:[c,g?(0,o.jsx)(O,{title:e,view:f,onPick:p}):null]}):null]}),n?(0,o.jsx)(`p`,{className:C.caveat,role:`note`,children:n}):null,h?f===`table`?(0,o.jsx)(`div`,{className:C.table,children:u}):(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(`div`,{className:C.plot,children:l}),d]}):(0,o.jsx)(T,{status:r})]})}function A(e,t,n=4){if(!Number.isFinite(e)||!Number.isFinite(t))return[0];if(t<e&&([e,t]=[t,e]),t===e){if(t===0)return[0,1];let r=Math.abs(t)*.5;return A(Math.min(0,e-r),t+r,n)}let r=(t-e)/Math.max(1,n),i=10**Math.floor(Math.log10(r)),a=r/i,o=(a<=1?1:a<=2?2:a<=2.5?2.5:a<=5?5:10)*i,s=Math.floor(e/o)*o,c=Math.ceil(t/o)*o,l=[],u=Math.max(0,-Math.floor(Math.log10(o))+1);for(let e=s;e<=c+o/2;e+=o)l.push(Number(e.toFixed(u)));return l}function j(e,t,n,r){let i=t-e;return i===0?()=>(n+r)/2:t=>n+(t-e)/i*(r-n)}function M(e,t){if(e<=0)return[];if(t<=1)return[e-1];if(e<=t)return Array.from({length:e},(e,t)=>t);let n=Math.ceil((e-1)/(t-1)),r=[];for(let t=e-1;t>=0;t-=n)r.push(t);return r.reverse()}function N(e,t,n){return Math.min(n,Math.max(t,e))}function P(e){let t=[],n=[];for(let r of e){if(r.y===null||!Number.isFinite(r.y)){n.length&&t.push(n),n=[];continue}n.push({x:r.x,y:r.y})}return n.length&&t.push(n),t}function F(e){return e.map((e,t)=>`${t===0?`M`:`L`}${L(e.x)},${L(e.y)}`).join(` `)}function I(e,t){if(e.length===0)return``;let n=[...t].reverse();return`${F(e)} ${n.map(e=>`L${L(e.x)},${L(e.y)}`).join(` `)} Z`}function L(e){return Math.round(e*10)/10}function R(e){let t=0,n=!1,r=0,i=[];return e.forEach((e,a)=>{if(e===null||!Number.isFinite(e)){n=!0;return}r++;let o=Math.max(0,e);o>0&&i.push({index:a,value:o,y0:t,y1:t+o}),t+=o}),{segments:i,total:t,incomplete:n,unknown:r===0&&e.length>0}}function z(e,t,n,r,i=4){if(r<=0||n<=0)return``;let a=Math.max(0,Math.min(i,n/2,r));return[`M${L(e)},${L(t+r)}`,`L${L(e)},${L(t+a)}`,`Q${L(e)},${L(t)} ${L(e+a)},${L(t)}`,`L${L(e+n-a)},${L(t)}`,`Q${L(e+n)},${L(t)} ${L(e+n)},${L(t+a)}`,`L${L(e+n)},${L(t+r)}`,`Z`].join(` `)}function B(e,t,n,r,i=4){if(r<=0||n<=0)return``;let a=Math.max(0,Math.min(i,r/2,n));return[`M${L(e)},${L(t)}`,`L${L(e+n-a)},${L(t)}`,`Q${L(e+n)},${L(t)} ${L(e+n)},${L(t+a)}`,`L${L(e+n)},${L(t+r-a)}`,`Q${L(e+n)},${L(t+r)} ${L(e+n-a)},${L(t+r)}`,`L${L(e)},${L(t+r)}`,`Z`].join(` `)}function V(e){let t=e[0]??null;return e.map((n,r)=>{let i=r>0?e[r-1]??null:null;return{value:n,ofFirst:n!==null&&t!==null&&t>0?n/t:null,ofPrevious:r>0&&n!==null&&i!==null&&i>0?n/i:null}})}var H=[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`];function U(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;let t=Date.parse(`${e}T00:00:00Z`);return Number.isFinite(t)&&new Date(t).toISOString().slice(0,10)===e?t:null}function W(e,t=1){let n=new Map,r=1/0,i=-1/0;for(let t of e){let e=U(t.day);e!==null&&(n.set(t.day,t.value),r=Math.min(r,e),i=Math.max(i,e))}if(!Number.isFinite(r))return{cells:[],weeks:0,months:[]};let a=864e5,o=(new Date(r).getUTCDay()-t+7)%7,s=r-o*a,c=(new Date(i).getUTCDay()-t+7)%7,l=i+(6-c)*a,u=[],d=[],f=-1;for(let e=s,t=0;e<=l;e+=a,t++){let a=new Date(e).toISOString().slice(0,10),o=Math.floor(t/7),s=t%7,c=e<r||e>i;u.push({day:a,value:c?null:n.has(a)?n.get(a):null,week:o,weekday:s,outside:c});let l=new Date(e).getUTCMonth();!c&&l!==f&&(d.push({week:o,label:H[l]}),f=l)}return{cells:u,weeks:Math.floor((l-s)/a/7)+1,months:d}}function G(e,t,n=4){return e===null||!Number.isFinite(e)?null:e<=0||t<=0?0:N(Math.ceil(e/t*n),1,n)}function K(e,t,n={}){let r=e.filter(e=>e.remaining!==null&&Number.isFinite(e.remaining)&&Number.isFinite(e.t)).sort((e,t)=>e.t-t.t),i=r.length?r[r.length-1]:null,a=r.slice(-(n.window??6));if(!i||a.length<2)return{slopePerMs:null,exhaustAt:null,reserveAt:null,remainingAtReset:null,from:i};let o=a.length,s=a.reduce((e,t)=>e+t.t,0)/o,c=a.reduce((e,t)=>e+t.remaining,0)/o,l=0,u=0;for(let e of a)l+=(e.t-s)*(e.remaining-c),u+=(e.t-s)**2;let d=u===0?0:l/u,f=e=>{if(d>=0||i.remaining<=e)return i.remaining<=e?i.t:null;let n=i.t+(e-i.remaining)/d;return n<=t?n:null},p=n.reserve??null;return{slopePerMs:d,exhaustAt:f(0),reserveAt:p===null?null:f(p),remainingAtReset:Math.max(0,i.remaining+d*Math.max(0,t-i.t)),from:i}}function q(e,t,n,r){return{x:e+n*Math.cos(r),y:t-n*Math.sin(r)}}function J(e,t,n,r,i){let a=N(r,0,1),o=N(i,0,1);if(o<=a)return``;let s=q(e,t,n,Math.PI*(1-a)),c=q(e,t,n,Math.PI*(1-o));return`M${L(s.x)},${L(s.y)} A${n},${n} 0 0 1 ${L(c.x)},${L(c.y)}`}function Y(e,t,n){return e===null||!Number.isFinite(e)?`unknown`:e>=n?`danger`:e>=t?`warn`:`ok`}function X(e,t,n=640){let[r,i]=(0,a.useState)(null),[o,s]=(0,a.useState)(null);return(0,a.useLayoutEffect)(()=>{e.current!==o&&s(e.current)}),(0,a.useLayoutEffect)(()=>{if(t!==void 0)return;let e=o;if(!e)return;let n=()=>{let t=Math.floor(e.getBoundingClientRect().width);t>0&&i(e=>e===t?e:t)};if(n(),typeof ResizeObserver>`u`)return;let r=0,a=new ResizeObserver(()=>{cancelAnimationFrame(r),r=requestAnimationFrame(n)});return a.observe(e),()=>{cancelAnimationFrame(r),a.disconnect()}},[o,t]),Math.max(280,t??r??n)}export{f as A,v as C,d as D,s as E,l as O,y as S,m as T,M as _,J as a,_ as b,F as c,q as d,K as f,R as g,P as h,V as i,c as j,u as k,j as l,z as m,I as n,Y as o,B as p,W as r,G as s,X as t,A as u,k as v,h as w,x,g as y};
2
- //# sourceMappingURL=useChartWidth-MEXvDxDL.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useChartWidth-MEXvDxDL.js","names":[],"sources":["../../../../../../src/web-ui/components/charts/chart-tokens.css","../../../../../../src/web-ui/components/charts/format.ts","../../../../../../src/web-ui/components/charts/TableView.module.css","../../../../../../src/web-ui/components/charts/TableView.tsx","../../../../../../src/web-ui/components/charts/plot.module.css","../../../../../../src/web-ui/components/charts/ChartParts.tsx","../../../../../../src/web-ui/components/charts/ChartFrame.module.css","../../../../../../src/web-ui/components/charts/ChartFrame.tsx","../../../../../../src/web-ui/components/charts/chart-math.ts","../../../../../../src/web-ui/components/charts/useChartWidth.ts"],"sourcesContent":["/**\n * components/charts/chart-tokens.css — chart-only aliases over the design\n * tokens (owner: unit C0, with colors.ts; the chart components are C7's).\n * Every value below is `var(--existing-token)`, never a hex: the raw values\n * and their light/dark variants live in design/tokens.css, so theming is\n * inherited and can never drift out of sync with the rest of the app.\n *\n * V3.10 COLOUR ROLES (SPEC-310C §6), one meaning per hue:\n *\n * QUANTITY — `--chart-seq-1..7`, the fixed azure ramp at 214°\n * (tokens.css --data-seq-*). Every magnitude — heat cells, a single\n * nominal series, gauge fills, the positive diverging pole — is azure.\n * It is NEVER the accent: the accent is interaction-only and the\n * operator can drag it to any hue, which used to re-colour every chart\n * (tokens-310.test.ts fails if a data token here points at --accent-*).\n *\n * CATEGORICAL — `--chart-series-1..6` (tokens.css --data-cat-*). Six\n * identity inks chosen to avoid every engine, status and quantity hue,\n * with the validator scores recorded in tokens.css. Order is identity,\n * never rank: a series keeps its slot even when others are filtered out.\n * A seventh series goes to `--chart-neutral` (\"Other\") — colors.ts never\n * cycles, because a repeated colour would say two series are one.\n *\n * UNKNOWN — gray, drawn as a 45° HATCH with an outline, never a solid\n * fill on a data ramp (a solid gray would read as \"zero\" or \"neutral\").\n * `--chart-unknown-hatch` for CSS fills; colors.ts UNKNOWN_HATCH for SVG.\n *\n * QUEUED / PARKED — a neutral OUTLINE with no fill (Fleet Gantt, Swimlane).\n *\n * ENGINES — identity only, and only in charts that show nothing else\n * (runs by engine, usage bars); passed explicitly via colors.ts\n * engineColor(), never picked by index.\n *\n * STATUS — unchanged; always travels with a text label.\n *\n * Mandatory secondary encoding (direct or legend labels, and the TableView\n * twin every chart has) stays in place whatever the palette scores — colour\n * is never the only carrier of meaning.\n */\n:root {\n /* Categorical identity (fixed order; see tokens.css for the derivation). */\n --chart-series-1: var(--data-cat-1); /* steel */\n --chart-series-2: var(--data-cat-2); /* olive */\n --chart-series-3: var(--data-cat-3); /* wine */\n --chart-series-4: var(--data-cat-4); /* purple */\n --chart-series-5: var(--data-cat-5); /* green */\n --chart-series-6: var(--data-cat-6); /* pink */\n\n /* Overflow \"Other\" bucket — never part of the identity rotation above. */\n --chart-neutral: var(--status-neutral-solid);\n\n /* Quantity: the fixed azure ramp, low → high. */\n --chart-seq-1: var(--data-seq-1);\n --chart-seq-2: var(--data-seq-2);\n --chart-seq-3: var(--data-seq-3);\n --chart-seq-4: var(--data-seq-4);\n --chart-seq-5: var(--data-seq-5);\n --chart-seq-6: var(--data-seq-6);\n --chart-seq-7: var(--data-seq-7);\n\n /* The single hue for magnitude and for one nominal series (one series\n needs no legend box — it takes this colour and a direct label). */\n --chart-sequential: var(--chart-seq-5);\n --chart-sequential-soft: var(--chart-seq-3);\n\n /* Diverging pair around a neutral midpoint: azure reads \"up / better\",\n danger reads \"down / worse\" (ForestPlot effect sizes, deltas). */\n --chart-diverging-pos: var(--chart-seq-5);\n --chart-diverging-neg: var(--status-danger-solid);\n --chart-diverging-mid: var(--border-strong);\n\n /* Unknown: gray, hatched at 45°, outlined. */\n --chart-unknown: var(--status-unknown-solid);\n --chart-unknown-hatch: repeating-linear-gradient(135deg, var(--chart-unknown) 0 1px, transparent 1px 5px);\n\n /* Queued / parked: an outline, no fill. */\n --chart-queued-outline: var(--status-neutral-solid);\n\n /* Chart chrome — hairline grid/axis, one step off the surface. */\n --chart-grid: var(--border-subtle);\n --chart-axis: var(--border-strong);\n --chart-surface: var(--bg-surface);\n --chart-tooltip-bg: var(--bg-surface-raised);\n --chart-tooltip-border: var(--border-default);\n\n /* Heat (CalendarHeatmap, MatrixHeatmap): four steps of the quantity ramp.\n Step 0 is a TRUE ZERO; \"no data\" is the unknown hatch or an outlined\n empty cell, never a colour on this ramp. */\n --chart-heat-0: var(--chart-grid);\n --chart-heat-1: var(--chart-seq-2);\n --chart-heat-2: var(--chart-seq-3);\n --chart-heat-3: var(--chart-seq-5);\n --chart-heat-4: var(--chart-seq-7);\n\n /* Gauge/meter track: the lightest step of the fill's own ramp. */\n --chart-track: var(--chart-seq-1);\n}\n","/**\n * components/charts/format.ts — number formatting shared by every chart and\n * stat tile. Proportional figures everywhere EXCEPT columns that must align\n * vertically (table cells, axis ticks) — see marks-and-anatomy.md \"Proportional\n * figures for big numbers; tabular only in columns.\" Callers apply\n * `font-variant-numeric: tabular-nums` via CSS where that applies; these\n * functions only produce the string.\n */\n\n/** Auto-compact a count: 1,284 / 12.9K / 4.2M. */\nexport function formatCompact(n: number): string {\n if (!Number.isFinite(n)) return '—';\n const abs = Math.abs(n);\n if (abs >= 1_000_000) return `${(n / 1_000_000).toFixed(abs >= 10_000_000 ? 0 : 1)}M`;\n if (abs >= 10_000) return `${Math.round(n / 1000)}K`;\n if (abs >= 1_000) return n.toLocaleString('en-US');\n return Number.isInteger(n) ? String(n) : n.toFixed(1);\n}\n\n/** Auto-compact USD: $4.20 / $1.2K / $4.2M. */\nexport function formatUsd(n: number): string {\n if (!Number.isFinite(n)) return '—';\n const abs = Math.abs(n);\n const sign = n < 0 ? '-' : '';\n if (abs >= 1_000_000) return `${sign}$${(abs / 1_000_000).toFixed(1)}M`;\n if (abs >= 1_000) return `${sign}$${(abs / 1_000).toFixed(1)}K`;\n return `${sign}$${abs.toFixed(2)}`;\n}\n\n/** Fraction (0..1) as a percentage. */\nexport function formatPercent(fraction: number, digits = 0): string {\n if (!Number.isFinite(fraction)) return '—';\n return `${(fraction * 100).toFixed(digits)}%`;\n}\n\n/** Signed delta for a stat tile: \"+12\" / \"-3\" / \"0\". */\nexport function formatSignedCompact(n: number): string {\n if (!Number.isFinite(n)) return '—';\n const s = formatCompact(Math.abs(n));\n if (n > 0) return `+${s}`;\n if (n < 0) return `-${s}`;\n return s;\n}\n\n/** YYYY-MM-DD -> short label, e.g. \"Aug 14\". Local-independent (UTC parse). */\nexport function formatDayLabel(day: string): string {\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(day)) return day;\n const d = new Date(`${day}T00:00:00Z`);\n // Date normalizes impossible dates; compare the padded UTC date to reject rollover.\n if (Number.isNaN(d.getTime()) || d.toISOString().slice(0, 10) !== day) return day;\n return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', timeZone: 'UTC' });\n}\n\n/** Epoch ms -> short label for axis ticks. */\nexport function formatTimeLabel(ms: number): string {\n const d = new Date(ms);\n if (Number.isNaN(d.getTime())) return '';\n return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });\n}\n",".table {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--text-xs-size);\n}\n\n.table th,\n.table td {\n text-align: left;\n padding: var(--space-1) var(--space-2);\n border-bottom: 1px solid var(--border-subtle);\n}\n\n.table th {\n color: var(--text-tertiary);\n font-weight: var(--font-weight-medium);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n font-size: var(--text-xs-size);\n}\n\n.numeric {\n text-align: right;\n font-variant-numeric: tabular-nums;\n}\n\n.empty {\n color: var(--text-tertiary);\n text-align: center;\n}\n","/**\n * components/charts/TableView.tsx — the WCAG-clean accessibility twin every\n * chart should ship (dataviz skill: \"no table view / color-only encoding on\n * a continuous scale\" is an anti-pattern). Every value a chart's tooltip or\n * direct label shows must also be reachable here without hovering anything.\n */\nimport type { ReactNode } from 'react';\nimport styles from './TableView.module.css';\n\nexport interface TableColumn<T> {\n key: string;\n label: string;\n numeric?: boolean;\n render: (row: T) => ReactNode;\n}\n\nexport function TableView<T>({\n caption,\n columns,\n rows,\n rowKey,\n emptyMessage = 'No rows.',\n}: {\n caption: string;\n columns: TableColumn<T>[];\n rows: T[];\n rowKey: (row: T, index: number) => string;\n /** Shown as a single full-width row when `rows` is empty (V3.10). */\n emptyMessage?: string;\n}) {\n return (\n <table className={styles.table}>\n <caption className=\"visually-hidden\">{caption}</caption>\n <thead>\n <tr>\n {columns.map((c) => (\n <th key={c.key} scope=\"col\" className={c.numeric ? styles.numeric : undefined}>\n {c.label}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.length === 0 ? (\n <tr>\n <td colSpan={Math.max(1, columns.length)} className={styles.empty}>\n {emptyMessage}\n </td>\n </tr>\n ) : null}\n {rows.map((row, i) => (\n <tr key={rowKey(row, i)}>\n {columns.map((c) => (\n <td key={c.key} className={c.numeric ? styles.numeric : undefined}>\n {c.render(row)}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n );\n}\n","/* Shared plot chrome for the V3.10 charts: recessive hairline grid/axes,\n text in text tokens (never the series colour), one tooltip style. */\n.plotWrap {\n position: relative;\n width: 100%;\n min-width: 0;\n}\n\n.svg {\n display: block;\n overflow: visible;\n max-width: 100%;\n}\n\n.grid {\n stroke: var(--chart-grid);\n stroke-width: 1;\n shape-rendering: crispEdges;\n}\n\n.axis {\n stroke: var(--chart-axis);\n stroke-width: 1;\n shape-rendering: crispEdges;\n}\n\n.tick {\n font-family: var(--font-ui);\n font-size: var(--text-xs-size);\n fill: var(--text-tertiary);\n font-variant-numeric: tabular-nums;\n}\n\n.label {\n font-family: var(--font-ui);\n font-size: var(--text-xs-size);\n fill: var(--text-secondary);\n}\n\n.labelStrong {\n font-family: var(--font-ui);\n font-size: var(--text-xs-size);\n font-weight: var(--font-weight-medium);\n fill: var(--text-primary);\n}\n\n.line {\n fill: none;\n stroke-width: 2;\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n\n.wash {\n stroke: none;\n opacity: 0.1;\n}\n\n.reference {\n fill: none;\n stroke: var(--text-tertiary);\n stroke-width: 1;\n stroke-dasharray: 4 3;\n}\n\n.projection {\n fill: none;\n stroke-width: 2;\n stroke-dasharray: 5 4;\n stroke-linecap: round;\n}\n\n.marker {\n stroke: var(--chart-surface);\n stroke-width: 2;\n}\n\n.crosshair {\n stroke: var(--chart-axis);\n stroke-width: 1;\n pointer-events: none;\n}\n\n.hit {\n fill: transparent;\n cursor: default;\n}\n\n.hit:focus {\n outline: none;\n}\n\n.hit:focus-visible {\n stroke: var(--border-focus);\n stroke-width: 2;\n}\n\n.focusable:focus {\n outline: none;\n}\n\n.focusable:focus-visible {\n outline: 2px solid var(--border-focus);\n outline-offset: 2px;\n border-radius: var(--radius-sm);\n}\n\n.track {\n fill: var(--chart-track);\n}\n\n.noData {\n fill: none;\n stroke: var(--chart-grid);\n stroke-width: 1;\n stroke-dasharray: 2 2;\n}\n\n.tooltip {\n position: absolute;\n z-index: var(--z-dropdown);\n pointer-events: none;\n transform: translate(-50%, calc(-100% - 8px));\n padding: var(--space-2);\n border: 1px solid var(--chart-tooltip-border);\n border-radius: var(--radius-sm);\n background: var(--chart-tooltip-bg);\n box-shadow: var(--shadow-md);\n color: var(--text-primary);\n font-size: var(--text-xs-size);\n white-space: nowrap;\n}\n\n.tooltipTitle {\n color: var(--text-tertiary);\n margin-bottom: var(--space-1);\n}\n\n.tooltipRow {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n}\n\n.tooltipKey {\n width: 8px;\n height: 8px;\n border-radius: 2px;\n flex: none;\n}\n\n.tooltipValue {\n margin-left: auto;\n padding-left: var(--space-3);\n font-weight: var(--font-weight-semibold);\n font-variant-numeric: tabular-nums;\n}\n\n.tooltipMuted {\n color: var(--text-tertiary);\n font-style: italic;\n}\n\n.legend {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-1) var(--space-3);\n margin: var(--space-2) 0 0;\n padding: 0;\n list-style: none;\n font-size: var(--text-xs-size);\n color: var(--text-secondary);\n}\n\n.legendItem {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n}\n\n.swatch {\n width: 10px;\n height: 10px;\n border-radius: 2px;\n flex: none;\n}\n\n.swatchLine {\n width: 12px;\n height: 2px;\n flex: none;\n}\n\n.swatchEmpty {\n width: 10px;\n height: 10px;\n border-radius: 2px;\n flex: none;\n border: 1px dashed var(--chart-axis);\n}\n\n.note {\n margin: var(--space-2) 0 0;\n font-size: var(--text-xs-size);\n color: var(--text-tertiary);\n}\n\n.srOnly {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n .animated {\n transition: opacity 120ms ease;\n }\n}\n\n/* V3.10 — engine monogram beside a lane label (EngineTick). */\n.monogram {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n font-weight: var(--font-weight-semibold);\n fill: var(--text-secondary);\n}\n\n/* V3.10 — an unknown mark: hatch fill (set inline via url(#id)) + outline. */\n.unknownMark {\n stroke: var(--chart-unknown);\n stroke-width: 1;\n}\n\n/* A swatch in a legend that stands for \"unknown / not measured\". */\n.swatchHatch {\n width: 10px;\n height: 10px;\n border-radius: 2px;\n flex: none;\n border: 1px solid var(--chart-unknown);\n background: var(--chart-unknown-hatch);\n}\n\n/* Text laid over the plot (reference labels): a surface-coloured halo keeps it\n legible where it crosses a line, in both themes. */\n.halo {\n paint-order: stroke;\n stroke: var(--chart-surface);\n stroke-width: 3px;\n stroke-linejoin: round;\n}\n","/**\n * components/charts/ChartParts.tsx — small shared pieces of the V3.10 charts:\n * the legend list, the tooltip, the unknown hatch and the engine tick.\n * Identity is never colour alone: every swatch sits beside its text label,\n * and text always wears text tokens.\n */\nimport type { ReactNode } from 'react';\nimport { UNKNOWN_HATCH, engineColor, type ChartEngine } from './colors.js';\nimport plot from './plot.module.css';\n\nexport interface ChartLegendItem {\n label: string;\n color?: string;\n /** `hatch` = the unknown texture (not measured), never a colour. */\n kind?: 'swatch' | 'line' | 'empty' | 'hatch';\n}\n\n/** Renders nothing for fewer than `min` items (a lone series is named by the title). */\nexport function ChartLegend({ items, min = 2 }: { items: ChartLegendItem[]; min?: number }): ReactNode {\n if (items.length < min) return null;\n return (\n <ul className={plot.legend}>\n {items.map((item) => (\n <li key={item.label} className={plot.legendItem}>\n <span\n aria-hidden=\"true\"\n className={\n item.kind === 'line' ? plot.swatchLine : item.kind === 'empty' ? plot.swatchEmpty : item.kind === 'hatch' ? plot.swatchHatch : plot.swatch\n }\n style={item.kind === 'empty' || item.kind === 'hatch' ? undefined : { background: item.color }}\n />\n {item.label}\n </li>\n ))}\n </ul>\n );\n}\n\nexport interface TooltipRow {\n key: string;\n label: string;\n value: string | null;\n color?: string;\n}\n\n/**\n * Positioned in the plot's own pixel space (the plot wrapper is\n * position:relative). `left` is clamped by the caller so it never overflows.\n */\nexport function ChartTooltip({ left, top, title, rows }: { left: number; top: number; title: string; rows: TooltipRow[] }) {\n return (\n <div className={plot.tooltip} style={{ left, top }} role=\"presentation\">\n <div className={plot.tooltipTitle}>{title}</div>\n {rows.map((row) => (\n <div key={row.key} className={plot.tooltipRow}>\n {row.color ? <span className={plot.tooltipKey} style={{ background: row.color }} aria-hidden=\"true\" /> : null}\n <span>{row.label}</span>\n {row.value === null ? (\n <span className={`${plot.tooltipValue} ${plot.tooltipMuted}`}>no data</span>\n ) : (\n <span className={plot.tooltipValue}>{row.value}</span>\n )}\n </div>\n ))}\n </div>\n );\n}\n\n/** Keep a centred tooltip inside [margin, width - margin]. */\nexport function clampTooltipLeft(x: number, width: number, margin = 70): number {\n return Math.min(Math.max(x, Math.min(margin, width / 2)), Math.max(width - margin, width / 2));\n}\n\n// ---------------------------------------------------------------------------\n// Unknown hatch (V3.10) — one <pattern> per chart instance\n// ---------------------------------------------------------------------------\n\n/**\n * The 45° unknown hatch as an SVG <pattern>. Render it inside the chart's own\n * <svg><defs> with an id from `hatchPatternId(useId())` (colors.ts) — ids are\n * document-global, so a shared literal id would let one chart's unmount blank\n * another's hatch — then fill unknown marks with `url(#id)` and outline them\n * with CHART_UNKNOWN. Texture, not hue, is what separates \"not measured\" from\n * a low value, so it survives colour-blindness and greyscale print.\n */\nexport function HatchPattern({ id }: { id: string }) {\n const { size, angle, strokeWidth, stroke } = UNKNOWN_HATCH;\n return (\n <pattern id={id} width={size} height={size} patternUnits=\"userSpaceOnUse\" patternTransform={`rotate(${angle})`}>\n <line x1={0} y1={0} x2={0} y2={size} stroke={stroke} strokeWidth={strokeWidth} />\n </pattern>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Engine identity (V3.10) — a 2px tick plus a one-letter monogram\n// ---------------------------------------------------------------------------\n\nconst ENGINE_LETTER: Readonly<Record<ChartEngine, string>> = { claude: 'C', codex: 'X', grok: 'G', local: 'L' };\n\n/** The monogram letter for an engine (mirrors workbench-types ENGINE_MONOGRAM; charts stay core-free). */\nexport function engineLetter(engine: ChartEngine): string {\n return ENGINE_LETTER[engine];\n}\n\n/**\n * SVG engine mark for a lane label: the 2px identity tick and the monogram.\n * Never a vendor logo (SPEC-310C §6). The engine's NAME still travels in the\n * lane's spoken summary and the table — the letter is a glance aid only.\n */\nexport function EngineTick({ engine, x, y, height }: { engine: ChartEngine; x: number; y: number; height: number }) {\n return (\n <g data-engine={engine} aria-hidden=\"true\">\n <rect x={x} y={y} width={2} height={height} rx={1} fill={engineColor(engine)} />\n <text className={plot.monogram} x={x + 6} y={y + height / 2} dy=\"0.34em\">\n {ENGINE_LETTER[engine]}\n </text>\n </g>\n );\n}\n\n/** A quiet ⋯ glyph (three dots), currentColor, 16px. */\nexport function MoreGlyph() {\n return (\n <svg width={16} height={16} viewBox=\"0 0 16 16\" aria-hidden=\"true\" focusable=\"false\">\n <circle cx={3.5} cy={8} r={1.4} fill=\"currentColor\" />\n <circle cx={8} cy={8} r={1.4} fill=\"currentColor\" />\n <circle cx={12.5} cy={8} r={1.4} fill=\"currentColor\" />\n </svg>\n );\n}\n",".frame {\n margin: 0;\n min-width: 0;\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-lg);\n background: var(--bg-surface);\n /* V3.10: 16px (12px compact density) — the card-pad token follows density. */\n padding: var(--card-pad, var(--space-4));\n}\n\n.header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: var(--space-3);\n flex-wrap: wrap;\n margin-bottom: var(--space-3);\n}\n\n.actions {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n flex: none;\n margin-left: auto;\n}\n\n.menuWrap {\n position: relative;\n display: inline-flex;\n}\n\n/* The ⋯ button: quiet until hovered or focused, but always a real control. */\n.more {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: calc(var(--control-h-xs, 20px) + 4px);\n height: calc(var(--control-h-xs, 20px) + 4px);\n padding: 0;\n border: 1px solid transparent;\n border-radius: var(--radius-sm);\n background: transparent;\n color: var(--text-tertiary);\n cursor: pointer;\n transition: background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);\n}\n\n.more:hover,\n.more[aria-expanded='true'] {\n background: var(--bg-hover);\n color: var(--text-primary);\n}\n\n.more:focus-visible {\n outline: 2px solid var(--border-focus);\n outline-offset: 1px;\n}\n\n.menu {\n position: absolute;\n top: calc(100% + var(--space-1));\n right: 0;\n z-index: var(--z-dropdown);\n display: flex;\n flex-direction: column;\n min-width: 176px;\n padding: var(--space-1);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-md);\n background: var(--bg-surface-raised);\n box-shadow: var(--shadow-menu);\n}\n\n.menuItem {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n padding: var(--space-1) var(--space-2);\n border: 0;\n border-radius: var(--radius-sm);\n background: transparent;\n color: var(--text-primary);\n font: inherit;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n text-align: left;\n cursor: pointer;\n}\n\n.menuItem:hover,\n.menuItem:focus-visible {\n background: var(--bg-hover);\n outline: none;\n}\n\n.check {\n width: 1em;\n color: var(--text-secondary);\n}\n\n.hint {\n margin-left: auto;\n padding: 0 var(--space-1);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-xs, 3px);\n color: var(--text-tertiary);\n font-family: var(--font-mono);\n font-size: var(--text-2xs-size);\n}\n\n.heading {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.title {\n font-size: var(--text-sm-size);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n}\n\n.description {\n font-size: var(--text-xs-size);\n color: var(--text-tertiary);\n}\n\n.plot {\n position: relative;\n width: 100%;\n min-width: 0;\n}\n\n.table {\n max-height: 360px;\n overflow: auto;\n}\n\n.caveat {\n margin: 0 0 var(--space-3);\n padding: var(--space-2) var(--space-3);\n border-radius: var(--radius-md);\n background: var(--status-unknown-bg);\n color: var(--status-unknown-fg);\n font-size: var(--text-xs-size);\n line-height: var(--text-sm-line);\n}\n\n.state {\n margin: 0;\n padding: var(--space-6) var(--space-3);\n text-align: center;\n color: var(--text-tertiary);\n font-size: var(--text-sm-size);\n}\n\n.dark {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n align-items: center;\n}\n\n.darkTitle {\n margin: 0;\n color: var(--text-secondary);\n font-weight: var(--font-weight-semibold);\n}\n\n.darkBody {\n margin: 0;\n font-size: var(--text-xs-size);\n max-width: 44ch;\n}\n\n.unknown {\n color: var(--status-unknown-fg);\n}\n","/**\n * components/charts/ChartFrame.tsx — the shell every V3.10 chart renders in:\n * title + description, an honest caveat, the Table twin (the WCAG-clean view,\n * reachable without hovering anything), and the designed non-ready states. A\n * chart never draws empty axes: it says what the emptiness means.\n *\n * loading — the previous render is held when there is one (no skeleton\n * flash on refetch); otherwise a quiet placeholder.\n * empty — \"No runs in this window.\" A genuine, known zero.\n * dark — \"Fleet dark since Sep 1\": nothing has happened since a date.\n * unknown — the source could not be read. Never drawn as zeros.\n *\n * V3.10 (SPEC-310C §6 \"Table toggle: moves into ⋯\"): the Chart | Table\n * segmented control used to sit beside every title — noise on a KPI-sized\n * card, and it wrapped against long titles (\"Memo hit rate\"). It is now a\n * quiet ⋯ menu button (still a real, labelled button: the table stays one\n * Tab + Enter away) plus the `T` key anywhere inside the card, which is the\n * `chart.table` command in routes/verse/shell/command-catalog.ts. The key is\n * matched here directly rather than through the catalog so this shared kit\n * (also used by the legacy console) never imports a route module; the chart\n * tests assert the two stay the same key.\n */\nimport { useCallback, useEffect, useId, useRef, useState, type KeyboardEvent, type ReactNode } from 'react';\nimport { MoreGlyph } from './ChartParts.js';\nimport { formatDayLabel } from './format.js';\nimport './chart-tokens.css';\nimport styles from './ChartFrame.module.css';\n\nexport type ChartStatus =\n | { kind: 'ready' }\n | { kind: 'loading' }\n | { kind: 'empty'; message?: string }\n | { kind: 'dark'; since: string; subject?: string; detail?: string }\n | { kind: 'unknown'; reason?: string };\n\nexport type ChartView = 'chart' | 'table';\n\n/** The key that flips a focused chart card between plot and table (catalog `chart.table`). */\nexport const CHART_TABLE_KEY = 't';\n\nexport interface ChartFrameProps {\n title: string;\n description?: string;\n caveat?: string;\n status?: ChartStatus;\n /** Start on the table (e.g. a screen-reader-first surface, or a matrix at 375 px). */\n defaultView?: ChartView;\n /** Hide the view menu (only for a chart that already IS its numbers). */\n hideToggle?: boolean;\n /** Extra header controls (a facet picker), rendered before the ⋯ menu. */\n actions?: ReactNode;\n /** The plot. */\n children: ReactNode;\n table: ReactNode;\n /** Rendered under the plot in chart view (legends, notes). */\n footer?: ReactNode;\n}\n\n/** \"Sep 1\" from an ISO timestamp or YYYY-MM-DD (UTC day, like the axis labels). */\nexport function sinceLabel(since: string): string {\n return formatDayLabel(since.slice(0, 10));\n}\n\nfunction StatusMessage({ status }: { status: Exclude<ChartStatus, { kind: 'ready' }> }): ReactNode {\n switch (status.kind) {\n case 'loading':\n return <p className={styles.state} aria-busy=\"true\">Loading…</p>;\n case 'empty':\n return <p className={styles.state}>{status.message ?? 'Nothing happened in this window.'}</p>;\n case 'dark':\n return (\n <div className={`${styles.state} ${styles.dark}`}>\n <p className={styles.darkTitle}>\n {status.subject ?? 'Fleet'} dark since {sinceLabel(status.since)}\n </p>\n <p className={styles.darkBody}>{status.detail ?? 'No runs or proposals have been recorded since then.'}</p>\n </div>\n );\n case 'unknown':\n return (\n <p className={`${styles.state} ${styles.unknown}`} role=\"note\">\n Unknown — {status.reason ?? 'the data source could not be read.'} Nothing is shown rather than a guess.\n </p>\n );\n }\n}\n\n/** True when a key press is typing into a field — never steal it for the T shortcut. */\nfunction isEditableTarget(target: EventTarget | null): boolean {\n if (!(target instanceof HTMLElement)) return false;\n const tag = target.tagName;\n return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || target.isContentEditable;\n}\n\nconst VIEW_ITEMS: ReadonlyArray<{ view: ChartView; label: string; hint: string | null }> = [\n { view: 'chart', label: 'Show as chart', hint: null },\n { view: 'table', label: 'Show as table', hint: 'T' },\n];\n\n/**\n * The ⋯ menu: a menu button (WAI-ARIA menu-button pattern) with two\n * menuitemradio entries. Arrow keys move, Enter / Space pick, Escape and Tab\n * close; focus returns to the button on every close so the keyboard user is\n * never dropped at the top of the document.\n */\nfunction ViewMenu({ title, view, onPick }: { title: string; view: ChartView; onPick: (view: ChartView) => void }) {\n const [open, setOpen] = useState(false);\n const [active, setActive] = useState(0);\n const buttonRef = useRef<HTMLButtonElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const menuId = useId();\n\n const close = useCallback((refocus: boolean) => {\n setOpen(false);\n if (refocus) buttonRef.current?.focus();\n }, []);\n\n useEffect(() => {\n if (!open) return undefined;\n const onDown = (e: PointerEvent): void => {\n const t = e.target as Node | null;\n if (t && (menuRef.current?.contains(t) || buttonRef.current?.contains(t))) return;\n setOpen(false);\n };\n document.addEventListener('pointerdown', onDown);\n return () => document.removeEventListener('pointerdown', onDown);\n }, [open]);\n\n useEffect(() => {\n if (!open) return;\n menuRef.current?.querySelectorAll<HTMLElement>('[role=\"menuitemradio\"]')[active]?.focus();\n }, [open, active]);\n\n function openAt(index: number): void {\n setActive(index);\n setOpen(true);\n }\n\n function onButtonKey(e: KeyboardEvent<HTMLButtonElement>): void {\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {\n e.preventDefault();\n openAt(e.key === 'ArrowUp' ? VIEW_ITEMS.length - 1 : 0);\n }\n }\n\n function onMenuKey(e: KeyboardEvent<HTMLDivElement>): void {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setActive((a) => (a + 1) % VIEW_ITEMS.length);\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setActive((a) => (a - 1 + VIEW_ITEMS.length) % VIEW_ITEMS.length);\n } else if (e.key === 'Home') {\n e.preventDefault();\n setActive(0);\n } else if (e.key === 'End') {\n e.preventDefault();\n setActive(VIEW_ITEMS.length - 1);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n e.stopPropagation();\n close(true);\n } else if (e.key === 'Tab') {\n close(false);\n }\n }\n\n return (\n <span className={styles.menuWrap}>\n <button\n ref={buttonRef}\n type=\"button\"\n className={styles.more}\n aria-label={`${title}: view options`}\n aria-haspopup=\"menu\"\n aria-expanded={open}\n aria-controls={open ? menuId : undefined}\n title=\"View options (T toggles the table)\"\n onClick={() => (open ? close(false) : openAt(Math.max(0, VIEW_ITEMS.findIndex((i) => i.view === view))))}\n onKeyDown={onButtonKey}\n >\n <MoreGlyph />\n </button>\n {open ? (\n <div ref={menuRef} id={menuId} role=\"menu\" aria-label={`${title} view`} className={styles.menu} onKeyDown={onMenuKey}>\n {VIEW_ITEMS.map((item, i) => (\n <button\n key={item.view}\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={view === item.view}\n tabIndex={i === active ? 0 : -1}\n className={styles.menuItem}\n onClick={() => {\n onPick(item.view);\n close(true);\n }}\n >\n <span className={styles.check} aria-hidden=\"true\">{view === item.view ? '✓' : ''}</span>\n <span>{item.label}</span>\n {item.hint ? <kbd className={styles.hint}>{item.hint}</kbd> : null}\n </button>\n ))}\n </div>\n ) : null}\n </span>\n );\n}\n\nexport function ChartFrame({\n title,\n description,\n caveat,\n status = { kind: 'ready' },\n defaultView = 'chart',\n hideToggle = false,\n actions,\n children,\n table,\n footer,\n}: ChartFrameProps) {\n const [view, setView] = useState<ChartView>(defaultView);\n const titleId = useId();\n const ready = status.kind === 'ready';\n const canToggle = ready && !hideToggle;\n\n function onKeyDown(e: KeyboardEvent<HTMLElement>): void {\n if (!canToggle || e.defaultPrevented) return;\n if (e.metaKey || e.ctrlKey || e.altKey || e.shiftKey) return;\n if (e.key.toLowerCase() !== CHART_TABLE_KEY || isEditableTarget(e.target)) return;\n e.preventDefault();\n setView((v) => (v === 'chart' ? 'table' : 'chart'));\n }\n\n return (\n <figure className={styles.frame} aria-labelledby={titleId} data-chart-card=\"\" data-view={view} onKeyDown={onKeyDown}>\n <figcaption className={styles.header}>\n <span className={styles.heading}>\n <span id={titleId} className={styles.title}>{title}</span>\n {description ? <span className={styles.description}>{description}</span> : null}\n </span>\n {actions || canToggle ? (\n <span className={styles.actions}>\n {actions}\n {canToggle ? <ViewMenu title={title} view={view} onPick={setView} /> : null}\n </span>\n ) : null}\n </figcaption>\n {caveat ? (\n <p className={styles.caveat} role=\"note\">\n {caveat}\n </p>\n ) : null}\n {!ready ? (\n <StatusMessage status={status} />\n ) : view === 'table' ? (\n <div className={styles.table}>{table}</div>\n ) : (\n <>\n <div className={styles.plot}>{children}</div>\n {footer}\n </>\n )}\n </figure>\n );\n}\n","/**\n * components/charts/chart-math.ts — the pure geometry and statistics behind\n * the V3.10 chart kit (AreaTrend, BarStack, Swimlane, Funnel, CalendarHeatmap,\n * BurnDown, Gauge). No React, no DOM: every function here is unit tested\n * directly, so a chart component is only layout glue around numbers that are\n * already proven.\n *\n * Honesty rule shared with types.ts: `null` is UNKNOWN and is never coerced to\n * 0 by anything in this file. Functions that need a number skip nulls and say\n * so in their return value.\n */\n\n// ---------------------------------------------------------------------------\n// Scales and ticks\n// ---------------------------------------------------------------------------\n\n/**\n * \"Nice\" axis ticks: a step of 1, 2, 2.5 or 5 × 10^n chosen so there are\n * about `count` intervals, starting at or below `min` and ending at or above\n * `max`. Clean numbers (0 / 250 / 500), never 0 / 233.3 / 466.7.\n */\nexport function niceTicks(min: number, max: number, count = 4): number[] {\n if (!Number.isFinite(min) || !Number.isFinite(max)) return [0];\n if (max < min) [min, max] = [max, min];\n if (max === min) {\n if (max === 0) return [0, 1];\n const pad = Math.abs(max) * 0.5;\n return niceTicks(Math.min(0, min - pad), max + pad, count);\n }\n const rawStep = (max - min) / Math.max(1, count);\n const magnitude = 10 ** Math.floor(Math.log10(rawStep));\n const residual = rawStep / magnitude;\n const nice = residual <= 1 ? 1 : residual <= 2 ? 2 : residual <= 2.5 ? 2.5 : residual <= 5 ? 5 : 10;\n const step = nice * magnitude;\n const start = Math.floor(min / step) * step;\n const end = Math.ceil(max / step) * step;\n const ticks: number[] = [];\n // Round away float drift (0.1 + 0.2) so labels stay clean.\n const decimals = Math.max(0, -Math.floor(Math.log10(step)) + 1);\n for (let v = start; v <= end + step / 2; v += step) ticks.push(Number(v.toFixed(decimals)));\n return ticks;\n}\n\n/** Linear map from [d0, d1] to [r0, r1]; a zero-width domain maps to the range midpoint. */\nexport function linearScale(d0: number, d1: number, r0: number, r1: number): (v: number) => number {\n const span = d1 - d0;\n if (span === 0) return () => (r0 + r1) / 2;\n return (v: number) => r0 + ((v - d0) / span) * (r1 - r0);\n}\n\n/** Evenly thinned indexes so at most `max` labels are drawn, always keeping the last one. */\nexport function thinIndexes(length: number, max: number): number[] {\n if (length <= 0) return [];\n if (max <= 1) return [length - 1];\n if (length <= max) return Array.from({ length }, (_, i) => i);\n const step = Math.ceil((length - 1) / (max - 1));\n const out: number[] = [];\n for (let i = length - 1; i >= 0; i -= step) out.push(i);\n return out.reverse();\n}\n\n/** Clamp to [lo, hi]. */\nexport function clamp(v: number, lo: number, hi: number): number {\n return Math.min(hi, Math.max(lo, v));\n}\n\n// ---------------------------------------------------------------------------\n// Runs (null-aware line segments)\n// ---------------------------------------------------------------------------\n\nexport interface XY {\n x: number;\n y: number;\n}\n\n/** Split a series at nulls so a gap renders as a break, never as a dip to zero. */\nexport function splitRuns(points: ReadonlyArray<{ x: number; y: number | null }>): XY[][] {\n const runs: XY[][] = [];\n let current: XY[] = [];\n for (const p of points) {\n if (p.y === null || !Number.isFinite(p.y)) {\n if (current.length) runs.push(current);\n current = [];\n continue;\n }\n current.push({ x: p.x, y: p.y });\n }\n if (current.length) runs.push(current);\n return runs;\n}\n\nexport function linePath(run: ReadonlyArray<XY>): string {\n return run.map((p, i) => `${i === 0 ? 'M' : 'L'}${round(p.x)},${round(p.y)}`).join(' ');\n}\n\n/** Closed area under (or between) a run and a baseline run of equal length. */\nexport function areaPath(top: ReadonlyArray<XY>, bottom: ReadonlyArray<XY>): string {\n if (top.length === 0) return '';\n const back = [...bottom].reverse();\n return `${linePath(top)} ${back.map((p) => `L${round(p.x)},${round(p.y)}`).join(' ')} Z`;\n}\n\nexport function round(v: number): number {\n return Math.round(v * 10) / 10;\n}\n\n// ---------------------------------------------------------------------------\n// Stacking\n// ---------------------------------------------------------------------------\n\nexport interface StackSegment {\n /** Segment index in the caller's segment list. */\n index: number;\n value: number;\n y0: number;\n y1: number;\n}\n\nexport interface StackedColumn {\n segments: StackSegment[];\n /** Sum of known values. */\n total: number;\n /** True when at least one segment value is null (the total is a lower bound). */\n incomplete: boolean;\n /** True when every segment value is null (nothing is known). */\n unknown: boolean;\n}\n\n/** Stack one column's values bottom-up. Nulls are skipped and flagged, zeros take no height. */\nexport function stackColumn(values: ReadonlyArray<number | null>): StackedColumn {\n let acc = 0;\n let incomplete = false;\n let known = 0;\n const segments: StackSegment[] = [];\n values.forEach((value, index) => {\n if (value === null || !Number.isFinite(value)) {\n incomplete = true;\n return;\n }\n known++;\n const v = Math.max(0, value);\n if (v > 0) segments.push({ index, value: v, y0: acc, y1: acc + v });\n acc += v;\n });\n return { segments, total: acc, incomplete, unknown: known === 0 && values.length > 0 };\n}\n\n// ---------------------------------------------------------------------------\n// Rounded-end bars (4 px data end, square at the baseline)\n// ---------------------------------------------------------------------------\n\n/**\n * Path for a vertical bar whose TOP corners are rounded by `r` (the data end)\n * and whose bottom sits square on the baseline. `r` shrinks for short bars so\n * the corners never cross.\n */\nexport function roundedTopBar(x: number, y: number, w: number, h: number, r = 4): string {\n if (h <= 0 || w <= 0) return '';\n const rr = Math.max(0, Math.min(r, w / 2, h));\n return [\n `M${round(x)},${round(y + h)}`,\n `L${round(x)},${round(y + rr)}`,\n `Q${round(x)},${round(y)} ${round(x + rr)},${round(y)}`,\n `L${round(x + w - rr)},${round(y)}`,\n `Q${round(x + w)},${round(y)} ${round(x + w)},${round(y + rr)}`,\n `L${round(x + w)},${round(y + h)}`,\n 'Z',\n ].join(' ');\n}\n\n/** Horizontal twin: RIGHT corners rounded (the data end), left square on the baseline. */\nexport function roundedRightBar(x: number, y: number, w: number, h: number, r = 4): string {\n if (h <= 0 || w <= 0) return '';\n const rr = Math.max(0, Math.min(r, h / 2, w));\n return [\n `M${round(x)},${round(y)}`,\n `L${round(x + w - rr)},${round(y)}`,\n `Q${round(x + w)},${round(y)} ${round(x + w)},${round(y + rr)}`,\n `L${round(x + w)},${round(y + h - rr)}`,\n `Q${round(x + w)},${round(y + h)} ${round(x + w - rr)},${round(y + h)}`,\n `L${round(x)},${round(y + h)}`,\n 'Z',\n ].join(' ');\n}\n\n// ---------------------------------------------------------------------------\n// Funnel\n// ---------------------------------------------------------------------------\n\nexport interface FunnelStep {\n value: number | null;\n /** Share of the FIRST stage (0..1), null when either side is unknown or the first is 0. */\n ofFirst: number | null;\n /** Share of the PREVIOUS stage (0..1), null for the first stage or when unknown. */\n ofPrevious: number | null;\n}\n\nexport function funnelSteps(values: ReadonlyArray<number | null>): FunnelStep[] {\n const first = values[0] ?? null;\n return values.map((value, i) => {\n const previous = i > 0 ? values[i - 1] ?? null : null;\n return {\n value,\n ofFirst: value !== null && first !== null && first > 0 ? value / first : null,\n ofPrevious: i > 0 && value !== null && previous !== null && previous > 0 ? value / previous : null,\n };\n });\n}\n\n// ---------------------------------------------------------------------------\n// Calendar heatmap\n// ---------------------------------------------------------------------------\n\nexport interface CalendarCell {\n day: string;\n value: number | null;\n /** Column (week index from the first rendered week). */\n week: number;\n /** Row, 0 = weekStart. */\n weekday: number;\n /** True for days before the first datum / after the last (padding cells). */\n outside: boolean;\n}\n\nexport interface CalendarGrid {\n cells: CalendarCell[];\n weeks: number;\n /** Week index where each month first appears, for the month labels. */\n months: { week: number; label: string }[];\n}\n\nconst MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n\nfunction utcDayMs(day: string): number | null {\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(day)) return null;\n const ms = Date.parse(`${day}T00:00:00Z`);\n return Number.isFinite(ms) && new Date(ms).toISOString().slice(0, 10) === day ? ms : null;\n}\n\n/**\n * Lay out consecutive days on a weeks × weekdays grid. Input days may be\n * sparse or unordered; missing days in the span become `value: null`\n * (unknown), never 0. `weekStart` 1 = Monday (ISO), 0 = Sunday.\n */\nexport function calendarGrid(\n days: ReadonlyArray<{ day: string; value: number | null }>,\n weekStart: 0 | 1 = 1,\n): CalendarGrid {\n const byDay = new Map<string, number | null>();\n let minMs = Infinity;\n let maxMs = -Infinity;\n for (const d of days) {\n const ms = utcDayMs(d.day);\n if (ms === null) continue;\n byDay.set(d.day, d.value);\n minMs = Math.min(minMs, ms);\n maxMs = Math.max(maxMs, ms);\n }\n if (!Number.isFinite(minMs)) return { cells: [], weeks: 0, months: [] };\n const DAY = 86_400_000;\n const firstWeekday = (new Date(minMs).getUTCDay() - weekStart + 7) % 7;\n const gridStart = minMs - firstWeekday * DAY;\n const lastWeekday = (new Date(maxMs).getUTCDay() - weekStart + 7) % 7;\n const gridEnd = maxMs + (6 - lastWeekday) * DAY;\n const cells: CalendarCell[] = [];\n const months: { week: number; label: string }[] = [];\n let lastMonth = -1;\n for (let ms = gridStart, i = 0; ms <= gridEnd; ms += DAY, i++) {\n const day = new Date(ms).toISOString().slice(0, 10);\n const week = Math.floor(i / 7);\n const weekday = i % 7;\n const outside = ms < minMs || ms > maxMs;\n cells.push({ day, value: outside ? null : byDay.has(day) ? byDay.get(day)! : null, week, weekday, outside });\n const month = new Date(ms).getUTCMonth();\n // First rendered week of each month; the component drops a label that\n // would collide with the previous one.\n if (!outside && month !== lastMonth) {\n months.push({ week, label: MONTHS[month]! });\n lastMonth = month;\n }\n }\n return { cells, weeks: Math.floor((gridEnd - gridStart) / DAY / 7) + 1, months };\n}\n\n/**\n * Bucket a value into 0..steps for a sequential ramp: 0 is reserved for a\n * true zero, 1..steps split (0, max] evenly. null → null (unknown).\n */\nexport function heatBucket(value: number | null, max: number, steps = 4): number | null {\n if (value === null || !Number.isFinite(value)) return null;\n if (value <= 0 || max <= 0) return 0;\n return clamp(Math.ceil((value / max) * steps), 1, steps);\n}\n\n// ---------------------------------------------------------------------------\n// Burn-down projection\n// ---------------------------------------------------------------------------\n\nexport interface BurnPoint {\n t: number;\n remaining: number | null;\n}\n\nexport interface BurnProjection {\n /** Units per millisecond (negative while burning). Null with fewer than two known points. */\n slopePerMs: number | null;\n /** When the projection crosses 0, if it does before `resetAt`. */\n exhaustAt: number | null;\n /** When it crosses `reserve`, if a reserve is set and it does before `resetAt`. */\n reserveAt: number | null;\n /** Projected remaining at reset (clamped at 0), or null when there is no slope. */\n remainingAtReset: number | null;\n /** The last known point the projection starts from. */\n from: { t: number; remaining: number } | null;\n}\n\n/**\n * Least-squares slope over the most recent `window` known points, projected\n * forward from the last known point. A flat or rising series never\n * \"exhausts\". Pure: the caller supplies `resetAt`.\n */\nexport function projectBurnDown(\n points: ReadonlyArray<BurnPoint>,\n resetAt: number,\n opts: { window?: number; reserve?: number | null } = {},\n): BurnProjection {\n const known = points\n .filter((p): p is { t: number; remaining: number } => p.remaining !== null && Number.isFinite(p.remaining) && Number.isFinite(p.t))\n .sort((a, b) => a.t - b.t);\n const from = known.length ? known[known.length - 1]! : null;\n const recent = known.slice(-(opts.window ?? 6));\n if (!from || recent.length < 2) {\n return { slopePerMs: null, exhaustAt: null, reserveAt: null, remainingAtReset: null, from };\n }\n const n = recent.length;\n const meanT = recent.reduce((s, p) => s + p.t, 0) / n;\n const meanR = recent.reduce((s, p) => s + p.remaining, 0) / n;\n let num = 0;\n let den = 0;\n for (const p of recent) {\n num += (p.t - meanT) * (p.remaining - meanR);\n den += (p.t - meanT) ** 2;\n }\n const slope = den === 0 ? 0 : num / den;\n const crossing = (level: number): number | null => {\n if (slope >= 0 || from.remaining <= level) return from.remaining <= level ? from.t : null;\n const at = from.t + (level - from.remaining) / slope;\n return at <= resetAt ? at : null;\n };\n const reserve = opts.reserve ?? null;\n return {\n slopePerMs: slope,\n exhaustAt: crossing(0),\n reserveAt: reserve === null ? null : crossing(reserve),\n remainingAtReset: Math.max(0, from.remaining + slope * Math.max(0, resetAt - from.t)),\n from,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Gauge arcs\n// ---------------------------------------------------------------------------\n\n/** Point on a circle; angle in radians, 0 = +x axis, measured counter-clockwise (SVG y flipped). */\nexport function polar(cx: number, cy: number, r: number, angle: number): XY {\n return { x: cx + r * Math.cos(angle), y: cy - r * Math.sin(angle) };\n}\n\n/**\n * SVG arc for a 180° gauge from fraction `f0` to `f1` (0 = left end, 1 =\n * right end, sweeping over the top). Fractions are clamped to [0, 1].\n */\nexport function gaugeArc(cx: number, cy: number, r: number, f0: number, f1: number): string {\n const a = clamp(f0, 0, 1);\n const b = clamp(f1, 0, 1);\n if (b <= a) return '';\n const start = polar(cx, cy, r, Math.PI * (1 - a));\n const end = polar(cx, cy, r, Math.PI * (1 - b));\n // A 180° gauge never needs the large-arc flag (the span is at most π).\n return `M${round(start.x)},${round(start.y)} A${r},${r} 0 0 1 ${round(end.x)},${round(end.y)}`;\n}\n\nexport type GaugeSeverity = 'ok' | 'warn' | 'danger' | 'unknown';\n\nexport function gaugeSeverity(value: number | null, warn: number, danger: number): GaugeSeverity {\n if (value === null || !Number.isFinite(value)) return 'unknown';\n if (value >= danger) return 'danger';\n if (value >= warn) return 'warn';\n return 'ok';\n}\n","/**\n * components/charts/useChartWidth.ts — the measured pixel width of a chart's\n * container, so the V3.10 charts draw at their REAL size (text stays 12 px at\n * 375 px wide) instead of scaling a fixed viewBox down until labels are\n * unreadable. Falls back to `fallback` until measured (jsdom, SSR, first paint).\n */\nimport { useLayoutEffect, useState, type RefObject } from 'react';\n\n/** Narrowest width any chart lays itself out for (a 375 px phone minus padding). */\nexport const MIN_CHART_WIDTH = 280;\n\nexport function useChartWidth(ref: RefObject<HTMLElement | null>, fixed: number | undefined, fallback = 640): number {\n const [measured, setMeasured] = useState<number | null>(null);\n // WHY track the node: a chart whose frame starts in a non-ready state\n // (loading / empty / dark) mounts its plot — and so this ref — LATER than\n // the hook. An effect keyed only on the ref object never re-ran, so every\n // chart that first rendered \"Loading…\" stayed at the 640 px fallback and\n // was scaled down by CSS (V3.10 fix, found in the 1440 harness).\n const [node, setNode] = useState<HTMLElement | null>(null);\n // Runs after every render on purpose (ref.current is not a dependency React\n // can see); the equality guard makes it settle in one pass, never a loop.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useLayoutEffect(() => {\n if (ref.current !== node) setNode(ref.current);\n });\n useLayoutEffect(() => {\n if (fixed !== undefined) return undefined;\n const el = node;\n if (!el) return undefined;\n const read = (): void => {\n const w = Math.floor(el.getBoundingClientRect().width);\n // 0 means \"not laid out yet\" (hidden tab, jsdom) — keep the fallback.\n if (w > 0) setMeasured((prev) => (prev === w ? prev : w));\n };\n read();\n if (typeof ResizeObserver === 'undefined') return undefined;\n // rAF-coalesced: a drag-resize fires many entries per frame.\n let frame = 0;\n const observer = new ResizeObserver(() => {\n cancelAnimationFrame(frame);\n frame = requestAnimationFrame(read);\n });\n observer.observe(el);\n return () => {\n cancelAnimationFrame(frame);\n observer.disconnect();\n };\n }, [node, fixed]);\n return Math.max(MIN_CHART_WIDTH, fixed ?? measured ?? fallback);\n}\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{o as e}from"./index-afDA8cwW.js";import{K as t,W as n,q as r,tt as i}from"./global-DVgMguLr.js";var a=e({CODEX_EXPANSIVE_METERING_NOTE:()=>_,ENGINE_LABEL:()=>s,ENGINE_ORDER:()=>o,SEAT_CAPACITY_WORD:()=>b,WINDOW_SOURCE_TEXT:()=>h,firstRunnableModel:()=>v,formatDuration:()=>D,formatElapsed:()=>E,formatRelative:()=>O,groupSeats:()=>w,groupSessions:()=>T,isAbsolutePath:()=>M,modelLabel:()=>d,modelOptionFor:()=>f,prettyJson:()=>j,projectName:()=>c,seatById:()=>l,seatCapacity:()=>C,seatLabel:()=>u,seatPillLabel:()=>N,seatUnavailableReason:()=>y,seatWindowLabel:()=>S,sessionContextBudget:()=>m,summarizeToolInput:()=>k,truncate:()=>A,windowSourceText:()=>g}),o=[`claude`,`codex`,`grok`,`local`],s={claude:`Claude`,codex:`Codex`,grok:`Grok`,local:`Local`};function c(e,t=[]){let n=t.find(t=>t.path===e);return n?n.name:e.split(/[\\/]/).filter(Boolean).at(-1)??e}function l(e,t){return e.find(e=>e.id===t)}function u(e,t){return l(e,t.seatId)?.label??s[t.engine]}function d(e,t){return l(e,t.seatId)?.models.find(e=>e.id===t.model)?.label??t.model}function f(e,n){let r=l(e,n.seatId);if(!r)return null;let i=r.models.find(e=>e.id===n.model);if(i)return i;let a=t(n.model);return r.models.find(e=>t(e.id)===a)??null}function p(e){return typeof e==`number`&&Number.isFinite(e)&&e>0?e:null}function m(e,t){let a=t.usage,o=t.contextMode??`standard`,s=f(e,t),c={contextTokens:typeof a.contextTokens==`number`&&Number.isFinite(a.contextTokens)?Math.max(0,a.contextTokens):0,exact:a.contextTokensExact!==!1,mode:o,option:s},u=n(s,o),d=p(a.contextWindow);if(d!==null&&(t.engine===`local`||a.contextWindowSource===`runtime`)){let e=p(a.autoCompactAt??null)??i({engine:t.engine,runtimeWindow:d,budget:t.engine===`local`?null:u,autocompactWindow:t.engine===`claude`?r(s,o):null,maxOutputTokens:s?.maxOutputTokens??null}),n=t.engine===`local`?a.contextWindowSource??null:`runtime`;return{...c,contextWindow:d,autoCompactAt:e,source:n}}if(u)return{...c,contextWindow:u.contextWindow,autoCompactAt:u.autoCompactAt,source:s?.windowSource??`fallback`};if(d!==null)return{...c,contextWindow:d,autoCompactAt:p(a.autoCompactAt??null),source:a.contextWindowSource??null};let m=p(l(e,t.seatId)?.contextWindow??null);return{...c,contextWindow:m,autoCompactAt:null,source:m===null?null:`fallback`}}var h={runtime:`reported by the CLI on the last turn`,"provider-catalog":`from this seat's own model catalog`,"cli-catalog":`from the pinned CLI's built-in model table`,documented:`from the provider's published model table`,fallback:`a default estimate — the CLI has not reported the real window yet`};function g(e,t){return t===`local`?`${e===`runtime`?`measured from the local model server`:e===`fallback`?`a default estimate — the model server did not report one`:h[e]}; Verse passes this window to Claude Code for this chat`:h[e]}var _=`OpenAI reportedly also counts requests above 272k tokens at about 2× against plan limits, so a turn near the expansive limit may cost roughly twice that.`;function v(e){return e.models.find(e=>!e.unavailableReason)??null}function y(e){return e.health.state===`unavailable`?e.health.summary??`seat unavailable`:null}var b={ready:`usable`,tight:`tight`,blocked:`blocked`,unread:`no reading`},x=85;function S(e){let t={five_hour:`5-hour window`,seven_day:`weekly window`,codex:`weekly window`};if(t[e])return t[e];let n=/^seven_day_(.+)$/.exec(e);return n?`weekly ${n[1].replace(/_/g,` `)} window`:`${e.replace(/_/g,` `)} window`}function C(e){let t=y(e);if(t!==null)return{cls:`blocked`,usedPercent:null,text:t};let n=e.health.windows.filter(e=>typeof e.usedPercent==`number`&&Number.isFinite(e.usedPercent));if(n.length===0)return{cls:`unread`,usedPercent:null,text:`no capacity reading`};let r=n.reduce((e,t)=>t.usedPercent>e.usedPercent?t:e),i=Math.max(0,Math.min(100,r.usedPercent)),a=S(r.id);return i>=100?{cls:`blocked`,usedPercent:null,text:`${a} limit reached`}:{cls:i>=x?`tight`:`ready`,usedPercent:i,text:`${Math.round(i)}% of ${a} used`}}function w(e){return o.map(t=>({engine:t,seats:e.filter(e=>e.engine===t)})).filter(e=>e.seats.length>0)}function T(e,t,n=``){let r=n.trim().toLowerCase(),i=r?e.filter(e=>e.title.toLowerCase().includes(r)||e.projectPath.toLowerCase().includes(r)||e.model.toLowerCase().includes(r)||e.seatId.toLowerCase().includes(r)):[...e],a=new Map;for(let e of i){let t=a.get(e.projectPath)??[];t.push(e),a.set(e.projectPath,t)}let o=[];for(let[e,n]of a)n.sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt)),o.push({projectPath:e,name:c(e,t),enrolled:t.find(t=>t.path===e)?.enrolled??!1,sessions:n});return o.sort((e,t)=>t.sessions[0].updatedAt.localeCompare(e.sessions[0].updatedAt)),o}function E(e){if(!Number.isFinite(e)||e<0)return`0s`;let t=Math.floor(e/1e3);if(t<60)return`${t}s`;let n=Math.floor(t/60);return n<60?`${n}m ${t%60}s`:`${Math.floor(n/60)}h ${n%60}m`}function D(e){return!Number.isFinite(e)||e<0?`—`:e<1e3?`${Math.round(e)}ms`:e<6e4?`${(e/1e3).toFixed(1)}s`:E(e)}function O(e,t=Date.now()){let n=Date.parse(e);if(!Number.isFinite(n))return``;let r=Math.round((t-n)/1e3);if(r<0||r<60)return`now`;let i=Math.floor(r/60);if(i<60)return`${i}m`;let a=Math.floor(i/60);if(a<24)return`${a}h`;let o=Math.floor(a/24);return o<7?`${o}d`:new Date(n).toLocaleDateString([],{month:`short`,day:`numeric`})}function k(e){if(e==null)return``;if(typeof e==`string`)return A(e,96);if(typeof e!=`object`)return A(String(e),96);let t=e;for(let e of[`command`,`cmd`,`file_path`,`path`,`pattern`,`query`,`url`,`description`,`prompt`,`text`]){let n=t[e];if(typeof n==`string`&&n.trim())return A(n.trim().replace(/\s+/g,` `),96)}let n=Object.keys(t);if(n.length===0)return``;let r=t[n[0]],i=typeof r==`string`?r:JSON.stringify(r);return A(`${n[0]}: ${i??``}`.replace(/\s+/g,` `),96)}function A(e,t){return e.length>t?`${e.slice(0,t-1)}…`:e}function j(e){if(typeof e==`string`)return e;try{return JSON.stringify(e,null,2)??``}catch{return String(e)}}function M(e){return/^(?:\/|~(?:\/|$)|[a-zA-Z]:[\\/]|\\\\)/.test(e)&&![...e].some(e=>e.charCodeAt(0)<32||e.charCodeAt(0)>=127&&e.charCodeAt(0)<=159)}function N(e,t){let n=u(e,t),r=d(e,t);return!r||n.toLowerCase().includes(r.toLowerCase())?n:`${n} · ${r}`}export{g as C,a as S,N as _,v as a,m as b,O as c,M as d,f,C as g,l as h,h as i,w as l,c as m,s as n,D as o,j as p,b as r,E as s,_ as t,T as u,y as v,k as x,S as y};
2
- //# sourceMappingURL=verse-model-E98kXngO.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"verse-model-E98kXngO.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/verse-model.ts"],"sourcesContent":["/**\n * routes/verse/verse-model.ts — small pure helpers shared by the Verse\n * components (labels, grouping, health → tone). No React, no I/O.\n */\nimport type { VerseEngine, VerseModelOption, VerseProject, VerseSeat, VerseSeatHealth, VerseSession } from '../../data/api-types.js';\nimport type { VerseContextMode, VerseWindowSource } from '../../../core/verse/types.js';\nimport type { Tone } from '../../components/primitives/StatusBadge.js';\n// context-math is PURE and browser-safe by contract (its only import is\n// type-only), so a value import here does not drag node into the bundle.\nimport { budgetFor, canonicalModelId, claudeAutocompactFlag, reconcileAutoCompactAt } from '../../../core/verse/context-math.js';\n\nexport const ENGINE_ORDER: readonly VerseEngine[] = ['claude', 'codex', 'grok', 'local'];\n\nexport const ENGINE_LABEL: Record<VerseEngine, string> = {\n claude: 'Claude',\n codex: 'Codex',\n grok: 'Grok',\n local: 'Local',\n};\n\nexport function isVerseEngine(value: string): value is VerseEngine {\n return (ENGINE_ORDER as readonly string[]).includes(value);\n}\n\nexport function projectName(path: string, projects: readonly VerseProject[] = []): string {\n const known = projects.find((p) => p.path === path);\n if (known) return known.name;\n return path.split(/[\\\\/]/).filter(Boolean).at(-1) ?? path;\n}\n\nexport function seatById(seats: readonly VerseSeat[], seatId: string): VerseSeat | undefined {\n return seats.find((s) => s.id === seatId);\n}\n\nexport function seatLabel(seats: readonly VerseSeat[], session: Pick<VerseSession, 'seatId' | 'engine'>): string {\n return seatById(seats, session.seatId)?.label ?? ENGINE_LABEL[session.engine];\n}\n\nexport function modelLabel(seats: readonly VerseSeat[], session: Pick<VerseSession, 'seatId' | 'model'>): string {\n const seat = seatById(seats, session.seatId);\n return seat?.models.find((m) => m.id === session.model)?.label ?? session.model;\n}\n\n/**\n * The seat's catalog entry for a session's model. Exact id first; then the\n * canonical form, because a session created before the alias fix stores\n * `claude-opus-5.5` while today's catalog lists `claude-opus-5-5` (context-math\n * `VERSE_MODEL_ID_ALIASES`) — the record keeps its id, the lookup must not miss.\n */\nexport function modelOptionFor(seats: readonly VerseSeat[], session: Pick<VerseSession, 'seatId' | 'model'>): VerseModelOption | null {\n const seat = seatById(seats, session.seatId);\n if (!seat) return null;\n const exact = seat.models.find((m) => m.id === session.model);\n if (exact) return exact;\n const canonical = canonicalModelId(session.model);\n return seat.models.find((m) => canonicalModelId(m.id) === canonical) ?? null;\n}\n\n/** Everything the meter, the composer's cost hint and the advice banners read. */\nexport interface SessionContextBudget {\n /** Live occupancy as stored — UNCLAMPED; only the drawing clamps. */\n contextTokens: number;\n contextWindow: number | null;\n autoCompactAt: number | null;\n /** False when `contextTokens` is an upper bound (codex before its rollout is read). */\n exact: boolean;\n /** Where `contextWindow` came from; null when nothing on the record says. */\n source: VerseWindowSource | null;\n mode: VerseContextMode;\n /** The catalog option the session's model maps to on its seat, when listed. */\n option: VerseModelOption | null;\n}\n\nfunction positive(value: number | null | undefined): number | null {\n return typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : null;\n}\n\n/**\n * The window a session is measured against, and where it compacts.\n *\n * Precedence (docs/VERSE-CONTEXT.md, \"honesty rules\"):\n *\n * 0. LOCAL — the window STORED on the record, whatever its source. Verse\n * SETS a local seat's window: the claude adapter passes the stored\n * `usage.contextWindow` as `CLAUDE_CODE_MAX_CONTEXT_TOKENS`, and the\n * engine refreshes that stored value from live discovery before each\n * turn. The seat's CURRENT option can differ (another dispatch lane,\n * another resident num_ctx), and drawing it measured the chat against a\n * window the CLI was never told — \"past the 66k window\" for a chat the\n * CLI compacts at 229k. The meter and the CLI must quote one number.\n * 1. RUNTIME — the CLI reported the window for this session's last turn\n * (`usage.contextWindowSource === 'runtime'`). Nothing outranks what the\n * CLI said it is actually running with (e.g. Claude Code clamping a 1M\n * model to 200k when long-context credit runs out).\n * 2. CATALOG — the seat's CURRENT option for the session's model, in the\n * session's mode. Current rather than stored so a corrected catalog (a\n * fixed window table, a mode switch) shows up without waiting for a turn.\n * 3. STORED — whatever the record carries (every pre-3.9 session).\n * 4. The seat's default window, marked `fallback`.\n *\n * A compaction point is only ever DERIVED from a window it belongs to: a\n * runtime window without a stored point is reconciled with context-math's\n * per-engine formula, never paired with a catalog point for another window.\n */\nexport function sessionContextBudget(\n seats: readonly VerseSeat[],\n session: Pick<VerseSession, 'seatId' | 'model' | 'usage' | 'engine' | 'contextMode'>,\n): SessionContextBudget {\n const usage = session.usage;\n // No UI-side legacy rule: the engine materialises a pre-3.9 Claude\n // record's mode (and its budget) on startup and on every touch, so every\n // record reaching the browser already names the mode it runs in.\n const mode: VerseContextMode = session.contextMode ?? 'standard';\n const option = modelOptionFor(seats, session);\n const base = {\n contextTokens: typeof usage.contextTokens === 'number' && Number.isFinite(usage.contextTokens) ? Math.max(0, usage.contextTokens) : 0,\n exact: usage.contextTokensExact !== false,\n mode,\n option,\n };\n const catalog = budgetFor(option, mode);\n\n const stored = positive(usage.contextWindow);\n if (stored !== null && (session.engine === 'local' || usage.contextWindowSource === 'runtime')) {\n const storedPoint = positive(usage.autoCompactAt ?? null);\n const autoCompactAt = storedPoint ?? reconcileAutoCompactAt({\n engine: session.engine,\n runtimeWindow: stored,\n // A local window is the whole budget (no --autocompact); pairing it\n // with the seat's current option would borrow another window's point.\n budget: session.engine === 'local' ? null : catalog,\n autocompactWindow: session.engine === 'claude' ? claudeAutocompactFlag(option, mode) : null,\n maxOutputTokens: option?.maxOutputTokens ?? null,\n });\n const source = session.engine === 'local' ? usage.contextWindowSource ?? null : 'runtime';\n return { ...base, contextWindow: stored, autoCompactAt, source };\n }\n if (catalog) {\n return { ...base, contextWindow: catalog.contextWindow, autoCompactAt: catalog.autoCompactAt, source: option?.windowSource ?? 'fallback' };\n }\n if (stored !== null) {\n return { ...base, contextWindow: stored, autoCompactAt: positive(usage.autoCompactAt ?? null), source: usage.contextWindowSource ?? null };\n }\n const seatWindow = positive(seatById(seats, session.seatId)?.contextWindow ?? null);\n return { ...base, contextWindow: seatWindow, autoCompactAt: null, source: seatWindow !== null ? 'fallback' : null };\n}\n\n/** Context window for a session — see {@link sessionContextBudget} for the precedence. */\nexport function contextWindowFor(\n seats: readonly VerseSeat[],\n session: Pick<VerseSession, 'seatId' | 'model' | 'usage' | 'engine' | 'contextMode'>,\n): number | null {\n return sessionContextBudget(seats, session).contextWindow;\n}\n\n/** Plain words for a window's provenance — the meter's tooltip and the resources panel share them. */\nexport const WINDOW_SOURCE_TEXT: Record<VerseWindowSource, string> = {\n runtime: 'reported by the CLI on the last turn',\n 'provider-catalog': \"from this seat's own model catalog\",\n 'cli-catalog': \"from the pinned CLI's built-in model table\",\n documented: \"from the provider's published model table\",\n fallback: 'a default estimate — the CLI has not reported the real window yet',\n};\n\n/**\n * The same provenance, per engine. On a LOCAL seat nothing is \"reported by\n * the CLI\": Verse measures the window from the model server (llama-server\n * slot, Ollama residency/defaults) and TELLS Claude Code to use it, so the\n * sentence names both halves.\n */\nexport function windowSourceText(source: VerseWindowSource, engine: VerseEngine | null | undefined): string {\n if (engine !== 'local') return WINDOW_SOURCE_TEXT[source];\n const from = source === 'runtime' ? 'measured from the local model server'\n : source === 'fallback' ? 'a default estimate — the model server did not report one'\n : WINDOW_SOURCE_TEXT[source];\n return `${from}; Verse passes this window to Claude Code for this chat`;\n}\n\n/**\n * The one sentence about Codex's surcharge above its standard window, for\n * every surface that prices Expansive on codex (the mode menu, the\n * \"Expansive could help\" chip, the new-chat mode selector, the handoff\n * dialog). Worded as REPORTED because that is all it is: the sources\n * docs/VERSE-CONTEXT.md §2.3 cites say GPT-5.6-class requests above 272k\n * count about 2× against plan limits, and Verse has no reading of its own\n * that confirms the multiplier. It multiplies the size ratio the copy quotes\n * (the ratio of the two compaction points), which is why it says \"twice that\".\n */\nexport const CODEX_EXPANSIVE_METERING_NOTE =\n 'OpenAI reportedly also counts requests above 272k tokens at about 2× against plan limits, so a turn near the expansive limit may cost roughly twice that.';\n\n/** The first model on a seat that can actually run (skips ones listed with an `unavailableReason`). */\nexport function firstRunnableModel(seat: VerseSeat): VerseModelOption | null {\n return seat.models.find((m) => !m.unavailableReason) ?? null;\n}\n\nexport function healthTone(state: VerseSeatHealth['state']): Tone {\n switch (state) {\n case 'ready':\n return 'success';\n case 'degraded':\n return 'warning';\n case 'unavailable':\n return 'danger';\n default:\n return 'unknown';\n }\n}\n\nexport function seatUnavailableReason(seat: VerseSeat): string | null {\n if (seat.health.state !== 'unavailable') return null;\n return seat.health.summary ?? 'seat unavailable';\n}\n\n// ---------------------------------------------------------------------------\n// Seat capacity — \"which account can I actually use right now\", at the point\n// the choice is made\n// ---------------------------------------------------------------------------\n\n/**\n * The four answers a picker needs. Same vocabulary as the Usage section's\n * `CapacityClass` so the two surfaces never use different words for one state.\n */\nexport type SeatCapacityClass = 'ready' | 'tight' | 'blocked' | 'unread';\n\n/** Word, never colour alone (DESIGN-V2 §6). */\nexport const SEAT_CAPACITY_WORD: Record<SeatCapacityClass, string> = {\n ready: 'usable',\n tight: 'tight',\n blocked: 'blocked',\n unread: 'no reading',\n};\n\n/** Above this share of the binding window a seat is worth flagging. */\nconst TIGHT_PERCENT = 85;\n\nexport interface SeatCapacityNote {\n cls: SeatCapacityClass;\n /**\n * The binding window's percent when it is a real measurement. Null for an\n * unread seat AND at the 100 ceiling, where the upstream value may be the\n * provider's \"limit reached\" sentinel rather than a reading\n * (docs/VERSE-TELEMETRY-V2.md) — and \"limit reached\" is true under either.\n */\n usedPercent: number | null;\n /** One short phrase for an option label, a pill title, a menu row. */\n text: string;\n}\n\n/** `seven_day_fable` → `weekly (fable)`; `five_hour` → `5-hour`. */\nexport function seatWindowLabel(id: string): string {\n const known: Record<string, string> = {\n five_hour: '5-hour window',\n seven_day: 'weekly window',\n codex: 'weekly window',\n };\n if (known[id]) return known[id];\n const perModel = /^seven_day_(.+)$/.exec(id);\n if (perModel) return `weekly ${perModel[1]!.replace(/_/g, ' ')} window`;\n return `${id.replace(/_/g, ' ')} window`;\n}\n\n/**\n * What a seat's own health says about whether a turn sent to it will land.\n *\n * This exists because the seat picker showed NOTHING: it annotated an option\n * only when `health.state === 'unavailable'`, and Claude's `health` is\n * `unknown` by construction (docs/VERSE-TELEMETRY-V2.md). So a Claude seat\n * whose binding weekly window reads 100% used appeared as an ordinary,\n * enabled, unannotated choice, and the exhaustion was discovered at turn time\n * — exactly the failure the Usage section was built to prevent.\n *\n * A `blocked` seat is MARKED, never disabled: a used-up window can coexist\n * with a spendable credit balance, so refusing the choice would be a stronger\n * claim than the data supports.\n */\nexport function seatCapacity(seat: VerseSeat): SeatCapacityNote {\n const reason = seatUnavailableReason(seat);\n if (reason !== null) return { cls: 'blocked', usedPercent: null, text: reason };\n\n const measured = seat.health.windows.filter(\n (w): w is { id: string; usedPercent: number; resetsAt: string | null } =>\n typeof w.usedPercent === 'number' && Number.isFinite(w.usedPercent),\n );\n // No window reported a number. That is an unanswered question, not a zero —\n // an empty meter would read \"plenty left\".\n if (measured.length === 0) return { cls: 'unread', usedPercent: null, text: 'no capacity reading' };\n\n const binding = measured.reduce((a, b) => (b.usedPercent > a.usedPercent ? b : a));\n const pct = Math.max(0, Math.min(100, binding.usedPercent));\n const where = seatWindowLabel(binding.id);\n if (pct >= 100) return { cls: 'blocked', usedPercent: null, text: `${where} limit reached` };\n const rounded = Math.round(pct);\n return {\n cls: pct >= TIGHT_PERCENT ? 'tight' : 'ready',\n usedPercent: pct,\n text: `${rounded}% of ${where} used`,\n };\n}\n\n/** Seats grouped in the fixed engine order; empty engines are omitted. */\nexport function groupSeats(seats: readonly VerseSeat[]): Array<{ engine: VerseEngine; seats: VerseSeat[] }> {\n return ENGINE_ORDER.map((engine) => ({ engine, seats: seats.filter((s) => s.engine === engine) })).filter((g) => g.seats.length > 0);\n}\n\nexport interface SessionGroup {\n projectPath: string;\n name: string;\n enrolled: boolean;\n sessions: VerseSession[];\n}\n\n/** Sidebar grouping: by project, most recently touched project first, sessions newest first. */\nexport function groupSessions(sessions: readonly VerseSession[], projects: readonly VerseProject[], query = ''): SessionGroup[] {\n const q = query.trim().toLowerCase();\n const filtered = q\n ? sessions.filter((s) =>\n s.title.toLowerCase().includes(q) ||\n s.projectPath.toLowerCase().includes(q) ||\n s.model.toLowerCase().includes(q) ||\n s.seatId.toLowerCase().includes(q))\n : [...sessions];\n const byProject = new Map<string, VerseSession[]>();\n for (const s of filtered) {\n const list = byProject.get(s.projectPath) ?? [];\n list.push(s);\n byProject.set(s.projectPath, list);\n }\n const groups: SessionGroup[] = [];\n for (const [projectPath, list] of byProject) {\n list.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\n groups.push({\n projectPath,\n name: projectName(projectPath, projects),\n enrolled: projects.find((p) => p.path === projectPath)?.enrolled ?? false,\n sessions: list,\n });\n }\n groups.sort((a, b) => b.sessions[0]!.updatedAt.localeCompare(a.sessions[0]!.updatedAt));\n return groups;\n}\n\nexport function formatElapsed(ms: number): string {\n if (!Number.isFinite(ms) || ms < 0) return '0s';\n const s = Math.floor(ms / 1000);\n if (s < 60) return `${s}s`;\n const m = Math.floor(s / 60);\n if (m < 60) return `${m}m ${s % 60}s`;\n const h = Math.floor(m / 60);\n return `${h}h ${m % 60}m`;\n}\n\nexport function formatDuration(ms: number): string {\n if (!Number.isFinite(ms) || ms < 0) return '—';\n if (ms < 1000) return `${Math.round(ms)}ms`;\n if (ms < 60_000) return `${(ms / 1000).toFixed(1)}s`;\n return formatElapsed(ms);\n}\n\n/**\n * Sidebar rows carry a right-aligned relative time. Short by design — the\n * row has ~5ch for it — and it degrades to a date rather than \"412d\".\n * `now` is injectable so the format is testable without faking the clock.\n */\nexport function formatRelative(iso: string, now: number = Date.now()): string {\n const then = Date.parse(iso);\n if (!Number.isFinite(then)) return '';\n const seconds = Math.round((now - then) / 1000);\n if (seconds < 0) return 'now';\n if (seconds < 60) return 'now';\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h`;\n const days = Math.floor(hours / 24);\n if (days < 7) return `${days}d`;\n return new Date(then).toLocaleDateString([], { month: 'short', day: 'numeric' });\n}\n\nexport function formatClock(iso: string): string {\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return '';\n return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n}\n\n/** One-line description of a tool call for a collapsed card header. */\nexport function summarizeToolInput(input: unknown): string {\n if (input === null || input === undefined) return '';\n if (typeof input === 'string') return truncate(input, 96);\n if (typeof input !== 'object') return truncate(String(input), 96);\n const record = input as Record<string, unknown>;\n const preferred = ['command', 'cmd', 'file_path', 'path', 'pattern', 'query', 'url', 'description', 'prompt', 'text'];\n for (const key of preferred) {\n const v = record[key];\n if (typeof v === 'string' && v.trim()) return truncate(v.trim().replace(/\\s+/g, ' '), 96);\n }\n const keys = Object.keys(record);\n if (keys.length === 0) return '';\n const first = record[keys[0]!];\n const rendered = typeof first === 'string' ? first : JSON.stringify(first);\n return truncate(`${keys[0]}: ${rendered ?? ''}`.replace(/\\s+/g, ' '), 96);\n}\n\nexport function truncate(value: string, max: number): string {\n return value.length > max ? `${value.slice(0, max - 1)}…` : value;\n}\n\n/** Pretty JSON for tool cards; falls back to String() for non-serializable input. */\nexport function prettyJson(value: unknown): string {\n if (typeof value === 'string') return value;\n try {\n return JSON.stringify(value, null, 2) ?? '';\n } catch {\n return String(value);\n }\n}\n\n/**\n * Accepts POSIX/Windows absolute paths and `~/...`. The server rewrites the\n * home directory as `~` in every outbound payload (sanitizePublicJson) and\n * expands it again on the way in, so a `~/` project from bootstrap is valid.\n */\nexport function isAbsolutePath(value: string): boolean {\n return /^(?:\\/|~(?:\\/|$)|[a-zA-Z]:[\\\\/]|\\\\\\\\)/.test(value) &&\n ![...value].some((c) => c.charCodeAt(0) < 32 || (c.charCodeAt(0) >= 127 && c.charCodeAt(0) <= 159));\n}\n\n/**\n * Seat pill text: \"<seat> · <model>\", collapsing to just the seat when the\n * model label is already contained in it (local seats expose one model whose\n * name is the seat name), so the pill never reads \"Qwen3-Coder · Qwen3-Coder\".\n */\nexport function seatPillLabel(seats: readonly VerseSeat[], ref: Pick<VerseSession, 'seatId' | 'engine' | 'model'>): string {\n const seat = seatLabel(seats, ref);\n const model = modelLabel(seats, ref);\n if (!model || seat.toLowerCase().includes(model.toLowerCase())) return seat;\n return `${seat} · ${model}`;\n}\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{tt as e}from"./global-DVgMguLr.js";import{c as t}from"./types-Dypu22dp.js";var n={turnId:null,startedAt:null,progress:null,thinking:null,notice:null,settledTurnId:null},r={session:null,events:[],lastSeq:0,loaded:!1,loadError:null,stream:`idle`,live:n},i=new Map,a=new Map,o=new Map,s=new Map,c=new Set,l=new Map,u=new Set;function d(e){if(e!==null){let t=l.get(e);if(t)for(let e of[...t])e()}else for(let e of[...l.values()])for(let t of[...e])t();for(let e of[...c])e()}function f(e){return c.add(e),()=>c.delete(e)}function p(e,t){let n=l.get(e);return n||(n=new Set,l.set(e,n)),n.add(t),()=>{let n=l.get(e);n&&(n.delete(t),n.size===0&&l.delete(e))}}function m(e){return u.add(e),()=>u.delete(e)}function h(e){return{sessionId:e.sessionId,session:e.session,events:e.events,lastSeq:e.lastSeq,loaded:e.loaded,loadError:e.loadError,stream:e.stream}}function g(e){let t=i.get(e);return t||(t={sessionId:e,...r},i.set(e,t),a.set(e,h(t))),t}function _(e,t,n){i.set(e,t);let r=a.get(e);(!r||n||r.session!==t.session||r.loaded!==t.loaded||r.loadError!==t.loadError||r.stream!==t.stream)&&a.set(e,h(t))}function v(e,t,n=!1){_(e,{...g(e),...t},n),d(e)}var y={sessionId:``,...r},b=h(y);function x(e){return e?g(e):y}function S(e){return e?(g(e),a.get(e)):b}function C(e){return e?g(e).live:n}var w={items:[],live:!1,usage:null,segments:[]};function T(e){if(!e)return w;let t=g(e),n=s.get(e);if(n&&n.events===t.events)return n.transcript;let r=n?.cache??X(),i=$(t.events,{cache:r,thinkingStats:o.get(e)});return s.set(e,{events:t.events,transcript:i,cache:r}),i}function E(e,t,n){let r=g(e),i=K(r.events,n),a=A(t,i),o=r.session&&J(r.session,a)?r.session:a,s=i!==r.events,c=s||o!==r.session?R(r.live,i,o):r.live;(s||o!==r.session||!r.loaded||r.loadError!==null||c!==r.live)&&(_(e,{...r,session:o,events:i,lastSeq:i.length?Math.max(r.lastSeq,i[i.length-1].seq):r.lastSeq,loaded:!0,loadError:null,live:c},s),d(e))}function D(e,t){v(e,{loadError:t,loaded:!0})}function O(e,t){g(e).stream!==t&&v(e,{stream:t})}function k(e,t,n){v(e,{session:A(t,g(e).events,n)})}function A(e,t,n){if(e.status!==`running`)return e;let r=-1,i=n??null;if(!n){for(let e of t)(e.type===`user-message`||e.type===`turn-started`)&&(r=e.seq,i=e.turnId);if(i===null)return e}let a=null,o=null;for(let e of t)e.seq<=r||(e.type===`error`&&e.turnId===i&&(o=e.message),(e.type===`turn-done`||e.type===`cancelled`)&&e.turnId===i&&(a=e));if(!a)return e;let s=a.type===`turn-done`&&!a.ok&&o!==null;return{...e,status:s?`error`:`idle`,lastError:s?o:null,updatedAt:a.at>e.updatedAt?a.at:e.updatedAt}}function j(e,t){let n=g(e);n.session&&n.session.status!==t&&v(e,{session:{...n.session,status:t}})}function M(e,n){let r=g(e),i=r.events,a=!1,o=r.lastSeq,s=r.session,c=r.live,l=0,u=!1,f=!1,p=!1,m=Date.now();for(let r of n){if(t(r)){let e=I(c,r,m);e!==c&&(c=e,p=!0);continue}if(!Number.isFinite(r.seq))continue;let n=i.length>0?i[i.length-1].seq:-1/0;if(r.seq>n)a||=(i=i.slice(),!0),i.push(r);else{let e=W(i,r.seq);if(e.found)continue;a||=(i=i.slice(),!0),i.splice(e.index,0,r)}l+=1,o=Math.max(o,r.seq),r.type!==`text-delta`&&(f=!0),(r.type===`turn-done`||r.type===`cancelled`||r.type===`error`)&&(u=!0),s&&=N(s,r);let d=L(c,r,m,e);d!==c&&(c=d)}return l===0&&!p?{applied:0,settled:!1,liveChanged:!1}:(_(e,{...r,events:i,lastSeq:o,session:s,live:c},f),d(e),{applied:l,settled:u,liveChanged:p})}function N(e,t){switch(t.type){case`turn-started`:return{...e,status:`running`,lastError:null,updatedAt:t.at};case`usage`:return{...e,usage:z(e,t.usage),updatedAt:t.at};case`context`:return{...e,usage:ee(e,t),updatedAt:t.at};case`compaction`:return{...e,compactionCount:(e.compactionCount??0)+1,updatedAt:t.at};case`turn-done`:return{...e,status:t.ok?`idle`:e.lastError?`error`:`idle`,turnCount:e.turnCount+1,nativeSessionId:t.nativeSessionId??e.nativeSessionId,updatedAt:t.at};case`error`:return{...e,status:`error`,lastError:t.message,updatedAt:t.at};case`cancelled`:return{...e,status:`idle`,updatedAt:t.at};default:return e}}function P(e,t){let n=Date.parse(e);return Number.isFinite(n)?n:t}function F(e,t,r){return e.turnId===t?e:{...n,turnId:t,startedAt:r,settledTurnId:e.settledTurnId}}function I(e,t,n){if(t.turnId!==null&&t.turnId===e.settledTurnId)return e;let r=t.turnId===null?e:F(e,t.turnId,n);switch(t.type){case`thinking-delta`:{if(t.text.length===0)return r;let e=r.thinking&&r.thinking.turnId===t.turnId?{...r.thinking,text:r.thinking.text+t.text}:{turnId:t.turnId,text:t.text,startedAt:n,estimatedTokens:null};return{...r,thinking:e,notice:null}}case`thinking-progress`:{let e=r.thinking&&r.thinking.turnId===t.turnId?{...r.thinking,estimatedTokens:t.estimatedTokens}:{turnId:t.turnId,text:``,startedAt:n,estimatedTokens:t.estimatedTokens};return{...r,thinking:e}}case`progress`:return{...r,progress:{phase:t.phase,tool:typeof t.tool==`string`&&t.tool.length>0?t.tool:null,elapsedMs:t.elapsedMs,outTokens:t.outTokens??null,tokPerSec:t.tokPerSec??null,receivedAt:n}};case`status`:return{...r,notice:{kind:t.kind,message:t.message,at:t.at,receivedAt:n}};default:return r}}function L(e,t,r,i){switch(t.type){case`turn-started`:return t.turnId===e.settledTurnId?e:e.turnId===t.turnId?{...e,startedAt:P(t.at,e.startedAt??r)}:{...n,turnId:t.turnId,startedAt:P(t.at,r),settledTurnId:e.settledTurnId};case`thinking`:{let n=e.thinking&&e.thinking.turnId===t.turnId?e.thinking:null;if(n){let e=o.get(i);e||(e=new Map,o.set(i,e)),e.set(t.seq,{durationMs:typeof t.durationMs==`number`?t.durationMs:Math.max(0,r-n.startedAt),estimatedTokens:n.estimatedTokens})}return n||e.notice?{...e,thinking:n?null:e.thinking,notice:null}:e}case`text-delta`:case`assistant-message`:case`tool-use`:case`tool-result`:return e.notice&&(t.turnId===e.turnId||e.turnId===null)?{...e,notice:null}:e;case`turn-done`:case`cancelled`:return{...n,settledTurnId:t.turnId};default:return e}}function R(e,t,r){let i=null,a=e.settledTurnId;for(let e=t.length-1;e>=0;--e){let n=t[e];if(n.type===`turn-done`||n.type===`cancelled`){a=n.turnId;break}if(n.type===`turn-started`){i=n;break}}return i?r&&r.status!==`running`?e.turnId===null?e:{...n,settledTurnId:e.settledTurnId}:e.turnId===i.turnId?e:{...n,turnId:i.turnId,startedAt:P(i.at,Date.now()),settledTurnId:e.settledTurnId}:e.turnId!==null&&e.turnId===a?{...n,settledTurnId:a}:e.settledTurnId===a?e:{...e,settledTurnId:a}}function z(e,t){let n=e.usage,r={...n,inputTokens:n.inputTokens+t.inputTokens,outputTokens:n.outputTokens+t.outputTokens,cacheReadTokens:n.cacheReadTokens+t.cacheReadTokens,cacheCreationTokens:n.cacheCreationTokens+t.cacheCreationTokens,contextTokens:t.contextTokens},i=typeof t.contextWindow==`number`&&t.contextWindow>0?t.contextWindow:null,a=t.contextWindowSource!==void 0||e.engine!==`local`;return i!==null&&a&&(r.contextWindow=i),t.contextWindowSource!==void 0&&(r.contextWindowSource=t.contextWindowSource),t.autoCompactAt!==void 0&&(r.autoCompactAt=t.autoCompactAt),t.contextTokensExact===!1?r.contextTokensExact=!1:t.contextWindowSource!==void 0&&delete r.contextTokensExact,r}var B=new Set([`runtime`,`provider-catalog`,`cli-catalog`,`documented`,`fallback`]);function V(e){return typeof e==`string`&&B.has(e)?e:null}function ee(t,n){let r=t.usage,i={...r,contextTokens:Math.max(0,Math.floor(n.contextTokens)),contextTokensExact:n.exact},a=typeof n.contextWindow==`number`&&n.contextWindow>0?n.contextWindow:null,o=V(n.contextWindowSource);return a===null||t.engine===`local`&&o===null?(n.autoCompactAt!==void 0&&n.autoCompactAt!==null&&(i.autoCompactAt=n.autoCompactAt),i):(i.contextWindow=a,i.contextWindowSource=o??`runtime`,n.autoCompactAt===void 0?a!==r.contextWindow&&(i.autoCompactAt=e({engine:t.engine,runtimeWindow:a,budget:r.contextWindow?{contextWindow:r.contextWindow,autoCompactAt:r.autoCompactAt??null}:null})):i.autoCompactAt=n.autoCompactAt,i)}function H(e){let t=null;for(let n of e)(n.type===`usage`||n.type===`turn-done`||n.type===`cancelled`||n.type===`context`&&n.turnId!==null)&&typeof n.at==`string`&&(t===null||n.at>t)&&(t=n.at);return t}function U(e){let t=i.delete(e);a.delete(e),s.delete(e),o.delete(e);for(let t of[...u])t({kind:`forget`,sessionId:e});t&&d(e)}function W(e,t){let n=0,r=e.length;for(;n<r;){let i=n+r>>>1,a=e[i].seq;if(a===t)return{found:!0,index:i};a<t?n=i+1:r=i}return{found:!1,index:n}}function G(e){let t=!0;for(let n=0;n<e.length;n+=1){let r=e[n].seq;if(!Number.isFinite(r)||n>0&&r<=e[n-1].seq){t=!1;break}}if(t)return e.slice();let n=new Map;for(let t of e)Number.isFinite(t.seq)&&!n.has(t.seq)&&n.set(t.seq,t);return[...n.values()].sort((e,t)=>e.seq-t.seq)}function K(e,t){if(t.length===0)return e;let n=G(t);if(n.length===0)return e;if(e.length===0)return n;if(n[0].seq>e[e.length-1].seq)return e.concat(n);let r=[],i=0,a=0,o=0;for(;a<e.length||o<n.length;){let t=e[a],s=n[o];s===void 0||t!==void 0&&t.seq<s.seq?(r.push(t),a+=1):t===void 0||s.seq<t.seq?(r.push(s),i+=1,o+=1):(r.push(t),a+=1,o+=1)}return i===0?e:r}function q(e,t){if(Object.is(e,t))return!0;if(!e||!t||typeof e!=`object`||typeof t!=`object`||Array.isArray(e)!==Array.isArray(t))return!1;let n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(let r of n)if(!Object.is(e[r],t[r]))return!1;return!0}function J(e,t){if(e===t)return!0;let n=Object.keys(e);return n.length===Object.keys(t).length&&n.every(n=>q(e[n],t[n]))}function Y(e,t){let n=Date.parse(e),r=Date.parse(t);return Number.isFinite(n)&&Number.isFinite(r)?Math.max(0,r-n):null}function X(){return{segments:new Map}}function Z(e,t,n,r){let i=[],a=new Map,o=[],s=[],c=null,l=null,u=null,d=()=>{c&&=(i.push({kind:`assistant`,key:c.key,turnId:c.turnId,at:c.at,text:c.text,streaming:!1}),null)};for(let f=t;f<n;f+=1){let t=e[f];switch(t.type){case`user-message`:d(),i.push({kind:`user`,key:`u-${t.seq}`,turnId:t.turnId,at:t.at,text:t.text});break;case`turn-started`:l=!0;break;case`text-delta`:c&&c.turnId!==t.turnId&&d(),c||={turnId:t.turnId,at:t.at,text:``,key:`d-${t.seq}`},c.text+=t.text;break;case`assistant-message`:c=null,i.push({kind:`assistant`,key:`a-${t.seq}`,turnId:t.turnId,at:t.at,text:t.text,streaming:!1});break;case`thinking`:{d();let e=r?.get(t.seq);i.push({kind:`thinking`,key:`t-${t.seq}`,turnId:t.turnId,at:t.at,text:t.text,redacted:t.redacted===!0,durationMs:typeof t.durationMs==`number`&&Number.isFinite(t.durationMs)&&t.durationMs>=0?t.durationMs:e?.durationMs??null,estimatedTokens:e?.estimatedTokens??null,thinkingKind:t.kind??null});break}case`tool-use`:d(),a.set(t.toolUseId,i.length),s.push(t.toolUseId),i.push({kind:`tool`,key:`tu-${t.seq}`,turnId:t.turnId,at:t.at,toolUseId:t.toolUseId,name:t.name,input:t.input,result:null,durationMs:null});break;case`tool-result`:{let e=a.get(t.toolUseId),n=e===void 0?void 0:i[e];n&&n.kind===`tool`?i[e]={...n,result:{output:t.output,isError:t.isError},durationMs:Y(n.at,t.at)}:(o.push(t.toolUseId),i.push({kind:`tool`,key:`tr-${t.seq}`,turnId:t.turnId,at:t.at,toolUseId:t.toolUseId,name:`tool`,input:null,result:{output:t.output,isError:t.isError},durationMs:null}));break}case`usage`:u=t.usage;break;case`compaction`:i.push({kind:`compaction`,key:`k-${t.seq}`,turnId:t.turnId,at:t.at,trigger:t.trigger,preTokens:t.preTokens,postTokens:t.postTokens,durationMs:t.durationMs});break;case`error`:d(),i.push({kind:`error`,key:`e-${t.seq}`,turnId:t.turnId,at:t.at,message:t.message,code:typeof t.code==`string`&&t.code?t.code:null});break;case`cancelled`:d(),l=!1,i.push({kind:`cancelled`,key:`c-${t.seq}`,turnId:t.turnId,at:t.at});break;case`turn-done`:d(),l=!1,i.push({kind:`turn-done`,key:`td-${t.seq}`,turnId:t.turnId,at:t.at,ok:t.ok,durationMs:t.durationMs});break;case`recovered`:i.push({kind:`recovered`,key:`r-${t.seq}`,turnId:t.turnId,at:t.at,how:t.how,message:t.message});break;case`history-truncated`:i.push({kind:`truncated`,key:`h-${t.seq}`,turnId:null,at:t.at,droppedBefore:t.droppedBefore})}}return{items:i,pending:c,liveEffect:l,usage:u,orphanResults:o,toolUseIds:s}}function Q(e,t,n){let r=t.pending;return r?{key:e,items:[...t.items,{kind:`assistant`,key:r.key,turnId:r.turnId,at:r.at,text:r.text,streaming:n}]}:{key:e,items:t.items}}function $(e,t={}){let{cache:n,thinkingStats:r}=t;if(e.length===0)return{items:[],live:!1,usage:null,segments:[]};let i=[0];for(let t=1;t<e.length;t+=1)e[t].type===`user-message`&&i.push(t);let a=[],o=new Set;for(let t=0;t<i.length;t+=1){let s=i[t],c=t+1<i.length?i[t+1]:e.length,l=e[s].seq,u=e[c-1].seq,d=c-s,f=`s-${l}`;o.add(f);let p=n?.segments.get(f);if(p&&p.firstSeq===l&&p.lastSeq===u&&p.count===d){a.push({key:f,build:p.build,cached:p});continue}let m=Z(e,s,c,r),h={firstSeq:l,lastSeq:u,count:d,build:m,finalized:null};n?.segments.set(f,h),a.push({key:f,build:m,cached:h})}if(n)for(let e of[...n.segments.keys()])o.has(e)||n.segments.delete(e);if(a.length>1){let t=new Set;for(let n of a){if(n.build.orphanResults.some(e=>t.has(e)))return te(e,r);for(let e of n.build.toolUseIds)t.add(e)}}let s=!1,c=null;for(let e of a)e.build.liveEffect!==null&&(s=e.build.liveEffect),e.build.usage!==null&&(c=e.build.usage);let l=[],u=[];for(let e=0;e<a.length;e+=1){let t=a[e],n=e===a.length-1&&s,r;t.cached?.finalized&&t.cached.finalized.streaming===n?r=t.cached.finalized.segment:(r=Q(t.key,t.build,n),t.cached&&(t.cached.finalized={streaming:n,segment:r})),l.push(r);for(let e of r.items)u.push(e)}return{items:u,live:s,usage:c,segments:l}}function te(e,t){let n=Z(e,0,e.length,t),r=n.liveEffect??!1,i=Q(`s-${e[0].seq}`,n,r);return{items:i.items,live:r,usage:n.usage,segments:[i]}}function ne(e){let t=[],n=[],r=()=>{if(n.length===0)return;let e=n.length;for(;e>0&&n[e-1].kind===`thinking`;)--e;let r=n.slice(0,e),i=n.slice(e);if(r.filter(e=>e.kind===`tool`).length>=2)t.push(re(r));else for(let e of r)t.push(e);for(let e of i)t.push(e);n=[]};for(let i of e){if((i.kind===`tool`||i.kind===`thinking`)&&(n.length===0||n[0].turnId===i.turnId)){n.push(i);continue}r(),i.kind===`tool`||i.kind===`thinking`?n.push(i):t.push(i)}return r(),t}function re(e){let t=new Map,n=0,r=!1;for(let i of e)i.kind===`tool`&&(t.set(i.name,(t.get(i.name)??0)+1),i.result===null?r=!0:i.result.isError&&(n+=1));let i=[...t.values()].reduce((e,t)=>e+t,0),a=[...t.entries()].map(([e,t])=>t>1?`${e} ×${t}`:e).join(`, `),o=Y(e[0].at,e[e.length-1].at);return{kind:`toolGroup`,key:`g-${e[0].key}`,turnId:e[0].turnId,at:e[0].at,items:e,toolCount:i,summary:a,errorCount:n,pending:r,spanMs:o}}function ie(e){return e==null||!Number.isFinite(e)?`—`:Math.round(e)<1e3?String(Math.round(e)):Math.round(e/1e3)<1e3?`${Math.round(e/1e3)}k`:`${(e/1e6).toFixed(1).replace(/\.0$/,``)}M`}export{m as _,S as a,ne as c,D as d,k as f,f as g,p as h,C as i,H as l,O as m,U as n,x as o,j as p,ie as r,T as s,M as t,E as u};
2
- //# sourceMappingURL=verse-store-BgKx_YGs.js.map