@ashlr/hub 3.10.0 → 3.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (534) hide show
  1. package/CHANGELOG.md +156 -0
  2. package/README.md +343 -82
  3. package/dist/authority-surface.json +109 -29
  4. package/dist/build-identity.json +2 -2
  5. package/dist/cli/cloud.d.ts +39 -0
  6. package/dist/cli/cloud.js +448 -0
  7. package/dist/cli/cloud.js.map +1 -0
  8. package/dist/cli/completions.js +4 -0
  9. package/dist/cli/completions.js.map +1 -1
  10. package/dist/cli/help.js +2 -0
  11. package/dist/cli/help.js.map +1 -1
  12. package/dist/cli/index.d.ts +1 -0
  13. package/dist/cli/index.js +10 -0
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/core/cloud/backlog.d.ts +17 -0
  16. package/dist/core/cloud/backlog.js +177 -0
  17. package/dist/core/cloud/backlog.js.map +1 -0
  18. package/dist/core/cloud/budget.d.ts +19 -0
  19. package/dist/core/cloud/budget.js +99 -0
  20. package/dist/core/cloud/budget.js.map +1 -0
  21. package/dist/core/cloud/checkout.d.ts +41 -0
  22. package/dist/core/cloud/checkout.js +168 -0
  23. package/dist/core/cloud/checkout.js.map +1 -0
  24. package/dist/core/cloud/cloud-api.d.ts +86 -0
  25. package/dist/core/cloud/cloud-api.js +599 -0
  26. package/dist/core/cloud/cloud-api.js.map +1 -0
  27. package/dist/core/cloud/delivery-contract.d.ts +25 -0
  28. package/dist/core/cloud/delivery-contract.js +138 -0
  29. package/dist/core/cloud/delivery-contract.js.map +1 -0
  30. package/dist/core/cloud/improvement-backlog.d.ts +11 -0
  31. package/dist/core/cloud/improvement-backlog.js +26 -0
  32. package/dist/core/cloud/improvement-backlog.js.map +1 -0
  33. package/dist/core/cloud/launcher.d.ts +68 -0
  34. package/dist/core/cloud/launcher.js +312 -0
  35. package/dist/core/cloud/launcher.js.map +1 -0
  36. package/dist/core/cloud/service.d.ts +51 -0
  37. package/dist/core/cloud/service.js +215 -0
  38. package/dist/core/cloud/service.js.map +1 -0
  39. package/dist/core/cloud/store.d.ts +41 -0
  40. package/dist/core/cloud/store.js +278 -0
  41. package/dist/core/cloud/store.js.map +1 -0
  42. package/dist/core/cloud/tracker.d.ts +30 -0
  43. package/dist/core/cloud/tracker.js +152 -0
  44. package/dist/core/cloud/tracker.js.map +1 -0
  45. package/dist/core/cloud/types.d.ts +233 -0
  46. package/dist/core/cloud/types.js +73 -0
  47. package/dist/core/cloud/types.js.map +1 -0
  48. package/dist/core/daemon/capacity-publisher.d.ts +19 -0
  49. package/dist/core/daemon/capacity-publisher.js +49 -2
  50. package/dist/core/daemon/capacity-publisher.js.map +1 -1
  51. package/dist/core/daemon/overnight-status.d.ts +13 -0
  52. package/dist/core/daemon/overnight-status.js +93 -8
  53. package/dist/core/daemon/overnight-status.js.map +1 -1
  54. package/dist/core/fleet/dispatch-router.js +26 -9
  55. package/dist/core/fleet/dispatch-router.js.map +1 -1
  56. package/dist/core/fleet/fleet-runtime-journal.js +12 -5
  57. package/dist/core/fleet/fleet-runtime-journal.js.map +1 -1
  58. package/dist/core/fleet/fleet-types.d.ts +13 -0
  59. package/dist/core/routing/budget-store.js +11 -5
  60. package/dist/core/routing/budget-store.js.map +1 -1
  61. package/dist/core/routing/capacity-history-api.d.ts +30 -0
  62. package/dist/core/routing/capacity-history-api.js +147 -0
  63. package/dist/core/routing/capacity-history-api.js.map +1 -0
  64. package/dist/core/routing/capacity-history-types.d.ts +63 -0
  65. package/dist/core/routing/capacity-history-types.js +18 -0
  66. package/dist/core/routing/capacity-history-types.js.map +1 -0
  67. package/dist/core/routing/capacity-history.d.ts +130 -0
  68. package/dist/core/routing/capacity-history.js +654 -0
  69. package/dist/core/routing/capacity-history.js.map +1 -0
  70. package/dist/core/routing/headroom.d.ts +5 -1
  71. package/dist/core/routing/headroom.js +82 -41
  72. package/dist/core/routing/headroom.js.map +1 -1
  73. package/dist/core/routing/router.d.ts +8 -1
  74. package/dist/core/routing/router.js +49 -16
  75. package/dist/core/routing/router.js.map +1 -1
  76. package/dist/core/routing/seat-reasons.d.ts +35 -0
  77. package/dist/core/routing/seat-reasons.js +48 -0
  78. package/dist/core/routing/seat-reasons.js.map +1 -0
  79. package/dist/core/routing/types.d.ts +37 -0
  80. package/dist/core/routing/types.js.map +1 -1
  81. package/dist/core/verse/activity-api.d.ts +3 -1
  82. package/dist/core/verse/activity-api.js +16 -1
  83. package/dist/core/verse/activity-api.js.map +1 -1
  84. package/dist/core/verse/activity.d.ts +7 -0
  85. package/dist/core/verse/activity.js +23 -0
  86. package/dist/core/verse/activity.js.map +1 -1
  87. package/dist/core/verse/fleet-history-types.d.ts +12 -4
  88. package/dist/core/verse/fleet-history-types.js +4 -2
  89. package/dist/core/verse/fleet-history-types.js.map +1 -1
  90. package/dist/core/verse/fleet-live-api.d.ts +14 -1
  91. package/dist/core/verse/fleet-live-api.js +31 -11
  92. package/dist/core/verse/fleet-live-api.js.map +1 -1
  93. package/dist/core/verse/preferences.d.ts +3 -1
  94. package/dist/core/verse/preferences.js +5 -2
  95. package/dist/core/verse/preferences.js.map +1 -1
  96. package/dist/core/verse/types.d.ts +5 -1
  97. package/dist/core/verse/types.js.map +1 -1
  98. package/dist/core/verse/verse-api.d.ts +1 -1
  99. package/dist/core/verse/verse-api.js +4 -1
  100. package/dist/core/verse/verse-api.js.map +1 -1
  101. package/dist/core/vision/leader-cloud.d.ts +63 -0
  102. package/dist/core/vision/leader-cloud.js +134 -0
  103. package/dist/core/vision/leader-cloud.js.map +1 -0
  104. package/dist/core/vision/leader.d.ts +6 -0
  105. package/dist/core/vision/leader.js +12 -1
  106. package/dist/core/vision/leader.js.map +1 -1
  107. package/dist/core/web/public/next/assets/{ActionMenu-DhbNne-M.js → ActionMenu-CQvNJvHY.js} +2 -2
  108. package/dist/core/web/public/next/assets/{ActionMenu-DhbNne-M.js.map → ActionMenu-CQvNJvHY.js.map} +1 -1
  109. package/dist/core/web/public/next/assets/Advanced-Bywv_iYR.css +1 -0
  110. package/dist/core/web/public/next/assets/Advanced-DEM93sKI.js +2 -0
  111. package/dist/core/web/public/next/assets/Advanced-DEM93sKI.js.map +1 -0
  112. package/dist/core/web/public/next/assets/{App-DyBg1v_q.js → App-CimXmK0L.js} +5 -5
  113. package/dist/core/web/public/next/assets/{App-DyBg1v_q.js.map → App-CimXmK0L.js.map} +1 -1
  114. package/dist/core/web/public/next/assets/AppsSection-D6U-dSj6.js +2 -0
  115. package/dist/core/web/public/next/assets/AppsSection-D6U-dSj6.js.map +1 -0
  116. package/dist/core/web/public/next/assets/AreaTrend-LD9lCPkT.js +2 -0
  117. package/dist/core/web/public/next/assets/AreaTrend-LD9lCPkT.js.map +1 -0
  118. package/dist/core/web/public/next/assets/AutonomySection-3V9pUyxm.js +2 -0
  119. package/dist/core/web/public/next/assets/{AutonomySection-CoMngwNB.js.map → AutonomySection-3V9pUyxm.js.map} +1 -1
  120. package/dist/core/web/public/next/assets/BranchBar-BZNQ50YE.css +1 -0
  121. package/dist/core/web/public/next/assets/BranchBar-U8UdpfEB.js +2 -0
  122. package/dist/core/web/public/next/assets/BranchBar-U8UdpfEB.js.map +1 -0
  123. package/dist/core/web/public/next/assets/BudgetControl-DOTlMSmW.js +2 -0
  124. package/dist/core/web/public/next/assets/BudgetControl-DOTlMSmW.js.map +1 -0
  125. package/dist/core/web/public/next/assets/BurnDown-x4PWH9JF.js +2 -0
  126. package/dist/core/web/public/next/assets/BurnDown-x4PWH9JF.js.map +1 -0
  127. package/dist/core/web/public/next/assets/{Button-0-nNbv1h.js → Button-DYv_KKxr.js} +2 -2
  128. package/dist/core/web/public/next/assets/{Button-0-nNbv1h.js.map → Button-DYv_KKxr.js.map} +1 -1
  129. package/dist/core/web/public/next/assets/CapacityStrip-C667yQe8.js +2 -0
  130. package/dist/core/web/public/next/assets/CapacityStrip-C667yQe8.js.map +1 -0
  131. package/dist/core/web/public/next/assets/CapacityStrip-Cc28CyWk.css +1 -0
  132. package/dist/core/web/public/next/assets/ChatSection-CCcIPpOq.js +3 -0
  133. package/dist/core/web/public/next/assets/{ChatSection-B9cdRKUh.js.map → ChatSection-CCcIPpOq.js.map} +1 -1
  134. package/dist/core/web/public/next/assets/CloudBudgetForm-DJeJvBEu.js +2 -0
  135. package/dist/core/web/public/next/assets/CloudBudgetForm-DJeJvBEu.js.map +1 -0
  136. package/dist/core/web/public/next/assets/{CommandPalette-GpeCSrPy.js → CommandPalette-FiD4N8XD.js} +2 -2
  137. package/dist/core/web/public/next/assets/{CommandPalette-GpeCSrPy.js.map → CommandPalette-FiD4N8XD.js.map} +1 -1
  138. package/dist/core/web/public/next/assets/CommandSection-DN8KwH-X.js +2 -0
  139. package/dist/core/web/public/next/assets/CommandSection-DN8KwH-X.js.map +1 -0
  140. package/dist/core/web/public/next/assets/Composer-ByzxOJK6.css +1 -0
  141. package/dist/core/web/public/next/assets/Composer.module-C8U73KdQ.js +2 -0
  142. package/dist/core/web/public/next/assets/{Composer.module-DJMdrqNt.js.map → Composer.module-C8U73KdQ.js.map} +1 -1
  143. package/dist/core/web/public/next/assets/DiffPane-BAvvbBsf.css +1 -0
  144. package/dist/core/web/public/next/assets/DiffPane-DLJ3gGGK.js +2 -0
  145. package/dist/core/web/public/next/assets/DiffPane-DLJ3gGGK.js.map +1 -0
  146. package/dist/core/web/public/next/assets/{DiffViewer-tOGWk0CA.js → DiffViewer-B7NWPjIO.js} +2 -2
  147. package/dist/core/web/public/next/assets/{DiffViewer-tOGWk0CA.js.map → DiffViewer-B7NWPjIO.js.map} +1 -1
  148. package/dist/core/web/public/next/assets/DockHost-B4RaYOET.css +1 -0
  149. package/dist/core/web/public/next/assets/DockHost-DvR-hPhZ.js +2 -0
  150. package/dist/core/web/public/next/assets/DockHost-DvR-hPhZ.js.map +1 -0
  151. package/dist/core/web/public/next/assets/{EmptyState-DdJ4CxtO.js → EmptyState-DhNgDDrF.js} +2 -2
  152. package/dist/core/web/public/next/assets/{EmptyState-DdJ4CxtO.js.map → EmptyState-DhNgDDrF.js.map} +1 -1
  153. package/dist/core/web/public/next/assets/{Epistemic-BLjM5y_y.js → Epistemic-uARPnx9x.js} +2 -2
  154. package/dist/core/web/public/next/assets/{Epistemic-BLjM5y_y.js.map → Epistemic-uARPnx9x.js.map} +1 -1
  155. package/dist/core/web/public/next/assets/FleetSection-CFiWeOEs.css +1 -0
  156. package/dist/core/web/public/next/assets/FleetSection-D_zRBCub.js +3 -0
  157. package/dist/core/web/public/next/assets/FleetSection-D_zRBCub.js.map +1 -0
  158. package/dist/core/web/public/next/assets/Funnel-CL8uHONq.js +2 -0
  159. package/dist/core/web/public/next/assets/Funnel-CL8uHONq.js.map +1 -0
  160. package/dist/core/web/public/next/assets/GearTray-C7k4l_BW.js +2 -0
  161. package/dist/core/web/public/next/assets/GearTray-C7k4l_BW.js.map +1 -0
  162. package/dist/core/web/public/next/assets/GrowthSection-DwdNSGj8.js +2 -0
  163. package/dist/core/web/public/next/assets/GrowthSection-DwdNSGj8.js.map +1 -0
  164. package/dist/core/web/public/next/assets/HandoffDialog-FPVOqOMN.js +2 -0
  165. package/dist/core/web/public/next/assets/HandoffDialog-FPVOqOMN.js.map +1 -0
  166. package/dist/core/web/public/next/assets/{Input-CTu0CycC.js → Input-B9-VLcHS.js} +2 -2
  167. package/dist/core/web/public/next/assets/{Input-CTu0CycC.js.map → Input-B9-VLcHS.js.map} +1 -1
  168. package/dist/core/web/public/next/assets/{LeaderCard-BuSDeATv.js → LeaderCard-4R0BhDzT.js} +2 -2
  169. package/dist/core/web/public/next/assets/{LeaderCard-BuSDeATv.js.map → LeaderCard-4R0BhDzT.js.map} +1 -1
  170. package/dist/core/web/public/next/assets/{MatrixHeatmap-9dKgJ_pT.css → MatrixHeatmap-Bmnvo1l1.css} +1 -1
  171. package/dist/core/web/public/next/assets/MatrixHeatmap-DiuushcS.js +2 -0
  172. package/dist/core/web/public/next/assets/MatrixHeatmap-DiuushcS.js.map +1 -0
  173. package/dist/core/web/public/next/assets/McpSection-CJ__OJKl.js +2 -0
  174. package/dist/core/web/public/next/assets/{McpSection-1UncWBpW.js.map → McpSection-CJ__OJKl.js.map} +1 -1
  175. package/dist/core/web/public/next/assets/MessageMarkdown-Cgh5f1-Q.css +1 -0
  176. package/dist/core/web/public/next/assets/MessageMarkdown-qWKyJvAQ.js +3 -0
  177. package/dist/core/web/public/next/assets/{MessageMarkdown-C4pl9LI5.js.map → MessageMarkdown-qWKyJvAQ.js.map} +1 -1
  178. package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-CZsF77ZM.js → MessageMarkdownRenderer-x05TrsrW.js} +2 -2
  179. package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-CZsF77ZM.js.map → MessageMarkdownRenderer-x05TrsrW.js.map} +1 -1
  180. package/dist/core/web/public/next/assets/{Meter-C18ciKz4.js → Meter-D-hncpkO.js} +2 -2
  181. package/dist/core/web/public/next/assets/{Meter-C18ciKz4.js.map → Meter-D-hncpkO.js.map} +1 -1
  182. package/dist/core/web/public/next/assets/MindSection-BjXHkQPS.js +2 -0
  183. package/dist/core/web/public/next/assets/MindSection-BjXHkQPS.js.map +1 -0
  184. package/dist/core/web/public/next/assets/MutationTokenDialog-SkRxqV_I.js +2 -0
  185. package/dist/core/web/public/next/assets/MutationTokenDialog-SkRxqV_I.js.map +1 -0
  186. package/dist/core/web/public/next/assets/NeedsYouDrawer-BpvidnM2.css +1 -0
  187. package/dist/core/web/public/next/assets/NeedsYouDrawer-rSd1ZHAR.js +2 -0
  188. package/dist/core/web/public/next/assets/NeedsYouDrawer-rSd1ZHAR.js.map +1 -0
  189. package/dist/core/web/public/next/assets/NeedsYouList-CG-nB1tr.js +2 -0
  190. package/dist/core/web/public/next/assets/NeedsYouList-CG-nB1tr.js.map +1 -0
  191. package/dist/core/web/public/next/assets/NeedsYouList-CruOt4JT.css +1 -0
  192. package/dist/core/web/public/next/assets/NewChatDialog-BeDQ1eW3.js +3 -0
  193. package/dist/core/web/public/next/assets/{NewChatDialog-B_BsS9pr.js.map → NewChatDialog-BeDQ1eW3.js.map} +1 -1
  194. package/dist/core/web/public/next/assets/OnboardingFlow-CkTZtt-m.js +2 -0
  195. package/dist/core/web/public/next/assets/{OnboardingFlow-CtCPpgoX.js.map → OnboardingFlow-CkTZtt-m.js.map} +1 -1
  196. package/dist/core/web/public/next/assets/PreviewPane-DoMsJSG3.css +1 -0
  197. package/dist/core/web/public/next/assets/PreviewPane-kzbbSK4u.js +2 -0
  198. package/dist/core/web/public/next/assets/PreviewPane-kzbbSK4u.js.map +1 -0
  199. package/dist/core/web/public/next/assets/RailStatus-D-t2gPae.js +2 -0
  200. package/dist/core/web/public/next/assets/RailStatus-D-t2gPae.js.map +1 -0
  201. package/dist/core/web/public/next/assets/{RefreshIndicator-CnhEovMZ.js → RefreshIndicator-BLnr9IOM.js} +2 -2
  202. package/dist/core/web/public/next/assets/{RefreshIndicator-CnhEovMZ.js.map → RefreshIndicator-BLnr9IOM.js.map} +1 -1
  203. package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-28gLwmwV.js → ResourcePoolConsoleApp-BeG0gBif.js} +4 -4
  204. package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-28gLwmwV.js.map → ResourcePoolConsoleApp-BeG0gBif.js.map} +1 -1
  205. package/dist/core/web/public/next/assets/ResourcesChrome-B3Z3O98t.css +1 -0
  206. package/dist/core/web/public/next/assets/ResourcesChrome-BzV6bkIa.js +3 -0
  207. package/dist/core/web/public/next/assets/ResourcesChrome-BzV6bkIa.js.map +1 -0
  208. package/dist/core/web/public/next/assets/ResourcesDrawer-CSKIO_wZ.css +1 -0
  209. package/dist/core/web/public/next/assets/ResourcesDrawer-o4ILHdep.js +2 -0
  210. package/dist/core/web/public/next/assets/ResourcesDrawer-o4ILHdep.js.map +1 -0
  211. package/dist/core/web/public/next/assets/{RouteErrorBoundary-AyUPCIb3.js → RouteErrorBoundary-C5SxA2Dg.js} +2 -2
  212. package/dist/core/web/public/next/assets/{RouteErrorBoundary-AyUPCIb3.js.map → RouteErrorBoundary-C5SxA2Dg.js.map} +1 -1
  213. package/dist/core/web/public/next/assets/RunInCloudAction-C3LBp7C4.js +2 -0
  214. package/dist/core/web/public/next/assets/RunInCloudAction-C3LBp7C4.js.map +1 -0
  215. package/dist/core/web/public/next/assets/SeatSelector-DpvvbjNm.js +3 -0
  216. package/dist/core/web/public/next/assets/{SeatSelector-DaUO-zoK.js.map → SeatSelector-DpvvbjNm.js.map} +1 -1
  217. package/dist/core/web/public/next/assets/{Segmented-B_8c_83S.js → Segmented-BL40udoO.js} +2 -2
  218. package/dist/core/web/public/next/assets/{Segmented-B_8c_83S.js.map → Segmented-BL40udoO.js.map} +1 -1
  219. package/dist/core/web/public/next/assets/{Select-Bl5g5Dt_.js → Select-FWLnAw_j.js} +2 -2
  220. package/dist/core/web/public/next/assets/{Select-Bl5g5Dt_.js.map → Select-FWLnAw_j.js.map} +1 -1
  221. package/dist/core/web/public/next/assets/{SessionInsightChip-w0I21q0c.js → SessionInsightChip-CWye87Ju.js} +2 -2
  222. package/dist/core/web/public/next/assets/{SessionInsightChip-w0I21q0c.js.map → SessionInsightChip-CWye87Ju.js.map} +1 -1
  223. package/dist/core/web/public/next/assets/SessionSearch-YvCHFUuN.js +2 -0
  224. package/dist/core/web/public/next/assets/{SessionSearch-B5aQ0BCM.js.map → SessionSearch-YvCHFUuN.js.map} +1 -1
  225. package/dist/core/web/public/next/assets/SettingsSection-Dr18upeE.js +2 -0
  226. package/dist/core/web/public/next/assets/SettingsSection-Dr18upeE.js.map +1 -0
  227. package/dist/core/web/public/next/assets/{Sheet-CVjk-cLI.js → Sheet-DZKcQXQg.js} +2 -2
  228. package/dist/core/web/public/next/assets/{Sheet-CVjk-cLI.js.map → Sheet-DZKcQXQg.js.map} +1 -1
  229. package/dist/core/web/public/next/assets/{ShortcutsOverlay-BiBjnBcc.js → ShortcutsOverlay-BpDimdPq.js} +2 -2
  230. package/dist/core/web/public/next/assets/{ShortcutsOverlay-BiBjnBcc.js.map → ShortcutsOverlay-BpDimdPq.js.map} +1 -1
  231. package/dist/core/web/public/next/assets/Sidebar-BRc1vGDF.css +1 -0
  232. package/dist/core/web/public/next/assets/Sidebar-BoBzBEFX.js +3 -0
  233. package/dist/core/web/public/next/assets/Sidebar-BoBzBEFX.js.map +1 -0
  234. package/dist/core/web/public/next/assets/{Slider-BS9MU5ZV.js → Slider-DUMo9HDD.js} +2 -2
  235. package/dist/core/web/public/next/assets/{Slider-BS9MU5ZV.js.map → Slider-DUMo9HDD.js.map} +1 -1
  236. package/dist/core/web/public/next/assets/{StatusBadge-DAf-ArKE.js → StatusBadge-BwnBNFQr.js} +2 -2
  237. package/dist/core/web/public/next/assets/{StatusBadge-DAf-ArKE.js.map → StatusBadge-BwnBNFQr.js.map} +1 -1
  238. package/dist/core/web/public/next/assets/StepBand-PDXMIlRk.js +2 -0
  239. package/dist/core/web/public/next/assets/StepBand-PDXMIlRk.js.map +1 -0
  240. package/dist/core/web/public/next/assets/{Surface-CiYOdNKQ.js → Surface-B3TZVoER.js} +2 -2
  241. package/dist/core/web/public/next/assets/{Surface-CiYOdNKQ.js.map → Surface-B3TZVoER.js.map} +1 -1
  242. package/dist/core/web/public/next/assets/Swimlane-DR4OgON_.js +2 -0
  243. package/dist/core/web/public/next/assets/Swimlane-DR4OgON_.js.map +1 -0
  244. package/dist/core/web/public/next/assets/{Switch-BzRXtNPt.js → Switch-CcR5Llk5.js} +2 -2
  245. package/dist/core/web/public/next/assets/{Switch-BzRXtNPt.js.map → Switch-CcR5Llk5.js.map} +1 -1
  246. package/dist/core/web/public/next/assets/{Tag-DEEbDz7T.js → Tag-_-K1h7Hk.js} +2 -2
  247. package/dist/core/web/public/next/assets/{Tag-DEEbDz7T.js.map → Tag-_-K1h7Hk.js.map} +1 -1
  248. package/dist/core/web/public/next/assets/TerminalPane-BwfMbnJz.css +1 -0
  249. package/dist/core/web/public/next/assets/TerminalPane-_1aH4ndN.js +7 -0
  250. package/dist/core/web/public/next/assets/TerminalPane-_1aH4ndN.js.map +1 -0
  251. package/dist/core/web/public/next/assets/UniverseConsoleApp-BUsq-inZ.js +2 -0
  252. package/dist/core/web/public/next/assets/{UniverseConsoleApp-DKqAf-eD.js.map → UniverseConsoleApp-BUsq-inZ.js.map} +1 -1
  253. package/dist/core/web/public/next/assets/{UniverseView-D6081LQL.js → UniverseView-Dogy_dsB.js} +2 -2
  254. package/dist/core/web/public/next/assets/{UniverseView-D6081LQL.js.map → UniverseView-Dogy_dsB.js.map} +1 -1
  255. package/dist/core/web/public/next/assets/UsageSection-DiX_dTyo.js +2 -0
  256. package/dist/core/web/public/next/assets/UsageSection-DiX_dTyo.js.map +1 -0
  257. package/dist/core/web/public/next/assets/UsageSection-DsB-Jqyl.css +1 -0
  258. package/dist/core/web/public/next/assets/VerseConsoleApp-Cxqr-3qc.css +1 -0
  259. package/dist/core/web/public/next/assets/VerseConsoleApp-WVeyJnW7.js +3 -0
  260. package/dist/core/web/public/next/assets/VerseConsoleApp-WVeyJnW7.js.map +1 -0
  261. package/dist/core/web/public/next/assets/Workspace-BYW9dm90.css +1 -0
  262. package/dist/core/web/public/next/assets/Workspace-BbxZHwQd.js +10 -0
  263. package/dist/core/web/public/next/assets/Workspace-BbxZHwQd.js.map +1 -0
  264. package/dist/core/web/public/next/assets/actions-Ddfg2iLl.css +1 -0
  265. package/dist/core/web/public/next/assets/actions-s2lfm_5k.js +2 -0
  266. package/dist/core/web/public/next/assets/actions-s2lfm_5k.js.map +1 -0
  267. package/dist/core/web/public/next/assets/apps-model-CDFvmsQV.js +2 -0
  268. package/dist/core/web/public/next/assets/apps-model-CDFvmsQV.js.map +1 -0
  269. package/dist/core/web/public/next/assets/{budget-queries-Dacv1VYP.js → budget-queries-wUshcovN.js} +2 -2
  270. package/dist/core/web/public/next/assets/{budget-queries-Dacv1VYP.js.map → budget-queries-wUshcovN.js.map} +1 -1
  271. package/dist/core/web/public/next/assets/calendar-day-BxBYHfX1.js +2 -0
  272. package/dist/core/web/public/next/assets/calendar-day-BxBYHfX1.js.map +1 -0
  273. package/dist/core/web/public/next/assets/capacity-strip-model-Bj_9ztzs.js +2 -0
  274. package/dist/core/web/public/next/assets/capacity-strip-model-Bj_9ztzs.js.map +1 -0
  275. package/dist/core/web/public/next/assets/charts-CMSgAUKn.js +2 -0
  276. package/dist/core/web/public/next/assets/charts-CMSgAUKn.js.map +1 -0
  277. package/dist/core/web/public/next/assets/cloud-C1KPNRHC.css +1 -0
  278. package/dist/core/web/public/next/assets/cloud-queries-CnV1yaNG.js +2 -0
  279. package/dist/core/web/public/next/assets/cloud-queries-CnV1yaNG.js.map +1 -0
  280. package/dist/core/web/public/next/assets/cloud.module-CiwatLj3.js +2 -0
  281. package/dist/core/web/public/next/assets/cloud.module-CiwatLj3.js.map +1 -0
  282. package/dist/core/web/public/next/assets/colors-BZ3a9wFf.js +2 -0
  283. package/dist/core/web/public/next/assets/colors-BZ3a9wFf.js.map +1 -0
  284. package/dist/core/web/public/next/assets/{command-bus-CpYuam1F.js → command-bus-DqimKCUY.js} +2 -2
  285. package/dist/core/web/public/next/assets/{command-bus-CpYuam1F.js.map → command-bus-DqimKCUY.js.map} +1 -1
  286. package/dist/core/web/public/next/assets/command-catalog-BdtDH93o.js +2 -0
  287. package/dist/core/web/public/next/assets/command-catalog-BdtDH93o.js.map +1 -0
  288. package/dist/core/web/public/next/assets/{composer-keys-CYz4U4Bg.js → composer-keys-DBRymxQn.js} +2 -2
  289. package/dist/core/web/public/next/assets/{composer-keys-CYz4U4Bg.js.map → composer-keys-DBRymxQn.js.map} +1 -1
  290. package/dist/core/web/public/next/assets/context-model-Dwd49-dp.js +2 -0
  291. package/dist/core/web/public/next/assets/context-model-Dwd49-dp.js.map +1 -0
  292. package/dist/core/web/public/next/assets/context-model-MT17V86_.js +2 -0
  293. package/dist/core/web/public/next/assets/context-model-MT17V86_.js.map +1 -0
  294. package/dist/core/web/public/next/assets/context-queries-xVKIeynP.js +2 -0
  295. package/dist/core/web/public/next/assets/context-queries-xVKIeynP.js.map +1 -0
  296. package/dist/core/web/public/next/assets/context.module-BijAfoJw.js +2 -0
  297. package/dist/core/web/public/next/assets/context.module-BijAfoJw.js.map +1 -0
  298. package/dist/core/web/public/next/assets/{control-queries-BGjarMm9.js → control-queries-DOZR-D8G.js} +2 -2
  299. package/dist/core/web/public/next/assets/{control-queries-BGjarMm9.js.map → control-queries-DOZR-D8G.js.map} +1 -1
  300. package/dist/core/web/public/next/assets/dark-since-DOMvtB_G.js +2 -0
  301. package/dist/core/web/public/next/assets/dark-since-DOMvtB_G.js.map +1 -0
  302. package/dist/core/web/public/next/assets/dock-icons-8EtARwUm.js +2 -0
  303. package/dist/core/web/public/next/assets/dock-icons-8EtARwUm.js.map +1 -0
  304. package/dist/core/web/public/next/assets/dock-panes-UKS-mXhr.js +2 -0
  305. package/dist/core/web/public/next/assets/{dock-panes-BNTLvX7G.js.map → dock-panes-UKS-mXhr.js.map} +1 -1
  306. package/dist/core/web/public/next/assets/{dock-store-_E5h6TEq.js → dock-store-BA1cHOYA.js} +2 -2
  307. package/dist/core/web/public/next/assets/{dock-store-_E5h6TEq.js.map → dock-store-BA1cHOYA.js.map} +1 -1
  308. package/dist/core/web/public/next/assets/fleet-model-CNe8Wh-s.js +2 -0
  309. package/dist/core/web/public/next/assets/fleet-model-CNe8Wh-s.js.map +1 -0
  310. package/dist/core/web/public/next/assets/fleet-queries-BSdRlUwJ.js +2 -0
  311. package/dist/core/web/public/next/assets/fleet-queries-BSdRlUwJ.js.map +1 -0
  312. package/dist/core/web/public/next/assets/format-B8DAVcn2.js +2 -0
  313. package/dist/core/web/public/next/assets/format-B8DAVcn2.js.map +1 -0
  314. package/dist/core/web/public/next/assets/format-DKrNjdwD.js +2 -0
  315. package/dist/core/web/public/next/assets/format-DKrNjdwD.js.map +1 -0
  316. package/dist/core/web/public/next/assets/{git-model-5v5xGobf.js → git-model-CivuBY_D.js} +2 -2
  317. package/dist/core/web/public/next/assets/{git-model-5v5xGobf.js.map → git-model-CivuBY_D.js.map} +1 -1
  318. package/dist/core/web/public/next/assets/global-Di2PUgj4.js +2 -0
  319. package/dist/core/web/public/next/assets/global-Di2PUgj4.js.map +1 -0
  320. package/dist/core/web/public/next/assets/{guarded-action-vOPc8v75.js → guarded-action-CvOHcqyH.js} +2 -2
  321. package/dist/core/web/public/next/assets/{guarded-action-vOPc8v75.js.map → guarded-action-CvOHcqyH.js.map} +1 -1
  322. package/dist/core/web/public/next/assets/{icons-DWb24OA6.js → icons-B_yuAgdN.js} +2 -2
  323. package/dist/core/web/public/next/assets/{icons-DWb24OA6.js.map → icons-B_yuAgdN.js.map} +1 -1
  324. package/dist/core/web/public/next/assets/{index-afDA8cwW.js → index-oAAq8XJa.js} +3 -3
  325. package/dist/core/web/public/next/assets/{index-afDA8cwW.js.map → index-oAAq8XJa.js.map} +1 -1
  326. package/dist/core/web/public/next/assets/live-model-DCw_IFRI.js +2 -0
  327. package/dist/core/web/public/next/assets/live-model-DCw_IFRI.js.map +1 -0
  328. package/dist/core/web/public/next/assets/local-model-DFyjKX0b.js +2 -0
  329. package/dist/core/web/public/next/assets/local-model-DFyjKX0b.js.map +1 -0
  330. package/dist/core/web/public/next/assets/mind-B9PzLcl0.css +1 -0
  331. package/dist/core/web/public/next/assets/mind.module-vnuJcwvD.js +2 -0
  332. package/dist/core/web/public/next/assets/mind.module-vnuJcwvD.js.map +1 -0
  333. package/dist/core/web/public/next/assets/mutations-Dpsql5t7.js +2 -0
  334. package/dist/core/web/public/next/assets/{mutations-C6E10SPX.js.map → mutations-Dpsql5t7.js.map} +1 -1
  335. package/dist/core/web/public/next/assets/{overnight-queries-CCGfiS-g.js → overnight-queries-X-44Gsw5.js} +2 -2
  336. package/dist/core/web/public/next/assets/{overnight-queries-CCGfiS-g.js.map → overnight-queries-X-44Gsw5.js.map} +1 -1
  337. package/dist/core/web/public/next/assets/pane-chrome-8JmEhHVD.css +1 -0
  338. package/dist/core/web/public/next/assets/pane-chrome.module-D7o-fVd0.js +2 -0
  339. package/dist/core/web/public/next/assets/pane-chrome.module-D7o-fVd0.js.map +1 -0
  340. package/dist/core/web/public/next/assets/primitives-BDIcUvob.js +1 -0
  341. package/dist/core/web/public/next/assets/{queries-BuYIEHst.js → queries-BA4rNGD-.js} +2 -2
  342. package/dist/core/web/public/next/assets/{queries-BuYIEHst.js.map → queries-BA4rNGD-.js.map} +1 -1
  343. package/dist/core/web/public/next/assets/{reasoning-pref-BVzGczV7.js → reasoning-pref-B9-DJUXP.js} +2 -2
  344. package/dist/core/web/public/next/assets/{reasoning-pref-BVzGczV7.js.map → reasoning-pref-B9-DJUXP.js.map} +1 -1
  345. package/dist/core/web/public/next/assets/seat-subscription-CH6fW4fJ.js +2 -0
  346. package/dist/core/web/public/next/assets/seat-subscription-CH6fW4fJ.js.map +1 -0
  347. package/dist/core/web/public/next/assets/{section-visibility-CSrsTcwK.js → section-visibility-qFqc_d4Z.js} +2 -2
  348. package/dist/core/web/public/next/assets/{section-visibility-CSrsTcwK.js.map → section-visibility-qFqc_d4Z.js.map} +1 -1
  349. package/dist/core/web/public/next/assets/{sidebar-model-C8fyqSQY.js → sidebar-model-M1GaQU5l.js} +2 -2
  350. package/dist/core/web/public/next/assets/{sidebar-model-C8fyqSQY.js.map → sidebar-model-M1GaQU5l.js.map} +1 -1
  351. package/dist/core/web/public/next/assets/slots-Ds9ZIqUL.js +3 -0
  352. package/dist/core/web/public/next/assets/{slots-W8gkmdfE.js.map → slots-Ds9ZIqUL.js.map} +1 -1
  353. package/dist/core/web/public/next/assets/surface-data-J52iIGMD.js +2 -0
  354. package/dist/core/web/public/next/assets/surface-data-J52iIGMD.js.map +1 -0
  355. package/dist/core/web/public/next/assets/surface-prefetch-CgZ-LEJK.js +2 -0
  356. package/dist/core/web/public/next/assets/surface-prefetch-CgZ-LEJK.js.map +1 -0
  357. package/dist/core/web/public/next/assets/tasks-model-ent8f0jZ.js +2 -0
  358. package/dist/core/web/public/next/assets/{tasks-model-CnYQzgxk.js.map → tasks-model-ent8f0jZ.js.map} +1 -1
  359. package/dist/core/web/public/next/assets/{terminal-icons-CxUYaWX9.js → terminal-icons-DJTK7QpR.js} +2 -2
  360. package/dist/core/web/public/next/assets/{terminal-icons-CxUYaWX9.js.map → terminal-icons-DJTK7QpR.js.map} +1 -1
  361. package/dist/core/web/public/next/assets/{tool-semantics-CTRuLF5j.js → tool-semantics-GX8ScuSH.js} +2 -2
  362. package/dist/core/web/public/next/assets/{tool-semantics-CTRuLF5j.js.map → tool-semantics-GX8ScuSH.js.map} +1 -1
  363. package/dist/core/web/public/next/assets/{turn-files-BvB5LLNw.js → turn-files-BPHQzYuH.js} +2 -2
  364. package/dist/core/web/public/next/assets/{turn-files-BvB5LLNw.js.map → turn-files-BPHQzYuH.js.map} +1 -1
  365. package/dist/core/web/public/next/assets/types-D5XOdyw8.js +2 -0
  366. package/dist/core/web/public/next/assets/types-D5XOdyw8.js.map +1 -0
  367. package/dist/core/web/public/next/assets/{usage-queries-CQOpeE1H.js → usage-queries-Bn8ccqyN.js} +2 -2
  368. package/dist/core/web/public/next/assets/{usage-queries-CQOpeE1H.js.map → usage-queries-Bn8ccqyN.js.map} +1 -1
  369. package/dist/core/web/public/next/assets/use-guarded-action-C2HlSzkz.js +2 -0
  370. package/dist/core/web/public/next/assets/use-guarded-action-C2HlSzkz.js.map +1 -0
  371. package/dist/core/web/public/next/assets/{use-ticker-hryPXnyp.js → use-ticker-BNc1H4ZC.js} +2 -2
  372. package/dist/core/web/public/next/assets/{use-ticker-hryPXnyp.js.map → use-ticker-BNc1H4ZC.js.map} +1 -1
  373. package/dist/core/web/public/next/assets/use-token-gate-B3IJL6bf.js +2 -0
  374. package/dist/core/web/public/next/assets/use-token-gate-B3IJL6bf.js.map +1 -0
  375. package/dist/core/web/public/next/assets/{useActivity-Cg_9-7nt.js → useActivity-Bk3XgXjL.js} +2 -2
  376. package/dist/core/web/public/next/assets/{useActivity-Cg_9-7nt.js.map → useActivity-Bk3XgXjL.js.map} +1 -1
  377. package/dist/core/web/public/next/assets/useChartWidth-BAtVgn2n.css +1 -0
  378. package/dist/core/web/public/next/assets/useChartWidth-lZ9PrQn0.js +2 -0
  379. package/dist/core/web/public/next/assets/useChartWidth-lZ9PrQn0.js.map +1 -0
  380. package/dist/core/web/public/next/assets/{useSeatsRefresh-4Ov9eT1F.js → useSeatsRefresh-CG4jczeL.js} +2 -2
  381. package/dist/core/web/public/next/assets/{useSeatsRefresh-4Ov9eT1F.js.map → useSeatsRefresh-CG4jczeL.js.map} +1 -1
  382. package/dist/core/web/public/next/assets/verse-model-D7NZQFAR.js +2 -0
  383. package/dist/core/web/public/next/assets/verse-model-D7NZQFAR.js.map +1 -0
  384. package/dist/core/web/public/next/assets/{verse-queries-BjQoOTwv.js → verse-queries-DvIJcn6Z.js} +2 -2
  385. package/dist/core/web/public/next/assets/{verse-queries-BjQoOTwv.js.map → verse-queries-DvIJcn6Z.js.map} +1 -1
  386. package/dist/core/web/public/next/assets/verse-store-DjBWj04q.js +3 -0
  387. package/dist/core/web/public/next/assets/verse-store-DjBWj04q.js.map +1 -0
  388. package/dist/core/web/public/next/assets/verse-ui-store-zafyzXKD.js +3 -0
  389. package/dist/core/web/public/next/assets/{verse-ui-store-KTTKfv-T.js.map → verse-ui-store-zafyzXKD.js.map} +1 -1
  390. package/dist/core/web/public/next/assets/{viewport-ZB86jdES.js → viewport-BEqGUoTA.js} +2 -2
  391. package/dist/core/web/public/next/assets/{viewport-ZB86jdES.js.map → viewport-BEqGUoTA.js.map} +1 -1
  392. package/dist/core/web/public/next/assets/warmup-BR6pxAKs.js +3 -0
  393. package/dist/core/web/public/next/assets/warmup-BR6pxAKs.js.map +1 -0
  394. package/dist/core/web/public/next/assets/{workspace-model-4hq_Mv3N.js → workspace-model-D_tWD5Wt.js} +2 -2
  395. package/dist/core/web/public/next/assets/{workspace-model-4hq_Mv3N.js.map → workspace-model-D_tWD5Wt.js.map} +1 -1
  396. package/dist/core/web/public/next/index.html +1 -1
  397. package/dist/release-dependency-inventory.json +1 -1
  398. package/package.json +1 -1
  399. package/dist/core/web/public/next/assets/Advanced-CHjxJt2z.css +0 -1
  400. package/dist/core/web/public/next/assets/Advanced-DM0DYibH.js +0 -2
  401. package/dist/core/web/public/next/assets/Advanced-DM0DYibH.js.map +0 -1
  402. package/dist/core/web/public/next/assets/AppsSection-CXxbfPJQ.js +0 -2
  403. package/dist/core/web/public/next/assets/AppsSection-CXxbfPJQ.js.map +0 -1
  404. package/dist/core/web/public/next/assets/AreaTrend-gUVXkfhf.js +0 -2
  405. package/dist/core/web/public/next/assets/AreaTrend-gUVXkfhf.js.map +0 -1
  406. package/dist/core/web/public/next/assets/AutonomySection-CoMngwNB.js +0 -2
  407. package/dist/core/web/public/next/assets/BranchBar-C-NovaXr.js +0 -2
  408. package/dist/core/web/public/next/assets/BranchBar-C-NovaXr.js.map +0 -1
  409. package/dist/core/web/public/next/assets/BranchBar-C9BpPVLr.css +0 -1
  410. package/dist/core/web/public/next/assets/BudgetControl-P5lMxHvQ.js +0 -2
  411. package/dist/core/web/public/next/assets/BudgetControl-P5lMxHvQ.js.map +0 -1
  412. package/dist/core/web/public/next/assets/BurnDown-4P1LDoCL.js +0 -2
  413. package/dist/core/web/public/next/assets/BurnDown-4P1LDoCL.js.map +0 -1
  414. package/dist/core/web/public/next/assets/CapacityStrip-D6Yyg4a1.js +0 -2
  415. package/dist/core/web/public/next/assets/CapacityStrip-D6Yyg4a1.js.map +0 -1
  416. package/dist/core/web/public/next/assets/CapacityStrip-wgFP9MUA.css +0 -1
  417. package/dist/core/web/public/next/assets/ChatSection-B9cdRKUh.js +0 -3
  418. package/dist/core/web/public/next/assets/CommandSection-BC0uXim_.js +0 -2
  419. package/dist/core/web/public/next/assets/CommandSection-BC0uXim_.js.map +0 -1
  420. package/dist/core/web/public/next/assets/Composer-CkcwbQhG.css +0 -1
  421. package/dist/core/web/public/next/assets/Composer.module-DJMdrqNt.js +0 -2
  422. package/dist/core/web/public/next/assets/DiffPane-5uLKa0au.js +0 -2
  423. package/dist/core/web/public/next/assets/DiffPane-5uLKa0au.js.map +0 -1
  424. package/dist/core/web/public/next/assets/DiffPane-Csboxnn0.css +0 -1
  425. package/dist/core/web/public/next/assets/DockHost-BGnTgdIb.css +0 -1
  426. package/dist/core/web/public/next/assets/DockHost-CBV_6Ehi.js +0 -2
  427. package/dist/core/web/public/next/assets/DockHost-CBV_6Ehi.js.map +0 -1
  428. package/dist/core/web/public/next/assets/FleetSection-DuJcQCGg.js +0 -3
  429. package/dist/core/web/public/next/assets/FleetSection-DuJcQCGg.js.map +0 -1
  430. package/dist/core/web/public/next/assets/FleetSection-w9AjqfTR.css +0 -1
  431. package/dist/core/web/public/next/assets/Funnel-qX3Hlbce.js +0 -2
  432. package/dist/core/web/public/next/assets/Funnel-qX3Hlbce.js.map +0 -1
  433. package/dist/core/web/public/next/assets/GearTray-kVGP1coG.js +0 -2
  434. package/dist/core/web/public/next/assets/GearTray-kVGP1coG.js.map +0 -1
  435. package/dist/core/web/public/next/assets/GrowthSection-CYxJ9MH5.js +0 -2
  436. package/dist/core/web/public/next/assets/GrowthSection-CYxJ9MH5.js.map +0 -1
  437. package/dist/core/web/public/next/assets/HandoffDialog-DHZo3Ev0.js +0 -2
  438. package/dist/core/web/public/next/assets/HandoffDialog-DHZo3Ev0.js.map +0 -1
  439. package/dist/core/web/public/next/assets/MatrixHeatmap-B_JWCjZx.js +0 -2
  440. package/dist/core/web/public/next/assets/MatrixHeatmap-B_JWCjZx.js.map +0 -1
  441. package/dist/core/web/public/next/assets/McpSection-1UncWBpW.js +0 -2
  442. package/dist/core/web/public/next/assets/MessageMarkdown-C4pl9LI5.js +0 -3
  443. package/dist/core/web/public/next/assets/MessageMarkdown-Czcl3L_Q.css +0 -1
  444. package/dist/core/web/public/next/assets/MindSection-C3fCw_fD.js +0 -2
  445. package/dist/core/web/public/next/assets/MindSection-C3fCw_fD.js.map +0 -1
  446. package/dist/core/web/public/next/assets/MutationTokenDialog-Dn0tzCrh.js +0 -2
  447. package/dist/core/web/public/next/assets/MutationTokenDialog-Dn0tzCrh.js.map +0 -1
  448. package/dist/core/web/public/next/assets/NeedsYouDrawer-CuNYJCJ0.js +0 -2
  449. package/dist/core/web/public/next/assets/NeedsYouDrawer-CuNYJCJ0.js.map +0 -1
  450. package/dist/core/web/public/next/assets/NeedsYouDrawer-SkhvvdLb.css +0 -1
  451. package/dist/core/web/public/next/assets/NewChatDialog-B_BsS9pr.js +0 -3
  452. package/dist/core/web/public/next/assets/OnboardingFlow-CtCPpgoX.js +0 -2
  453. package/dist/core/web/public/next/assets/PreviewPane-Cx6RRwzM.js +0 -2
  454. package/dist/core/web/public/next/assets/PreviewPane-Cx6RRwzM.js.map +0 -1
  455. package/dist/core/web/public/next/assets/PreviewPane-WQJFjSXe.css +0 -1
  456. package/dist/core/web/public/next/assets/RailStatus-BWs6xevj.js +0 -2
  457. package/dist/core/web/public/next/assets/RailStatus-BWs6xevj.js.map +0 -1
  458. package/dist/core/web/public/next/assets/SeatSelector-DaUO-zoK.js +0 -3
  459. package/dist/core/web/public/next/assets/SessionSearch-B5aQ0BCM.js +0 -2
  460. package/dist/core/web/public/next/assets/SettingsSection-CuESA30a.js +0 -2
  461. package/dist/core/web/public/next/assets/SettingsSection-CuESA30a.js.map +0 -1
  462. package/dist/core/web/public/next/assets/Sidebar-DfD8MNZt.css +0 -1
  463. package/dist/core/web/public/next/assets/Sidebar-q11dtYZf.js +0 -3
  464. package/dist/core/web/public/next/assets/Sidebar-q11dtYZf.js.map +0 -1
  465. package/dist/core/web/public/next/assets/StepBand-B1W7rU70.js +0 -2
  466. package/dist/core/web/public/next/assets/StepBand-B1W7rU70.js.map +0 -1
  467. package/dist/core/web/public/next/assets/Swimlane-BR40WVcj.js +0 -2
  468. package/dist/core/web/public/next/assets/Swimlane-BR40WVcj.js.map +0 -1
  469. package/dist/core/web/public/next/assets/TerminalPane-CPKUTD9K.js +0 -7
  470. package/dist/core/web/public/next/assets/TerminalPane-CPKUTD9K.js.map +0 -1
  471. package/dist/core/web/public/next/assets/TerminalPane-CmE2QL-Q.css +0 -1
  472. package/dist/core/web/public/next/assets/UniverseConsoleApp-DKqAf-eD.js +0 -2
  473. package/dist/core/web/public/next/assets/UsageSection-B6fR3cru.js +0 -2
  474. package/dist/core/web/public/next/assets/UsageSection-B6fR3cru.js.map +0 -1
  475. package/dist/core/web/public/next/assets/UsageSection-DwgNOYvi.css +0 -1
  476. package/dist/core/web/public/next/assets/VerseConsoleApp-C0V221WL.css +0 -1
  477. package/dist/core/web/public/next/assets/VerseConsoleApp-bjARLPwN.js +0 -3
  478. package/dist/core/web/public/next/assets/VerseConsoleApp-bjARLPwN.js.map +0 -1
  479. package/dist/core/web/public/next/assets/Workspace-DQXMVDf7.css +0 -1
  480. package/dist/core/web/public/next/assets/Workspace-DtJb5tiM.js +0 -10
  481. package/dist/core/web/public/next/assets/Workspace-DtJb5tiM.js.map +0 -1
  482. package/dist/core/web/public/next/assets/actions-Bszsdpms.js +0 -2
  483. package/dist/core/web/public/next/assets/actions-Bszsdpms.js.map +0 -1
  484. package/dist/core/web/public/next/assets/actions-Dug8YIf0.css +0 -1
  485. package/dist/core/web/public/next/assets/capacity-strip-model-BR539Ci8.js +0 -2
  486. package/dist/core/web/public/next/assets/capacity-strip-model-BR539Ci8.js.map +0 -1
  487. package/dist/core/web/public/next/assets/charts-D4NaLaXA.js +0 -2
  488. package/dist/core/web/public/next/assets/charts-D4NaLaXA.js.map +0 -1
  489. package/dist/core/web/public/next/assets/colors-B-vHsX1S.js +0 -2
  490. package/dist/core/web/public/next/assets/colors-B-vHsX1S.js.map +0 -1
  491. package/dist/core/web/public/next/assets/command-catalog-s3W6Z96D.js +0 -2
  492. package/dist/core/web/public/next/assets/command-catalog-s3W6Z96D.js.map +0 -1
  493. package/dist/core/web/public/next/assets/context-model-Bto3LZn2.js +0 -2
  494. package/dist/core/web/public/next/assets/context-model-Bto3LZn2.js.map +0 -1
  495. package/dist/core/web/public/next/assets/context-queries-DVdSLrYy.js +0 -2
  496. package/dist/core/web/public/next/assets/context-queries-DVdSLrYy.js.map +0 -1
  497. package/dist/core/web/public/next/assets/context.module-B_k02HNU.js +0 -2
  498. package/dist/core/web/public/next/assets/context.module-B_k02HNU.js.map +0 -1
  499. package/dist/core/web/public/next/assets/dock-icons-oG8d7mNZ.js +0 -2
  500. package/dist/core/web/public/next/assets/dock-icons-oG8d7mNZ.js.map +0 -1
  501. package/dist/core/web/public/next/assets/dock-panes-BNTLvX7G.js +0 -2
  502. package/dist/core/web/public/next/assets/fleet-model-ClBbQ0Uj.js +0 -2
  503. package/dist/core/web/public/next/assets/fleet-model-ClBbQ0Uj.js.map +0 -1
  504. package/dist/core/web/public/next/assets/format-BNYWGJat.js +0 -2
  505. package/dist/core/web/public/next/assets/format-BNYWGJat.js.map +0 -1
  506. package/dist/core/web/public/next/assets/global-DVgMguLr.js +0 -2
  507. package/dist/core/web/public/next/assets/global-DVgMguLr.js.map +0 -1
  508. package/dist/core/web/public/next/assets/live-model-Dm6ITHvX.js +0 -2
  509. package/dist/core/web/public/next/assets/live-model-Dm6ITHvX.js.map +0 -1
  510. package/dist/core/web/public/next/assets/mind-B-lYfSUJ.css +0 -1
  511. package/dist/core/web/public/next/assets/mind.module-BzhAlg3e.js +0 -2
  512. package/dist/core/web/public/next/assets/mind.module-BzhAlg3e.js.map +0 -1
  513. package/dist/core/web/public/next/assets/mutations-C6E10SPX.js +0 -2
  514. package/dist/core/web/public/next/assets/primitives-DQvYikjm.js +0 -1
  515. package/dist/core/web/public/next/assets/seat-subscription-CrWOV4Qc.js +0 -2
  516. package/dist/core/web/public/next/assets/seat-subscription-CrWOV4Qc.js.map +0 -1
  517. package/dist/core/web/public/next/assets/slots-W8gkmdfE.js +0 -3
  518. package/dist/core/web/public/next/assets/surface-data-ZtCegYMQ.js +0 -2
  519. package/dist/core/web/public/next/assets/surface-data-ZtCegYMQ.js.map +0 -1
  520. package/dist/core/web/public/next/assets/tasks-model-CnYQzgxk.js +0 -2
  521. package/dist/core/web/public/next/assets/types-Dypu22dp.js +0 -3
  522. package/dist/core/web/public/next/assets/types-Dypu22dp.js.map +0 -1
  523. package/dist/core/web/public/next/assets/use-guarded-action-CO_aAsed.js +0 -2
  524. package/dist/core/web/public/next/assets/use-guarded-action-CO_aAsed.js.map +0 -1
  525. package/dist/core/web/public/next/assets/use-token-gate-DYA2-ALC.js +0 -2
  526. package/dist/core/web/public/next/assets/use-token-gate-DYA2-ALC.js.map +0 -1
  527. package/dist/core/web/public/next/assets/useChartWidth-B8E5mJgM.css +0 -1
  528. package/dist/core/web/public/next/assets/useChartWidth-MEXvDxDL.js +0 -2
  529. package/dist/core/web/public/next/assets/useChartWidth-MEXvDxDL.js.map +0 -1
  530. package/dist/core/web/public/next/assets/verse-model-E98kXngO.js +0 -2
  531. package/dist/core/web/public/next/assets/verse-model-E98kXngO.js.map +0 -1
  532. package/dist/core/web/public/next/assets/verse-store-BgKx_YGs.js +0 -2
  533. package/dist/core/web/public/next/assets/verse-store-BgKx_YGs.js.map +0 -1
  534. package/dist/core/web/public/next/assets/verse-ui-store-KTTKfv-T.js +0 -3
@@ -0,0 +1,2 @@
1
+ import{_ as e,o as t}from"./colors-BZ3a9wFf.js";import{y as n}from"./format-B8DAVcn2.js";var r=new Set([`headroom`,`switched-off`,`signed-out`,`unreachable`,`spent`,`reserve`,`session-ceiling`,`unknown-usage`,`spend-cap`,`model-window`,`context`,`grant`,`lane`,`demoted`,`other`]);function i(e){let t=e.trim().replace(/[\s;,:]+$/,``);return t?/[.!?…]$/.test(t)?t:`${t}.`:``}function a(e){return e.map(i).filter(Boolean).join(` `)}function o(e){return e.length<=1?e[0]??``:`${e.slice(0,-1).join(`, `)} and ${e[e.length-1]}`}var s=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/,c=/\b\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d{1,9})?)?(?:Z|[+-]\d{2}:?\d{2})?(?![\w:])/g;function l(e,t=Date.now()){return e.replace(c,e=>n(e,t)??e)}function u(e){return typeof e==`string`&&s.test(e)&&Number.isFinite(Date.parse(e))}function d(e){return/^autonomy is switched off/i.test(e)?`switched-off`:/^signed out/i.test(e)?`signed-out`:/not reachable/i.test(e)?`unreachable`:/limits that model only/.test(e)?`model-window`:/ is spent — /.test(e)?`spent`:/is kept for you, so autonomy stops at/.test(e)?`reserve`:/used; autonomy stops at .* to protect your live session/.test(e)?`session-ceiling`:/unknown usage is not headroom|too stale to spend against|too uncertain to spend against/.test(e)?`unknown-usage`:/daily cap/.test(e)?`spend-cap`:/tokens of context/.test(e)?`context`:/is demoted/.test(e)?`demoted`:/\bgrant\b/i.test(e)?`grant`:/\blanes?\b|\bslots?\b|producer slice is held/i.test(e)?`lane`:`other`}var f=[[/(?<![\w-])grok-cli(?![\w-])/g,`Grok`],[/(?<![\w-])claude-cli(?![\w-])/g,`Claude`],[/(?<![\w-])codex(?![\w-])/g,`Codex`]];function p(e){let t=e.trim();t=t.replace(/^Codex lanes stay off until the Leader enables them\b/,`Codex stays off until the Leader turns it on`),t=t.replace(/\s*\(an? class-([A-Za-z])\s+action\)/g,(e,t)=>/^[ab]$/i.test(t)?` (you can veto it)`:``),t=t.replace(/\b(\d+)((?:\s+[A-Za-z-]+)*?)\s+([A-Za-z]+)\(s\)/g,(e,t,n,r)=>`${t}${n} ${r}${Number(t)===1?``:`s`}`),t=t.replace(/\b([A-Za-z]+)\(s\)/g,`$1s`);for(let[e,n]of f)t=t.replace(e,n);return t}function m(e){let t=e.trim(),n=/^([\s\S]*?) \(resets ([\s\S]+)\)\.?$/.exec(t),r=n?`${n[1]}.`:t,i=n?n[2].trim():null,a=u(i)?i:null,o=/ is demoted until (\S+): /.exec(r);return o&&u(o[1])&&(a=o[1],r=r.replace(` until ${o[1]}:`,`:`)),{kind:d(r),text:r,resetsAt:a,resetDescription:i!==null&&!u(i)?i:null}}function h(e){return Array.isArray(e.details)&&(e.details.length>0||e.reasons.length===0)?e.details.map(e=>r.has(e.kind)?e:{...e,kind:`other`}):e.reasons.map(m)}function g(e){return a(h(e).filter(e=>e.kind!==`headroom`).map(e=>e.kind===`lane`?p(e.text):e.text))}var _={"switched-off":`you switch autonomy on for this seat`,"signed-out":`you reconnect this account`,unreachable:`it is reachable again`,"unknown-usage":`a fresh usage reading arrives`,"spend-cap":`its daily spend cap resets`,grant:`the standing grant allows it`,lane:`its lane has a free slot`},v=new Set([`spent`,`reserve`,`session-ceiling`,`demoted`]);function y(e){return e.trim().replace(/^resets\s+/i,``)}function b(e){let t=[],n=[],r=null,i=!1,a=null;for(let o of h(e)){if(o.kind===`context`){a=`not for this task — it needs a larger context window than this seat has`;continue}let e=_[o.kind];if(e&&!t.includes(e)&&t.push(e),v.has(o.kind)){if(u(o.resetsAt))(r===null||Date.parse(o.resetsAt)>Date.parse(r))&&(r=o.resetsAt);else if(o.resetDescription){let e=y(o.resetDescription);n.includes(e)||n.push(e)}else i=!0}}return r===null&&n.length===0&&u(e.nextEligibleAt)&&(r=e.nextEligibleAt,i=!1),{conditions:t,at:r,prose:n,timeUnknown:i,never:a}}function x(e,t=Date.now()){if(e.never)return e.never;let r=[...e.at?[n(e.at,t)??e.at]:[],...e.prose],i=r.length>0?r.join(` and `):null,a=e.conditions.length>0?`when ${o(e.conditions)}`:null;return a&&i?`${a}, not before ${i}`:a||i||`unknown`}var S=/^Routed (?:autonomous )?[\w-]+-difficulty \w+ work to (.+?) \(([^()]+)\)(?: with (\d+)% of its (5-hour|weekly) window left for autonomy| (at no cost))?: ([\w-]+) mode prefers (.+?) first for this work(?:; held back [\s\S]*)?\.$/,C=/^(No seat (?:the grant lets produce )?can take [\s\S]*?) \([\s\S]*\)(?:; the earliest known reopening is \S+)?\.$/;function w(e){let t=e.trim(),n=S.exec(t);if(n){let[,e,,t,r,i,a,o]=n,s=t?` — ${t}% of its ${r} window left`:i?` — free, no usage window`:``;return s?`${e}${s}; ${a} mode prefers ${o} for this work.`:`${e} — ${a} mode prefers ${o} for this work.`}let r=C.exec(t);return r?`${r[1]}.`:t}function T(e){let t=i(e.summary??w(e.why)),n=e.exclusions.length;return n===0?t:`${t} ${n===1?`1 seat`:`${n} seats`} held back.`}var E={local:`local`,"grok-cli":`grok`,"claude-cli":`claude`,codex:`codex`},D={local:`Local`,"grok-cli":`Grok`,"claude-cli":`Claude`,codex:`Codex`};function O(e){return{name:D[e.lane],slots:e.slots===0?`off`:`${e.busy}/${e.slots}`}}function k(e){let t=e.capReason?.trim();return t?p(t):null}function A(e){let t=new Map;for(let n of e){let e=k(n);if(!e)continue;let r=t.get(e)??[];r.push(n.lane),t.set(e,r)}return[...t.entries()].map(([t,n])=>({lanes:n,all:n.length===e.length&&e.length>1,reason:t}))}function j(e){return e.phase===`queued`||e.phase===`parked`?e.phase:e.phase===`reverting`?`reverting`:e.outcome??e.phase}var M={producing:`running`,verifying:`running`,judging:`running`,landing:`running`,watching:`info`,reverting:`danger`,merged:`success`,proposed:`info`,"owner-lane":`warning`,refused:`warning`,failed:`danger`,reverted:`danger`,cancelled:`neutral`,queued:`neutral`,parked:`neutral`};function N(e){return M[e]??`unknown`}function P(e){let t=Date.parse(e.startedAt??e.phaseStartedAt??``);return Number.isFinite(t)?t:null}function F(e){if(!e.endedAt)return null;let t=Date.parse(e.endedAt);return Number.isFinite(t)?t:null}function I(e){return[e.repo.includes(`/`)?e.repo.split(`/`)[1]:e.repo,e.title,e.model,e.prNumber?`PR #${e.prNumber}`:null].filter(Boolean).join(` · `)}var L=[`local`,`grok-cli`,`claude-cli`,`codex`,`none`];function R(e,t,n,r={}){let i=r.includeParked??!0,a=new Map;for(let r of e){if(!i&&r.phase===`parked`)continue;let e=P(r);if(e===null||(F(r)??n)<t||e>n)continue;let o=r.lane??`none`;a.has(o)||a.set(o,[]),a.get(o).push(r)}let o=[];for(let e of L){let t=a.get(e);if(!t?.length)continue;t.sort((e,t)=>P(e)-P(t));let r=[],i=[];for(let e of t){let t=P(e),a=F(e)??n,o=r.findIndex(e=>e<=t);o===-1?(o=r.length,r.push(a),i.push([])):r[o]=a,i[o].push(e)}let s=e===`none`?`Unassigned`:D[e];i.forEach((t,n)=>{o.push({id:`${e}:${n}`,label:i.length>1?`${s} · ${n+1}`:s,...e===`none`?{}:{engine:E[e]},items:t.map(e=>({id:e.id,start:P(e),end:F(e),status:j(e),detail:I(e)}))})})}return o}function z(e,t){let n=e.filter(e=>e.phase===`parked`||e.hold!==null),r=n.map(e=>e.hold?.nextEligibleAt?Date.parse(e.hold.nextEligibleAt):NaN).filter(Number.isFinite),i=n.map(e=>P(e)??t),a=Math.min(t-36e5,...i),o=Math.min(t+1728e5,Math.max(t+72e5,...r)),s=0;return{lanes:n.map(e=>{let n=e.hold?.nextEligibleAt?Date.parse(e.hold.nextEligibleAt):NaN;Number.isFinite(n)||s++;let r=e.repo.includes(`/`)?e.repo.split(`/`)[1]:e.repo;return{id:e.id,label:`${r}: ${e.title}`,...e.lane?{engine:E[e.lane]}:{},items:[{id:e.id,start:P(e)??t,end:Number.isFinite(n)?n:null,status:e.hold?.kind===`split`?`split`:`parked`,outline:!0,detail:`${l(e.hold?.reason??`parked`,t)}${Number.isFinite(n)?``:` · release time unknown`}`}]}}),from:a,to:o,unknownRelease:s}}var B={G0:`Authority`,G1:`Protected paths`,G1b:`Tamper`,G2:`Scope`,G3:`Verify`,G4:`Claims`,G5:`Blast radius`,G6:`Judge`,G7:`GitHub checks`};function V(e){return!e||e.stages.length===0?[]:[{id:`entered`,label:`Proposals`,value:e.stages[0].entered},...e.stages.map(e=>({id:e.gate,label:`${e.gate} ${B[e.gate]??``}`.trim(),value:e.passed}))]}function H(n,r=5){if(!n)return{categories:[],segments:[],values:[],total:0};let i=new Map;for(let e of n.stages)for(let t of e.refusals){let e=i.get(t.code);i.set(t.code,{reason:e?.reason??t.reason,count:(e?.count??0)+t.count})}let a=[...i.entries()].sort((e,t)=>t[1].count-e[1].count||e[0].localeCompare(t[0])),o=a.slice(0,r).map(([e])=>e),s=a.length>r,c=[...o.map((t,n)=>({id:t,label:i.get(t).reason,color:e(n)})),...s?[{id:`__other`,label:`Other reasons`,color:t}]:[]],l=n.stages.filter(e=>e.refusals.length>0||e.entered!==e.passed);return{categories:l.map(e=>e.gate),segments:c,values:l.map(e=>{let t=o.map(t=>e.refusals.find(e=>e.code===t)?.count??0);return s&&t.push(e.refusals.filter(e=>!o.includes(e.code)).reduce((e,t)=>e+t.count,0)),t}),total:a.reduce((e,[,t])=>e+t.count,0)}}function U(e){if(!e)return null;let t=e.runs.filter(e=>e.seatDecision!==null);if(!t.length)return null;t.sort((e,t)=>(P(t)??0)-(P(e)??0));let n=t[0];return{decision:n.seatDecision,run:n}}export{l as _,A as a,U as c,N as d,i as f,g,b as h,O as i,z as l,x as m,D as n,k as o,T as p,V as r,R as s,E as t,H as u,m as v};
2
+ //# sourceMappingURL=live-model-DCw_IFRI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-model-DCw_IFRI.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/fleet/why-seat-model.ts","../../../../../../src/web-ui/routes/verse/fleet/live-model.ts"],"sourcesContent":["/**\n * routes/verse/fleet/why-seat-model.ts — \"Why this seat\" in words (3.10.1).\n *\n * The card used to print the router's log sentence verbatim — one run-on with\n * every held-back seat's first reason in nested parentheses and a literal\n * \"…\" — and each HELD BACK entry as `reasons.join('; ')` (hence \".;\"), with\n * raw UTC instants and \"eligible again: unknown\" for seats whose reset was\n * known all along. Now:\n *\n * - the headline is one short sentence (`SeatDecision.summary`, or the\n * same words recovered from a 3.10.0 `why`) plus \"N seats held back.\";\n * - each held-back seat lists its reasons as prose sentences, without the\n * reset clauses — those move to \"eligible again\";\n * - \"eligible again\" is derived from the reasons AS DATA: every condition\n * that must change first (\"when you switch autonomy on for this seat\")\n * and the time every time-bound blocker has lifted, in the viewer's zone\n * (\"Fri 11:46 PM\") or, for Claude, the provider's own words verbatim.\n * \"unknown\" only when nothing says.\n *\n * Records written before 3.10.1 carry only sentences; `parseLegacyReason`\n * recovers the same data from them.\n *\n * Framework-free; tested directly.\n */\nimport type { SeatDecision, SeatExclusion, SeatReason, SeatReasonKind } from '../../../../core/routing/types.js';\nimport { describeResetAt } from '../../../../core/verse/seat-readiness.js';\n\nconst KINDS: ReadonlySet<string> = new Set<SeatReasonKind>([\n 'headroom', 'switched-off', 'signed-out', 'unreachable', 'spent', 'reserve', 'session-ceiling',\n 'unknown-usage', 'spend-cap', 'model-window', 'context', 'grant', 'lane', 'demoted', 'other',\n]);\n\n// ---------------------------------------------------------------------------\n// Sentences\n// ---------------------------------------------------------------------------\n\n/**\n * One sentence: trimmed and closed by exactly one full stop (a trailing \";\"\n * or \",\" is dropped). Never re-cased — a sentence may open on a seat id.\n */\nexport function asSentence(text: string): string {\n const t = text.trim().replace(/[\\s;,:]+$/, '');\n if (!t) return '';\n return /[.!?…]$/.test(t) ? t : `${t}.`;\n}\n\n/** Sentences as prose — \"A. B.\" — never \"A.; B\" and never \"A.. B\". */\nexport function joinSentences(texts: readonly string[]): string {\n return texts.map(asSentence).filter(Boolean).join(' ');\n}\n\n/** \"a\", \"a and b\", \"a, b and c\". */\nfunction listWords(words: readonly string[]): string {\n if (words.length <= 1) return words[0] ?? '';\n return `${words.slice(0, -1).join(', ')} and ${words[words.length - 1]}`;\n}\n\n// ---------------------------------------------------------------------------\n// Reasons as data\n// ---------------------------------------------------------------------------\n\nconst ISO_INSTANT = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}/;\nconst ISO_IN_TEXT = /\\b\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{1,9})?)?(?:Z|[+-]\\d{2}:?\\d{2})?(?![\\w:])/g;\n\n/**\n * Server prose with every ISO instant in it shown in the viewer's zone (\"the\n * earliest known reopening is Fri 2:25 PM\") — for sentences the server keeps\n * machine-exact for its logs, like a park hold's reason.\n */\nexport function localTimes(text: string, now: number = Date.now()): string {\n return text.replace(ISO_IN_TEXT, (iso) => describeResetAt(iso, now) ?? iso);\n}\n\nfunction isInstant(text: string | null | undefined): text is string {\n return typeof text === 'string' && ISO_INSTANT.test(text) && Number.isFinite(Date.parse(text));\n}\n\nfunction legacyKind(text: string): SeatReasonKind {\n if (/^autonomy is switched off/i.test(text)) return 'switched-off';\n if (/^signed out/i.test(text)) return 'signed-out';\n if (/not reachable/i.test(text)) return 'unreachable';\n if (/limits that model only/.test(text)) return 'model-window';\n if (/ is spent — /.test(text)) return 'spent';\n if (/is kept for you, so autonomy stops at/.test(text)) return 'reserve';\n if (/used; autonomy stops at .* to protect your live session/.test(text)) return 'session-ceiling';\n if (/unknown usage is not headroom|too stale to spend against|too uncertain to spend against/.test(text)) return 'unknown-usage';\n if (/daily cap/.test(text)) return 'spend-cap';\n if (/tokens of context/.test(text)) return 'context';\n if (/is demoted/.test(text)) return 'demoted';\n if (/\\bgrant\\b/i.test(text)) return 'grant';\n // A lane cap, as 3.10.0's router wrote it into exclusions: \"Codex lanes\n // stay off until…\", \"The Leader set 0 grok-cli lanes.\", \"The local runtime\n // serves 0 slot(s).\", \"…the Claude producer slice is held for your own\n // session.\" (3.10.1 sends these as `kind: 'lane'`.)\n if (/\\blanes?\\b|\\bslots?\\b|producer slice is held/i.test(text)) return 'lane';\n return 'other';\n}\n\n// ---------------------------------------------------------------------------\n// Lane cap reasons in operator words\n// ---------------------------------------------------------------------------\n\n/** Lane ids as the operator reads them — never inside a seat id (`codex-cmp`). */\nconst LANE_WORDS: ReadonlyArray<readonly [RegExp, string]> = [\n [/(?<![\\w-])grok-cli(?![\\w-])/g, 'Grok'],\n [/(?<![\\w-])claude-cli(?![\\w-])/g, 'Claude'],\n [/(?<![\\w-])codex(?![\\w-])/g, 'Codex'],\n];\n\n/**\n * A lane cap reason (the router's `capReason`, also a held-back seat's lane\n * reason) in plain words. The router words these for its log: \"The local\n * runtime serves 2 slot(s).\", \"A harness experiment is using 1 local\n * slot(s).\", \"Codex lanes stay off until the Leader enables them after the\n * usage reset (a class-B action).\", \"The Leader set 0 grok-cli lanes.\" The\n * operator reads \"2 slots\", \"1 local slot\", \"Codex stays off until the Leader\n * turns it on after the usage reset (you can veto it)\" and \"0 Grok lanes\".\n * Anything it does not recognise passes through unchanged.\n */\nexport function laneReasonText(reason: string): string {\n let text = reason.trim();\n text = text.replace(/^Codex lanes stay off until the Leader enables them\\b/, 'Codex stays off until the Leader turns it on');\n // A class-A/B Leader action waits out a veto window; class C does not.\n text = text.replace(/\\s*\\(an? class-([A-Za-z])\\s+action\\)/g, (_m, cls: string) => (/^[ab]$/i.test(cls) ? ' (you can veto it)' : ''));\n // \"2 slot(s)\" → \"2 slots\"; \"1 local slot(s)\" → \"1 local slot\".\n text = text.replace(/\\b(\\d+)((?:\\s+[A-Za-z-]+)*?)\\s+([A-Za-z]+)\\(s\\)/g, (_m, n: string, mid: string, word: string) => `${n}${mid} ${word}${Number(n) === 1 ? '' : 's'}`);\n text = text.replace(/\\b([A-Za-z]+)\\(s\\)/g, '$1s');\n for (const [re, word] of LANE_WORDS) text = text.replace(re, word);\n return text;\n}\n\n/**\n * A pre-3.10.1 reason sentence, back into data: the \" (resets …)\" clause the\n * server appended is split off (an instant → `resetsAt`, Claude's prose →\n * `resetDescription`), as is a demotion's \"until <instant>\".\n */\nexport function parseLegacyReason(sentence: string): SeatReason {\n const trimmed = sentence.trim();\n const clause = /^([\\s\\S]*?) \\(resets ([\\s\\S]+)\\)\\.?$/.exec(trimmed);\n let text = clause ? `${clause[1]}.` : trimmed;\n const reset = clause ? clause[2]!.trim() : null;\n let resetsAt: string | null = isInstant(reset) ? reset : null;\n const demoted = / is demoted until (\\S+): /.exec(text);\n if (demoted && isInstant(demoted[1])) {\n resetsAt = demoted[1];\n text = text.replace(` until ${demoted[1]}:`, ':');\n }\n return {\n kind: legacyKind(text),\n text,\n resetsAt,\n resetDescription: reset !== null && !isInstant(reset) ? reset : null,\n };\n}\n\n/** An exclusion's reasons as data: its 3.10.1 `details`, or its sentences parsed. */\nexport function exclusionReasons(x: SeatExclusion): SeatReason[] {\n if (Array.isArray(x.details) && (x.details.length > 0 || x.reasons.length === 0)) {\n // A newer server may add kinds; anything unrecognised reads as `other`.\n return x.details.map((r) => (KINDS.has(r.kind) ? r : { ...r, kind: 'other' as const }));\n }\n return x.reasons.map(parseLegacyReason);\n}\n\n/** The reasons a HELD BACK row prints: blockers and notes, never the \"N% left\" line; lane caps in plain words. */\nexport function heldBackText(x: SeatExclusion): string {\n return joinSentences(exclusionReasons(x).filter((r) => r.kind !== 'headroom').map((r) => (r.kind === 'lane' ? laneReasonText(r.text) : r.text)));\n}\n\n// ---------------------------------------------------------------------------\n// Eligible again\n// ---------------------------------------------------------------------------\n\n/** What must change before the seat can take this work again. */\nexport interface EligibleAgain {\n /** Conditions a person or the fleet must meet first, in words. */\n conditions: string[];\n /** The instant every time-bound blocker has lifted (the LATEST reset among them); null when none is known. */\n at: string | null;\n /** Provider reset wording with no instant (Claude), verbatim. */\n prose: string[];\n /** A time-bound blocker whose lift time nobody reported. */\n timeUnknown: boolean;\n /** Set when the seat can never take THIS work (it does not fit). */\n never: string | null;\n}\n\nconst CONDITION: Partial<Record<SeatReasonKind, string>> = {\n 'switched-off': 'you switch autonomy on for this seat',\n 'signed-out': 'you reconnect this account',\n unreachable: 'it is reachable again',\n 'unknown-usage': 'a fresh usage reading arrives',\n 'spend-cap': 'its daily spend cap resets',\n grant: 'the standing grant allows it',\n lane: 'its lane has a free slot',\n};\n\n/** Blockers that lift on their own at a time: a window reset, a demotion's end. */\nconst TIMED: ReadonlySet<SeatReasonKind> = new Set<SeatReasonKind>(['spent', 'reserve', 'session-ceiling', 'demoted']);\n\n/** Claude's wording, without the \"resets\" some sources lead with. */\nfunction resetWords(text: string): string {\n return text.trim().replace(/^resets\\s+/i, '');\n}\n\nexport function eligibleAgain(x: SeatExclusion): EligibleAgain {\n const conditions: string[] = [];\n const prose: string[] = [];\n let at: string | null = null;\n let timeUnknown = false;\n let never: string | null = null;\n for (const r of exclusionReasons(x)) {\n if (r.kind === 'context') {\n never = 'not for this task — it needs a larger context window than this seat has';\n continue;\n }\n const condition = CONDITION[r.kind];\n if (condition && !conditions.includes(condition)) conditions.push(condition);\n if (!TIMED.has(r.kind)) continue;\n // The seat is free only once EVERY time-bound blocker has lifted.\n if (isInstant(r.resetsAt)) {\n if (at === null || Date.parse(r.resetsAt) > Date.parse(at)) at = r.resetsAt;\n } else if (r.resetDescription) {\n const words = resetWords(r.resetDescription);\n if (!prose.includes(words)) prose.push(words);\n } else {\n timeUnknown = true;\n }\n }\n // The server's own estimate, when the reasons themselves carried no time.\n if (at === null && prose.length === 0 && isInstant(x.nextEligibleAt)) {\n at = x.nextEligibleAt;\n timeUnknown = false;\n }\n return { conditions, at, prose, timeUnknown, never };\n}\n\n/**\n * \"Fri 11:46 PM\"; \"when you switch autonomy on for this seat, not before Fri\n * 11:46 PM\"; \"Sep 25 at 6:59pm (America/New_York)\" (Claude's words); and\n * \"unknown\" only when nothing says.\n */\nexport function describeEligibleAgain(e: EligibleAgain, now: number = Date.now()): string {\n if (e.never) return e.never;\n const times = [...(e.at ? [describeResetAt(e.at, now) ?? e.at] : []), ...e.prose];\n const time = times.length > 0 ? times.join(' and ') : null;\n const when = e.conditions.length > 0 ? `when ${listWords(e.conditions)}` : null;\n if (when && time) return `${when}, not before ${time}`;\n if (when) return when;\n if (time) return time;\n return 'unknown';\n}\n\n// ---------------------------------------------------------------------------\n// Headline\n// ---------------------------------------------------------------------------\n\nconst ROUTED = /^Routed (?:autonomous )?[\\w-]+-difficulty \\w+ work to (.+?) \\(([^()]+)\\)(?: with (\\d+)% of its (5-hour|weekly) window left for autonomy| (at no cost))?: ([\\w-]+) mode prefers (.+?) first for this work(?:; held back [\\s\\S]*)?\\.$/;\nconst NOTHING = /^(No seat (?:the grant lets produce )?can take [\\s\\S]*?) \\([\\s\\S]*\\)(?:; the earliest known reopening is \\S+)?\\.$/;\n\n/**\n * The short headline recovered from a 3.10.0 `why` — the same words a 3.10.1\n * router writes as `summary` (\"Grok — 94% of its weekly window left; balanced\n * mode prefers Grok for this work.\"). Anything unrecognised is returned as is.\n */\nexport function legacySummary(why: string): string {\n const text = why.trim();\n const routed = ROUTED.exec(text);\n if (routed) {\n const [, label, , room, windowWord, free, mode, engine] = routed;\n const lead = room ? ` — ${room}% of its ${windowWord} window left` : free ? ' — free, no usage window' : '';\n return lead ? `${label}${lead}; ${mode} mode prefers ${engine} for this work.` : `${label} — ${mode} mode prefers ${engine} for this work.`;\n }\n const nothing = NOTHING.exec(text);\n if (nothing) return `${nothing[1]}.`;\n return text;\n}\n\n/** The card's one-line headline: the choice and why, then how many seats were held back. */\nexport function decisionSummary(d: SeatDecision): string {\n const lead = asSentence(d.summary ?? legacySummary(d.why));\n const n = d.exclusions.length;\n return n === 0 ? lead : `${lead} ${n === 1 ? '1 seat' : `${n} seats`} held back.`;\n}\n","/**\n * routes/verse/fleet/live-model.ts — FleetLiveSnapshotV1 → chart props\n * (unit C7; SPEC-310B §6 Fleet, SPEC-310C §5). Shared by Command's 12 h\n * swimlane and every Fleet card, so both make the same decisions:\n *\n * - rows are LANES × SLOTS: runs overlapping in one lane stack into\n * numbered slot rows (\"Grok · 2\"), so a bar never hides behind another;\n * - bar colour is STATUS (running amber, merged green, reverted red …);\n * the lane's ENGINE is the tick + monogram beside its label;\n * - queued and parked work draws as an outline (it holds a place; nothing\n * runs) — the Parked Gantt runs from \"parked since\" to `nextEligibleAt`,\n * and an unknown `nextEligibleAt` stays open-ended with \"unknown\" in words.\n *\n * Framework-free; tested directly.\n */\nimport type { FleetEngine, FleetGateFunnel, FleetLaneState, FleetLiveRun, FleetLiveSnapshotV1 } from '../../../../core/fleet/fleet-types.js';\nimport type { SeatDecision } from '../../../../core/routing/types.js';\nimport type { ChartEngine, ChartTone } from '../../../components/charts/colors.js';\nimport { CHART_NEUTRAL, seriesColor } from '../../../components/charts/colors.js';\nimport type { SwimlaneLane } from '../../../components/charts/Swimlane.js';\nimport type { FunnelStage } from '../../../components/charts/Funnel.js';\nimport type { BarStackSegment } from '../../../components/charts/BarStack.js';\nimport { laneReasonText, localTimes } from './why-seat-model.js';\n\nexport const LANE_ENGINE: Readonly<Record<FleetEngine, ChartEngine>> = {\n local: 'local',\n 'grok-cli': 'grok',\n 'claude-cli': 'claude',\n codex: 'codex',\n};\n\nexport const LANE_LABEL: Readonly<Record<FleetEngine, string>> = {\n local: 'Local',\n 'grok-cli': 'Grok',\n 'claude-cli': 'Claude',\n codex: 'Codex',\n};\n\n/** A lane chip's words: \"Local · off\", \"Grok · 1/2\". The why is a separate line (`laneNotes`). */\nexport function laneChipText(lane: FleetLaneState): { name: string; slots: string } {\n return { name: LANE_LABEL[lane.lane], slots: lane.slots === 0 ? 'off' : `${lane.busy}/${lane.slots}` };\n}\n\nexport interface LaneNote {\n /** The lanes this reason applies to, in strip order. */\n lanes: FleetEngine[];\n /** True when every lane shares it — then it is said once, without names. */\n all: boolean;\n reason: string;\n}\n\n/** A lane's cap reason as the operator reads it (`laneReasonText`); null when it has none. */\nexport function laneReason(lane: FleetLaneState): string | null {\n const reason = lane.capReason?.trim();\n return reason ? laneReasonText(reason) : null;\n}\n\n/**\n * Each distinct lane cap reason ONCE, with the lanes it covers, in plain\n * words (the router's \"slot(s)\" and \"class-B action\" never reach the\n * operator). A dark fleet gives every lane the same sentence; 3.10.0\n * repeated it inside every chip and truncated it there.\n */\nexport function laneNotes(lanes: readonly FleetLaneState[]): LaneNote[] {\n const byReason = new Map<string, FleetEngine[]>();\n for (const lane of lanes) {\n const reason = laneReason(lane);\n if (!reason) continue;\n const list = byReason.get(reason) ?? [];\n list.push(lane.lane);\n byReason.set(reason, list);\n }\n return [...byReason.entries()].map(([reason, covered]) => ({\n lanes: covered,\n all: covered.length === lanes.length && lanes.length > 1,\n reason,\n }));\n}\n\n/** The word a bar is labelled with: the outcome once it ended, else the phase. */\nexport function runStatus(run: FleetLiveRun): string {\n if (run.phase === 'queued' || run.phase === 'parked') return run.phase;\n if (run.phase === 'reverting') return 'reverting';\n return run.outcome ?? run.phase;\n}\n\nconst TONES: Readonly<Record<string, ChartTone>> = {\n producing: 'running',\n verifying: 'running',\n judging: 'running',\n landing: 'running',\n watching: 'info',\n reverting: 'danger',\n merged: 'success',\n proposed: 'info',\n 'owner-lane': 'warning',\n refused: 'warning',\n failed: 'danger',\n reverted: 'danger',\n cancelled: 'neutral',\n queued: 'neutral',\n parked: 'neutral',\n};\n\nexport function runTone(status: string): ChartTone {\n return TONES[status] ?? 'unknown';\n}\n\nfunction startOf(run: FleetLiveRun): number | null {\n const t = Date.parse(run.startedAt ?? run.phaseStartedAt ?? '');\n return Number.isFinite(t) ? t : null;\n}\n\nfunction endOf(run: FleetLiveRun): number | null {\n if (!run.endedAt) return null;\n const t = Date.parse(run.endedAt);\n return Number.isFinite(t) ? t : null;\n}\n\nfunction runDetail(run: FleetLiveRun): string {\n const where = run.repo.includes('/') ? run.repo.split('/')[1] : run.repo;\n return [where, run.title, run.model, run.prNumber ? `PR #${run.prNumber}` : null].filter(Boolean).join(' · ');\n}\n\nconst LANE_ORDER: readonly (FleetEngine | 'none')[] = ['local', 'grok-cli', 'claude-cli', 'codex', 'none'];\n\n/**\n * Runs within [from, now] packed into lane × slot rows. `parkedAsGantt`\n * leaves parked runs out (the Fleet surface draws them in their own Gantt);\n * Command keeps them in, as outlines.\n */\nexport function laneRows(runs: readonly FleetLiveRun[], from: number, now: number, opts: { includeParked?: boolean } = {}): SwimlaneLane[] {\n const includeParked = opts.includeParked ?? true;\n const byLane = new Map<FleetEngine | 'none', FleetLiveRun[]>();\n for (const run of runs) {\n if (!includeParked && run.phase === 'parked') continue;\n const s = startOf(run);\n if (s === null) continue;\n const e = endOf(run) ?? now;\n if (e < from || s > now) continue;\n const key = run.lane ?? 'none';\n if (!byLane.has(key)) byLane.set(key, []);\n byLane.get(key)!.push(run);\n }\n const lanes: SwimlaneLane[] = [];\n for (const key of LANE_ORDER) {\n const list = byLane.get(key);\n if (!list?.length) continue;\n list.sort((a, b) => startOf(a)! - startOf(b)!);\n const slotEnds: number[] = [];\n const slotItems: FleetLiveRun[][] = [];\n for (const run of list) {\n const s = startOf(run)!;\n const e = endOf(run) ?? now;\n let slot = slotEnds.findIndex((end) => end <= s);\n if (slot === -1) {\n slot = slotEnds.length;\n slotEnds.push(e);\n slotItems.push([]);\n } else {\n slotEnds[slot] = e;\n }\n slotItems[slot]!.push(run);\n }\n const name = key === 'none' ? 'Unassigned' : LANE_LABEL[key];\n slotItems.forEach((items, i) => {\n lanes.push({\n id: `${key}:${i}`,\n label: slotItems.length > 1 ? `${name} · ${i + 1}` : name,\n ...(key === 'none' ? {} : { engine: LANE_ENGINE[key] }),\n items: items.map((run) => ({\n id: run.id,\n start: startOf(run)!,\n end: endOf(run),\n status: runStatus(run),\n detail: runDetail(run),\n })),\n });\n });\n }\n return lanes;\n}\n\nexport interface GanttRow {\n lanes: SwimlaneLane[];\n from: number;\n to: number;\n /** Rows whose release time is unknown (drawn open-ended). */\n unknownRelease: number;\n}\n\n/**\n * The Parked Gantt: one row per parked item, from when it parked to when its\n * seat should free up. The window always shows \"now\" plus the furthest known\n * release (capped at 48 h — a week-long wait still reads, it just runs off\n * the right edge and the table carries the exact time).\n */\nexport function parkedGantt(runs: readonly FleetLiveRun[], now: number): GanttRow {\n const parked = runs.filter((r) => r.phase === 'parked' || r.hold !== null);\n const releases = parked.map((r) => (r.hold?.nextEligibleAt ? Date.parse(r.hold.nextEligibleAt) : NaN)).filter(Number.isFinite);\n const starts = parked.map((r) => startOf(r) ?? now);\n const from = Math.min(now - 60 * 60_000, ...starts);\n const to = Math.min(now + 48 * 3_600_000, Math.max(now + 2 * 3_600_000, ...releases));\n let unknownRelease = 0;\n const lanes: SwimlaneLane[] = parked.map((r) => {\n const release = r.hold?.nextEligibleAt ? Date.parse(r.hold.nextEligibleAt) : NaN;\n if (!Number.isFinite(release)) unknownRelease++;\n const where = r.repo.includes('/') ? r.repo.split('/')[1] : r.repo;\n return {\n id: r.id,\n label: `${where}: ${r.title}`,\n ...(r.lane ? { engine: LANE_ENGINE[r.lane] } : {}),\n items: [{\n id: r.id,\n start: startOf(r) ?? now,\n end: Number.isFinite(release) ? release : null,\n status: r.hold?.kind === 'split' ? 'split' : 'parked',\n outline: true,\n detail: `${localTimes(r.hold?.reason ?? 'parked', now)}${Number.isFinite(release) ? '' : ' · release time unknown'}`,\n }],\n };\n });\n return { lanes, from, to, unknownRelease };\n}\n\n// ---------------------------------------------------------------------------\n// Gate funnel + refusal reasons\n// ---------------------------------------------------------------------------\n\n/** Gate names in operator words (the funnel's stage labels). */\nexport const GATE_LABEL: Readonly<Record<string, string>> = {\n G0: 'Authority',\n G1: 'Protected paths',\n G1b: 'Tamper',\n G2: 'Scope',\n G3: 'Verify',\n G4: 'Claims',\n G5: 'Blast radius',\n G6: 'Judge',\n G7: 'GitHub checks',\n};\n\n/** Entered G0, then how many passed each gate — a strictly narrowing pipeline. */\nexport function funnelStages(funnel: FleetGateFunnel | null): FunnelStage[] {\n if (!funnel || funnel.stages.length === 0) return [];\n return [\n { id: 'entered', label: 'Proposals', value: funnel.stages[0]!.entered },\n ...funnel.stages.map((s) => ({ id: s.gate, label: `${s.gate} ${GATE_LABEL[s.gate] ?? ''}`.trim(), value: s.passed })),\n ];\n}\n\nexport interface RefusalStack {\n categories: string[];\n segments: BarStackSegment[];\n values: (number | null)[][];\n total: number;\n}\n\n/**\n * Refusals per gate, stacked by reason. The top five reasons (by count over\n * the window) keep FIXED identity slots — a reason's colour never changes\n * when another is filtered out — and the rest fold into a neutral \"Other\".\n */\nexport function refusalStack(funnel: FleetGateFunnel | null, topN = 5): RefusalStack {\n if (!funnel) return { categories: [], segments: [], values: [], total: 0 };\n const totals = new Map<string, { reason: string; count: number }>();\n for (const s of funnel.stages) for (const r of s.refusals) {\n const prev = totals.get(r.code);\n totals.set(r.code, { reason: prev?.reason ?? r.reason, count: (prev?.count ?? 0) + r.count });\n }\n const ranked = [...totals.entries()].sort((a, b) => b[1].count - a[1].count || a[0].localeCompare(b[0]));\n const top = ranked.slice(0, topN).map(([code]) => code);\n const hasOther = ranked.length > topN;\n const segments: BarStackSegment[] = [\n ...top.map((code, i) => ({ id: code, label: totals.get(code)!.reason, color: seriesColor(i) })),\n ...(hasOther ? [{ id: '__other', label: 'Other reasons', color: CHART_NEUTRAL }] : []),\n ];\n const stages = funnel.stages.filter((s) => s.refusals.length > 0 || s.entered !== s.passed);\n return {\n categories: stages.map((s) => s.gate),\n segments,\n values: stages.map((s) => {\n const row = top.map((code) => s.refusals.find((r) => r.code === code)?.count ?? 0);\n if (hasOther) row.push(s.refusals.filter((r) => !top.includes(r.code)).reduce((n, r) => n + r.count, 0));\n return row;\n }),\n total: ranked.reduce((n, [, v]) => n + v.count, 0),\n };\n}\n\n/** The newest seat decision behind a live dispatch (\"why this seat\"). */\nexport function latestDecision(fleet: FleetLiveSnapshotV1 | null): { decision: SeatDecision; run: FleetLiveRun } | null {\n if (!fleet) return null;\n const withDecision = fleet.runs.filter((r) => r.seatDecision !== null);\n if (!withDecision.length) return null;\n withDecision.sort((a, b) => (startOf(b) ?? 0) - (startOf(a) ?? 0));\n const run = withDecision[0]!;\n return { decision: run.seatDecision!, run };\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ function e(e){return e===null?`unknown`:e.includes(`tools`)?`supported`:`unsupported`}function t(t,n){return t===null?n!==null&&n.length===0?`unknown`:e(n):t?`supported`:`unsupported`}function n(e,n){let r=e.expiresAt?Date.parse(e.expiresAt):NaN,i=e.gpuPercent??(e.sizeBytes!==null&&e.sizeBytes>0&&e.sizeVramBytes!==null?Math.max(0,Math.min(100,e.sizeVramBytes/e.sizeBytes*100)):null);return{name:e.name,runtime:e.runtime,resident:e.loaded,placement:e.placement,memoryPct:e.loaded?e.memoryPercent:null,family:e.family,sizeBytes:e.sizeBytes,sizeVramBytes:e.sizeVramBytes,gpuPct:i,expiresInMs:e.loaded&&!Number.isNaN(r)?r-n:null,expiresAtMs:e.loaded&&!Number.isNaN(r)?r:null,parameterSize:e.parameterSize,quantization:e.quantization,nativeContext:e.nativeContext,configuredContext:e.configuredContext,contextTruncated:e.nativeContext!==null&&e.configuredContext!==null&&e.configuredContext<e.nativeContext,tools:t(e.supportsTools,e.capabilities)}}function r(e){let t=e.filter(e=>e.stale);if(t.length===0)return{stale:!1,staleForMs:null,runtimes:[]};let n=t.map(e=>e.staleForMs).filter(e=>e!==null);return{stale:!0,staleForMs:n.length===0?null:Math.max(...n),runtimes:t.map(e=>e.runtime)}}function i(e){if(e===null||!Number.isFinite(e)||e<0)return`an unreported interval`;let t=Math.round(e/1e3);if(t<60)return`${t}s`;let n=Math.floor(t/60),r=t%60;return r===0?`${n}m`:`${n}m ${r}s`}function a(e,t=Date.now()){if(!e)return null;let r=e.models.map(e=>n(e,t)).sort((e,t)=>Number(t.resident)-Number(e.resident)||e.name.localeCompare(t.name)),i=r.filter(e=>e.resident),a=i.some(e=>e.sizeBytes===null)?null:i.reduce((e,t)=>e+(t.sizeBytes??0),0),o=e.memoryBudgetBytes;return{reachable:e.reachable,reason:e.reason,rows:r,residentBytes:a,memoryBudgetBytes:o,memoryUsedPct:a!==null&&o!==null&&o>0?Math.max(0,Math.min(100,a/o*100)):null,freeMemoryBytes:e.freeMemoryBytes,runtimes:e.runtimes,notes:e.notes,agenticCount:r.filter(e=>e.tools===`supported`).length,nonAgenticCount:r.filter(e=>e.tools===`unsupported`).length,unknownToolCount:r.filter(e=>e.tools===`unknown`).length}}function o(e){if(e===null||!Number.isFinite(e))return`—`;let t=e/1024**3;if(t>=10)return`${t.toFixed(0)} GB`;if(t>=1)return`${t.toFixed(1)} GB`;let n=e/1024**2;return`${Math.round(n)} MB`}function s(e){if(e===null||!Number.isFinite(e))return`—`;if(e<=0)return`expired`;let t=Math.floor(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60;return n>0?`${n}h ${r}m`:r>0?`${r}m ${i}s`:`${i}s`}function c(e){return e===null||!Number.isFinite(e)?`—`:e>=1024?`${Math.round(e/1024)}k`:String(e)}export{s as a,c as i,i as n,r as o,o as r,a as t};
2
+ //# sourceMappingURL=local-model-DFyjKX0b.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-model-DFyjKX0b.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/usage/local-model.ts"],"sourcesContent":["/**\n * routes/verse/usage/local-model.ts — local availability, projected for\n * display.\n *\n * \"Can I run this locally right now\" is a different question from \"is it\n * installed\", and the answer has four independent parts the old surface threw\n * away (docs/VERSE-TELEMETRY-V2.md, \"Local models\"):\n *\n * - RESIDENT vs INSTALLED — `/api/ps` vs `/api/tags`. Only a resident model\n * answers without a load delay.\n * - GPU/CPU SPLIT — `size_vram` against `size`. A model that spilled to CPU\n * is usable but slow, and that is a fact the operator should see, not\n * discover mid-turn.\n * - KEEP-ALIVE — `expires_at` is when residency ends. Rendered as a\n * countdown because it genuinely is one (unlike Claude's reset prose,\n * which is not a timestamp and must stay verbatim).\n * - TOOLS — a model whose `capabilities` lack `tools` CANNOT drive an\n * agentic session at all. That is a hard gate, so it is stated up front\n * rather than failing at turn time. `capabilities: null` means the list\n * was not reported, which is NOT the same as \"no tool support\" and is\n * rendered as unknown.\n *\n * Pure: no React, no I/O.\n */\nimport type { LocalModel, LocalModelsSnapshot, LocalRuntimeStatus } from './usage-contract.js';\n\nexport type ToolSupport = 'supported' | 'unsupported' | 'unknown';\n\nexport interface LocalModelRow {\n name: string;\n /** Which runtime reported it, so a flattened list stays attributable. */\n runtime: LocalModel['runtime'];\n resident: boolean;\n /**\n * Where the weights sit. `split` is the one that changes the answer: a model\n * that only half-fits the GPU is usable but slow, and an operator should see\n * that before picking the seat rather than discovering it mid-turn.\n */\n placement: LocalModel['placement'];\n /** Resident size against total machine memory (0–100), or null. */\n memoryPct: number | null;\n family: string | null;\n sizeBytes: number | null;\n sizeVramBytes: number | null;\n /** Share of resident bytes held in VRAM (0–100), or null when unreported. */\n gpuPct: number | null;\n /** ms until keep-alive expiry AT BUILD TIME; null when not resident or not reported. */\n expiresInMs: number | null;\n /**\n * Epoch ms of the keep-alive expiry — the durable fact. A rendered countdown\n * must derive from THIS against a live clock; `expiresInMs` is frozen into\n * the view model and would print the same number forever.\n */\n expiresAtMs: number | null;\n parameterSize: string | null;\n quantization: string | null;\n nativeContext: number | null;\n configuredContext: number | null;\n /** True when Ashlr runs this model at less than its native context. */\n contextTruncated: boolean;\n tools: ToolSupport;\n}\n\nexport function toolSupport(capabilities: string[] | null): ToolSupport {\n if (capabilities === null) return 'unknown';\n return capabilities.includes('tools') ? 'supported' : 'unsupported';\n}\n\n/**\n * The runtime's own `supportsTools` is AUTHORITATIVE and outranks the\n * capability array.\n *\n * The server sends `capabilities: []` when a runtime reported no capability\n * list at all, and reading that array alone renders \"no tools\" — a hard gate\n * that would wrongly tell the operator a model cannot drive an agentic\n * session. `supportsTools: null` is the honest \"the runtime did not say\".\n */\nexport function resolveToolSupport(\n supportsTools: boolean | null,\n capabilities: string[] | null,\n): ToolSupport {\n if (supportsTools !== null) return supportsTools ? 'supported' : 'unsupported';\n if (capabilities !== null && capabilities.length === 0) return 'unknown';\n return toolSupport(capabilities);\n}\n\nexport function buildLocalModelRow(model: LocalModel, now: number): LocalModelRow {\n const expiresMs = model.expiresAt ? Date.parse(model.expiresAt) : Number.NaN;\n // The runtime's own `gpuPercent` is authoritative — it knows how the layers\n // were actually placed. Recomputing from size/size_vram is the fallback for\n // a server that predates the field, never an override of it.\n const gpuPct =\n model.gpuPercent ??\n (model.sizeBytes !== null && model.sizeBytes > 0 && model.sizeVramBytes !== null\n ? Math.max(0, Math.min(100, (model.sizeVramBytes / model.sizeBytes) * 100))\n : null);\n\n return {\n name: model.name,\n runtime: model.runtime,\n resident: model.loaded,\n placement: model.placement,\n // Only a RESIDENT model occupies memory. `sizeBytes` for an unloaded model\n // is the on-disk size, so a machine-memory share computed from it would\n // report memory that is not in use.\n memoryPct: model.loaded ? model.memoryPercent : null,\n family: model.family,\n sizeBytes: model.sizeBytes,\n sizeVramBytes: model.sizeVramBytes,\n gpuPct,\n expiresInMs: model.loaded && !Number.isNaN(expiresMs) ? expiresMs - now : null,\n expiresAtMs: model.loaded && !Number.isNaN(expiresMs) ? expiresMs : null,\n parameterSize: model.parameterSize,\n quantization: model.quantization,\n nativeContext: model.nativeContext,\n configuredContext: model.configuredContext,\n contextTruncated:\n model.nativeContext !== null &&\n model.configuredContext !== null &&\n model.configuredContext < model.nativeContext,\n tools: resolveToolSupport(model.supportsTools, model.capabilities),\n };\n}\n\nexport interface LocalModelsView {\n reachable: boolean;\n reason: string | null;\n /** Resident first (they are the answer to \"right now\"), then by name. */\n rows: LocalModelRow[];\n residentBytes: number | null;\n memoryBudgetBytes: number | null;\n memoryUsedPct: number | null;\n /** The machine's own reported free memory, or null. */\n freeMemoryBytes: number | null;\n /** Per-runtime reachability and staleness, for the panel's banner. */\n runtimes: LocalRuntimeStatus[];\n /** The server's plain-language caveats for this snapshot. */\n notes: string[];\n /** Models that CAN drive an agentic session. */\n agenticCount: number;\n /** Models that explicitly cannot. Separate from `unknownToolCount`. */\n nonAgenticCount: number;\n /** Models whose runtime did not say — never counted as \"cannot\". */\n unknownToolCount: number;\n}\n\n/**\n * The staleness verdict for the whole local reading.\n *\n * A retained known-good report is the right server-side choice (a timeout is\n * \"no answer yet\", not \"the runtime is gone\"), but it obliges this surface to\n * say the numbers are N seconds old rather than presenting them as fresh.\n * The oldest retained report wins, because a panel is only as fresh as its\n * stalest input.\n */\nexport interface LocalStaleness {\n stale: boolean;\n /** Age of the OLDEST retained reading, in ms. Null when nothing is stale. */\n staleForMs: number | null;\n /** Which runtimes were served from a retained reading. */\n runtimes: LocalRuntimeStatus['runtime'][];\n}\n\nexport function localStaleness(runtimes: readonly LocalRuntimeStatus[]): LocalStaleness {\n const stale = runtimes.filter((r) => r.stale);\n if (stale.length === 0) return { stale: false, staleForMs: null, runtimes: [] };\n const ages = stale.map((r) => r.staleForMs).filter((ms): ms is number => ms !== null);\n return {\n stale: true,\n // A retained report with no reported age is still stale; the age is simply\n // unknown, and null says that rather than implying \"0ms old\".\n staleForMs: ages.length === 0 ? null : Math.max(...ages),\n runtimes: stale.map((r) => r.runtime),\n };\n}\n\n/** \"12s\" / \"4m 30s\" — how old a retained reading is, for a plain sentence. */\nexport function formatAge(ms: number | null): string {\n if (ms === null || !Number.isFinite(ms) || ms < 0) return 'an unreported interval';\n const total = Math.round(ms / 1000);\n if (total < 60) return `${total}s`;\n const m = Math.floor(total / 60);\n const s = total % 60;\n return s === 0 ? `${m}m` : `${m}m ${s}s`;\n}\n\nexport function buildLocalModelsView(\n snapshot: LocalModelsSnapshot | null,\n now: number = Date.now(),\n): LocalModelsView | null {\n if (!snapshot) return null;\n const rows = snapshot.models\n .map((m) => buildLocalModelRow(m, now))\n .sort((a, b) => Number(b.resident) - Number(a.resident) || a.name.localeCompare(b.name));\n\n const resident = rows.filter((r) => r.resident);\n // A resident model with no reported size makes the TOTAL unknown — summing\n // the rest would understate it, and understating a memory figure is exactly\n // the kind of quiet lie this surface refuses.\n const residentBytes = resident.some((r) => r.sizeBytes === null)\n ? null\n : resident.reduce((acc, r) => acc + (r.sizeBytes ?? 0), 0);\n\n const budget = snapshot.memoryBudgetBytes;\n return {\n reachable: snapshot.reachable,\n reason: snapshot.reason,\n rows,\n residentBytes,\n memoryBudgetBytes: budget,\n memoryUsedPct:\n residentBytes !== null && budget !== null && budget > 0\n ? Math.max(0, Math.min(100, (residentBytes / budget) * 100))\n : null,\n freeMemoryBytes: snapshot.freeMemoryBytes,\n runtimes: snapshot.runtimes,\n notes: snapshot.notes,\n // Three counts, not two: \"cannot drive a session\" and \"the runtime did not\n // say\" are different facts, and folding the second into the first would\n // turn an unanswered question into a hard gate.\n agenticCount: rows.filter((r) => r.tools === 'supported').length,\n nonAgenticCount: rows.filter((r) => r.tools === 'unsupported').length,\n unknownToolCount: rows.filter((r) => r.tools === 'unknown').length,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Formatting helpers local to this panel (chartFormat owns counts/currency;\n// bytes and countdowns are not in its vocabulary).\n// ---------------------------------------------------------------------------\n\n/** Binary-ish GB, matching how Ollama and Activity Monitor talk about models. */\nexport function formatBytes(bytes: number | null): string {\n if (bytes === null || !Number.isFinite(bytes)) return '—';\n const gb = bytes / 1024 ** 3;\n if (gb >= 10) return `${gb.toFixed(0)} GB`;\n if (gb >= 1) return `${gb.toFixed(1)} GB`;\n const mb = bytes / 1024 ** 2;\n return `${Math.round(mb)} MB`;\n}\n\n/** \"expires in 4m 12s\" material. Past-due reads as expired, never negative. */\nexport function formatCountdown(ms: number | null): string {\n if (ms === null || !Number.isFinite(ms)) return '—';\n if (ms <= 0) return 'expired';\n const total = Math.floor(ms / 1000);\n const h = Math.floor(total / 3600);\n const m = Math.floor((total % 3600) / 60);\n const s = total % 60;\n if (h > 0) return `${h}h ${m}m`;\n if (m > 0) return `${m}m ${s}s`;\n return `${s}s`;\n}\n\n/**\n * Context windows are powers of two and are quoted that way everywhere the\n * user will have seen them (262144 is \"256k\", not \"262k\"), so the divisor is\n * 1024 rather than 1000. Getting this wrong makes the UI disagree with the\n * model card the operator read five minutes ago.\n */\nexport function formatContext(tokens: number | null): string {\n if (tokens === null || !Number.isFinite(tokens)) return '—';\n if (tokens >= 1024) return `${Math.round(tokens / 1024)}k`;\n return String(tokens);\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ ._stack_1bdwr_5{gap:var(--surface-gap);flex-direction:column;display:flex}._muted_1bdwr_11{color:var(--text-tertiary);font-size:var(--text-xs-size);margin:0}._link_1bdwr_17{color:var(--text-link);font:inherit;font-size:var(--text-xs-size);cursor:pointer;background:0 0;border:0;align-self:flex-start;padding:0}._link_1bdwr_17:hover{text-decoration:underline}._link_1bdwr_17:focus-visible,._veto_1bdwr_33:focus-visible,._chip_1bdwr_34:focus-visible{outline:2px solid var(--border-focus);outline-offset:2px}._timeline_1bdwr_40{flex-direction:column;margin:0;padding:0;list-style:none;display:flex}._memo_1bdwr_48{gap:var(--space-3);padding:var(--space-3) 0;border-top:1px solid var(--border-subtle);grid-template-columns:88px 20px minmax(0,1fr) auto;align-items:start;display:grid}._memo_1bdwr_48:first-child{border-top:0;padding-top:0}._memoDay_1bdwr_62{color:var(--text-tertiary);font-size:var(--text-xs-size);line-height:var(--text-sm-line);font-variant-numeric:tabular-nums}._mark_1bdwr_69{border-radius:var(--radius-full);background:var(--status-neutral-bg);width:20px;height:20px;color:var(--status-neutral-fg);font-size:var(--text-xs-size);font-weight:var(--font-weight-semibold);justify-content:center;align-items:center;display:inline-flex}._mark_1bdwr_69[data-outcome=hit]{background:var(--status-success-bg);color:var(--status-success-fg)}._mark_1bdwr_69[data-outcome=miss]{background:var(--status-danger-bg);color:var(--status-danger-fg)}._memoBody_1bdwr_92{flex-direction:column;gap:2px;min-width:0;display:flex}._memoMove_1bdwr_99{color:var(--text-primary);font-size:var(--text-sm-size);line-height:var(--text-sm-line);overflow-wrap:anywhere}._memoWhy_1bdwr_106{color:var(--text-secondary);font-size:var(--text-xs-size);line-height:var(--text-xs-line);overflow-wrap:anywhere}._memoMeta_1bdwr_113{color:var(--text-tertiary);font-size:var(--text-xs-size);line-height:var(--text-xs-line)}._memoMeta_1bdwr_113 [data-outcome=hit]{color:var(--status-success-fg)}._memoMeta_1bdwr_113 [data-outcome=miss]{color:var(--status-danger-fg)}._veto_1bdwr_33{min-height:var(--control-h-sm);padding:0 var(--space-3);border:1px solid var(--border-default);border-radius:var(--radius-sm);color:var(--text-primary);font:inherit;font-size:var(--text-xs-size);cursor:pointer;background:0 0}._veto_1bdwr_33:hover{background:var(--bg-hover)}._veto_1bdwr_33:disabled{color:var(--text-disabled);cursor:default}[data-viewport=compact] ._memo_1bdwr_48{grid-template-columns:20px minmax(0,1fr) auto}[data-viewport=compact] ._memoDay_1bdwr_62{grid-column:1/-1}._standards_1bdwr_157{gap:var(--space-3);flex-direction:column;margin:0;padding:0;list-style:none;display:flex}._standards_1bdwr_157 li{flex-direction:column;gap:2px;display:flex}._standardRule_1bdwr_172{color:var(--text-primary);font-size:var(--text-sm-size);line-height:var(--text-sm-line-relaxed)}._standardMeta_1bdwr_178{color:var(--text-tertiary);font-size:var(--text-xs-size)}._insights_1bdwr_184{gap:var(--surface-gap);grid-template-columns:repeat(3,minmax(0,1fr));margin:0;padding:0;list-style:none;display:grid}[data-viewport=compact] ._insights_1bdwr_184,[data-viewport=medium] ._insights_1bdwr_184{grid-template-columns:minmax(0,1fr)}._insight_1bdwr_184{gap:var(--space-2);padding:var(--card-pad);border:1px solid var(--border-subtle);border-radius:var(--radius-lg);background:var(--bg-surface);box-shadow:inset 0 1px 0 var(--hairline-lift,transparent);flex-direction:column;display:flex}._insight_1bdwr_184[data-severity=high]{border-color:var(--status-danger-solid)}._insightKind_1bdwr_213{justify-content:space-between;align-items:center;gap:var(--space-2);display:flex}._insightSeverity_1bdwr_220{color:var(--text-tertiary);font-size:var(--text-xs-size)}._insightSeverity_1bdwr_220[data-severity=high]{color:var(--status-danger-fg)}._insightSeverity_1bdwr_220[data-severity=warn]{color:var(--status-warning-fg)}._insightTitle_1bdwr_233{color:var(--text-primary);font-size:var(--text-sm-size);line-height:var(--text-sm-line-relaxed);overflow-wrap:anywhere}._insightMeta_1bdwr_240{color:var(--text-tertiary);font-size:var(--text-xs-size);line-height:var(--text-xs-line)}._insightPlace_1bdwr_248{color:var(--text-secondary);overflow-wrap:anywhere}._scratchTag_1bdwr_254{margin-left:var(--space-1);padding:0 var(--space-1);border:1px solid var(--border-subtle);border-radius:var(--radius-sm);color:var(--text-tertiary);font-size:var(--text-2xs-size);line-height:var(--text-2xs-line);vertical-align:1px;display:inline-block}._log_1bdwr_266{flex-direction:column;margin:0;padding:0;list-style:none;display:flex}._facet_1bdwr_274{align-items:center;gap:var(--space-2);color:var(--text-tertiary);font-size:var(--text-xs-size);display:inline-flex}._facet_1bdwr_274 select{min-height:var(--control-h-xs);padding:0 var(--space-2);border:1px solid var(--border-default);border-radius:var(--radius-sm);background:var(--bg-input);color:var(--text-primary);font:inherit;font-size:var(--text-xs-size)}._chipWrap_1bdwr_294{display:inline-flex;position:relative}._chip_1bdwr_34{align-items:center;gap:var(--space-1);min-height:var(--control-h-xs);padding:0 var(--space-2);border:1px solid var(--border-default);border-radius:var(--radius-full);background:var(--bg-surface);color:var(--text-secondary);font:inherit;font-size:var(--text-xs-size);white-space:nowrap;cursor:pointer;display:inline-flex}._chip_1bdwr_34:hover,._chip_1bdwr_34[aria-expanded=true]{background:var(--bg-hover);color:var(--text-primary)}._chipDot_1bdwr_321{border-radius:var(--radius-full);background:var(--status-warning-solid);width:6px;height:6px}._chipDot_1bdwr_321[data-severity=high]{background:var(--status-danger-solid)}._chipMore_1bdwr_332{color:var(--text-tertiary)}._chipPanel_1bdwr_336{top:calc(100% + var(--space-1));z-index:var(--z-dropdown);gap:var(--space-3);width:min(320px, calc(100vw - var(--space-8)));padding:var(--space-3);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}._chipList_1bdwr_352{gap:var(--space-2);flex-direction:column;margin:0;padding:0;list-style:none;display:flex}._chipList_1bdwr_352 li{flex-direction:column;gap:2px;display:flex}
@@ -0,0 +1,2 @@
1
+ import{v as e}from"./colors-BZ3a9wFf.js";import{a as t}from"./workspace-model-D_tWD5Wt.js";import{t as n}from"./calendar-day-BxBYHfX1.js";function r(e){let t=e.trim().replace(/\\/g,`/`).replace(/\/+$/,``);return t=t.replace(/^\/private(?=\/(?:tmp|var)(?:\/|$))/,``),t=t.replace(/^(?:\/Users\/[^/]+|\/home\/[^/]+|[A-Za-z]:\/Users\/[^/]+)(?=\/|$)/,`~`),t||`/`}var i=[/^\/tmp(?:\/|$)/,/^\/var\/tmp(?:\/|$)/,/^\/var\/folders\/[^/]+\/[^/]+\/T(?:\/|$)/,/^[A-Za-z]:\/Windows\/Temp(?:\/|$)/i,/\/AppData\/Local\/Temp(?:\/|$)/i];function a(e){let t=r(e);return i.some(e=>e.test(t))}function o(e,t){let n=new Map,i=(e,t)=>{let i=r(e),a=t.trim();i!==`/`&&i!==`~`&&a&&!n.has(i)&&n.set(i,a)};for(let t of e??[])for(let e of t.roots)i(e.path,t.name);for(let e of t??[])i(e.path,e.name);return n}function s(e,t){let n=r(e),i=t.get(n);if(i!==void 0)return i;let a=null;for(let[e,r]of t)n.startsWith(`${e}/`)&&(!a||e.length>a.root.length)&&(a={root:e,name:r});return a?.name??null}function c(e,n=new Map){return{label:s(e,n)??t(e),full:e,scratch:a(e)}}var l=e=>e.length>14?`${e.slice(0,13)}…`:e;function u(e,t){let n=new Map(e.map(e=>[e,e.split(`/`).filter(Boolean).reverse()])),r=new Map;for(let i of e){let a=n.get(i),o=null,s=null;for(let r=0;r<a.length&&s===null;r++){let c=a[r];c!==t&&c!==`~`&&(o??=c,e.every(e=>e===i||n.get(e)[r]!==c)&&(s=c))}r.set(i,s??o)}return r}function d(e,t=new Map){let n=new Map;for(let t of[...new Set(e)].sort()){let e=r(t);n.set(e,[...n.get(e)??[],t])}let i=new Map;for(let[e,r]of n){let n=c(r[0],t).label;i.set(n,[...i.get(n)??[],e])}let o=new Map,s=new Map;for(let[e,t]of i){let n=t.length>1?u(t,e):null;for(let r of t){let t=n?.get(r)??null;o.set(r,t?`${e} (${l(t)})`:e),t&&l(t)!==t&&s.set(r,`${e} (${t})`)}}let d=new Map;for(let e of o.values())d.set(e,(d.get(e)??0)+1);let f=new Set,p=new Map;for(let e of[...o.keys()].sort()){let t=o.get(e),n=d.get(t)>1?s.get(e)??t:t,r=n;for(let e=2;f.has(r);e++)r=`${n} #${e}`;f.add(r),p.set(e,r)}let m=new Map;for(let[e,t]of n)for(let n of t)m.set(n,{label:p.get(e),full:n,scratch:a(n)});return m}var f=[`loop`,`struggle`,`verification-gap`,`uncertainty`,`backtrack`,`win`],p={loop:`Loops`,struggle:`Repeated failures`,"verification-gap":`Edits without tests`,uncertainty:`Uncertainty`,backtrack:`Backtracking`,win:`Wins`},m={claude:`Claude`,codex:`Codex`,grok:`Grok`,local:`Local`},h=[`claude`,`codex`,`grok`,`local`];function g(e){return h.includes(e)?e:null}function _(e){if(!e)return[];let t=new Map;for(let n of e.insights){if(!n.repo)continue;let e=r(n.repo),i=t.get(e)??{total:0,spellings:new Map};i.total+=n.count,i.spellings.set(n.repo,(i.spellings.get(n.repo)??0)+n.count),t.set(e,i)}let n=(e,t)=>t[1]-e[1]||e[0].localeCompare(t[0]);return[...t.values()].map(e=>[[...e.spellings.entries()].sort(n)[0][0],e.total]).sort(n).map(([e])=>e)}function v(e,t){return!!e&&(e===t||r(e)===r(t))}function y(e,t){let n=f.map(e=>({id:e,label:p[e]}));if(!e)return{rows:n,columns:[],values:[]};let r=[...new Set([...Object.keys(e.totals.byEngine),...e.insights.map(e=>e.engine).filter(e=>!!e)])].sort((e,t)=>{let n=h.indexOf(e),r=h.indexOf(t);return(n===-1?99:n)-(r===-1?99:r)||e.localeCompare(t)}),i=r.map(e=>{let t=g(e);return{id:e,label:m[e]??e,...t?{engine:t}:{}}}),a=e.insights.filter(e=>t===null||v(e.repo,t));return{rows:n,columns:i,values:f.map(t=>r.map(n=>{let r=(e.totals.byEngine[n]??0)>0,i=a.filter(e=>e.kind===t&&e.engine===n).reduce((e,t)=>e+t.count,0);return r||i>0?i:null}))}}function b(e,t=3){if(!e)return[];let n={high:0,warn:1,info:2};return e.insights.filter(e=>e.kind!==`win`).sort((e,t)=>n[e.severity]-n[t.severity]||Date.parse(t.lastAt)-Date.parse(e.lastAt)).slice(0,t)}function x(t){if(!t)return[];let r=e=>t.trends.map(t=>({x:n(t.day),y:t.steps===0?null:e(t)}));return[{id:`struggles`,label:`Struggles`,color:e(`warning`),points:r(e=>e.struggles)},{id:`wins`,label:`Wins`,color:e(`success`),points:r(e=>e.wins)}]}var S=new Set([`loop`,`struggle`]);function C(e,t){return e.evidence.some(e=>e.ref.startsWith(`session:${t}#`)||e.ref.startsWith(`verse:${t}:`))}function w(e,t){return!e||!t?[]:e.insights.filter(e=>S.has(e.kind)&&C(e,t)).sort((e,t)=>Date.parse(t.lastAt)-Date.parse(e.lastAt))}var T={stack:`_stack_1bdwr_5`,muted:`_muted_1bdwr_11`,link:`_link_1bdwr_17`,veto:`_veto_1bdwr_33`,chip:`_chip_1bdwr_34`,timeline:`_timeline_1bdwr_40`,memo:`_memo_1bdwr_48`,memoDay:`_memoDay_1bdwr_62`,mark:`_mark_1bdwr_69`,memoBody:`_memoBody_1bdwr_92`,memoMove:`_memoMove_1bdwr_99`,memoWhy:`_memoWhy_1bdwr_106`,memoMeta:`_memoMeta_1bdwr_113`,standards:`_standards_1bdwr_157`,standardRule:`_standardRule_1bdwr_172`,standardMeta:`_standardMeta_1bdwr_178`,insights:`_insights_1bdwr_184`,insight:`_insight_1bdwr_184`,insightKind:`_insightKind_1bdwr_213`,insightSeverity:`_insightSeverity_1bdwr_220`,insightTitle:`_insightTitle_1bdwr_233`,insightMeta:`_insightMeta_1bdwr_240`,insightPlace:`_insightPlace_1bdwr_248`,scratchTag:`_scratchTag_1bdwr_254`,log:`_log_1bdwr_266`,facet:`_facet_1bdwr_274`,chipWrap:`_chipWrap_1bdwr_294`,chipDot:`_chipDot_1bdwr_321`,chipMore:`_chipMore_1bdwr_332`,chipPanel:`_chipPanel_1bdwr_336`,chipList:`_chipList_1bdwr_352`};export{x as a,c,_ as i,d as l,p as n,w as o,y as r,b as s,T as t,o as u};
2
+ //# sourceMappingURL=mind.module-vnuJcwvD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mind.module-vnuJcwvD.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/mind/project-label.ts","../../../../../../src/web-ui/routes/verse/mind/mind-model.ts","../../../../../../src/web-ui/routes/verse/mind/mind.module.css"],"sourcesContent":["/**\n * routes/verse/mind/project-label.ts — how Mind names the place a reasoning\n * insight happened.\n *\n * A7 keys insights by the workspace path the engine ran in, verbatim, so the\n * cards used to read \"/private/tmp/claude-501/-Users-…/9d28bdb1-…/scratchpad/\n * grokpad · grok · 1×\". The card now shows a human label:\n *\n * 1. the REGISTERED name — a saved project (Chat → Projects) whose root is\n * that folder or contains it, else a project Verse knows from bootstrap;\n * 2. otherwise the folder's own name (`grokpad`), the same rule a saved\n * project uses when the operator names nothing (defaultWorkspaceName).\n *\n * The full path is never dropped: it rides in the tooltip. A folder under the\n * OS temp directory (an agent's scratchpad, a test fixture) is tagged\n * `scratch` rather than hidden — the insight is real, the place is throwaway.\n * The browser cannot ask the OS for its temp dir, so the well-known locations\n * are matched instead (macOS /tmp, /private/tmp and the per-user\n * /var/folders/…/T; Linux /tmp and /var/tmp; Windows …\\AppData\\Local\\Temp).\n *\n * Two different folders that would read the same (two agents' `scratchpad`s)\n * get a short distinguisher appended, so the Repo facet never offers two\n * identical choices; two spellings of ONE folder share one label.\n *\n * Framework-free; tested directly.\n */\nimport type { VerseProject, VerseWorkspace } from '../../../data/api-types.js';\nimport { defaultWorkspaceName } from '../workspace-model.js';\n\nexport interface ProjectLabel {\n /** What the card draws: the registered name, else the folder's own name. */\n label: string;\n /** The path (or slug) exactly as recorded — the tooltip. */\n full: string;\n /** Lives under the OS temp directory: a scratch folder, not a project. */\n scratch: boolean;\n}\n\n/** Registered names keyed by `pathKey(root)`. */\nexport type ProjectNames = ReadonlyMap<string, string>;\n\n/**\n * A comparable form of a path: `/` separators, no trailing separator, the\n * macOS `/private` alias folded (`/tmp` and `/var` are symlinks into it, and\n * the same folder is recorded either way), a home directory as `~` (a project\n * saved as `~/dev/hub` still runs in `/Users/me/dev/hub`).\n */\nexport function pathKey(path: string): string {\n let p = path.trim().replace(/\\\\/g, '/').replace(/\\/+$/, '');\n p = p.replace(/^\\/private(?=\\/(?:tmp|var)(?:\\/|$))/, '');\n p = p.replace(/^(?:\\/Users\\/[^/]+|\\/home\\/[^/]+|[A-Za-z]:\\/Users\\/[^/]+)(?=\\/|$)/, '~');\n return p || '/';\n}\n\nconst SCRATCH_ROOTS: readonly RegExp[] = [\n /^\\/tmp(?:\\/|$)/, // also /private/tmp, folded by pathKey\n /^\\/var\\/tmp(?:\\/|$)/,\n /^\\/var\\/folders\\/[^/]+\\/[^/]+\\/T(?:\\/|$)/, // macOS per-user $TMPDIR\n /^[A-Za-z]:\\/Windows\\/Temp(?:\\/|$)/i,\n /\\/AppData\\/Local\\/Temp(?:\\/|$)/i,\n];\n\n/** Is this folder under the OS temp directory? */\nexport function isScratchPath(path: string): boolean {\n const key = pathKey(path);\n return SCRATCH_ROOTS.some((re) => re.test(key));\n}\n\n/**\n * Registered names by root. Saved projects win (the operator named them),\n * then Verse's known projects; every root of a multi-folder project maps to\n * that project's name.\n */\nexport function projectNames(\n workspaces: readonly { name: VerseWorkspace['name']; roots: readonly { path: string }[] }[] | null | undefined,\n projects: readonly Pick<VerseProject, 'name' | 'path'>[] | null | undefined,\n): Map<string, string> {\n const names = new Map<string, string>();\n const add = (path: string, name: string) => {\n const key = pathKey(path);\n const label = name.trim();\n if (key !== '/' && key !== '~' && label && !names.has(key)) names.set(key, label);\n };\n for (const w of workspaces ?? []) for (const r of w.roots) add(r.path, w.name);\n for (const p of projects ?? []) add(p.path, p.name);\n return names;\n}\n\n/** The registered name for `path`: its own root, else the longest registered root containing it. */\nfunction registeredName(path: string, names: ProjectNames): string | null {\n const key = pathKey(path);\n const exact = names.get(key);\n if (exact !== undefined) return exact;\n let best: { root: string; name: string } | null = null;\n for (const [root, name] of names) {\n if (key.startsWith(`${root}/`) && (!best || root.length > best.root.length)) best = { root, name };\n }\n return best?.name ?? null;\n}\n\n/** One insight's place, as the card draws it. */\nexport function projectLabel(repo: string, names: ProjectNames = new Map()): ProjectLabel {\n return { label: registeredName(repo, names) ?? defaultWorkspaceName(repo), full: repo, scratch: isScratchPath(repo) };\n}\n\nconst short = (name: string) => (name.length > 14 ? `${name.slice(0, 13)}…` : name);\n\n/**\n * What tells same-label folders apart, per folder (keyed by `pathKey`):\n * walking up from the folder itself, the NEAREST path segment that no other\n * folder in the group has at that same depth — `grokpad (9d28bdb1-4c1e…)` for\n * two agents' `…/<uuid>/scratchpad/grokpad` (their parents are both\n * `scratchpad`), `Hub (a)` for two folders under one registered project. A\n * segment that only repeats the label (or is the home `~`) says nothing and\n * is skipped. When no single segment is unique, the nearest informative one\n * is returned and `projectLabels` settles whatever still collides.\n */\nfunction distinguishers(keys: readonly string[], label: string): Map<string, string | null> {\n const parts = new Map(keys.map((k) => [k, k.split('/').filter(Boolean).reverse()]));\n const out = new Map<string, string | null>();\n for (const key of keys) {\n const mine = parts.get(key)!;\n let nearest: string | null = null;\n let unique: string | null = null;\n for (let depth = 0; depth < mine.length && unique === null; depth++) {\n const seg = mine[depth]!;\n if (seg === label || seg === '~') continue;\n nearest ??= seg;\n if (keys.every((other) => other === key || parts.get(other)![depth] !== seg)) unique = seg;\n }\n out.set(key, unique ?? nearest);\n }\n return out;\n}\n\n/**\n * Labels for every repo on a surface at once, so the cards and the Repo facet\n * agree — and two different folders NEVER read the same:\n *\n * 1. spellings of one folder (`/tmp/x` and `/private/tmp/x`: one `pathKey`)\n * share one label; each keeps its own `full` path for the tooltip;\n * 2. different folders that would read the same get their nearest\n * distinguishing ancestor appended, shortened (`distinguishers`);\n * 3. whatever still collides — two ancestors that shorten alike, a folder\n * with nothing left to tell it apart — is settled by construction: the\n * whole segment instead of the shortened one, then an ordinal (\"#2\").\n */\nexport function projectLabels(repos: readonly string[], names: ProjectNames = new Map()): Map<string, ProjectLabel> {\n // One entry per folder, in a stable order: the labels never depend on the\n // order the insights arrived in.\n const spellings = new Map<string, string[]>();\n for (const repo of [...new Set(repos)].sort()) {\n const key = pathKey(repo);\n spellings.set(key, [...(spellings.get(key) ?? []), repo]);\n }\n const byLabel = new Map<string, string[]>();\n for (const [key, list] of spellings) {\n const label = projectLabel(list[0]!, names).label;\n byLabel.set(label, [...(byLabel.get(label) ?? []), key]);\n }\n\n const wanted = new Map<string, string>();\n const whole = new Map<string, string>();\n for (const [label, keys] of byLabel) {\n const extra = keys.length > 1 ? distinguishers(keys, label) : null;\n for (const key of keys) {\n const seg = extra?.get(key) ?? null;\n wanted.set(key, seg ? `${label} (${short(seg)})` : label);\n if (seg && short(seg) !== seg) whole.set(key, `${label} (${seg})`);\n }\n }\n\n const shared = new Map<string, number>();\n for (const l of wanted.values()) shared.set(l, (shared.get(l) ?? 0) + 1);\n const taken = new Set<string>();\n const labelOf = new Map<string, string>();\n for (const key of [...wanted.keys()].sort()) {\n const first = wanted.get(key)!;\n const pick = shared.get(first)! > 1 ? (whole.get(key) ?? first) : first;\n let label = pick;\n for (let n = 2; taken.has(label); n++) label = `${pick} #${n}`;\n taken.add(label);\n labelOf.set(key, label);\n }\n\n const out = new Map<string, ProjectLabel>();\n for (const [key, list] of spellings) {\n for (const repo of list) out.set(repo, { label: labelOf.get(key)!, full: repo, scratch: isScratchPath(repo) });\n }\n return out;\n}\n","/**\n * routes/verse/mind/mind-model.ts — the reasoning digest (A7) as Mind's\n * charts and cards, plus the chat-header chip's matching rule (unit C7;\n * SPEC-310B §6 Mind, SPEC-310C §5).\n *\n * The matrix is insight KIND × ENGINE, faceted by repo. A cell is:\n * - a count of insight occurrences when that engine produced reasoning in\n * the window (0 is a real zero: it reasoned and nothing was flagged);\n * - UNKNOWN (null) when that engine recorded no reasoning at all — nothing\n * was measured, so nothing can be said (hatched, never a pale zero).\n *\n * Framework-free; tested directly.\n */\nimport type { ReasoningDigest, ReasoningInsight, ReasoningInsightKind } from '../../../../core/reasoning/types.js';\nimport type { ChartEngine } from '../../../components/charts/colors.js';\nimport type { MatrixAxisItem } from '../../../components/charts/MatrixHeatmap.js';\nimport type { AreaTrendSeries } from '../../../components/charts/AreaTrend.js';\nimport { toneColor } from '../../../components/charts/colors.js';\nimport { calendarDayStart } from '../growth/calendar-day.js';\nimport { pathKey } from './project-label.js';\n\nexport const INSIGHT_KINDS: readonly ReasoningInsightKind[] = ['loop', 'struggle', 'verification-gap', 'uncertainty', 'backtrack', 'win'];\n\nexport const KIND_LABEL: Readonly<Record<ReasoningInsightKind, string>> = {\n loop: 'Loops',\n struggle: 'Repeated failures',\n 'verification-gap': 'Edits without tests',\n uncertainty: 'Uncertainty',\n backtrack: 'Backtracking',\n win: 'Wins',\n};\n\nconst ENGINE_LABEL: Readonly<Record<string, string>> = { claude: 'Claude', codex: 'Codex', grok: 'Grok', local: 'Local' };\nconst KNOWN_ENGINES: readonly ChartEngine[] = ['claude', 'codex', 'grok', 'local'];\n\nfunction asEngine(name: string): ChartEngine | null {\n return (KNOWN_ENGINES as readonly string[]).includes(name) ? (name as ChartEngine) : null;\n}\n\n/**\n * Repos that appear in the digest's insights, most insight occurrences first\n * — ONE per folder: two spellings of the same folder (`/tmp/x` and\n * `/private/tmp/x`, which `pathKey` treats as one) are one Repo facet entry,\n * named by the spelling recorded most often.\n */\nexport function insightRepos(digest: ReasoningDigest | null): string[] {\n if (!digest) return [];\n const folders = new Map<string, { total: number; spellings: Map<string, number> }>();\n for (const i of digest.insights) {\n if (!i.repo) continue;\n const key = pathKey(i.repo);\n const f = folders.get(key) ?? { total: 0, spellings: new Map<string, number>() };\n f.total += i.count;\n f.spellings.set(i.repo, (f.spellings.get(i.repo) ?? 0) + i.count);\n folders.set(key, f);\n }\n const byCount = (a: [string, number], b: [string, number]) => b[1] - a[1] || a[0].localeCompare(b[0]);\n return [...folders.values()]\n .map((f) => [[...f.spellings.entries()].sort(byCount)[0]![0], f.total] as [string, number])\n .sort(byCount)\n .map(([r]) => r);\n}\n\n/** Does insight `repo` name the same folder as facet `facet` (any spelling)? */\nfunction sameFolder(repo: string | null | undefined, facet: string): boolean {\n return !!repo && (repo === facet || pathKey(repo) === pathKey(facet));\n}\n\nexport interface InsightMatrix {\n rows: MatrixAxisItem[];\n columns: MatrixAxisItem[];\n values: (number | null)[][];\n}\n\n/** `repo` null = every repo. */\nexport function insightMatrix(digest: ReasoningDigest | null, repo: string | null): InsightMatrix {\n const rows = INSIGHT_KINDS.map((k) => ({ id: k, label: KIND_LABEL[k] }));\n if (!digest) return { rows, columns: [], values: [] };\n // Columns: every engine that reasoned in the window, plus any engine an\n // insight names (so a count is never dropped), known engines first.\n const names = new Set<string>([...Object.keys(digest.totals.byEngine), ...digest.insights.map((i) => i.engine).filter((e): e is string => !!e)]);\n const ordered = [...names].sort((a, b) => {\n const ia = KNOWN_ENGINES.indexOf(a as ChartEngine);\n const ib = KNOWN_ENGINES.indexOf(b as ChartEngine);\n return (ia === -1 ? 99 : ia) - (ib === -1 ? 99 : ib) || a.localeCompare(b);\n });\n const columns: MatrixAxisItem[] = ordered.map((name) => {\n const engine = asEngine(name);\n return { id: name, label: ENGINE_LABEL[name] ?? name, ...(engine ? { engine } : {}) };\n });\n const insights = digest.insights.filter((i) => repo === null || sameFolder(i.repo, repo));\n const values = INSIGHT_KINDS.map((kind) =>\n ordered.map((engine) => {\n const measured = (digest.totals.byEngine[engine] ?? 0) > 0;\n const count = insights.filter((i) => i.kind === kind && i.engine === engine).reduce((n, i) => n + i.count, 0);\n return measured || count > 0 ? count : null;\n }),\n );\n return { rows, columns, values };\n}\n\n/** The three cards: most severe first, then most recent — wins are not problems. */\nexport function topInsights(digest: ReasoningDigest | null, n = 3): ReasoningInsight[] {\n if (!digest) return [];\n const rank = { high: 0, warn: 1, info: 2 } as const;\n return digest.insights\n .filter((i) => i.kind !== 'win')\n .sort((a, b) => rank[a.severity] - rank[b.severity] || Date.parse(b.lastAt) - Date.parse(a.lastAt))\n .slice(0, n);\n}\n\n/**\n * Struggles vs wins per day, for the trends card. Each day is stamped at the\n * viewer's LOCAL midnight (`calendarDayStart`), because the chart labels its\n * x values in the local zone: a UTC-midnight stamp read one day early west of\n * UTC (\"2026-09-24\" as \"Sep 23\").\n */\nexport function reasoningTrendSeries(digest: ReasoningDigest | null): AreaTrendSeries[] {\n if (!digest) return [];\n const pts = (pick: (d: ReasoningDigest['trends'][number]) => number) =>\n digest.trends.map((d) => ({ x: calendarDayStart(d.day), y: d.steps === 0 ? null : pick(d) }));\n return [\n { id: 'struggles', label: 'Struggles', color: toneColor('warning'), points: pts((d) => d.struggles) },\n { id: 'wins', label: 'Wins', color: toneColor('success'), points: pts((d) => d.wins) },\n ];\n}\n\n// ---------------------------------------------------------------------------\n// SessionInsightChip\n// ---------------------------------------------------------------------------\n\n/** The chip shows only the insight kinds that mean \"this chat is stuck\". */\nexport const CHIP_KINDS: ReadonlySet<ReasoningInsightKind> = new Set(['loop', 'struggle']);\n\n/**\n * Does `insight` cite chat `sessionId`? Verse evidence refs are\n * `session:<id>#<seq>` (tool / message events) or `verse:<id>:<turn|seq>`\n * (thinking steps) — A7's ingest-verse.ts. The id is matched exactly up to\n * its delimiter, so chat `s1` never matches `s12`.\n */\nexport function citesSession(insight: Pick<ReasoningInsight, 'evidence'>, sessionId: string): boolean {\n return insight.evidence.some((e) => e.ref.startsWith(`session:${sessionId}#`) || e.ref.startsWith(`verse:${sessionId}:`));\n}\n\nexport function sessionInsights(digest: ReasoningDigest | null, sessionId: string): ReasoningInsight[] {\n if (!digest || !sessionId) return [];\n return digest.insights\n .filter((i) => CHIP_KINDS.has(i.kind) && citesSession(i, sessionId))\n .sort((a, b) => Date.parse(b.lastAt) - Date.parse(a.lastAt));\n}\n","/*\n * routes/verse/mind/mind.module.css — Mind cards and the chat-header chip\n * (unit C7). Tokens only (style-scan-310).\n */\n.stack {\n display: flex;\n flex-direction: column;\n gap: var(--surface-gap);\n}\n\n.muted {\n margin: 0;\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n}\n\n.link {\n align-self: flex-start;\n padding: 0;\n border: 0;\n background: none;\n color: var(--text-link);\n font: inherit;\n font-size: var(--text-xs-size);\n cursor: pointer;\n}\n\n.link:hover {\n text-decoration: underline;\n}\n\n.link:focus-visible,\n.veto:focus-visible,\n.chip:focus-visible {\n outline: 2px solid var(--border-focus);\n outline-offset: 2px;\n}\n\n/* ---- memo timeline ---------------------------------------------------- */\n.timeline {\n display: flex;\n flex-direction: column;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.memo {\n display: grid;\n grid-template-columns: 88px 20px minmax(0, 1fr) auto;\n gap: var(--space-3);\n align-items: start;\n padding: var(--space-3) 0;\n border-top: 1px solid var(--border-subtle);\n}\n\n.memo:first-child {\n border-top: 0;\n padding-top: 0;\n}\n\n.memoDay {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-sm-line);\n font-variant-numeric: tabular-nums;\n}\n\n.mark {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border-radius: var(--radius-full);\n background: var(--status-neutral-bg);\n color: var(--status-neutral-fg);\n font-size: var(--text-xs-size);\n font-weight: var(--font-weight-semibold);\n}\n\n.mark[data-outcome='hit'] {\n background: var(--status-success-bg);\n color: var(--status-success-fg);\n}\n\n.mark[data-outcome='miss'] {\n background: var(--status-danger-bg);\n color: var(--status-danger-fg);\n}\n\n.memoBody {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.memoMove {\n color: var(--text-primary);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n overflow-wrap: anywhere;\n}\n\n.memoWhy {\n color: var(--text-secondary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n overflow-wrap: anywhere;\n}\n\n.memoMeta {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n\n.memoMeta [data-outcome='hit'] {\n color: var(--status-success-fg);\n}\n\n.memoMeta [data-outcome='miss'] {\n color: var(--status-danger-fg);\n}\n\n.veto {\n min-height: var(--control-h-sm);\n padding: 0 var(--space-3);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n background: transparent;\n color: var(--text-primary);\n font: inherit;\n font-size: var(--text-xs-size);\n cursor: pointer;\n}\n\n.veto:hover {\n background: var(--bg-hover);\n}\n\n.veto:disabled {\n color: var(--text-disabled);\n cursor: default;\n}\n\n[data-viewport='compact'] .memo {\n grid-template-columns: 20px minmax(0, 1fr) auto;\n}\n\n[data-viewport='compact'] .memoDay {\n grid-column: 1 / -1;\n}\n\n/* ---- standards -------------------------------------------------------- */\n.standards {\n display: flex;\n flex-direction: column;\n gap: var(--space-3);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.standards li {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.standardRule {\n color: var(--text-primary);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line-relaxed);\n}\n\n.standardMeta {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n}\n\n/* ---- insight cards ---------------------------------------------------- */\n.insights {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: var(--surface-gap);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n[data-viewport='compact'] .insights,\n[data-viewport='medium'] .insights {\n grid-template-columns: minmax(0, 1fr);\n}\n\n.insight {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n padding: var(--card-pad);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-lg);\n background: var(--bg-surface);\n box-shadow: inset 0 1px 0 var(--hairline-lift, transparent);\n}\n\n.insight[data-severity='high'] {\n border-color: var(--status-danger-solid);\n}\n\n.insightKind {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-2);\n}\n\n.insightSeverity {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n}\n\n.insightSeverity[data-severity='high'] {\n color: var(--status-danger-fg);\n}\n\n.insightSeverity[data-severity='warn'] {\n color: var(--status-warning-fg);\n}\n\n.insightTitle {\n color: var(--text-primary);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line-relaxed);\n overflow-wrap: anywhere;\n}\n\n.insightMeta {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n\n/* The project's name reads a step stronger than the rest of the meta line;\n the full path is its tooltip. */\n.insightPlace {\n color: var(--text-secondary);\n overflow-wrap: anywhere;\n}\n\n/* A folder under the OS temp dir: tagged, quietly — never hidden. */\n.scratchTag {\n display: inline-block;\n margin-left: var(--space-1);\n padding: 0 var(--space-1);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-sm);\n color: var(--text-tertiary);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n vertical-align: 1px;\n}\n\n.log {\n display: flex;\n flex-direction: column;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.facet {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n}\n\n.facet select {\n min-height: var(--control-h-xs);\n padding: 0 var(--space-2);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n background: var(--bg-input);\n color: var(--text-primary);\n font: inherit;\n font-size: var(--text-xs-size);\n}\n\n/* ---- chat-header chip ------------------------------------------------- */\n.chipWrap {\n position: relative;\n display: inline-flex;\n}\n\n.chip {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n min-height: var(--control-h-xs);\n padding: 0 var(--space-2);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-full);\n background: var(--bg-surface);\n color: var(--text-secondary);\n font: inherit;\n font-size: var(--text-xs-size);\n white-space: nowrap;\n cursor: pointer;\n}\n\n.chip:hover,\n.chip[aria-expanded='true'] {\n background: var(--bg-hover);\n color: var(--text-primary);\n}\n\n.chipDot {\n width: 6px;\n height: 6px;\n border-radius: var(--radius-full);\n background: var(--status-warning-solid);\n}\n\n.chipDot[data-severity='high'] {\n background: var(--status-danger-solid);\n}\n\n.chipMore {\n color: var(--text-tertiary);\n}\n\n.chipPanel {\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 gap: var(--space-3);\n width: min(320px, calc(100vw - var(--space-8)));\n padding: var(--space-3);\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.chipList {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.chipList li {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{D as e,P as t,at as n,ot as r,u as i}from"./global-Di2PUgj4.js";var a=class extends Error{constructor(){super(`No mutation token held for this session yet.`),this.name=`MissingMutationTokenError`}};async function o(n,r){let o=e();if(!o)throw new a;let s=await i(n,r,o);return t(),s}async function s(){await o(`/api/fleet/pause`,{}),n(`dashboard-snapshot`),n(`control-snapshot`),n(`fleet`),n(`fleet-activity`)}async function c(){await o(`/api/fleet/resume`,{}),n(`dashboard-snapshot`),n(`control-snapshot`),n(`fleet`),n(`fleet-activity`)}async function l(e){await o(`/api/inbox/${encodeURIComponent(e)}/approve`,{}),n(`inbox`),n(`dashboard-snapshot`),n(`proposal-detail-${e}`),r(`inbox-list:`)}async function u(e){await o(`/api/inbox/${encodeURIComponent(e)}/reject`,{}),n(`inbox`),n(`dashboard-snapshot`),n(`proposal-detail-${e}`),r(`inbox-list:`)}export{c as i,s as n,u as r,l as t};
2
+ //# sourceMappingURL=mutations-Dpsql5t7.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mutations-C6E10SPX.js","names":[],"sources":["../../../../../../src/web-ui/data/mutations.ts"],"sourcesContent":["/**\n * data/mutations.ts — every mutating call the foundation ships with, each\n * wrapped so it (a) pulls the held mutation token from auth-store instead\n * of asking every call site to thread it through, (b) touches the hold on\n * success so a burst of approvals doesn't idle-expire mid-session, and\n * (c) invalidates whatever cache keys the mutation obviously affects so\n * views update without waiting for the next SSE tick.\n *\n * Routes mirror the mutating surface documented at the top of\n * src/core/web/api.ts. Every one of these 404s (not 401/403) when the\n * server was started without --allow-dispatch — apiPost maps that code-less\n * 404 to DispatchDisabledError (a 404 carrying a `code` stays an ApiError).\n */\nimport { apiPost } from './client.js';\nimport { getMutationToken, touchMutationHold } from './auth-store.js';\nimport { invalidate, invalidatePrefix } from './cache.js';\n\nclass MissingMutationTokenError extends Error {\n constructor() {\n super('No mutation token held for this session yet.');\n this.name = 'MissingMutationTokenError';\n }\n}\n\nasync function post<T>(path: string, body: unknown): Promise<T> {\n const token = getMutationToken();\n if (!token) throw new MissingMutationTokenError();\n const result = await apiPost<T>(path, body, token);\n touchMutationHold();\n return result;\n}\n\nexport async function pauseFleet(): Promise<void> {\n await post('/api/fleet/pause', {});\n invalidate('dashboard-snapshot');\n invalidate('control-snapshot');\n invalidate('fleet');\n invalidate('fleet-activity');\n}\n\nexport async function resumeFleet(): Promise<void> {\n await post('/api/fleet/resume', {});\n invalidate('dashboard-snapshot');\n invalidate('control-snapshot');\n invalidate('fleet');\n invalidate('fleet-activity');\n}\n\nexport async function approveProposal(id: string): Promise<void> {\n await post(`/api/inbox/${encodeURIComponent(id)}/approve`, {});\n invalidate('inbox');\n invalidate('dashboard-snapshot');\n invalidate(`proposal-detail-${id}`);\n invalidatePrefix('inbox-list:');\n}\n\nexport async function rejectProposal(id: string): Promise<void> {\n await post(`/api/inbox/${encodeURIComponent(id)}/reject`, {});\n invalidate('inbox');\n invalidate('dashboard-snapshot');\n invalidate(`proposal-detail-${id}`);\n invalidatePrefix('inbox-list:');\n}\n\nexport interface OpenTargetRequest {\n path: string;\n target: 'editor' | 'finder';\n}\n\nexport async function openTarget(req: OpenTargetRequest): Promise<void> {\n await post('/api/open', req);\n}\n"],"mappings":"uEAiBA,IAAM,EAAN,cAAwC,KAAM,CAC5C,aAAc,CACZ,MAAM,8CAA8C,EACpD,KAAK,KAAO,2BACd,CACF,EAEA,eAAe,EAAQ,EAAc,EAA2B,CAC9D,IAAM,EAAQ,EAAiB,EAC/B,GAAI,CAAC,EAAO,MAAM,IAAI,EACtB,IAAM,EAAS,MAAM,EAAW,EAAM,EAAM,CAAK,EAEjD,OADA,EAAkB,EACX,CACT,CAEA,eAAsB,GAA4B,CAChD,MAAM,EAAK,mBAAoB,CAAC,CAAC,EACjC,EAAW,oBAAoB,EAC/B,EAAW,kBAAkB,EAC7B,EAAW,OAAO,EAClB,EAAW,gBAAgB,CAC7B,CAEA,eAAsB,GAA6B,CACjD,MAAM,EAAK,oBAAqB,CAAC,CAAC,EAClC,EAAW,oBAAoB,EAC/B,EAAW,kBAAkB,EAC7B,EAAW,OAAO,EAClB,EAAW,gBAAgB,CAC7B,CAEA,eAAsB,EAAgB,EAA2B,CAC/D,MAAM,EAAK,cAAc,mBAAmB,CAAE,EAAE,UAAW,CAAC,CAAC,EAC7D,EAAW,OAAO,EAClB,EAAW,oBAAoB,EAC/B,EAAW,mBAAmB,GAAI,EAClC,EAAiB,aAAa,CAChC,CAEA,eAAsB,EAAe,EAA2B,CAC9D,MAAM,EAAK,cAAc,mBAAmB,CAAE,EAAE,SAAU,CAAC,CAAC,EAC5D,EAAW,OAAO,EAClB,EAAW,oBAAoB,EAC/B,EAAW,mBAAmB,GAAI,EAClC,EAAiB,aAAa,CAChC"}
1
+ {"version":3,"file":"mutations-Dpsql5t7.js","names":[],"sources":["../../../../../../src/web-ui/data/mutations.ts"],"sourcesContent":["/**\n * data/mutations.ts — every mutating call the foundation ships with, each\n * wrapped so it (a) pulls the held mutation token from auth-store instead\n * of asking every call site to thread it through, (b) touches the hold on\n * success so a burst of approvals doesn't idle-expire mid-session, and\n * (c) invalidates whatever cache keys the mutation obviously affects so\n * views update without waiting for the next SSE tick.\n *\n * Routes mirror the mutating surface documented at the top of\n * src/core/web/api.ts. Every one of these 404s (not 401/403) when the\n * server was started without --allow-dispatch — apiPost maps that code-less\n * 404 to DispatchDisabledError (a 404 carrying a `code` stays an ApiError).\n */\nimport { apiPost } from './client.js';\nimport { getMutationToken, touchMutationHold } from './auth-store.js';\nimport { invalidate, invalidatePrefix } from './cache.js';\n\nclass MissingMutationTokenError extends Error {\n constructor() {\n super('No mutation token held for this session yet.');\n this.name = 'MissingMutationTokenError';\n }\n}\n\nasync function post<T>(path: string, body: unknown): Promise<T> {\n const token = getMutationToken();\n if (!token) throw new MissingMutationTokenError();\n const result = await apiPost<T>(path, body, token);\n touchMutationHold();\n return result;\n}\n\nexport async function pauseFleet(): Promise<void> {\n await post('/api/fleet/pause', {});\n invalidate('dashboard-snapshot');\n invalidate('control-snapshot');\n invalidate('fleet');\n invalidate('fleet-activity');\n}\n\nexport async function resumeFleet(): Promise<void> {\n await post('/api/fleet/resume', {});\n invalidate('dashboard-snapshot');\n invalidate('control-snapshot');\n invalidate('fleet');\n invalidate('fleet-activity');\n}\n\nexport async function approveProposal(id: string): Promise<void> {\n await post(`/api/inbox/${encodeURIComponent(id)}/approve`, {});\n invalidate('inbox');\n invalidate('dashboard-snapshot');\n invalidate(`proposal-detail-${id}`);\n invalidatePrefix('inbox-list:');\n}\n\nexport async function rejectProposal(id: string): Promise<void> {\n await post(`/api/inbox/${encodeURIComponent(id)}/reject`, {});\n invalidate('inbox');\n invalidate('dashboard-snapshot');\n invalidate(`proposal-detail-${id}`);\n invalidatePrefix('inbox-list:');\n}\n\nexport interface OpenTargetRequest {\n path: string;\n target: 'editor' | 'finder';\n}\n\nexport async function openTarget(req: OpenTargetRequest): Promise<void> {\n await post('/api/open', req);\n}\n"],"mappings":"uEAiBA,IAAM,EAAN,cAAwC,KAAM,CAC5C,aAAc,CACZ,MAAM,8CAA8C,EACpD,KAAK,KAAO,2BACd,CACF,EAEA,eAAe,EAAQ,EAAc,EAA2B,CAC9D,IAAM,EAAQ,EAAiB,EAC/B,GAAI,CAAC,EAAO,MAAM,IAAI,EACtB,IAAM,EAAS,MAAM,EAAW,EAAM,EAAM,CAAK,EAEjD,OADA,EAAkB,EACX,CACT,CAEA,eAAsB,GAA4B,CAChD,MAAM,EAAK,mBAAoB,CAAC,CAAC,EACjC,EAAW,oBAAoB,EAC/B,EAAW,kBAAkB,EAC7B,EAAW,OAAO,EAClB,EAAW,gBAAgB,CAC7B,CAEA,eAAsB,GAA6B,CACjD,MAAM,EAAK,oBAAqB,CAAC,CAAC,EAClC,EAAW,oBAAoB,EAC/B,EAAW,kBAAkB,EAC7B,EAAW,OAAO,EAClB,EAAW,gBAAgB,CAC7B,CAEA,eAAsB,EAAgB,EAA2B,CAC/D,MAAM,EAAK,cAAc,mBAAmB,CAAE,EAAE,UAAW,CAAC,CAAC,EAC7D,EAAW,OAAO,EAClB,EAAW,oBAAoB,EAC/B,EAAW,mBAAmB,GAAI,EAClC,EAAiB,aAAa,CAChC,CAEA,eAAsB,EAAe,EAA2B,CAC9D,MAAM,EAAK,cAAc,mBAAmB,CAAE,EAAE,SAAU,CAAC,CAAC,EAC5D,EAAW,OAAO,EAClB,EAAW,oBAAoB,EAC/B,EAAW,mBAAmB,GAAI,EAClC,EAAiB,aAAa,CAChC"}
@@ -1,2 +1,2 @@
1
- import{a as e,s as t}from"./index-afDA8cwW.js";import{D as n,P as r,h as i,it as a,l as o,s,u as c}from"./global-DVgMguLr.js";import{n as l,t as u}from"./control-queries-BGjarMm9.js";import{s as d}from"./format-BNYWGJat.js";var f=t(e(),1);function p(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function m(e){return typeof e==`string`&&e.trim()!==``?e:null}function h(e){return typeof e==`boolean`?e:null}function g(e){return typeof e!=`number`||!Number.isFinite(e)||e<0?null:Math.floor(e)}function _(e){if(!p(e))return null;let t=m(e.kind);if(t===`until-paused`)return{kind:`until-paused`};if(t===`at-time`){let t=m(e.at);return t===null||Number.isNaN(Date.parse(t))?null:{kind:`at-time`,at:t}}if(t===`after-iterations`){let t=g(e.iterations);return t===null||t<=0?null:{kind:`after-iterations`,iterations:t}}return null}function v(e){if(!Array.isArray(e))return[];let t=[];for(let[n,r]of e.entries()){if(!p(r))continue;let e=m(r.repo);e!==null&&t.push({id:m(r.id)??`${e}:${n}`,repo:e,title:m(r.title)??`untitled change`,at:m(r.at),commit:m(r.commit)})}return t}function y(e){if(!Array.isArray(e))return[];let t=[];for(let[n,r]of e.entries()){if(!p(r))continue;let e=m(r.repo);e!==null&&t.push({id:m(r.id)??`${e}:${n}`,repo:e,title:m(r.title)??`untitled change`,at:m(r.at),reason:m(r.reason)??`no reason recorded`})}return t}function b(e){return p(e)?{tests:h(e.tests),lint:h(e.lint),typecheck:h(e.typecheck),autoMerge:h(e.autoMerge),branch:m(e.branch)}:null}function x(e){if(!p(e))return null;let t=m(e.runId);return t===null?null:{runId:t,startedAt:m(e.startedAt),stopRule:_(e.stopRule),iterationsDone:g(e.iterationsDone),repo:m(e.repo),activity:m(e.activity),merged:v(e.merged),discarded:y(e.discarded)}}function S(e){if(!p(e))return null;let t=h(e.armed);return t===null?null:{armed:t,run:x(e.run),repos:g(e.repos),...e.mirrors===void 0?{}:{mirrors:g(e.mirrors)},gate:b(e.gate)}}function C(e,t=new Date){let n=/^(\d{1,2}):(\d{2})$/.exec(e.trim());if(!n)return null;let r=Number(n[1]),i=Number(n[2]);if(!Number.isInteger(r)||!Number.isInteger(i)||r<0||r>23||i<0||i>59)return null;let a=new Date(t);return a.setHours(r,i,0,0),a.getTime()<=t.getTime()&&a.setDate(a.getDate()+1),a.toISOString()}function w(e){if(!e)return`—`;let t=Date.parse(e);return Number.isNaN(t)?`—`:new Date(t).toLocaleTimeString(void 0,{hour:`2-digit`,minute:`2-digit`})}function T(e,t=new Date){if(!e)return!1;let n=Date.parse(e);return!Number.isNaN(n)&&new Date(n).toDateString()!==t.toDateString()}function E(e,t=new Date){switch(e.kind){case`until-paused`:return`Runs until you pause it — no stop time, no iteration limit.`;case`at-time`:return`Stops at ${w(e.at)}${T(e.at,t)?` tomorrow`:``}.`;case`after-iterations`:return`Stops after ${e.iterations} ${e.iterations===1?`iteration`:`iterations`}.`}}function D(e,t,n=Date.now()){if(e===null)return{headline:`Stop rule not stated`,remaining:`—`,percent:null,reached:!1};if(e.kind===`until-paused`)return{headline:`Runs until you pause it`,remaining:`no stop time, no iteration limit`,percent:null,reached:!1};if(e.kind===`at-time`){let r=Date.parse(e.at);if(Number.isNaN(r))return{headline:`Stop time not readable`,remaining:`—`,percent:null,reached:!1};let i=`Stops at ${w(e.at)}`,a=r-n;if(a<=0)return{headline:i,remaining:`stop time reached`,percent:100,reached:!0};let o=t?.startedAt?Date.parse(t.startedAt):NaN,s=Number.isNaN(o)||r<=o?null:Math.min(100,Math.max(0,Math.round((n-o)/(r-o)*100)));return{headline:i,remaining:`${d(a)} left`,percent:s,reached:!1}}let r=t?.iterationsDone,i=`Stops after ${e.iterations} ${e.iterations===1?`iteration`:`iterations`}`;return typeof r==`number`?{headline:i,remaining:`${r} of ${e.iterations} done`,percent:Math.min(100,Math.round(r/e.iterations*100)),reached:r>=e.iterations}:{headline:i,remaining:`— of ${e.iterations} done`,percent:null,reached:!1}}function O(e,t=Date.now()){if(!e)return`—`;let n=Date.parse(e);return Number.isNaN(n)?`—`:d(Math.max(0,t-n))}function k(e){if(e===null)return[];let t=[];return e.tests===!0&&t.push(`tests`),e.lint===!0&&t.push(`lint`),e.typecheck===!0&&t.push(`typecheck`),t}function A(e){if(e===null)return[`tests`,`lint`,`typecheck`];let t=[];return e.tests===null&&t.push(`tests`),e.lint===null&&t.push(`lint`),e.typecheck===null&&t.push(`typecheck`),t}function j(e){return e.length===0?``:e.length===1?e[0]:`${e.slice(0,-1).join(`, `)} and ${e[e.length-1]}`}var M=`verse-overnight`,N=`/api/verse/overnight`;function P(e){return e instanceof s?e.status===404?`This build does not expose ${N}, so an overnight run cannot be armed from here. It is a missing route, not a run that refused to start.`:`${N} answered HTTP ${e.status}.`:`${N} could not be reached.`}var F={key:M,fetch:async e=>{try{let t=S(await o(N,e));return t===null?{value:null,available:!0,reason:`${N} answered in a shape this client does not recognise, so nothing is shown rather than guessed.`}:{value:t,available:!0,reason:null}}catch(e){if(e instanceof s&&e.status===401||e instanceof DOMException&&e.name===`AbortError`)throw e;return{value:null,available:!1,reason:P(e)}}}};async function I(e,t){let i=n();if(!i)throw new l;let a=await c(e,t,i);return r(),a}function L(){a(M),a(u)}async function R(e){let t=await I(N,{action:`arm`,stopRule:e});return L(),t}async function z(){let e=await I(N,{action:`disarm`});return L(),e}var B=15e3;function V(e,t=B){let n=i(F);(0,f.useEffect)(()=>{if(!e)return;let r=null,i=()=>{r===null&&(r=setInterval(n,t))},a=()=>{r!==null&&(clearInterval(r),r=null)},o=()=>{if(document.visibilityState===`hidden`){a();return}n(),i()};return document.visibilityState!==`hidden`&&i(),document.addEventListener(`visibilitychange`,o),()=>{a(),document.removeEventListener(`visibilitychange`,o)}},[e,t,n])}export{E as a,A as c,D as d,V as i,j as l,z as n,O as o,F as r,k as s,R as t,C as u};
2
- //# sourceMappingURL=overnight-queries-CCGfiS-g.js.map
1
+ import{a as e,s as t}from"./index-oAAq8XJa.js";import{D as n,P as r,at as i,h as a,l as o,s,u as c}from"./global-Di2PUgj4.js";import{s as l}from"./format-B8DAVcn2.js";import{n as u,t as d}from"./control-queries-DOZR-D8G.js";var f=t(e(),1);function p(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function m(e){return typeof e==`string`&&e.trim()!==``?e:null}function h(e){return typeof e==`boolean`?e:null}function g(e){return typeof e!=`number`||!Number.isFinite(e)||e<0?null:Math.floor(e)}function _(e){if(!p(e))return null;let t=m(e.kind);if(t===`until-paused`)return{kind:`until-paused`};if(t===`at-time`){let t=m(e.at);return t===null||Number.isNaN(Date.parse(t))?null:{kind:`at-time`,at:t}}if(t===`after-iterations`){let t=g(e.iterations);return t===null||t<=0?null:{kind:`after-iterations`,iterations:t}}return null}function v(e){if(!Array.isArray(e))return[];let t=[];for(let[n,r]of e.entries()){if(!p(r))continue;let e=m(r.repo);e!==null&&t.push({id:m(r.id)??`${e}:${n}`,repo:e,title:m(r.title)??`untitled change`,at:m(r.at),commit:m(r.commit)})}return t}function y(e){if(!Array.isArray(e))return[];let t=[];for(let[n,r]of e.entries()){if(!p(r))continue;let e=m(r.repo);e!==null&&t.push({id:m(r.id)??`${e}:${n}`,repo:e,title:m(r.title)??`untitled change`,at:m(r.at),reason:m(r.reason)??`no reason recorded`})}return t}function b(e){return p(e)?{tests:h(e.tests),lint:h(e.lint),typecheck:h(e.typecheck),autoMerge:h(e.autoMerge),branch:m(e.branch)}:null}function x(e){if(!p(e))return null;let t=m(e.runId);return t===null?null:{runId:t,startedAt:m(e.startedAt),stopRule:_(e.stopRule),iterationsDone:g(e.iterationsDone),repo:m(e.repo),activity:m(e.activity),merged:v(e.merged),discarded:y(e.discarded)}}function S(e){if(!p(e))return null;let t=h(e.armed);return t===null?null:{armed:t,run:x(e.run),repos:g(e.repos),...e.mirrors===void 0?{}:{mirrors:g(e.mirrors)},gate:b(e.gate)}}function C(e,t=new Date){let n=/^(\d{1,2}):(\d{2})$/.exec(e.trim());if(!n)return null;let r=Number(n[1]),i=Number(n[2]);if(!Number.isInteger(r)||!Number.isInteger(i)||r<0||r>23||i<0||i>59)return null;let a=new Date(t);return a.setHours(r,i,0,0),a.getTime()<=t.getTime()&&a.setDate(a.getDate()+1),a.toISOString()}function w(e){if(!e)return`—`;let t=Date.parse(e);return Number.isNaN(t)?`—`:new Date(t).toLocaleTimeString(void 0,{hour:`2-digit`,minute:`2-digit`})}function T(e,t=new Date){if(!e)return!1;let n=Date.parse(e);return!Number.isNaN(n)&&new Date(n).toDateString()!==t.toDateString()}function E(e,t=new Date){switch(e.kind){case`until-paused`:return`Runs until you pause it — no stop time, no iteration limit.`;case`at-time`:return`Stops at ${w(e.at)}${T(e.at,t)?` tomorrow`:``}.`;case`after-iterations`:return`Stops after ${e.iterations} ${e.iterations===1?`iteration`:`iterations`}.`}}function D(e,t,n=Date.now()){if(e===null)return{headline:`Stop rule not stated`,remaining:`—`,percent:null,reached:!1};if(e.kind===`until-paused`)return{headline:`Runs until you pause it`,remaining:`no stop time, no iteration limit`,percent:null,reached:!1};if(e.kind===`at-time`){let r=Date.parse(e.at);if(Number.isNaN(r))return{headline:`Stop time not readable`,remaining:`—`,percent:null,reached:!1};let i=`Stops at ${w(e.at)}`,a=r-n;if(a<=0)return{headline:i,remaining:`stop time reached`,percent:100,reached:!0};let o=t?.startedAt?Date.parse(t.startedAt):NaN,s=Number.isNaN(o)||r<=o?null:Math.min(100,Math.max(0,Math.round((n-o)/(r-o)*100)));return{headline:i,remaining:`${l(a)} left`,percent:s,reached:!1}}let r=t?.iterationsDone,i=`Stops after ${e.iterations} ${e.iterations===1?`iteration`:`iterations`}`;return typeof r==`number`?{headline:i,remaining:`${r} of ${e.iterations} done`,percent:Math.min(100,Math.round(r/e.iterations*100)),reached:r>=e.iterations}:{headline:i,remaining:`— of ${e.iterations} done`,percent:null,reached:!1}}function O(e,t=Date.now()){if(!e)return`—`;let n=Date.parse(e);return Number.isNaN(n)?`—`:l(Math.max(0,t-n))}function k(e){if(e===null)return[];let t=[];return e.tests===!0&&t.push(`tests`),e.lint===!0&&t.push(`lint`),e.typecheck===!0&&t.push(`typecheck`),t}function A(e){if(e===null)return[`tests`,`lint`,`typecheck`];let t=[];return e.tests===null&&t.push(`tests`),e.lint===null&&t.push(`lint`),e.typecheck===null&&t.push(`typecheck`),t}function j(e){return e.length===0?``:e.length===1?e[0]:`${e.slice(0,-1).join(`, `)} and ${e[e.length-1]}`}var M=`verse-overnight`,N=`/api/verse/overnight`;function P(e){return e instanceof s?e.status===404?`This build does not expose ${N}, so an overnight run cannot be armed from here. It is a missing route, not a run that refused to start.`:`${N} answered HTTP ${e.status}.`:`${N} could not be reached.`}var F={key:M,fetch:async e=>{try{let t=S(await o(N,e));return t===null?{value:null,available:!0,reason:`${N} answered in a shape this client does not recognise, so nothing is shown rather than guessed.`}:{value:t,available:!0,reason:null}}catch(e){if(e instanceof s&&e.status===401||e instanceof DOMException&&e.name===`AbortError`)throw e;return{value:null,available:!1,reason:P(e)}}}};async function I(e,t){let i=n();if(!i)throw new u;let a=await c(e,t,i);return r(),a}function L(){i(M),i(d)}async function R(e){let t=await I(N,{action:`arm`,stopRule:e});return L(),t}async function z(){let e=await I(N,{action:`disarm`});return L(),e}var B=15e3;function V(e,t=B){let n=a(F);(0,f.useEffect)(()=>{if(!e)return;let r=null,i=()=>{r===null&&(r=setInterval(n,t))},a=()=>{r!==null&&(clearInterval(r),r=null)},o=()=>{if(document.visibilityState===`hidden`){a();return}n(),i()};return document.visibilityState!==`hidden`&&i(),document.addEventListener(`visibilitychange`,o),()=>{a(),document.removeEventListener(`visibilitychange`,o)}},[e,t,n])}export{E as a,A as c,D as d,V as i,j as l,z as n,O as o,F as r,k as s,R as t,C as u};
2
+ //# sourceMappingURL=overnight-queries-X-44Gsw5.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"overnight-queries-CCGfiS-g.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/autonomy/overnight-model.ts","../../../../../../src/web-ui/routes/verse/autonomy/overnight-queries.ts"],"sourcesContent":["/**\n * routes/verse/autonomy/overnight-model.ts — the pure half of the Overnight\n * panel: narrow the server's body, resolve the operator's stop rule, and\n * derive the one line that says how far the run is from stopping.\n *\n * Framework-free so it unit-tests without a DOM, and separate from the panel\n * because two of these functions are where the panel can most easily start\n * lying:\n *\n * - `projectOvernight` NARROWS, it does not cast. The route is being written\n * by another owner in parallel with this surface, so a field that drifts in\n * name or type has to degrade to `null` — which the panel renders as \"not\n * stated\" — rather than reach a render as `undefined` and crash, or reach\n * it as `0` and read as a fact. Same discipline as `fleet-model.ts`.\n * - `stopProgress` never invents a denominator. \"Until I pause it\" has no\n * progress, and drawing a bar for it would be a picture of a finish line\n * that does not exist.\n */\nimport { formatDuration, UNKNOWN } from './format.js';\nimport type {\n OvernightDiscard,\n OvernightGate,\n OvernightMerge,\n OvernightRun,\n OvernightStatus,\n OvernightStopRule,\n OvernightStopRuleKind,\n} from './overnight-contract.js';\n\n// ---------------------------------------------------------------------------\n// Narrowing\n// ---------------------------------------------------------------------------\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction str(value: unknown): string | null {\n return typeof value === 'string' && value.trim() !== '' ? value : null;\n}\n\nfunction bool(value: unknown): boolean | null {\n return typeof value === 'boolean' ? value : null;\n}\n\n/** A count. Negative and non-finite are not counts, so they are not observed. */\nfunction count(value: unknown): number | null {\n if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) return null;\n return Math.floor(value);\n}\n\nexport function projectStopRule(raw: unknown): OvernightStopRule | null {\n if (!isRecord(raw)) return null;\n const kind = str(raw['kind']);\n if (kind === 'until-paused') return { kind: 'until-paused' };\n if (kind === 'at-time') {\n const at = str(raw['at']);\n // An unparseable instant is worse than no rule: it would render as a\n // countdown to NaN. Refuse it here so the panel can say \"not stated\".\n if (at === null || Number.isNaN(Date.parse(at))) return null;\n return { kind: 'at-time', at };\n }\n if (kind === 'after-iterations') {\n const iterations = count(raw['iterations']);\n if (iterations === null || iterations <= 0) return null;\n return { kind: 'after-iterations', iterations };\n }\n return null;\n}\n\nfunction projectMerges(raw: unknown): OvernightMerge[] {\n if (!Array.isArray(raw)) return [];\n const out: OvernightMerge[] = [];\n for (const [index, item] of raw.entries()) {\n if (!isRecord(item)) continue;\n const repo = str(item['repo']);\n if (repo === null) continue;\n out.push({\n id: str(item['id']) ?? `${repo}:${index}`,\n repo,\n title: str(item['title']) ?? 'untitled change',\n at: str(item['at']),\n commit: str(item['commit']),\n });\n }\n return out;\n}\n\nfunction projectDiscards(raw: unknown): OvernightDiscard[] {\n if (!Array.isArray(raw)) return [];\n const out: OvernightDiscard[] = [];\n for (const [index, item] of raw.entries()) {\n if (!isRecord(item)) continue;\n const repo = str(item['repo']);\n if (repo === null) continue;\n out.push({\n id: str(item['id']) ?? `${repo}:${index}`,\n repo,\n title: str(item['title']) ?? 'untitled change',\n at: str(item['at']),\n // A discard with no stated reason is the one row an operator will ask\n // about in the morning, so it says that it has none rather than being\n // rendered as a blank cell.\n reason: str(item['reason']) ?? 'no reason recorded',\n });\n }\n return out;\n}\n\nfunction projectGate(raw: unknown): OvernightGate | null {\n if (!isRecord(raw)) return null;\n return {\n tests: bool(raw['tests']),\n lint: bool(raw['lint']),\n typecheck: bool(raw['typecheck']),\n autoMerge: bool(raw['autoMerge']),\n branch: str(raw['branch']),\n };\n}\n\nfunction projectRun(raw: unknown): OvernightRun | null {\n if (!isRecord(raw)) return null;\n const runId = str(raw['runId']);\n if (runId === null) return null;\n return {\n runId,\n startedAt: str(raw['startedAt']),\n stopRule: projectStopRule(raw['stopRule']),\n iterationsDone: count(raw['iterationsDone']),\n repo: str(raw['repo']),\n activity: str(raw['activity']),\n merged: projectMerges(raw['merged']),\n discarded: projectDiscards(raw['discarded']),\n };\n}\n\n/**\n * `GET /api/verse/overnight` → a status, or null when the body is not one.\n *\n * `armed` is the single field this refuses to guess: a body that does not say\n * whether a run is armed is not a status, because \"nothing is armed\" is\n * exactly the claim a person checks before closing the laptop.\n */\nexport function projectOvernight(raw: unknown): OvernightStatus | null {\n if (!isRecord(raw)) return null;\n const armed = bool(raw['armed']);\n if (armed === null) return null;\n return {\n armed,\n run: projectRun(raw['run']),\n repos: count(raw['repos']),\n // Present-but-invalid reads as null (\"not recorded\"); absent stays absent,\n // so an older server is not shown as having lost a count it never sent.\n ...(raw['mirrors'] !== undefined ? { mirrors: count(raw['mirrors']) } : {}),\n gate: projectGate(raw['gate']),\n };\n}\n\n// ---------------------------------------------------------------------------\n// The operator's side of the stop rule\n// ---------------------------------------------------------------------------\n\n/** Smallest and largest iteration cap the form will send. */\nexport const ITERATIONS_MIN = 1;\nexport const ITERATIONS_MAX = 500;\n\n/**\n * Turn an `<input type=\"time\">` value (\"23:30\") into the next occurrence of\n * that wall-clock time, as an absolute instant.\n *\n * The whole point of arming this at 11pm is that \"07:00\" means tomorrow\n * morning. Resolving it on the client, in the operator's own zone, is what\n * makes that unambiguous by the time it reaches a server that may not share\n * the zone — and rounds to the minute, so a run armed at 06:59:58 for 07:00\n * does not stop two seconds later.\n */\nexport function resolveStopAt(value: string, now: Date = new Date()): string | null {\n const match = /^(\\d{1,2}):(\\d{2})$/.exec(value.trim());\n if (!match) return null;\n const hours = Number(match[1]);\n const minutes = Number(match[2]);\n if (!Number.isInteger(hours) || !Number.isInteger(minutes)) return null;\n if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59) return null;\n const at = new Date(now);\n at.setHours(hours, minutes, 0, 0);\n if (at.getTime() <= now.getTime()) at.setDate(at.getDate() + 1);\n return at.toISOString();\n}\n\n/** \"07:00\" as the operator's locale writes it — never a raw ISO string. */\nexport function formatStopClock(iso: string | null): string {\n if (!iso) return UNKNOWN;\n const ms = Date.parse(iso);\n if (Number.isNaN(ms)) return UNKNOWN;\n return new Date(ms).toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });\n}\n\n/** True when the resolved instant is not today — \"07:00 tomorrow\". */\nexport function isNextDay(iso: string | null, now: Date = new Date()): boolean {\n if (!iso) return false;\n const ms = Date.parse(iso);\n if (Number.isNaN(ms)) return false;\n return new Date(ms).toDateString() !== now.toDateString();\n}\n\n/**\n * The sentence the Arm button is committing to, before the click.\n *\n * It restates the rule the operator chose in the operator's own units, so the\n * button is never the only description of what is about to be authorised.\n */\nexport function describeStopRule(rule: OvernightStopRule, now: Date = new Date()): string {\n switch (rule.kind) {\n case 'until-paused':\n return 'Runs until you pause it — no stop time, no iteration limit.';\n case 'at-time':\n return `Stops at ${formatStopClock(rule.at)}${isNextDay(rule.at, now) ? ' tomorrow' : ''}.`;\n case 'after-iterations':\n return `Stops after ${rule.iterations} ${rule.iterations === 1 ? 'iteration' : 'iterations'}.`;\n }\n}\n\n/** The short label each stop rule wears in the armed summary. */\nexport function stopRuleLabel(kind: OvernightStopRuleKind): string {\n switch (kind) {\n case 'until-paused':\n return 'Until paused';\n case 'at-time':\n return 'At a set time';\n case 'after-iterations':\n return 'After N iterations';\n }\n}\n\n// ---------------------------------------------------------------------------\n// How far to the stop condition\n// ---------------------------------------------------------------------------\n\nexport interface StopProgress {\n /** The rule, restated: \"Stops at 07:00\". */\n headline: string;\n /** How much is left: \"4h 12m left\", \"12 of 20 done\". */\n remaining: string;\n /** 0-100 for a meter, or null when there is no honest denominator. */\n percent: number | null;\n /** True once the condition is met and the loop should be winding down. */\n reached: boolean;\n}\n\n/**\n * How far the run is from its stop condition.\n *\n * `percent` is null for \"until I pause it\" on purpose: an open-ended run has\n * no finish line, and a bar with no denominator is the exact kind of confident\n * graphic this cockpit is not allowed to draw.\n */\nexport function stopProgress(\n rule: OvernightStopRule | null,\n run: OvernightRun | null,\n now: number = Date.now(),\n): StopProgress {\n if (rule === null) {\n return {\n headline: 'Stop rule not stated',\n remaining: UNKNOWN,\n percent: null,\n reached: false,\n };\n }\n\n if (rule.kind === 'until-paused') {\n return {\n headline: 'Runs until you pause it',\n remaining: 'no stop time, no iteration limit',\n percent: null,\n reached: false,\n };\n }\n\n if (rule.kind === 'at-time') {\n const at = Date.parse(rule.at);\n if (Number.isNaN(at)) {\n return { headline: 'Stop time not readable', remaining: UNKNOWN, percent: null, reached: false };\n }\n const headline = `Stops at ${formatStopClock(rule.at)}`;\n const left = at - now;\n if (left <= 0) {\n return { headline, remaining: 'stop time reached', percent: 100, reached: true };\n }\n const startedAt = run?.startedAt ? Date.parse(run.startedAt) : Number.NaN;\n // Elapsed over the run's whole window — which needs a start. Without one\n // the countdown is still true, so it is shown; only the bar is withheld.\n const percent =\n Number.isNaN(startedAt) || at <= startedAt\n ? null\n : Math.min(100, Math.max(0, Math.round(((now - startedAt) / (at - startedAt)) * 100)));\n return { headline, remaining: `${formatDuration(left)} left`, percent, reached: false };\n }\n\n const done = run?.iterationsDone;\n const headline = `Stops after ${rule.iterations} ${rule.iterations === 1 ? 'iteration' : 'iterations'}`;\n if (typeof done !== 'number') {\n return {\n headline,\n remaining: `${UNKNOWN} of ${rule.iterations} done`,\n percent: null,\n reached: false,\n };\n }\n return {\n headline,\n remaining: `${done} of ${rule.iterations} done`,\n percent: Math.min(100, Math.round((done / rule.iterations) * 100)),\n reached: done >= rule.iterations,\n };\n}\n\n/** \"3h 04m\" since the run started, or UNKNOWN when it never said. */\nexport function formatRunElapsed(startedAt: string | null | undefined, now: number = Date.now()): string {\n if (!startedAt) return UNKNOWN;\n const ms = Date.parse(startedAt);\n if (Number.isNaN(ms)) return UNKNOWN;\n return formatDuration(Math.max(0, now - ms));\n}\n\n/**\n * The checks named as one phrase: \"tests, lint and typecheck\".\n *\n * Only checks the server said `true` about are named. A `null` check is not\n * named as running AND not named as skipped — `gateCaveat` below says so in\n * words instead, because a gate an operator believes is running when it is not\n * is the single most expensive misreading this panel could cause.\n */\nexport function gateChecks(gate: OvernightGate | null): string[] {\n if (gate === null) return [];\n const named: string[] = [];\n if (gate.tests === true) named.push('tests');\n if (gate.lint === true) named.push('lint');\n if (gate.typecheck === true) named.push('typecheck');\n return named;\n}\n\n/** The checks the server would not commit to, if any. */\nexport function gateUnstated(gate: OvernightGate | null): string[] {\n if (gate === null) return ['tests', 'lint', 'typecheck'];\n const unstated: string[] = [];\n if (gate.tests === null) unstated.push('tests');\n if (gate.lint === null) unstated.push('lint');\n if (gate.typecheck === null) unstated.push('typecheck');\n return unstated;\n}\n\nexport function joinPhrase(parts: readonly string[]): string {\n if (parts.length === 0) return '';\n if (parts.length === 1) return parts[0]!;\n return `${parts.slice(0, -1).join(', ')} and ${parts[parts.length - 1]!}`;\n}\n","/**\n * routes/verse/autonomy/overnight-queries.ts — the one read and the one write\n * behind the Overnight panel: `GET /api/verse/overnight` and\n * `POST /api/verse/overnight`.\n *\n * Same contract as `control-queries.ts` and `fleet-queries.ts` — the read is a\n * QueryDef consumed through `useQuery` (cache-backed, so a poll never blanks a\n * populated panel); the write pulls the held mutation token from auth-store,\n * touches the hold on success, and invalidates exactly the keys it affects.\n * There is no new data layer here on purpose.\n *\n * TWO THINGS THAT ARE DELIBERATE:\n *\n * 1. **The read does not throw on absence.** The route does not exist yet —\n * four owners are building the engine, the permit, the budgets and the\n * local-only policy in parallel. A server without it answers 404, and 404\n * means \"this panel has no source yet\", not \"Autonomy is broken\". It comes\n * back as `OptionalFleetRead` (reused rather than re-declared, because two\n * shapes for \"a read that is allowed to be absent\" would be one too many)\n * and the panel renders a designed not-available state from `reason`.\n * 401 still propagates: an expired read session is an unauthorized state\n * for the whole surface, not a missing panel.\n *\n * 2. **There is no pause route here, and there must not be one.** The halt\n * this panel offers is the DAEMON-SCOPED pause — `~/.ashlr/daemon.paused`,\n * via `runDaemonAction('pause')` in control-queries.ts. Disarming stops\n * arming the next run; pausing stops the loop that is running now, and\n * they are different questions. Neither is `stopDaemon()`, which is\n * `setKill(true)` and therefore the emergency stop wearing a quieter name\n * (see the header of DaemonControls.tsx).\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 { useRefetch } from '../../../data/hooks.js';\nimport { useEffect } from 'react';\nimport { VERSE_CONTROL_KEY, VerseControlLockedError } from './control-queries.js';\nimport type { OptionalFleetRead } from './fleet-contract.js';\nimport type {\n OvernightAction,\n OvernightActionResult,\n OvernightStatus,\n OvernightStopRule,\n} from './overnight-contract.js';\nimport { projectOvernight } from './overnight-model.js';\n\nexport const VERSE_OVERNIGHT_KEY = 'verse-overnight';\nexport const OVERNIGHT_PATH = '/api/verse/overnight';\n\nfunction describeAbsence(err: unknown): string {\n if (err instanceof ApiError) {\n if (err.status === 404) {\n return `This build does not expose ${OVERNIGHT_PATH}, so an overnight run cannot be armed from here. It is a missing route, not a run that refused to start.`;\n }\n return `${OVERNIGHT_PATH} answered HTTP ${err.status}.`;\n }\n return `${OVERNIGHT_PATH} could not be reached.`;\n}\n\n/**\n * `GET /api/verse/overnight` — is a run armed, and what has it done.\n *\n * `value` is null both when the route was absent and when it answered\n * something this client could not narrow; `available` and `reason` are what\n * tell those two apart, and the panel words them differently.\n */\nexport const overnightQuery: QueryDef<OptionalFleetRead<OvernightStatus>> = {\n key: VERSE_OVERNIGHT_KEY,\n fetch: async (signal) => {\n try {\n const raw = await apiGet<unknown>(OVERNIGHT_PATH, signal);\n const value = projectOvernight(raw);\n if (value === null) {\n return {\n value: null,\n available: true,\n reason: `${OVERNIGHT_PATH} answered in a shape this client does not recognise, so nothing is shown rather than guessed.`,\n };\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: describeAbsence(err) };\n }\n },\n};\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\nfunction invalidateOvernight(): void {\n invalidate(VERSE_OVERNIGHT_KEY);\n // Arming changes what the daemon will do next, and the control snapshot is\n // what the rest of the cockpit reads that from.\n invalidate(VERSE_CONTROL_KEY);\n}\n\n/** Arm an overnight run with exactly one stop rule. */\nexport async function armOvernight(stopRule: OvernightStopRule): Promise<OvernightActionResult> {\n const body: OvernightAction = { action: 'arm', stopRule };\n const result = await post<OvernightActionResult>(OVERNIGHT_PATH, body);\n invalidateOvernight();\n return result;\n}\n\n/**\n * Disarm: no further overnight run starts.\n *\n * This is NOT the halt. It stops the arrangement, not the loop — a run already\n * in flight keeps going until it is paused. The panel says so at the click.\n */\nexport async function disarmOvernight(): Promise<OvernightActionResult> {\n const body: OvernightAction = { action: 'disarm' };\n const result = await post<OvernightActionResult>(OVERNIGHT_PATH, body);\n invalidateOvernight();\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Polling\n// ---------------------------------------------------------------------------\n\n/**\n * Slower than the fleet's 4s: an overnight run's counters move on the scale of\n * whole iterations, and the thing an operator watches second by second (the\n * elapsed clock and the countdown) is derived locally from `useNow`.\n */\nexport const OVERNIGHT_POLL_MS = 15_000;\n\n/**\n * Keep the overnight status live while a run is armed and the tab is visible.\n *\n * Only while armed: a disarmed panel has one boolean to report and polling it\n * every fifteen seconds forever would be pure waste. Hidden tabs stop the\n * timer and take one immediate reading when they come back, so a panel\n * returned to in the morning is current on the first frame.\n */\nexport function useOvernightPolling(armed: boolean, intervalMs: number = OVERNIGHT_POLL_MS): void {\n const refetch = useRefetch(overnightQuery);\n\n useEffect(() => {\n if (!armed) return;\n let timer: ReturnType<typeof setInterval> | null = null;\n\n const start = (): void => {\n if (timer !== null) return;\n timer = setInterval(refetch, intervalMs);\n };\n const stop = (): void => {\n if (timer === null) return;\n clearInterval(timer);\n timer = null;\n };\n const onVisibility = (): void => {\n if (document.visibilityState === 'hidden') {\n stop();\n return;\n }\n refetch();\n start();\n };\n\n if (document.visibilityState !== 'hidden') start();\n document.addEventListener('visibilitychange', onVisibility);\n return () => {\n stop();\n document.removeEventListener('visibilitychange', onVisibility);\n };\n }, [armed, intervalMs, refetch]);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"overnight-queries-X-44Gsw5.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/autonomy/overnight-model.ts","../../../../../../src/web-ui/routes/verse/autonomy/overnight-queries.ts"],"sourcesContent":["/**\n * routes/verse/autonomy/overnight-model.ts — the pure half of the Overnight\n * panel: narrow the server's body, resolve the operator's stop rule, and\n * derive the one line that says how far the run is from stopping.\n *\n * Framework-free so it unit-tests without a DOM, and separate from the panel\n * because two of these functions are where the panel can most easily start\n * lying:\n *\n * - `projectOvernight` NARROWS, it does not cast. The route is being written\n * by another owner in parallel with this surface, so a field that drifts in\n * name or type has to degrade to `null` — which the panel renders as \"not\n * stated\" — rather than reach a render as `undefined` and crash, or reach\n * it as `0` and read as a fact. Same discipline as `fleet-model.ts`.\n * - `stopProgress` never invents a denominator. \"Until I pause it\" has no\n * progress, and drawing a bar for it would be a picture of a finish line\n * that does not exist.\n */\nimport { formatDuration, UNKNOWN } from './format.js';\nimport type {\n OvernightDiscard,\n OvernightGate,\n OvernightMerge,\n OvernightRun,\n OvernightStatus,\n OvernightStopRule,\n OvernightStopRuleKind,\n} from './overnight-contract.js';\n\n// ---------------------------------------------------------------------------\n// Narrowing\n// ---------------------------------------------------------------------------\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction str(value: unknown): string | null {\n return typeof value === 'string' && value.trim() !== '' ? value : null;\n}\n\nfunction bool(value: unknown): boolean | null {\n return typeof value === 'boolean' ? value : null;\n}\n\n/** A count. Negative and non-finite are not counts, so they are not observed. */\nfunction count(value: unknown): number | null {\n if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) return null;\n return Math.floor(value);\n}\n\nexport function projectStopRule(raw: unknown): OvernightStopRule | null {\n if (!isRecord(raw)) return null;\n const kind = str(raw['kind']);\n if (kind === 'until-paused') return { kind: 'until-paused' };\n if (kind === 'at-time') {\n const at = str(raw['at']);\n // An unparseable instant is worse than no rule: it would render as a\n // countdown to NaN. Refuse it here so the panel can say \"not stated\".\n if (at === null || Number.isNaN(Date.parse(at))) return null;\n return { kind: 'at-time', at };\n }\n if (kind === 'after-iterations') {\n const iterations = count(raw['iterations']);\n if (iterations === null || iterations <= 0) return null;\n return { kind: 'after-iterations', iterations };\n }\n return null;\n}\n\nfunction projectMerges(raw: unknown): OvernightMerge[] {\n if (!Array.isArray(raw)) return [];\n const out: OvernightMerge[] = [];\n for (const [index, item] of raw.entries()) {\n if (!isRecord(item)) continue;\n const repo = str(item['repo']);\n if (repo === null) continue;\n out.push({\n id: str(item['id']) ?? `${repo}:${index}`,\n repo,\n title: str(item['title']) ?? 'untitled change',\n at: str(item['at']),\n commit: str(item['commit']),\n });\n }\n return out;\n}\n\nfunction projectDiscards(raw: unknown): OvernightDiscard[] {\n if (!Array.isArray(raw)) return [];\n const out: OvernightDiscard[] = [];\n for (const [index, item] of raw.entries()) {\n if (!isRecord(item)) continue;\n const repo = str(item['repo']);\n if (repo === null) continue;\n out.push({\n id: str(item['id']) ?? `${repo}:${index}`,\n repo,\n title: str(item['title']) ?? 'untitled change',\n at: str(item['at']),\n // A discard with no stated reason is the one row an operator will ask\n // about in the morning, so it says that it has none rather than being\n // rendered as a blank cell.\n reason: str(item['reason']) ?? 'no reason recorded',\n });\n }\n return out;\n}\n\nfunction projectGate(raw: unknown): OvernightGate | null {\n if (!isRecord(raw)) return null;\n return {\n tests: bool(raw['tests']),\n lint: bool(raw['lint']),\n typecheck: bool(raw['typecheck']),\n autoMerge: bool(raw['autoMerge']),\n branch: str(raw['branch']),\n };\n}\n\nfunction projectRun(raw: unknown): OvernightRun | null {\n if (!isRecord(raw)) return null;\n const runId = str(raw['runId']);\n if (runId === null) return null;\n return {\n runId,\n startedAt: str(raw['startedAt']),\n stopRule: projectStopRule(raw['stopRule']),\n iterationsDone: count(raw['iterationsDone']),\n repo: str(raw['repo']),\n activity: str(raw['activity']),\n merged: projectMerges(raw['merged']),\n discarded: projectDiscards(raw['discarded']),\n };\n}\n\n/**\n * `GET /api/verse/overnight` → a status, or null when the body is not one.\n *\n * `armed` is the single field this refuses to guess: a body that does not say\n * whether a run is armed is not a status, because \"nothing is armed\" is\n * exactly the claim a person checks before closing the laptop.\n */\nexport function projectOvernight(raw: unknown): OvernightStatus | null {\n if (!isRecord(raw)) return null;\n const armed = bool(raw['armed']);\n if (armed === null) return null;\n return {\n armed,\n run: projectRun(raw['run']),\n repos: count(raw['repos']),\n // Present-but-invalid reads as null (\"not recorded\"); absent stays absent,\n // so an older server is not shown as having lost a count it never sent.\n ...(raw['mirrors'] !== undefined ? { mirrors: count(raw['mirrors']) } : {}),\n gate: projectGate(raw['gate']),\n };\n}\n\n// ---------------------------------------------------------------------------\n// The operator's side of the stop rule\n// ---------------------------------------------------------------------------\n\n/** Smallest and largest iteration cap the form will send. */\nexport const ITERATIONS_MIN = 1;\nexport const ITERATIONS_MAX = 500;\n\n/**\n * Turn an `<input type=\"time\">` value (\"23:30\") into the next occurrence of\n * that wall-clock time, as an absolute instant.\n *\n * The whole point of arming this at 11pm is that \"07:00\" means tomorrow\n * morning. Resolving it on the client, in the operator's own zone, is what\n * makes that unambiguous by the time it reaches a server that may not share\n * the zone — and rounds to the minute, so a run armed at 06:59:58 for 07:00\n * does not stop two seconds later.\n */\nexport function resolveStopAt(value: string, now: Date = new Date()): string | null {\n const match = /^(\\d{1,2}):(\\d{2})$/.exec(value.trim());\n if (!match) return null;\n const hours = Number(match[1]);\n const minutes = Number(match[2]);\n if (!Number.isInteger(hours) || !Number.isInteger(minutes)) return null;\n if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59) return null;\n const at = new Date(now);\n at.setHours(hours, minutes, 0, 0);\n if (at.getTime() <= now.getTime()) at.setDate(at.getDate() + 1);\n return at.toISOString();\n}\n\n/** \"07:00\" as the operator's locale writes it — never a raw ISO string. */\nexport function formatStopClock(iso: string | null): string {\n if (!iso) return UNKNOWN;\n const ms = Date.parse(iso);\n if (Number.isNaN(ms)) return UNKNOWN;\n return new Date(ms).toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });\n}\n\n/** True when the resolved instant is not today — \"07:00 tomorrow\". */\nexport function isNextDay(iso: string | null, now: Date = new Date()): boolean {\n if (!iso) return false;\n const ms = Date.parse(iso);\n if (Number.isNaN(ms)) return false;\n return new Date(ms).toDateString() !== now.toDateString();\n}\n\n/**\n * The sentence the Arm button is committing to, before the click.\n *\n * It restates the rule the operator chose in the operator's own units, so the\n * button is never the only description of what is about to be authorised.\n */\nexport function describeStopRule(rule: OvernightStopRule, now: Date = new Date()): string {\n switch (rule.kind) {\n case 'until-paused':\n return 'Runs until you pause it — no stop time, no iteration limit.';\n case 'at-time':\n return `Stops at ${formatStopClock(rule.at)}${isNextDay(rule.at, now) ? ' tomorrow' : ''}.`;\n case 'after-iterations':\n return `Stops after ${rule.iterations} ${rule.iterations === 1 ? 'iteration' : 'iterations'}.`;\n }\n}\n\n/** The short label each stop rule wears in the armed summary. */\nexport function stopRuleLabel(kind: OvernightStopRuleKind): string {\n switch (kind) {\n case 'until-paused':\n return 'Until paused';\n case 'at-time':\n return 'At a set time';\n case 'after-iterations':\n return 'After N iterations';\n }\n}\n\n// ---------------------------------------------------------------------------\n// How far to the stop condition\n// ---------------------------------------------------------------------------\n\nexport interface StopProgress {\n /** The rule, restated: \"Stops at 07:00\". */\n headline: string;\n /** How much is left: \"4h 12m left\", \"12 of 20 done\". */\n remaining: string;\n /** 0-100 for a meter, or null when there is no honest denominator. */\n percent: number | null;\n /** True once the condition is met and the loop should be winding down. */\n reached: boolean;\n}\n\n/**\n * How far the run is from its stop condition.\n *\n * `percent` is null for \"until I pause it\" on purpose: an open-ended run has\n * no finish line, and a bar with no denominator is the exact kind of confident\n * graphic this cockpit is not allowed to draw.\n */\nexport function stopProgress(\n rule: OvernightStopRule | null,\n run: OvernightRun | null,\n now: number = Date.now(),\n): StopProgress {\n if (rule === null) {\n return {\n headline: 'Stop rule not stated',\n remaining: UNKNOWN,\n percent: null,\n reached: false,\n };\n }\n\n if (rule.kind === 'until-paused') {\n return {\n headline: 'Runs until you pause it',\n remaining: 'no stop time, no iteration limit',\n percent: null,\n reached: false,\n };\n }\n\n if (rule.kind === 'at-time') {\n const at = Date.parse(rule.at);\n if (Number.isNaN(at)) {\n return { headline: 'Stop time not readable', remaining: UNKNOWN, percent: null, reached: false };\n }\n const headline = `Stops at ${formatStopClock(rule.at)}`;\n const left = at - now;\n if (left <= 0) {\n return { headline, remaining: 'stop time reached', percent: 100, reached: true };\n }\n const startedAt = run?.startedAt ? Date.parse(run.startedAt) : Number.NaN;\n // Elapsed over the run's whole window — which needs a start. Without one\n // the countdown is still true, so it is shown; only the bar is withheld.\n const percent =\n Number.isNaN(startedAt) || at <= startedAt\n ? null\n : Math.min(100, Math.max(0, Math.round(((now - startedAt) / (at - startedAt)) * 100)));\n return { headline, remaining: `${formatDuration(left)} left`, percent, reached: false };\n }\n\n const done = run?.iterationsDone;\n const headline = `Stops after ${rule.iterations} ${rule.iterations === 1 ? 'iteration' : 'iterations'}`;\n if (typeof done !== 'number') {\n return {\n headline,\n remaining: `${UNKNOWN} of ${rule.iterations} done`,\n percent: null,\n reached: false,\n };\n }\n return {\n headline,\n remaining: `${done} of ${rule.iterations} done`,\n percent: Math.min(100, Math.round((done / rule.iterations) * 100)),\n reached: done >= rule.iterations,\n };\n}\n\n/** \"3h 04m\" since the run started, or UNKNOWN when it never said. */\nexport function formatRunElapsed(startedAt: string | null | undefined, now: number = Date.now()): string {\n if (!startedAt) return UNKNOWN;\n const ms = Date.parse(startedAt);\n if (Number.isNaN(ms)) return UNKNOWN;\n return formatDuration(Math.max(0, now - ms));\n}\n\n/**\n * The checks named as one phrase: \"tests, lint and typecheck\".\n *\n * Only checks the server said `true` about are named. A `null` check is not\n * named as running AND not named as skipped — `gateCaveat` below says so in\n * words instead, because a gate an operator believes is running when it is not\n * is the single most expensive misreading this panel could cause.\n */\nexport function gateChecks(gate: OvernightGate | null): string[] {\n if (gate === null) return [];\n const named: string[] = [];\n if (gate.tests === true) named.push('tests');\n if (gate.lint === true) named.push('lint');\n if (gate.typecheck === true) named.push('typecheck');\n return named;\n}\n\n/** The checks the server would not commit to, if any. */\nexport function gateUnstated(gate: OvernightGate | null): string[] {\n if (gate === null) return ['tests', 'lint', 'typecheck'];\n const unstated: string[] = [];\n if (gate.tests === null) unstated.push('tests');\n if (gate.lint === null) unstated.push('lint');\n if (gate.typecheck === null) unstated.push('typecheck');\n return unstated;\n}\n\nexport function joinPhrase(parts: readonly string[]): string {\n if (parts.length === 0) return '';\n if (parts.length === 1) return parts[0]!;\n return `${parts.slice(0, -1).join(', ')} and ${parts[parts.length - 1]!}`;\n}\n","/**\n * routes/verse/autonomy/overnight-queries.ts — the one read and the one write\n * behind the Overnight panel: `GET /api/verse/overnight` and\n * `POST /api/verse/overnight`.\n *\n * Same contract as `control-queries.ts` and `fleet-queries.ts` — the read is a\n * QueryDef consumed through `useQuery` (cache-backed, so a poll never blanks a\n * populated panel); the write pulls the held mutation token from auth-store,\n * touches the hold on success, and invalidates exactly the keys it affects.\n * There is no new data layer here on purpose.\n *\n * TWO THINGS THAT ARE DELIBERATE:\n *\n * 1. **The read does not throw on absence.** The route does not exist yet —\n * four owners are building the engine, the permit, the budgets and the\n * local-only policy in parallel. A server without it answers 404, and 404\n * means \"this panel has no source yet\", not \"Autonomy is broken\". It comes\n * back as `OptionalFleetRead` (reused rather than re-declared, because two\n * shapes for \"a read that is allowed to be absent\" would be one too many)\n * and the panel renders a designed not-available state from `reason`.\n * 401 still propagates: an expired read session is an unauthorized state\n * for the whole surface, not a missing panel.\n *\n * 2. **There is no pause route here, and there must not be one.** The halt\n * this panel offers is the DAEMON-SCOPED pause — `~/.ashlr/daemon.paused`,\n * via `runDaemonAction('pause')` in control-queries.ts. Disarming stops\n * arming the next run; pausing stops the loop that is running now, and\n * they are different questions. Neither is `stopDaemon()`, which is\n * `setKill(true)` and therefore the emergency stop wearing a quieter name\n * (see the header of DaemonControls.tsx).\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 { useRefetch } from '../../../data/hooks.js';\nimport { useEffect } from 'react';\nimport { VERSE_CONTROL_KEY, VerseControlLockedError } from './control-queries.js';\nimport type { OptionalFleetRead } from './fleet-contract.js';\nimport type {\n OvernightAction,\n OvernightActionResult,\n OvernightStatus,\n OvernightStopRule,\n} from './overnight-contract.js';\nimport { projectOvernight } from './overnight-model.js';\n\nexport const VERSE_OVERNIGHT_KEY = 'verse-overnight';\nexport const OVERNIGHT_PATH = '/api/verse/overnight';\n\nfunction describeAbsence(err: unknown): string {\n if (err instanceof ApiError) {\n if (err.status === 404) {\n return `This build does not expose ${OVERNIGHT_PATH}, so an overnight run cannot be armed from here. It is a missing route, not a run that refused to start.`;\n }\n return `${OVERNIGHT_PATH} answered HTTP ${err.status}.`;\n }\n return `${OVERNIGHT_PATH} could not be reached.`;\n}\n\n/**\n * `GET /api/verse/overnight` — is a run armed, and what has it done.\n *\n * `value` is null both when the route was absent and when it answered\n * something this client could not narrow; `available` and `reason` are what\n * tell those two apart, and the panel words them differently.\n */\nexport const overnightQuery: QueryDef<OptionalFleetRead<OvernightStatus>> = {\n key: VERSE_OVERNIGHT_KEY,\n fetch: async (signal) => {\n try {\n const raw = await apiGet<unknown>(OVERNIGHT_PATH, signal);\n const value = projectOvernight(raw);\n if (value === null) {\n return {\n value: null,\n available: true,\n reason: `${OVERNIGHT_PATH} answered in a shape this client does not recognise, so nothing is shown rather than guessed.`,\n };\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: describeAbsence(err) };\n }\n },\n};\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\nfunction invalidateOvernight(): void {\n invalidate(VERSE_OVERNIGHT_KEY);\n // Arming changes what the daemon will do next, and the control snapshot is\n // what the rest of the cockpit reads that from.\n invalidate(VERSE_CONTROL_KEY);\n}\n\n/** Arm an overnight run with exactly one stop rule. */\nexport async function armOvernight(stopRule: OvernightStopRule): Promise<OvernightActionResult> {\n const body: OvernightAction = { action: 'arm', stopRule };\n const result = await post<OvernightActionResult>(OVERNIGHT_PATH, body);\n invalidateOvernight();\n return result;\n}\n\n/**\n * Disarm: no further overnight run starts.\n *\n * This is NOT the halt. It stops the arrangement, not the loop — a run already\n * in flight keeps going until it is paused. The panel says so at the click.\n */\nexport async function disarmOvernight(): Promise<OvernightActionResult> {\n const body: OvernightAction = { action: 'disarm' };\n const result = await post<OvernightActionResult>(OVERNIGHT_PATH, body);\n invalidateOvernight();\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Polling\n// ---------------------------------------------------------------------------\n\n/**\n * Slower than the fleet's 4s: an overnight run's counters move on the scale of\n * whole iterations, and the thing an operator watches second by second (the\n * elapsed clock and the countdown) is derived locally from `useNow`.\n */\nexport const OVERNIGHT_POLL_MS = 15_000;\n\n/**\n * Keep the overnight status live while a run is armed and the tab is visible.\n *\n * Only while armed: a disarmed panel has one boolean to report and polling it\n * every fifteen seconds forever would be pure waste. Hidden tabs stop the\n * timer and take one immediate reading when they come back, so a panel\n * returned to in the morning is current on the first frame.\n */\nexport function useOvernightPolling(armed: boolean, intervalMs: number = OVERNIGHT_POLL_MS): void {\n const refetch = useRefetch(overnightQuery);\n\n useEffect(() => {\n if (!armed) return;\n let timer: ReturnType<typeof setInterval> | null = null;\n\n const start = (): void => {\n if (timer !== null) return;\n timer = setInterval(refetch, intervalMs);\n };\n const stop = (): void => {\n if (timer === null) return;\n clearInterval(timer);\n timer = null;\n };\n const onVisibility = (): void => {\n if (document.visibilityState === 'hidden') {\n stop();\n return;\n }\n refetch();\n start();\n };\n\n if (document.visibilityState !== 'hidden') start();\n document.addEventListener('visibilitychange', onVisibility);\n return () => {\n stop();\n document.removeEventListener('visibilitychange', onVisibility);\n };\n }, [armed, intervalMs, refetch]);\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ ._header_157en_11{align-items:center;gap:var(--space-2);min-width:0;min-height:calc(var(--control-h-sm) + 2 * var(--space-1));padding:var(--space-1) var(--space-2) var(--space-1) var(--space-3);border-bottom:1px solid var(--border-subtle);background:var(--bg-surface);flex:none;display:flex}._title_157en_25{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--text-secondary);font-size:var(--text-xs-size);line-height:var(--text-xs-line);flex:0 auto;overflow:hidden}._actions_157en_37{align-items:center;gap:var(--space-1);flex:none;margin-left:auto;display:flex}
@@ -0,0 +1,2 @@
1
+ var e={header:`_header_157en_11`,title:`_title_157en_25`,actions:`_actions_157en_37`};export{e as t};
2
+ //# sourceMappingURL=pane-chrome.module-D7o-fVd0.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pane-chrome.module-D7o-fVd0.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/dock/pane-chrome.module.css"],"sourcesContent":["/*\n * dock/pane-chrome.module.css — the header row every dock pane with controls\n * wears under the dock's own tabs (Terminal, Preview, Review): what the pane\n * is showing on the left, its actions on the right, one height and one\n * surface, so two panes stacked in a split line up row for row.\n *\n * The panes compose these classes with their own layout-only ones; box\n * properties (height, padding, border, background) live HERE only, so a\n * pane's module cannot drift from the others. Tokens only (style-scan-310).\n */\n.header {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n flex: none;\n min-width: 0;\n /* One sm control plus a hairline of air above and below. */\n min-height: calc(var(--control-h-sm) + 2 * var(--space-1));\n padding: var(--space-1) var(--space-2) var(--space-1) var(--space-3);\n border-bottom: 1px solid var(--border-subtle);\n background: var(--bg-surface);\n}\n\n/* The subject: a folder name, a repository. Truncates (its element carries the full text as a title). */\n.title {\n flex: 0 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--text-secondary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n\n/* Actions sit on the right and never shrink or wrap their labels. */\n.actions {\n display: flex;\n align-items: center;\n gap: var(--space-1);\n flex: none;\n margin-left: auto;\n}\n"],"mappings":""}
@@ -0,0 +1 @@
1
+ import"./global-Di2PUgj4.js";import"./MutationTokenDialog-SkRxqV_I.js";import"./Epistemic-uARPnx9x.js";import"./StatusBadge-BwnBNFQr.js";import"./RouteErrorBoundary-C5SxA2Dg.js";import"./RefreshIndicator-BLnr9IOM.js";import"./VerseConsoleApp-WVeyJnW7.js";import"./Segmented-BL40udoO.js";import"./Tag-_-K1h7Hk.js";import"./Button-DYv_KKxr.js";import"./EmptyState-DhNgDDrF.js";import"./Meter-D-hncpkO.js";import"./Slider-DUMo9HDD.js";import"./Switch-CcR5Llk5.js";import"./Select-FWLnAw_j.js";import"./Input-B9-VLcHS.js";import"./Sheet-DZKcQXQg.js";
@@ -1,2 +1,2 @@
1
- import{l as e}from"./global-DVgMguLr.js";var t={key:`dashboard-snapshot`,fetch:t=>e(`/api/snapshot`,t)},n={key:`control-snapshot`,fetch:t=>e(`/api/control`,t)},r={key:`agent-os-snapshot`,fetch:t=>e(`/api/agent-os`,t)},i={key:`universe-overview`,fetch:t=>e(`/api/universe`,t)};function a(t){return{key:`universe-graph-${t}`,fetch:n=>e(`/api/universe/graph?universeId=${encodeURIComponent(t)}`,n)}}var o={key:`runs`,fetch:t=>e(`/api/runs`,t)};function s(t){return{key:`run-detail-${t}`,fetch:n=>e(`/api/run/${encodeURIComponent(t)}`,n)}}var c={key:`swarms`,fetch:t=>e(`/api/swarms`,t)};function l(t){return{key:`swarm-detail-${t}`,fetch:n=>e(`/api/swarm/${encodeURIComponent(t)}`,n)}}var u={key:`daemon`,fetch:t=>e(`/api/daemon-observation`,t)},d={key:`fleet`,fetch:t=>e(`/api/fleet`,t)},f={key:`fleet-activity`,fetch:t=>e(`/api/fleet-activity`,t)},p={key:`goals`,fetch:t=>e(`/api/goals`,t)},m={key:`vision-mission`,fetch:t=>e(`/api/vision/mission`,t)},h={key:`inbox`,fetch:t=>e(`/api/inbox`,t)};function g(t={}){let n=new URLSearchParams;t.status!==void 0&&n.set(`status`,t.status),t.since!==void 0&&n.set(`since`,t.since),t.limit!==void 0&&n.set(`limit`,String(t.limit));let r=n.toString();return{key:`inbox-list:${t.status??`pending`}:${t.since??``}:${t.limit??``}`,fetch:t=>e(`/api/inbox${r?`?${r}`:``}`,t)}}function _(t){return{key:`proposal-detail-${t}`,fetch:n=>e(`/api/inbox/${encodeURIComponent(t)}`,n)}}var v={key:`control-logs-observation`,fetch:t=>e(`/api/logs-observation?tail=200`,t)};function y(t){return{key:`pulse-${t}`,fetch:n=>e(`/api/pulse?window=${t}`,n)}}function b(e){return typeof e==`object`&&!!e&&`entry`in e&&`score`in e}function x(t){let n=t.trim();return{key:n?`genome-search-${n}`:`genome-list`,fetch:t=>e(n?`/api/genome?q=${encodeURIComponent(n)}`:`/api/genome`,t)}}function S(t){return{key:`models-${t}`,fetch:n=>e(`/api/models?window=${t}`,n)}}var C={key:`portfolio`,fetch:t=>e(`/api/portfolio`,t)};export{m as C,i as S,s as _,t as a,c as b,x as c,h as d,b as f,y as g,_ as h,u as i,p as l,C as m,v as n,f as o,S as p,n as r,d as s,r as t,g as u,o as v,a as x,l as y};
2
- //# sourceMappingURL=queries-BuYIEHst.js.map
1
+ import{l as e}from"./global-Di2PUgj4.js";var t={key:`dashboard-snapshot`,fetch:t=>e(`/api/snapshot`,t)},n={key:`control-snapshot`,fetch:t=>e(`/api/control`,t)},r={key:`agent-os-snapshot`,fetch:t=>e(`/api/agent-os`,t)},i={key:`universe-overview`,fetch:t=>e(`/api/universe`,t)};function a(t){return{key:`universe-graph-${t}`,fetch:n=>e(`/api/universe/graph?universeId=${encodeURIComponent(t)}`,n)}}var o={key:`runs`,fetch:t=>e(`/api/runs`,t)};function s(t){return{key:`run-detail-${t}`,fetch:n=>e(`/api/run/${encodeURIComponent(t)}`,n)}}var c={key:`swarms`,fetch:t=>e(`/api/swarms`,t)};function l(t){return{key:`swarm-detail-${t}`,fetch:n=>e(`/api/swarm/${encodeURIComponent(t)}`,n)}}var u={key:`daemon`,fetch:t=>e(`/api/daemon-observation`,t)},d={key:`fleet`,fetch:t=>e(`/api/fleet`,t)},f={key:`fleet-activity`,fetch:t=>e(`/api/fleet-activity`,t)},p={key:`goals`,fetch:t=>e(`/api/goals`,t)},m={key:`vision-mission`,fetch:t=>e(`/api/vision/mission`,t)},h={key:`inbox`,fetch:t=>e(`/api/inbox`,t)};function g(t={}){let n=new URLSearchParams;t.status!==void 0&&n.set(`status`,t.status),t.since!==void 0&&n.set(`since`,t.since),t.limit!==void 0&&n.set(`limit`,String(t.limit));let r=n.toString();return{key:`inbox-list:${t.status??`pending`}:${t.since??``}:${t.limit??``}`,fetch:t=>e(`/api/inbox${r?`?${r}`:``}`,t)}}function _(t){return{key:`proposal-detail-${t}`,fetch:n=>e(`/api/inbox/${encodeURIComponent(t)}`,n)}}var v={key:`control-logs-observation`,fetch:t=>e(`/api/logs-observation?tail=200`,t)};function y(t){return{key:`pulse-${t}`,fetch:n=>e(`/api/pulse?window=${t}`,n)}}function b(e){return typeof e==`object`&&!!e&&`entry`in e&&`score`in e}function x(t){let n=t.trim();return{key:n?`genome-search-${n}`:`genome-list`,fetch:t=>e(n?`/api/genome?q=${encodeURIComponent(n)}`:`/api/genome`,t)}}function S(t){return{key:`models-${t}`,fetch:n=>e(`/api/models?window=${t}`,n)}}var C={key:`portfolio`,fetch:t=>e(`/api/portfolio`,t)};export{m as C,i as S,s as _,t as a,c as b,x as c,h as d,b as f,y as g,_ as h,u as i,p as l,C as m,v as n,f as o,S as p,n as r,d as s,r as t,g as u,o as v,a as x,l as y};
2
+ //# sourceMappingURL=queries-BA4rNGD-.js.map