@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.
- package/CHANGELOG.md +156 -0
- package/README.md +343 -82
- package/dist/authority-surface.json +109 -29
- package/dist/build-identity.json +2 -2
- package/dist/cli/cloud.d.ts +39 -0
- package/dist/cli/cloud.js +448 -0
- package/dist/cli/cloud.js.map +1 -0
- package/dist/cli/completions.js +4 -0
- package/dist/cli/completions.js.map +1 -1
- package/dist/cli/help.js +2 -0
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +10 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/cloud/backlog.d.ts +17 -0
- package/dist/core/cloud/backlog.js +177 -0
- package/dist/core/cloud/backlog.js.map +1 -0
- package/dist/core/cloud/budget.d.ts +19 -0
- package/dist/core/cloud/budget.js +99 -0
- package/dist/core/cloud/budget.js.map +1 -0
- package/dist/core/cloud/checkout.d.ts +41 -0
- package/dist/core/cloud/checkout.js +168 -0
- package/dist/core/cloud/checkout.js.map +1 -0
- package/dist/core/cloud/cloud-api.d.ts +86 -0
- package/dist/core/cloud/cloud-api.js +599 -0
- package/dist/core/cloud/cloud-api.js.map +1 -0
- package/dist/core/cloud/delivery-contract.d.ts +25 -0
- package/dist/core/cloud/delivery-contract.js +138 -0
- package/dist/core/cloud/delivery-contract.js.map +1 -0
- package/dist/core/cloud/improvement-backlog.d.ts +11 -0
- package/dist/core/cloud/improvement-backlog.js +26 -0
- package/dist/core/cloud/improvement-backlog.js.map +1 -0
- package/dist/core/cloud/launcher.d.ts +68 -0
- package/dist/core/cloud/launcher.js +312 -0
- package/dist/core/cloud/launcher.js.map +1 -0
- package/dist/core/cloud/service.d.ts +51 -0
- package/dist/core/cloud/service.js +215 -0
- package/dist/core/cloud/service.js.map +1 -0
- package/dist/core/cloud/store.d.ts +41 -0
- package/dist/core/cloud/store.js +278 -0
- package/dist/core/cloud/store.js.map +1 -0
- package/dist/core/cloud/tracker.d.ts +30 -0
- package/dist/core/cloud/tracker.js +152 -0
- package/dist/core/cloud/tracker.js.map +1 -0
- package/dist/core/cloud/types.d.ts +233 -0
- package/dist/core/cloud/types.js +73 -0
- package/dist/core/cloud/types.js.map +1 -0
- package/dist/core/daemon/capacity-publisher.d.ts +19 -0
- package/dist/core/daemon/capacity-publisher.js +49 -2
- package/dist/core/daemon/capacity-publisher.js.map +1 -1
- package/dist/core/daemon/overnight-status.d.ts +13 -0
- package/dist/core/daemon/overnight-status.js +93 -8
- package/dist/core/daemon/overnight-status.js.map +1 -1
- package/dist/core/fleet/dispatch-router.js +26 -9
- package/dist/core/fleet/dispatch-router.js.map +1 -1
- package/dist/core/fleet/fleet-runtime-journal.js +12 -5
- package/dist/core/fleet/fleet-runtime-journal.js.map +1 -1
- package/dist/core/fleet/fleet-types.d.ts +13 -0
- package/dist/core/routing/budget-store.js +11 -5
- package/dist/core/routing/budget-store.js.map +1 -1
- package/dist/core/routing/capacity-history-api.d.ts +30 -0
- package/dist/core/routing/capacity-history-api.js +147 -0
- package/dist/core/routing/capacity-history-api.js.map +1 -0
- package/dist/core/routing/capacity-history-types.d.ts +63 -0
- package/dist/core/routing/capacity-history-types.js +18 -0
- package/dist/core/routing/capacity-history-types.js.map +1 -0
- package/dist/core/routing/capacity-history.d.ts +130 -0
- package/dist/core/routing/capacity-history.js +654 -0
- package/dist/core/routing/capacity-history.js.map +1 -0
- package/dist/core/routing/headroom.d.ts +5 -1
- package/dist/core/routing/headroom.js +82 -41
- package/dist/core/routing/headroom.js.map +1 -1
- package/dist/core/routing/router.d.ts +8 -1
- package/dist/core/routing/router.js +49 -16
- package/dist/core/routing/router.js.map +1 -1
- package/dist/core/routing/seat-reasons.d.ts +35 -0
- package/dist/core/routing/seat-reasons.js +48 -0
- package/dist/core/routing/seat-reasons.js.map +1 -0
- package/dist/core/routing/types.d.ts +37 -0
- package/dist/core/routing/types.js.map +1 -1
- package/dist/core/verse/activity-api.d.ts +3 -1
- package/dist/core/verse/activity-api.js +16 -1
- package/dist/core/verse/activity-api.js.map +1 -1
- package/dist/core/verse/activity.d.ts +7 -0
- package/dist/core/verse/activity.js +23 -0
- package/dist/core/verse/activity.js.map +1 -1
- package/dist/core/verse/fleet-history-types.d.ts +12 -4
- package/dist/core/verse/fleet-history-types.js +4 -2
- package/dist/core/verse/fleet-history-types.js.map +1 -1
- package/dist/core/verse/fleet-live-api.d.ts +14 -1
- package/dist/core/verse/fleet-live-api.js +31 -11
- package/dist/core/verse/fleet-live-api.js.map +1 -1
- package/dist/core/verse/preferences.d.ts +3 -1
- package/dist/core/verse/preferences.js +5 -2
- package/dist/core/verse/preferences.js.map +1 -1
- package/dist/core/verse/types.d.ts +5 -1
- package/dist/core/verse/types.js.map +1 -1
- package/dist/core/verse/verse-api.d.ts +1 -1
- package/dist/core/verse/verse-api.js +4 -1
- package/dist/core/verse/verse-api.js.map +1 -1
- package/dist/core/vision/leader-cloud.d.ts +63 -0
- package/dist/core/vision/leader-cloud.js +134 -0
- package/dist/core/vision/leader-cloud.js.map +1 -0
- package/dist/core/vision/leader.d.ts +6 -0
- package/dist/core/vision/leader.js +12 -1
- package/dist/core/vision/leader.js.map +1 -1
- package/dist/core/web/public/next/assets/{ActionMenu-DhbNne-M.js → ActionMenu-CQvNJvHY.js} +2 -2
- package/dist/core/web/public/next/assets/{ActionMenu-DhbNne-M.js.map → ActionMenu-CQvNJvHY.js.map} +1 -1
- package/dist/core/web/public/next/assets/Advanced-Bywv_iYR.css +1 -0
- package/dist/core/web/public/next/assets/Advanced-DEM93sKI.js +2 -0
- package/dist/core/web/public/next/assets/Advanced-DEM93sKI.js.map +1 -0
- package/dist/core/web/public/next/assets/{App-DyBg1v_q.js → App-CimXmK0L.js} +5 -5
- package/dist/core/web/public/next/assets/{App-DyBg1v_q.js.map → App-CimXmK0L.js.map} +1 -1
- package/dist/core/web/public/next/assets/AppsSection-D6U-dSj6.js +2 -0
- package/dist/core/web/public/next/assets/AppsSection-D6U-dSj6.js.map +1 -0
- package/dist/core/web/public/next/assets/AreaTrend-LD9lCPkT.js +2 -0
- package/dist/core/web/public/next/assets/AreaTrend-LD9lCPkT.js.map +1 -0
- package/dist/core/web/public/next/assets/AutonomySection-3V9pUyxm.js +2 -0
- package/dist/core/web/public/next/assets/{AutonomySection-CoMngwNB.js.map → AutonomySection-3V9pUyxm.js.map} +1 -1
- package/dist/core/web/public/next/assets/BranchBar-BZNQ50YE.css +1 -0
- package/dist/core/web/public/next/assets/BranchBar-U8UdpfEB.js +2 -0
- package/dist/core/web/public/next/assets/BranchBar-U8UdpfEB.js.map +1 -0
- package/dist/core/web/public/next/assets/BudgetControl-DOTlMSmW.js +2 -0
- package/dist/core/web/public/next/assets/BudgetControl-DOTlMSmW.js.map +1 -0
- package/dist/core/web/public/next/assets/BurnDown-x4PWH9JF.js +2 -0
- package/dist/core/web/public/next/assets/BurnDown-x4PWH9JF.js.map +1 -0
- package/dist/core/web/public/next/assets/{Button-0-nNbv1h.js → Button-DYv_KKxr.js} +2 -2
- package/dist/core/web/public/next/assets/{Button-0-nNbv1h.js.map → Button-DYv_KKxr.js.map} +1 -1
- package/dist/core/web/public/next/assets/CapacityStrip-C667yQe8.js +2 -0
- package/dist/core/web/public/next/assets/CapacityStrip-C667yQe8.js.map +1 -0
- package/dist/core/web/public/next/assets/CapacityStrip-Cc28CyWk.css +1 -0
- package/dist/core/web/public/next/assets/ChatSection-CCcIPpOq.js +3 -0
- package/dist/core/web/public/next/assets/{ChatSection-B9cdRKUh.js.map → ChatSection-CCcIPpOq.js.map} +1 -1
- package/dist/core/web/public/next/assets/CloudBudgetForm-DJeJvBEu.js +2 -0
- package/dist/core/web/public/next/assets/CloudBudgetForm-DJeJvBEu.js.map +1 -0
- package/dist/core/web/public/next/assets/{CommandPalette-GpeCSrPy.js → CommandPalette-FiD4N8XD.js} +2 -2
- package/dist/core/web/public/next/assets/{CommandPalette-GpeCSrPy.js.map → CommandPalette-FiD4N8XD.js.map} +1 -1
- package/dist/core/web/public/next/assets/CommandSection-DN8KwH-X.js +2 -0
- package/dist/core/web/public/next/assets/CommandSection-DN8KwH-X.js.map +1 -0
- package/dist/core/web/public/next/assets/Composer-ByzxOJK6.css +1 -0
- package/dist/core/web/public/next/assets/Composer.module-C8U73KdQ.js +2 -0
- package/dist/core/web/public/next/assets/{Composer.module-DJMdrqNt.js.map → Composer.module-C8U73KdQ.js.map} +1 -1
- package/dist/core/web/public/next/assets/DiffPane-BAvvbBsf.css +1 -0
- package/dist/core/web/public/next/assets/DiffPane-DLJ3gGGK.js +2 -0
- package/dist/core/web/public/next/assets/DiffPane-DLJ3gGGK.js.map +1 -0
- package/dist/core/web/public/next/assets/{DiffViewer-tOGWk0CA.js → DiffViewer-B7NWPjIO.js} +2 -2
- package/dist/core/web/public/next/assets/{DiffViewer-tOGWk0CA.js.map → DiffViewer-B7NWPjIO.js.map} +1 -1
- package/dist/core/web/public/next/assets/DockHost-B4RaYOET.css +1 -0
- package/dist/core/web/public/next/assets/DockHost-DvR-hPhZ.js +2 -0
- package/dist/core/web/public/next/assets/DockHost-DvR-hPhZ.js.map +1 -0
- package/dist/core/web/public/next/assets/{EmptyState-DdJ4CxtO.js → EmptyState-DhNgDDrF.js} +2 -2
- package/dist/core/web/public/next/assets/{EmptyState-DdJ4CxtO.js.map → EmptyState-DhNgDDrF.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Epistemic-BLjM5y_y.js → Epistemic-uARPnx9x.js} +2 -2
- package/dist/core/web/public/next/assets/{Epistemic-BLjM5y_y.js.map → Epistemic-uARPnx9x.js.map} +1 -1
- package/dist/core/web/public/next/assets/FleetSection-CFiWeOEs.css +1 -0
- package/dist/core/web/public/next/assets/FleetSection-D_zRBCub.js +3 -0
- package/dist/core/web/public/next/assets/FleetSection-D_zRBCub.js.map +1 -0
- package/dist/core/web/public/next/assets/Funnel-CL8uHONq.js +2 -0
- package/dist/core/web/public/next/assets/Funnel-CL8uHONq.js.map +1 -0
- package/dist/core/web/public/next/assets/GearTray-C7k4l_BW.js +2 -0
- package/dist/core/web/public/next/assets/GearTray-C7k4l_BW.js.map +1 -0
- package/dist/core/web/public/next/assets/GrowthSection-DwdNSGj8.js +2 -0
- package/dist/core/web/public/next/assets/GrowthSection-DwdNSGj8.js.map +1 -0
- package/dist/core/web/public/next/assets/HandoffDialog-FPVOqOMN.js +2 -0
- package/dist/core/web/public/next/assets/HandoffDialog-FPVOqOMN.js.map +1 -0
- package/dist/core/web/public/next/assets/{Input-CTu0CycC.js → Input-B9-VLcHS.js} +2 -2
- package/dist/core/web/public/next/assets/{Input-CTu0CycC.js.map → Input-B9-VLcHS.js.map} +1 -1
- package/dist/core/web/public/next/assets/{LeaderCard-BuSDeATv.js → LeaderCard-4R0BhDzT.js} +2 -2
- package/dist/core/web/public/next/assets/{LeaderCard-BuSDeATv.js.map → LeaderCard-4R0BhDzT.js.map} +1 -1
- package/dist/core/web/public/next/assets/{MatrixHeatmap-9dKgJ_pT.css → MatrixHeatmap-Bmnvo1l1.css} +1 -1
- package/dist/core/web/public/next/assets/MatrixHeatmap-DiuushcS.js +2 -0
- package/dist/core/web/public/next/assets/MatrixHeatmap-DiuushcS.js.map +1 -0
- package/dist/core/web/public/next/assets/McpSection-CJ__OJKl.js +2 -0
- package/dist/core/web/public/next/assets/{McpSection-1UncWBpW.js.map → McpSection-CJ__OJKl.js.map} +1 -1
- package/dist/core/web/public/next/assets/MessageMarkdown-Cgh5f1-Q.css +1 -0
- package/dist/core/web/public/next/assets/MessageMarkdown-qWKyJvAQ.js +3 -0
- package/dist/core/web/public/next/assets/{MessageMarkdown-C4pl9LI5.js.map → MessageMarkdown-qWKyJvAQ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-CZsF77ZM.js → MessageMarkdownRenderer-x05TrsrW.js} +2 -2
- package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-CZsF77ZM.js.map → MessageMarkdownRenderer-x05TrsrW.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Meter-C18ciKz4.js → Meter-D-hncpkO.js} +2 -2
- package/dist/core/web/public/next/assets/{Meter-C18ciKz4.js.map → Meter-D-hncpkO.js.map} +1 -1
- package/dist/core/web/public/next/assets/MindSection-BjXHkQPS.js +2 -0
- package/dist/core/web/public/next/assets/MindSection-BjXHkQPS.js.map +1 -0
- package/dist/core/web/public/next/assets/MutationTokenDialog-SkRxqV_I.js +2 -0
- package/dist/core/web/public/next/assets/MutationTokenDialog-SkRxqV_I.js.map +1 -0
- package/dist/core/web/public/next/assets/NeedsYouDrawer-BpvidnM2.css +1 -0
- package/dist/core/web/public/next/assets/NeedsYouDrawer-rSd1ZHAR.js +2 -0
- package/dist/core/web/public/next/assets/NeedsYouDrawer-rSd1ZHAR.js.map +1 -0
- package/dist/core/web/public/next/assets/NeedsYouList-CG-nB1tr.js +2 -0
- package/dist/core/web/public/next/assets/NeedsYouList-CG-nB1tr.js.map +1 -0
- package/dist/core/web/public/next/assets/NeedsYouList-CruOt4JT.css +1 -0
- package/dist/core/web/public/next/assets/NewChatDialog-BeDQ1eW3.js +3 -0
- package/dist/core/web/public/next/assets/{NewChatDialog-B_BsS9pr.js.map → NewChatDialog-BeDQ1eW3.js.map} +1 -1
- package/dist/core/web/public/next/assets/OnboardingFlow-CkTZtt-m.js +2 -0
- package/dist/core/web/public/next/assets/{OnboardingFlow-CtCPpgoX.js.map → OnboardingFlow-CkTZtt-m.js.map} +1 -1
- package/dist/core/web/public/next/assets/PreviewPane-DoMsJSG3.css +1 -0
- package/dist/core/web/public/next/assets/PreviewPane-kzbbSK4u.js +2 -0
- package/dist/core/web/public/next/assets/PreviewPane-kzbbSK4u.js.map +1 -0
- package/dist/core/web/public/next/assets/RailStatus-D-t2gPae.js +2 -0
- package/dist/core/web/public/next/assets/RailStatus-D-t2gPae.js.map +1 -0
- package/dist/core/web/public/next/assets/{RefreshIndicator-CnhEovMZ.js → RefreshIndicator-BLnr9IOM.js} +2 -2
- package/dist/core/web/public/next/assets/{RefreshIndicator-CnhEovMZ.js.map → RefreshIndicator-BLnr9IOM.js.map} +1 -1
- package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-28gLwmwV.js → ResourcePoolConsoleApp-BeG0gBif.js} +4 -4
- package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-28gLwmwV.js.map → ResourcePoolConsoleApp-BeG0gBif.js.map} +1 -1
- package/dist/core/web/public/next/assets/ResourcesChrome-B3Z3O98t.css +1 -0
- package/dist/core/web/public/next/assets/ResourcesChrome-BzV6bkIa.js +3 -0
- package/dist/core/web/public/next/assets/ResourcesChrome-BzV6bkIa.js.map +1 -0
- package/dist/core/web/public/next/assets/ResourcesDrawer-CSKIO_wZ.css +1 -0
- package/dist/core/web/public/next/assets/ResourcesDrawer-o4ILHdep.js +2 -0
- package/dist/core/web/public/next/assets/ResourcesDrawer-o4ILHdep.js.map +1 -0
- package/dist/core/web/public/next/assets/{RouteErrorBoundary-AyUPCIb3.js → RouteErrorBoundary-C5SxA2Dg.js} +2 -2
- package/dist/core/web/public/next/assets/{RouteErrorBoundary-AyUPCIb3.js.map → RouteErrorBoundary-C5SxA2Dg.js.map} +1 -1
- package/dist/core/web/public/next/assets/RunInCloudAction-C3LBp7C4.js +2 -0
- package/dist/core/web/public/next/assets/RunInCloudAction-C3LBp7C4.js.map +1 -0
- package/dist/core/web/public/next/assets/SeatSelector-DpvvbjNm.js +3 -0
- package/dist/core/web/public/next/assets/{SeatSelector-DaUO-zoK.js.map → SeatSelector-DpvvbjNm.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Segmented-B_8c_83S.js → Segmented-BL40udoO.js} +2 -2
- package/dist/core/web/public/next/assets/{Segmented-B_8c_83S.js.map → Segmented-BL40udoO.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Select-Bl5g5Dt_.js → Select-FWLnAw_j.js} +2 -2
- package/dist/core/web/public/next/assets/{Select-Bl5g5Dt_.js.map → Select-FWLnAw_j.js.map} +1 -1
- package/dist/core/web/public/next/assets/{SessionInsightChip-w0I21q0c.js → SessionInsightChip-CWye87Ju.js} +2 -2
- package/dist/core/web/public/next/assets/{SessionInsightChip-w0I21q0c.js.map → SessionInsightChip-CWye87Ju.js.map} +1 -1
- package/dist/core/web/public/next/assets/SessionSearch-YvCHFUuN.js +2 -0
- package/dist/core/web/public/next/assets/{SessionSearch-B5aQ0BCM.js.map → SessionSearch-YvCHFUuN.js.map} +1 -1
- package/dist/core/web/public/next/assets/SettingsSection-Dr18upeE.js +2 -0
- package/dist/core/web/public/next/assets/SettingsSection-Dr18upeE.js.map +1 -0
- package/dist/core/web/public/next/assets/{Sheet-CVjk-cLI.js → Sheet-DZKcQXQg.js} +2 -2
- package/dist/core/web/public/next/assets/{Sheet-CVjk-cLI.js.map → Sheet-DZKcQXQg.js.map} +1 -1
- package/dist/core/web/public/next/assets/{ShortcutsOverlay-BiBjnBcc.js → ShortcutsOverlay-BpDimdPq.js} +2 -2
- package/dist/core/web/public/next/assets/{ShortcutsOverlay-BiBjnBcc.js.map → ShortcutsOverlay-BpDimdPq.js.map} +1 -1
- package/dist/core/web/public/next/assets/Sidebar-BRc1vGDF.css +1 -0
- package/dist/core/web/public/next/assets/Sidebar-BoBzBEFX.js +3 -0
- package/dist/core/web/public/next/assets/Sidebar-BoBzBEFX.js.map +1 -0
- package/dist/core/web/public/next/assets/{Slider-BS9MU5ZV.js → Slider-DUMo9HDD.js} +2 -2
- package/dist/core/web/public/next/assets/{Slider-BS9MU5ZV.js.map → Slider-DUMo9HDD.js.map} +1 -1
- package/dist/core/web/public/next/assets/{StatusBadge-DAf-ArKE.js → StatusBadge-BwnBNFQr.js} +2 -2
- package/dist/core/web/public/next/assets/{StatusBadge-DAf-ArKE.js.map → StatusBadge-BwnBNFQr.js.map} +1 -1
- package/dist/core/web/public/next/assets/StepBand-PDXMIlRk.js +2 -0
- package/dist/core/web/public/next/assets/StepBand-PDXMIlRk.js.map +1 -0
- package/dist/core/web/public/next/assets/{Surface-CiYOdNKQ.js → Surface-B3TZVoER.js} +2 -2
- package/dist/core/web/public/next/assets/{Surface-CiYOdNKQ.js.map → Surface-B3TZVoER.js.map} +1 -1
- package/dist/core/web/public/next/assets/Swimlane-DR4OgON_.js +2 -0
- package/dist/core/web/public/next/assets/Swimlane-DR4OgON_.js.map +1 -0
- package/dist/core/web/public/next/assets/{Switch-BzRXtNPt.js → Switch-CcR5Llk5.js} +2 -2
- package/dist/core/web/public/next/assets/{Switch-BzRXtNPt.js.map → Switch-CcR5Llk5.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Tag-DEEbDz7T.js → Tag-_-K1h7Hk.js} +2 -2
- package/dist/core/web/public/next/assets/{Tag-DEEbDz7T.js.map → Tag-_-K1h7Hk.js.map} +1 -1
- package/dist/core/web/public/next/assets/TerminalPane-BwfMbnJz.css +1 -0
- package/dist/core/web/public/next/assets/TerminalPane-_1aH4ndN.js +7 -0
- package/dist/core/web/public/next/assets/TerminalPane-_1aH4ndN.js.map +1 -0
- package/dist/core/web/public/next/assets/UniverseConsoleApp-BUsq-inZ.js +2 -0
- package/dist/core/web/public/next/assets/{UniverseConsoleApp-DKqAf-eD.js.map → UniverseConsoleApp-BUsq-inZ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{UniverseView-D6081LQL.js → UniverseView-Dogy_dsB.js} +2 -2
- package/dist/core/web/public/next/assets/{UniverseView-D6081LQL.js.map → UniverseView-Dogy_dsB.js.map} +1 -1
- package/dist/core/web/public/next/assets/UsageSection-DiX_dTyo.js +2 -0
- package/dist/core/web/public/next/assets/UsageSection-DiX_dTyo.js.map +1 -0
- package/dist/core/web/public/next/assets/UsageSection-DsB-Jqyl.css +1 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-Cxqr-3qc.css +1 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-WVeyJnW7.js +3 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-WVeyJnW7.js.map +1 -0
- package/dist/core/web/public/next/assets/Workspace-BYW9dm90.css +1 -0
- package/dist/core/web/public/next/assets/Workspace-BbxZHwQd.js +10 -0
- package/dist/core/web/public/next/assets/Workspace-BbxZHwQd.js.map +1 -0
- package/dist/core/web/public/next/assets/actions-Ddfg2iLl.css +1 -0
- package/dist/core/web/public/next/assets/actions-s2lfm_5k.js +2 -0
- package/dist/core/web/public/next/assets/actions-s2lfm_5k.js.map +1 -0
- package/dist/core/web/public/next/assets/apps-model-CDFvmsQV.js +2 -0
- package/dist/core/web/public/next/assets/apps-model-CDFvmsQV.js.map +1 -0
- package/dist/core/web/public/next/assets/{budget-queries-Dacv1VYP.js → budget-queries-wUshcovN.js} +2 -2
- package/dist/core/web/public/next/assets/{budget-queries-Dacv1VYP.js.map → budget-queries-wUshcovN.js.map} +1 -1
- package/dist/core/web/public/next/assets/calendar-day-BxBYHfX1.js +2 -0
- package/dist/core/web/public/next/assets/calendar-day-BxBYHfX1.js.map +1 -0
- package/dist/core/web/public/next/assets/capacity-strip-model-Bj_9ztzs.js +2 -0
- package/dist/core/web/public/next/assets/capacity-strip-model-Bj_9ztzs.js.map +1 -0
- package/dist/core/web/public/next/assets/charts-CMSgAUKn.js +2 -0
- package/dist/core/web/public/next/assets/charts-CMSgAUKn.js.map +1 -0
- package/dist/core/web/public/next/assets/cloud-C1KPNRHC.css +1 -0
- package/dist/core/web/public/next/assets/cloud-queries-CnV1yaNG.js +2 -0
- package/dist/core/web/public/next/assets/cloud-queries-CnV1yaNG.js.map +1 -0
- package/dist/core/web/public/next/assets/cloud.module-CiwatLj3.js +2 -0
- package/dist/core/web/public/next/assets/cloud.module-CiwatLj3.js.map +1 -0
- package/dist/core/web/public/next/assets/colors-BZ3a9wFf.js +2 -0
- package/dist/core/web/public/next/assets/colors-BZ3a9wFf.js.map +1 -0
- package/dist/core/web/public/next/assets/{command-bus-CpYuam1F.js → command-bus-DqimKCUY.js} +2 -2
- package/dist/core/web/public/next/assets/{command-bus-CpYuam1F.js.map → command-bus-DqimKCUY.js.map} +1 -1
- package/dist/core/web/public/next/assets/command-catalog-BdtDH93o.js +2 -0
- package/dist/core/web/public/next/assets/command-catalog-BdtDH93o.js.map +1 -0
- package/dist/core/web/public/next/assets/{composer-keys-CYz4U4Bg.js → composer-keys-DBRymxQn.js} +2 -2
- package/dist/core/web/public/next/assets/{composer-keys-CYz4U4Bg.js.map → composer-keys-DBRymxQn.js.map} +1 -1
- package/dist/core/web/public/next/assets/context-model-Dwd49-dp.js +2 -0
- package/dist/core/web/public/next/assets/context-model-Dwd49-dp.js.map +1 -0
- package/dist/core/web/public/next/assets/context-model-MT17V86_.js +2 -0
- package/dist/core/web/public/next/assets/context-model-MT17V86_.js.map +1 -0
- package/dist/core/web/public/next/assets/context-queries-xVKIeynP.js +2 -0
- package/dist/core/web/public/next/assets/context-queries-xVKIeynP.js.map +1 -0
- package/dist/core/web/public/next/assets/context.module-BijAfoJw.js +2 -0
- package/dist/core/web/public/next/assets/context.module-BijAfoJw.js.map +1 -0
- package/dist/core/web/public/next/assets/{control-queries-BGjarMm9.js → control-queries-DOZR-D8G.js} +2 -2
- package/dist/core/web/public/next/assets/{control-queries-BGjarMm9.js.map → control-queries-DOZR-D8G.js.map} +1 -1
- package/dist/core/web/public/next/assets/dark-since-DOMvtB_G.js +2 -0
- package/dist/core/web/public/next/assets/dark-since-DOMvtB_G.js.map +1 -0
- package/dist/core/web/public/next/assets/dock-icons-8EtARwUm.js +2 -0
- package/dist/core/web/public/next/assets/dock-icons-8EtARwUm.js.map +1 -0
- package/dist/core/web/public/next/assets/dock-panes-UKS-mXhr.js +2 -0
- package/dist/core/web/public/next/assets/{dock-panes-BNTLvX7G.js.map → dock-panes-UKS-mXhr.js.map} +1 -1
- package/dist/core/web/public/next/assets/{dock-store-_E5h6TEq.js → dock-store-BA1cHOYA.js} +2 -2
- package/dist/core/web/public/next/assets/{dock-store-_E5h6TEq.js.map → dock-store-BA1cHOYA.js.map} +1 -1
- package/dist/core/web/public/next/assets/fleet-model-CNe8Wh-s.js +2 -0
- package/dist/core/web/public/next/assets/fleet-model-CNe8Wh-s.js.map +1 -0
- package/dist/core/web/public/next/assets/fleet-queries-BSdRlUwJ.js +2 -0
- package/dist/core/web/public/next/assets/fleet-queries-BSdRlUwJ.js.map +1 -0
- package/dist/core/web/public/next/assets/format-B8DAVcn2.js +2 -0
- package/dist/core/web/public/next/assets/format-B8DAVcn2.js.map +1 -0
- package/dist/core/web/public/next/assets/format-DKrNjdwD.js +2 -0
- package/dist/core/web/public/next/assets/format-DKrNjdwD.js.map +1 -0
- package/dist/core/web/public/next/assets/{git-model-5v5xGobf.js → git-model-CivuBY_D.js} +2 -2
- package/dist/core/web/public/next/assets/{git-model-5v5xGobf.js.map → git-model-CivuBY_D.js.map} +1 -1
- package/dist/core/web/public/next/assets/global-Di2PUgj4.js +2 -0
- package/dist/core/web/public/next/assets/global-Di2PUgj4.js.map +1 -0
- package/dist/core/web/public/next/assets/{guarded-action-vOPc8v75.js → guarded-action-CvOHcqyH.js} +2 -2
- package/dist/core/web/public/next/assets/{guarded-action-vOPc8v75.js.map → guarded-action-CvOHcqyH.js.map} +1 -1
- package/dist/core/web/public/next/assets/{icons-DWb24OA6.js → icons-B_yuAgdN.js} +2 -2
- package/dist/core/web/public/next/assets/{icons-DWb24OA6.js.map → icons-B_yuAgdN.js.map} +1 -1
- package/dist/core/web/public/next/assets/{index-afDA8cwW.js → index-oAAq8XJa.js} +3 -3
- package/dist/core/web/public/next/assets/{index-afDA8cwW.js.map → index-oAAq8XJa.js.map} +1 -1
- package/dist/core/web/public/next/assets/live-model-DCw_IFRI.js +2 -0
- package/dist/core/web/public/next/assets/live-model-DCw_IFRI.js.map +1 -0
- package/dist/core/web/public/next/assets/local-model-DFyjKX0b.js +2 -0
- package/dist/core/web/public/next/assets/local-model-DFyjKX0b.js.map +1 -0
- package/dist/core/web/public/next/assets/mind-B9PzLcl0.css +1 -0
- package/dist/core/web/public/next/assets/mind.module-vnuJcwvD.js +2 -0
- package/dist/core/web/public/next/assets/mind.module-vnuJcwvD.js.map +1 -0
- package/dist/core/web/public/next/assets/mutations-Dpsql5t7.js +2 -0
- package/dist/core/web/public/next/assets/{mutations-C6E10SPX.js.map → mutations-Dpsql5t7.js.map} +1 -1
- package/dist/core/web/public/next/assets/{overnight-queries-CCGfiS-g.js → overnight-queries-X-44Gsw5.js} +2 -2
- package/dist/core/web/public/next/assets/{overnight-queries-CCGfiS-g.js.map → overnight-queries-X-44Gsw5.js.map} +1 -1
- package/dist/core/web/public/next/assets/pane-chrome-8JmEhHVD.css +1 -0
- package/dist/core/web/public/next/assets/pane-chrome.module-D7o-fVd0.js +2 -0
- package/dist/core/web/public/next/assets/pane-chrome.module-D7o-fVd0.js.map +1 -0
- package/dist/core/web/public/next/assets/primitives-BDIcUvob.js +1 -0
- package/dist/core/web/public/next/assets/{queries-BuYIEHst.js → queries-BA4rNGD-.js} +2 -2
- package/dist/core/web/public/next/assets/{queries-BuYIEHst.js.map → queries-BA4rNGD-.js.map} +1 -1
- package/dist/core/web/public/next/assets/{reasoning-pref-BVzGczV7.js → reasoning-pref-B9-DJUXP.js} +2 -2
- package/dist/core/web/public/next/assets/{reasoning-pref-BVzGczV7.js.map → reasoning-pref-B9-DJUXP.js.map} +1 -1
- package/dist/core/web/public/next/assets/seat-subscription-CH6fW4fJ.js +2 -0
- package/dist/core/web/public/next/assets/seat-subscription-CH6fW4fJ.js.map +1 -0
- package/dist/core/web/public/next/assets/{section-visibility-CSrsTcwK.js → section-visibility-qFqc_d4Z.js} +2 -2
- package/dist/core/web/public/next/assets/{section-visibility-CSrsTcwK.js.map → section-visibility-qFqc_d4Z.js.map} +1 -1
- package/dist/core/web/public/next/assets/{sidebar-model-C8fyqSQY.js → sidebar-model-M1GaQU5l.js} +2 -2
- package/dist/core/web/public/next/assets/{sidebar-model-C8fyqSQY.js.map → sidebar-model-M1GaQU5l.js.map} +1 -1
- package/dist/core/web/public/next/assets/slots-Ds9ZIqUL.js +3 -0
- package/dist/core/web/public/next/assets/{slots-W8gkmdfE.js.map → slots-Ds9ZIqUL.js.map} +1 -1
- package/dist/core/web/public/next/assets/surface-data-J52iIGMD.js +2 -0
- package/dist/core/web/public/next/assets/surface-data-J52iIGMD.js.map +1 -0
- package/dist/core/web/public/next/assets/surface-prefetch-CgZ-LEJK.js +2 -0
- package/dist/core/web/public/next/assets/surface-prefetch-CgZ-LEJK.js.map +1 -0
- package/dist/core/web/public/next/assets/tasks-model-ent8f0jZ.js +2 -0
- package/dist/core/web/public/next/assets/{tasks-model-CnYQzgxk.js.map → tasks-model-ent8f0jZ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{terminal-icons-CxUYaWX9.js → terminal-icons-DJTK7QpR.js} +2 -2
- package/dist/core/web/public/next/assets/{terminal-icons-CxUYaWX9.js.map → terminal-icons-DJTK7QpR.js.map} +1 -1
- package/dist/core/web/public/next/assets/{tool-semantics-CTRuLF5j.js → tool-semantics-GX8ScuSH.js} +2 -2
- package/dist/core/web/public/next/assets/{tool-semantics-CTRuLF5j.js.map → tool-semantics-GX8ScuSH.js.map} +1 -1
- package/dist/core/web/public/next/assets/{turn-files-BvB5LLNw.js → turn-files-BPHQzYuH.js} +2 -2
- package/dist/core/web/public/next/assets/{turn-files-BvB5LLNw.js.map → turn-files-BPHQzYuH.js.map} +1 -1
- package/dist/core/web/public/next/assets/types-D5XOdyw8.js +2 -0
- package/dist/core/web/public/next/assets/types-D5XOdyw8.js.map +1 -0
- package/dist/core/web/public/next/assets/{usage-queries-CQOpeE1H.js → usage-queries-Bn8ccqyN.js} +2 -2
- package/dist/core/web/public/next/assets/{usage-queries-CQOpeE1H.js.map → usage-queries-Bn8ccqyN.js.map} +1 -1
- package/dist/core/web/public/next/assets/use-guarded-action-C2HlSzkz.js +2 -0
- package/dist/core/web/public/next/assets/use-guarded-action-C2HlSzkz.js.map +1 -0
- package/dist/core/web/public/next/assets/{use-ticker-hryPXnyp.js → use-ticker-BNc1H4ZC.js} +2 -2
- package/dist/core/web/public/next/assets/{use-ticker-hryPXnyp.js.map → use-ticker-BNc1H4ZC.js.map} +1 -1
- package/dist/core/web/public/next/assets/use-token-gate-B3IJL6bf.js +2 -0
- package/dist/core/web/public/next/assets/use-token-gate-B3IJL6bf.js.map +1 -0
- package/dist/core/web/public/next/assets/{useActivity-Cg_9-7nt.js → useActivity-Bk3XgXjL.js} +2 -2
- package/dist/core/web/public/next/assets/{useActivity-Cg_9-7nt.js.map → useActivity-Bk3XgXjL.js.map} +1 -1
- package/dist/core/web/public/next/assets/useChartWidth-BAtVgn2n.css +1 -0
- package/dist/core/web/public/next/assets/useChartWidth-lZ9PrQn0.js +2 -0
- package/dist/core/web/public/next/assets/useChartWidth-lZ9PrQn0.js.map +1 -0
- package/dist/core/web/public/next/assets/{useSeatsRefresh-4Ov9eT1F.js → useSeatsRefresh-CG4jczeL.js} +2 -2
- package/dist/core/web/public/next/assets/{useSeatsRefresh-4Ov9eT1F.js.map → useSeatsRefresh-CG4jczeL.js.map} +1 -1
- package/dist/core/web/public/next/assets/verse-model-D7NZQFAR.js +2 -0
- package/dist/core/web/public/next/assets/verse-model-D7NZQFAR.js.map +1 -0
- package/dist/core/web/public/next/assets/{verse-queries-BjQoOTwv.js → verse-queries-DvIJcn6Z.js} +2 -2
- package/dist/core/web/public/next/assets/{verse-queries-BjQoOTwv.js.map → verse-queries-DvIJcn6Z.js.map} +1 -1
- package/dist/core/web/public/next/assets/verse-store-DjBWj04q.js +3 -0
- package/dist/core/web/public/next/assets/verse-store-DjBWj04q.js.map +1 -0
- package/dist/core/web/public/next/assets/verse-ui-store-zafyzXKD.js +3 -0
- package/dist/core/web/public/next/assets/{verse-ui-store-KTTKfv-T.js.map → verse-ui-store-zafyzXKD.js.map} +1 -1
- package/dist/core/web/public/next/assets/{viewport-ZB86jdES.js → viewport-BEqGUoTA.js} +2 -2
- package/dist/core/web/public/next/assets/{viewport-ZB86jdES.js.map → viewport-BEqGUoTA.js.map} +1 -1
- package/dist/core/web/public/next/assets/warmup-BR6pxAKs.js +3 -0
- package/dist/core/web/public/next/assets/warmup-BR6pxAKs.js.map +1 -0
- package/dist/core/web/public/next/assets/{workspace-model-4hq_Mv3N.js → workspace-model-D_tWD5Wt.js} +2 -2
- package/dist/core/web/public/next/assets/{workspace-model-4hq_Mv3N.js.map → workspace-model-D_tWD5Wt.js.map} +1 -1
- package/dist/core/web/public/next/index.html +1 -1
- package/dist/release-dependency-inventory.json +1 -1
- package/package.json +1 -1
- package/dist/core/web/public/next/assets/Advanced-CHjxJt2z.css +0 -1
- package/dist/core/web/public/next/assets/Advanced-DM0DYibH.js +0 -2
- package/dist/core/web/public/next/assets/Advanced-DM0DYibH.js.map +0 -1
- package/dist/core/web/public/next/assets/AppsSection-CXxbfPJQ.js +0 -2
- package/dist/core/web/public/next/assets/AppsSection-CXxbfPJQ.js.map +0 -1
- package/dist/core/web/public/next/assets/AreaTrend-gUVXkfhf.js +0 -2
- package/dist/core/web/public/next/assets/AreaTrend-gUVXkfhf.js.map +0 -1
- package/dist/core/web/public/next/assets/AutonomySection-CoMngwNB.js +0 -2
- package/dist/core/web/public/next/assets/BranchBar-C-NovaXr.js +0 -2
- package/dist/core/web/public/next/assets/BranchBar-C-NovaXr.js.map +0 -1
- package/dist/core/web/public/next/assets/BranchBar-C9BpPVLr.css +0 -1
- package/dist/core/web/public/next/assets/BudgetControl-P5lMxHvQ.js +0 -2
- package/dist/core/web/public/next/assets/BudgetControl-P5lMxHvQ.js.map +0 -1
- package/dist/core/web/public/next/assets/BurnDown-4P1LDoCL.js +0 -2
- package/dist/core/web/public/next/assets/BurnDown-4P1LDoCL.js.map +0 -1
- package/dist/core/web/public/next/assets/CapacityStrip-D6Yyg4a1.js +0 -2
- package/dist/core/web/public/next/assets/CapacityStrip-D6Yyg4a1.js.map +0 -1
- package/dist/core/web/public/next/assets/CapacityStrip-wgFP9MUA.css +0 -1
- package/dist/core/web/public/next/assets/ChatSection-B9cdRKUh.js +0 -3
- package/dist/core/web/public/next/assets/CommandSection-BC0uXim_.js +0 -2
- package/dist/core/web/public/next/assets/CommandSection-BC0uXim_.js.map +0 -1
- package/dist/core/web/public/next/assets/Composer-CkcwbQhG.css +0 -1
- package/dist/core/web/public/next/assets/Composer.module-DJMdrqNt.js +0 -2
- package/dist/core/web/public/next/assets/DiffPane-5uLKa0au.js +0 -2
- package/dist/core/web/public/next/assets/DiffPane-5uLKa0au.js.map +0 -1
- package/dist/core/web/public/next/assets/DiffPane-Csboxnn0.css +0 -1
- package/dist/core/web/public/next/assets/DockHost-BGnTgdIb.css +0 -1
- package/dist/core/web/public/next/assets/DockHost-CBV_6Ehi.js +0 -2
- package/dist/core/web/public/next/assets/DockHost-CBV_6Ehi.js.map +0 -1
- package/dist/core/web/public/next/assets/FleetSection-DuJcQCGg.js +0 -3
- package/dist/core/web/public/next/assets/FleetSection-DuJcQCGg.js.map +0 -1
- package/dist/core/web/public/next/assets/FleetSection-w9AjqfTR.css +0 -1
- package/dist/core/web/public/next/assets/Funnel-qX3Hlbce.js +0 -2
- package/dist/core/web/public/next/assets/Funnel-qX3Hlbce.js.map +0 -1
- package/dist/core/web/public/next/assets/GearTray-kVGP1coG.js +0 -2
- package/dist/core/web/public/next/assets/GearTray-kVGP1coG.js.map +0 -1
- package/dist/core/web/public/next/assets/GrowthSection-CYxJ9MH5.js +0 -2
- package/dist/core/web/public/next/assets/GrowthSection-CYxJ9MH5.js.map +0 -1
- package/dist/core/web/public/next/assets/HandoffDialog-DHZo3Ev0.js +0 -2
- package/dist/core/web/public/next/assets/HandoffDialog-DHZo3Ev0.js.map +0 -1
- package/dist/core/web/public/next/assets/MatrixHeatmap-B_JWCjZx.js +0 -2
- package/dist/core/web/public/next/assets/MatrixHeatmap-B_JWCjZx.js.map +0 -1
- package/dist/core/web/public/next/assets/McpSection-1UncWBpW.js +0 -2
- package/dist/core/web/public/next/assets/MessageMarkdown-C4pl9LI5.js +0 -3
- package/dist/core/web/public/next/assets/MessageMarkdown-Czcl3L_Q.css +0 -1
- package/dist/core/web/public/next/assets/MindSection-C3fCw_fD.js +0 -2
- package/dist/core/web/public/next/assets/MindSection-C3fCw_fD.js.map +0 -1
- package/dist/core/web/public/next/assets/MutationTokenDialog-Dn0tzCrh.js +0 -2
- package/dist/core/web/public/next/assets/MutationTokenDialog-Dn0tzCrh.js.map +0 -1
- package/dist/core/web/public/next/assets/NeedsYouDrawer-CuNYJCJ0.js +0 -2
- package/dist/core/web/public/next/assets/NeedsYouDrawer-CuNYJCJ0.js.map +0 -1
- package/dist/core/web/public/next/assets/NeedsYouDrawer-SkhvvdLb.css +0 -1
- package/dist/core/web/public/next/assets/NewChatDialog-B_BsS9pr.js +0 -3
- package/dist/core/web/public/next/assets/OnboardingFlow-CtCPpgoX.js +0 -2
- package/dist/core/web/public/next/assets/PreviewPane-Cx6RRwzM.js +0 -2
- package/dist/core/web/public/next/assets/PreviewPane-Cx6RRwzM.js.map +0 -1
- package/dist/core/web/public/next/assets/PreviewPane-WQJFjSXe.css +0 -1
- package/dist/core/web/public/next/assets/RailStatus-BWs6xevj.js +0 -2
- package/dist/core/web/public/next/assets/RailStatus-BWs6xevj.js.map +0 -1
- package/dist/core/web/public/next/assets/SeatSelector-DaUO-zoK.js +0 -3
- package/dist/core/web/public/next/assets/SessionSearch-B5aQ0BCM.js +0 -2
- package/dist/core/web/public/next/assets/SettingsSection-CuESA30a.js +0 -2
- package/dist/core/web/public/next/assets/SettingsSection-CuESA30a.js.map +0 -1
- package/dist/core/web/public/next/assets/Sidebar-DfD8MNZt.css +0 -1
- package/dist/core/web/public/next/assets/Sidebar-q11dtYZf.js +0 -3
- package/dist/core/web/public/next/assets/Sidebar-q11dtYZf.js.map +0 -1
- package/dist/core/web/public/next/assets/StepBand-B1W7rU70.js +0 -2
- package/dist/core/web/public/next/assets/StepBand-B1W7rU70.js.map +0 -1
- package/dist/core/web/public/next/assets/Swimlane-BR40WVcj.js +0 -2
- package/dist/core/web/public/next/assets/Swimlane-BR40WVcj.js.map +0 -1
- package/dist/core/web/public/next/assets/TerminalPane-CPKUTD9K.js +0 -7
- package/dist/core/web/public/next/assets/TerminalPane-CPKUTD9K.js.map +0 -1
- package/dist/core/web/public/next/assets/TerminalPane-CmE2QL-Q.css +0 -1
- package/dist/core/web/public/next/assets/UniverseConsoleApp-DKqAf-eD.js +0 -2
- package/dist/core/web/public/next/assets/UsageSection-B6fR3cru.js +0 -2
- package/dist/core/web/public/next/assets/UsageSection-B6fR3cru.js.map +0 -1
- package/dist/core/web/public/next/assets/UsageSection-DwgNOYvi.css +0 -1
- package/dist/core/web/public/next/assets/VerseConsoleApp-C0V221WL.css +0 -1
- package/dist/core/web/public/next/assets/VerseConsoleApp-bjARLPwN.js +0 -3
- package/dist/core/web/public/next/assets/VerseConsoleApp-bjARLPwN.js.map +0 -1
- package/dist/core/web/public/next/assets/Workspace-DQXMVDf7.css +0 -1
- package/dist/core/web/public/next/assets/Workspace-DtJb5tiM.js +0 -10
- package/dist/core/web/public/next/assets/Workspace-DtJb5tiM.js.map +0 -1
- package/dist/core/web/public/next/assets/actions-Bszsdpms.js +0 -2
- package/dist/core/web/public/next/assets/actions-Bszsdpms.js.map +0 -1
- package/dist/core/web/public/next/assets/actions-Dug8YIf0.css +0 -1
- package/dist/core/web/public/next/assets/capacity-strip-model-BR539Ci8.js +0 -2
- package/dist/core/web/public/next/assets/capacity-strip-model-BR539Ci8.js.map +0 -1
- package/dist/core/web/public/next/assets/charts-D4NaLaXA.js +0 -2
- package/dist/core/web/public/next/assets/charts-D4NaLaXA.js.map +0 -1
- package/dist/core/web/public/next/assets/colors-B-vHsX1S.js +0 -2
- package/dist/core/web/public/next/assets/colors-B-vHsX1S.js.map +0 -1
- package/dist/core/web/public/next/assets/command-catalog-s3W6Z96D.js +0 -2
- package/dist/core/web/public/next/assets/command-catalog-s3W6Z96D.js.map +0 -1
- package/dist/core/web/public/next/assets/context-model-Bto3LZn2.js +0 -2
- package/dist/core/web/public/next/assets/context-model-Bto3LZn2.js.map +0 -1
- package/dist/core/web/public/next/assets/context-queries-DVdSLrYy.js +0 -2
- package/dist/core/web/public/next/assets/context-queries-DVdSLrYy.js.map +0 -1
- package/dist/core/web/public/next/assets/context.module-B_k02HNU.js +0 -2
- package/dist/core/web/public/next/assets/context.module-B_k02HNU.js.map +0 -1
- package/dist/core/web/public/next/assets/dock-icons-oG8d7mNZ.js +0 -2
- package/dist/core/web/public/next/assets/dock-icons-oG8d7mNZ.js.map +0 -1
- package/dist/core/web/public/next/assets/dock-panes-BNTLvX7G.js +0 -2
- package/dist/core/web/public/next/assets/fleet-model-ClBbQ0Uj.js +0 -2
- package/dist/core/web/public/next/assets/fleet-model-ClBbQ0Uj.js.map +0 -1
- package/dist/core/web/public/next/assets/format-BNYWGJat.js +0 -2
- package/dist/core/web/public/next/assets/format-BNYWGJat.js.map +0 -1
- package/dist/core/web/public/next/assets/global-DVgMguLr.js +0 -2
- package/dist/core/web/public/next/assets/global-DVgMguLr.js.map +0 -1
- package/dist/core/web/public/next/assets/live-model-Dm6ITHvX.js +0 -2
- package/dist/core/web/public/next/assets/live-model-Dm6ITHvX.js.map +0 -1
- package/dist/core/web/public/next/assets/mind-B-lYfSUJ.css +0 -1
- package/dist/core/web/public/next/assets/mind.module-BzhAlg3e.js +0 -2
- package/dist/core/web/public/next/assets/mind.module-BzhAlg3e.js.map +0 -1
- package/dist/core/web/public/next/assets/mutations-C6E10SPX.js +0 -2
- package/dist/core/web/public/next/assets/primitives-DQvYikjm.js +0 -1
- package/dist/core/web/public/next/assets/seat-subscription-CrWOV4Qc.js +0 -2
- package/dist/core/web/public/next/assets/seat-subscription-CrWOV4Qc.js.map +0 -1
- package/dist/core/web/public/next/assets/slots-W8gkmdfE.js +0 -3
- package/dist/core/web/public/next/assets/surface-data-ZtCegYMQ.js +0 -2
- package/dist/core/web/public/next/assets/surface-data-ZtCegYMQ.js.map +0 -1
- package/dist/core/web/public/next/assets/tasks-model-CnYQzgxk.js +0 -2
- package/dist/core/web/public/next/assets/types-Dypu22dp.js +0 -3
- package/dist/core/web/public/next/assets/types-Dypu22dp.js.map +0 -1
- package/dist/core/web/public/next/assets/use-guarded-action-CO_aAsed.js +0 -2
- package/dist/core/web/public/next/assets/use-guarded-action-CO_aAsed.js.map +0 -1
- package/dist/core/web/public/next/assets/use-token-gate-DYA2-ALC.js +0 -2
- package/dist/core/web/public/next/assets/use-token-gate-DYA2-ALC.js.map +0 -1
- package/dist/core/web/public/next/assets/useChartWidth-B8E5mJgM.css +0 -1
- package/dist/core/web/public/next/assets/useChartWidth-MEXvDxDL.js +0 -2
- package/dist/core/web/public/next/assets/useChartWidth-MEXvDxDL.js.map +0 -1
- package/dist/core/web/public/next/assets/verse-model-E98kXngO.js +0 -2
- package/dist/core/web/public/next/assets/verse-model-E98kXngO.js.map +0 -1
- package/dist/core/web/public/next/assets/verse-store-BgKx_YGs.js +0 -2
- package/dist/core/web/public/next/assets/verse-store-BgKx_YGs.js.map +0 -1
- package/dist/core/web/public/next/assets/verse-ui-store-KTTKfv-T.js +0 -3
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{a as e,n as t,s as n}from"./index-afDA8cwW.js";import{n as r,t as i}from"./MutationTokenDialog-Dn0tzCrh.js";import{t as a}from"./Button-0-nNbv1h.js";import{t as o}from"./use-guarded-action-CO_aAsed.js";var s=n(e(),1),c={lead:`_lead_i2poc_8`,bar:`_bar_i2poc_14`,barSpacer:`_barSpacer_i2poc_22`,barSecondary:`_barSecondary_i2poc_26`,switchWrap:`_switchWrap_i2poc_32`,barLabel:`_barLabel_i2poc_38`,pillLabel:`_pillLabel_i2poc_39`,switchOption:`_switchOption_i2poc_48`,touchMark:`_touchMark_i2poc_54`,pill:`_pill_i2poc_39`,chip:`_chip_i2poc_59`,linkButton:`_linkButton_i2poc_88`,moreLink:`_moreLink_i2poc_89`,dot:`_dot_i2poc_103`,verdict:`_verdict_i2poc_126`,verdictPart:`_verdictPart_i2poc_135`,verdictSep:`_verdictSep_i2poc_149`,since:`_since_i2poc_153`,sinceLead:`_sinceLead_i2poc_162`,sinceEmpty:`_sinceEmpty_i2poc_166`,sinceChip:`_sinceChip_i2poc_170`,actionNote:`_actionNote_i2poc_196`,actionError:`_actionError_i2poc_197`,kbd:`_kbd_i2poc_251`,muted:`_muted_i2poc_260`,mono:`_mono_i2poc_267`,num:`_num_i2poc_272`,confirmBody:`_confirmBody_i2poc_277`,confirmActions:`_confirmActions_i2poc_283`,needsList:`_needsList_i2poc_291`,needsRow:`_needsRow_i2poc_299`,sevDot:`_sevDot_i2poc_313`,needsText:`_needsText_i2poc_327`,needsTitle:`_needsTitle_i2poc_334`,needsDetail:`_needsDetail_i2poc_341`,needsMeta:`_needsMeta_i2poc_348`,needsActions:`_needsActions_i2poc_355`,allClear:`_allClear_i2poc_363`,allClearTitle:`_allClearTitle_i2poc_370`,allClearBody:`_allClearBody_i2poc_378`,memo:`_memo_i2poc_384`,memoRow:`_memoRow_i2poc_391`,memoText:`_memoText_i2poc_402`,delta:`_delta_i2poc_408`,dryRun:`_dryRun_i2poc_421`,actionList:`_actionList_i2poc_433`,actionRow:`_actionRow_i2poc_442`,actionSummary:`_actionSummary_i2poc_451`,classBadge:`_classBadge_i2poc_456`,actionText:`_actionText_i2poc_479`,actionWhy:`_actionWhy_i2poc_492`,actionState:`_actionState_i2poc_499`,statusWord:`_statusWord_i2poc_505`,vetoChip:`_vetoChip_i2poc_520`,ring:`_ring_i2poc_524`,ringTrack:`_ringTrack_i2poc_534`,ringFill:`_ringFill_i2poc_540`,ringText:`_ringText_i2poc_547`,kpis:`_kpis_i2poc_552`,burnGrid:`_burnGrid_i2poc_567`,burnStrip:`_burnStrip_i2poc_579`,burnItem:`_burnItem_i2poc_590`,freeSeat:`_freeSeat_i2poc_598`,freeHead:`_freeHead_i2poc_608`,freeTitle:`_freeTitle_i2poc_614`,freeValue:`_freeValue_i2poc_621`,freeBody:`_freeBody_i2poc_628`,scope:`_scope_i2poc_635`,scopeBlock:`_scopeBlock_i2poc_641`,scopeLead:`_scopeLead_i2poc_647`,scopeMeta:`_scopeMeta_i2poc_654`,scopeTable:`_scopeTable_i2poc_661`,scopeList:`_scopeList_i2poc_681`,ladder:`_ladder_i2poc_689`,ladderId:`_ladderId_i2poc_708`,sheetFooter:`_sheetFooter_i2poc_713`,sheetFootnote:`_sheetFootnote_i2poc_719`,sheetButtons:`_sheetButtons_i2poc_726`},l=t();function u({spec:e,onConfirm:t,onCancel:n}){let i=(0,s.useId)(),o=(0,s.useRef)(null),u=(0,s.useRef)(null);return(0,l.jsxs)(r,{open:e!==null,onClose:n,titleId:i,title:e?.title??``,initialFocusRef:e?.destructive?o:u,children:[(0,l.jsx)(`div`,{className:c.confirmBody,children:e?.body}),(0,l.jsxs)(`div`,{className:c.confirmActions,children:[(0,l.jsx)(a,{ref:o,variant:`ghost`,onClick:n,children:`Cancel`}),(0,l.jsx)(a,{ref:u,variant:e?.destructive?`danger`:`primary`,onClick:t,children:e?.confirmLabel??`Confirm`})]})]})}function d(){let e=o(),[t,n]=(0,s.useState)(null),{request:r}=e,a=(0,s.useCallback)((e,t,i={})=>{let a=()=>r(e,t,i.onDone);i.confirm?n({spec:i.confirm,run:a}):a()},[r]),c=(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(u,{spec:t?.spec??null,onCancel:()=>n(null),onConfirm:()=>{let e=t;n(null),e?.run()}}),(0,l.jsx)(i,{open:e.tokenOpen,onClose:e.closeToken,reason:e.tokenReason,tokenHelp:`the mutation token ashlr verse printed`})]});return{act:a,busy:e.busy,error:e.error,clearError:e.clearError,readOnly:e.readOnly,dialogs:c}}function f({actions:e}){return e.readOnly?(0,l.jsx)(`p`,{className:c.actionNote,role:`status`,children:`Read-only session: this server was started without dispatch, so switching, stopping and vetoing are unavailable. Everything shown is live.`}):e.error?(0,l.jsxs)(`p`,{className:c.actionError,role:`alert`,children:[e.error,(0,l.jsx)(`button`,{type:`button`,className:c.linkButton,onClick:e.clearError,children:`Dismiss`})]}):null}export{d as n,c as r,f as t};
|
|
2
|
-
//# sourceMappingURL=actions-Bszsdpms.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"actions-Bszsdpms.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/command/command.module.css","../../../../../../src/web-ui/routes/verse/command/actions.tsx"],"sourcesContent":["/*\n * routes/verse/command/command.module.css — Command's cards and top bar\n * (unit C7). Tokens only: style-scan-310 bans raw hex colours and px font\n * sizes in this folder, and every colour here follows the theme.\n */\n\n/* ---- lead: top bar, verdict, since ------------------------------------ */\n.lead {\n display: flex;\n flex-direction: column;\n gap: var(--space-3);\n}\n\n.bar {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: var(--space-2) var(--space-3);\n min-height: var(--control-h);\n}\n\n.barSpacer {\n flex: 1;\n}\n\n.barSecondary {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-2);\n}\n\n.switchWrap {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n}\n\n.barLabel,\n.pillLabel {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n letter-spacing: var(--tracking-label);\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n\n.switchOption {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n}\n\n.touchMark {\n color: var(--text-tertiary);\n}\n\n.pill,\n.chip {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\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-full);\n background: var(--bg-surface);\n color: var(--text-primary);\n font-family: var(--font-ui);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n white-space: nowrap;\n}\n\nbutton.pill,\nbutton.chip {\n cursor: pointer;\n transition: background-color var(--duration-fast) var(--ease-standard);\n}\n\nbutton.pill:hover,\nbutton.chip:hover {\n background: var(--bg-hover);\n}\n\n.pill:focus-visible,\n.chip:focus-visible,\n.linkButton:focus-visible,\n.moreLink:focus-visible {\n outline: 2px solid var(--border-focus);\n outline-offset: 2px;\n}\n\n.chip[data-tone='warning'] {\n border-color: var(--status-warning-solid);\n}\n\n.chip[data-tone='danger'] {\n border-color: var(--status-danger-solid);\n color: var(--status-danger-fg);\n}\n\n.dot {\n width: 8px;\n height: 8px;\n border-radius: var(--radius-full);\n flex: none;\n background: var(--status-neutral-solid);\n}\n\n.dot[data-tone='success'] {\n background: var(--status-success-solid);\n}\n.dot[data-tone='warning'] {\n background: var(--status-warning-solid);\n}\n.dot[data-tone='danger'] {\n background: var(--status-danger-solid);\n}\n.dot[data-tone='unknown'] {\n background: var(--chart-unknown-hatch);\n border: 1px solid var(--status-unknown-solid);\n}\n\n/* Verdict: 17/24, weight 500 (SPEC-310C §6). */\n.verdict {\n margin: 0;\n font-size: var(--text-lg-size);\n line-height: var(--text-lg-line);\n font-weight: var(--font-weight-medium);\n color: var(--text-primary);\n font-variant-numeric: tabular-nums;\n}\n\n.verdictPart[data-tone='danger'] {\n color: var(--status-danger-fg);\n}\n.verdictPart[data-tone='warning'] {\n color: var(--status-warning-fg);\n}\n.verdictPart[data-tone='success'] {\n color: var(--status-success-fg);\n}\n.verdictPart[data-tone='unknown'] {\n color: var(--status-unknown-fg);\n font-style: italic;\n}\n\n.verdictSep {\n color: var(--text-tertiary);\n}\n\n.since {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-2);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n\n.sinceLead {\n color: var(--text-tertiary);\n}\n\n.sinceEmpty {\n color: var(--text-tertiary);\n}\n\n.sinceChip {\n display: inline-flex;\n align-items: center;\n padding: 1px var(--space-2);\n border-radius: var(--radius-full);\n background: var(--status-neutral-bg);\n color: var(--status-neutral-fg);\n font-variant-numeric: tabular-nums;\n}\n.sinceChip[data-tone='success'] {\n background: var(--status-success-bg);\n color: var(--status-success-fg);\n}\n.sinceChip[data-tone='danger'] {\n background: var(--status-danger-bg);\n color: var(--status-danger-fg);\n}\n.sinceChip[data-tone='warning'] {\n background: var(--status-warning-bg);\n color: var(--status-warning-fg);\n}\n.sinceChip[data-tone='info'] {\n background: var(--status-info-bg);\n color: var(--status-info-fg);\n}\n\n.actionNote,\n.actionError {\n margin: 0;\n padding: var(--space-2) var(--space-3);\n border-radius: var(--radius-md);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n\n.actionNote {\n background: var(--bg-hover);\n color: var(--text-secondary);\n}\n\n.actionError {\n display: flex;\n align-items: baseline;\n gap: var(--space-3);\n background: var(--status-danger-bg);\n color: var(--status-danger-fg);\n}\n\n/* ---- shared small controls ------------------------------------------- */\n.linkButton,\n.moreLink {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\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 line-height: var(--text-xs-line);\n text-decoration: none;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.linkButton:hover,\n.moreLink:hover {\n text-decoration: underline;\n}\n\n.moreLink {\n align-self: flex-start;\n}\n\n.moreLink:disabled {\n color: var(--text-disabled);\n cursor: default;\n text-decoration: none;\n}\n\n.kbd {\n padding: 0 var(--space-1);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-xs);\n color: var(--text-tertiary);\n font-family: var(--font-mono);\n font-size: var(--text-2xs-size);\n}\n\n.muted {\n margin: 0;\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n\n.mono {\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n}\n\n.num {\n text-align: right;\n font-variant-numeric: tabular-nums;\n}\n\n.confirmBody {\n color: var(--text-secondary);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line-relaxed);\n}\n\n.confirmActions {\n display: flex;\n justify-content: flex-end;\n gap: var(--space-2);\n margin-top: var(--space-5);\n}\n\n/* ---- Needs you ------------------------------------------------------- */\n.needsList {\n display: flex;\n flex-direction: column;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.needsRow {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) auto;\n align-items: start;\n gap: var(--space-2) var(--space-3);\n padding: var(--space-2) 0;\n border-top: 1px solid var(--border-subtle);\n}\n\n.needsRow:first-child {\n border-top: 0;\n padding-top: 0;\n}\n\n.sevDot {\n width: 8px;\n height: 8px;\n margin-top: 6px;\n border-radius: var(--radius-full);\n background: var(--status-info-solid);\n}\n.sevDot[data-severity='warn'] {\n background: var(--status-warning-solid);\n}\n.sevDot[data-severity='high'] {\n background: var(--status-danger-solid);\n}\n\n.needsText {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.needsTitle {\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.needsDetail {\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.needsMeta {\n color: var(--text-tertiary);\n font-family: var(--font-mono);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n}\n\n.needsActions {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-end;\n align-items: center;\n gap: var(--space-2);\n}\n\n.allClear {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n padding: var(--space-4) 0;\n}\n\n.allClearTitle {\n font-family: var(--font-display);\n font-size: var(--text-md-size);\n line-height: var(--text-md-line);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n}\n\n.allClearBody {\n color: var(--text-secondary);\n font-size: var(--text-sm-size);\n}\n\n/* ---- Leader ---------------------------------------------------------- */\n.memo {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n margin: 0;\n}\n\n.memoRow {\n display: grid;\n grid-template-columns: 96px minmax(0, 1fr);\n gap: var(--space-3);\n align-items: baseline;\n}\n\n.memoRow dd {\n margin: 0;\n}\n\n.memoText {\n color: var(--text-primary);\n font-size: var(--text-base-size);\n line-height: var(--text-base-line);\n}\n\n.delta {\n display: inline-block;\n margin-left: var(--space-2);\n padding: 0 var(--space-2);\n border-radius: var(--radius-full);\n background: var(--status-info-bg);\n color: var(--status-info-fg);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n\n.dryRun {\n font-family: var(--font-display); /* micro-labels follow the Display-font setting */\n padding: 0 var(--space-2);\n border: 1px dashed var(--border-strong);\n border-radius: var(--radius-full);\n color: var(--text-secondary);\n font-size: var(--text-2xs-size);\n line-height: var(--text-xs-line);\n text-transform: uppercase;\n letter-spacing: var(--tracking-label);\n}\n\n.actionList {\n display: flex;\n flex-direction: column;\n margin: 0;\n padding: 0;\n list-style: none;\n border-top: 1px solid var(--border-subtle);\n}\n\n.actionRow {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) auto;\n gap: var(--space-3);\n align-items: center;\n padding: var(--space-2) 0;\n border-bottom: 1px solid var(--border-subtle);\n}\n\n.actionRow[data-status='vetoed'] .actionSummary {\n text-decoration: line-through;\n color: var(--text-tertiary);\n}\n\n.classBadge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n color: var(--text-secondary);\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n font-weight: var(--font-weight-semibold);\n}\n\n.classBadge[data-class='B'] {\n border-color: var(--status-warning-solid);\n color: var(--status-warning-fg);\n}\n\n.classBadge[data-class='C'] {\n border-style: dashed;\n}\n\n.actionText {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.actionSummary {\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.actionWhy {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n overflow-wrap: anywhere;\n}\n\n.actionState {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n}\n\n.statusWord {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n white-space: nowrap;\n}\n\n.statusWord[data-status='escalated'] {\n color: var(--status-warning-fg);\n}\n\n.statusWord[data-status='failed'],\n.statusWord[data-status='refused'] {\n color: var(--status-danger-fg);\n}\n\n.vetoChip {\n border: 1px solid var(--border-default);\n}\n\n.ring {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n color: var(--status-warning-fg);\n font-size: var(--text-xs-size);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n\n.ringTrack {\n fill: none;\n stroke: var(--border-subtle);\n stroke-width: 2.5;\n}\n\n.ringFill {\n fill: none;\n stroke: var(--status-warning-solid);\n stroke-width: 2.5;\n stroke-linecap: round;\n}\n\n.ringText {\n min-width: 4ch;\n}\n\n/* ---- KPIs and burn-downs --------------------------------------------- */\n.kpis {\n display: grid;\n grid-template-columns: repeat(5, minmax(0, 1fr));\n gap: var(--surface-gap);\n align-items: start;\n}\n\n[data-viewport='medium'] .kpis {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n}\n\n[data-viewport='compact'] .kpis {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n}\n\n.burnGrid {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: var(--surface-gap);\n align-items: start;\n}\n\n[data-viewport='medium'] .burnGrid {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n}\n\n/* 375: one card at a time, snapping — the next card peeks in at the edge. */\n.burnStrip {\n display: grid;\n grid-auto-flow: column;\n grid-auto-columns: 86%;\n gap: var(--space-3);\n overflow-x: auto;\n overscroll-behavior-x: contain;\n scroll-snap-type: x mandatory;\n padding-bottom: var(--space-1);\n}\n\n.burnStrip > .burnItem {\n scroll-snap-align: start;\n}\n\n.burnItem {\n min-width: 0;\n}\n\n.freeSeat {\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}\n\n.freeHead {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n}\n\n.freeTitle {\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n}\n\n.freeValue {\n font-size: var(--text-2xl-size);\n line-height: var(--text-2xl-line);\n font-weight: var(--font-weight-semibold);\n color: var(--text-secondary);\n}\n\n.freeBody {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n}\n\n/* ---- Touch ID sheet -------------------------------------------------- */\n.scope {\n display: flex;\n flex-direction: column;\n gap: var(--space-5);\n}\n\n.scopeBlock {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n}\n\n.scopeLead {\n margin: 0;\n color: var(--text-primary);\n font-size: var(--text-base-size);\n line-height: var(--text-base-line);\n}\n\n.scopeMeta {\n margin: 0;\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n}\n\n.scopeTable {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--text-xs-size);\n}\n\n.scopeTable th {\n padding: var(--space-1) var(--space-2) var(--space-1) 0;\n border-bottom: 1px solid var(--border-subtle);\n color: var(--text-tertiary);\n font-weight: var(--font-weight-medium);\n text-align: left;\n}\n\n.scopeTable td {\n padding: var(--space-1) var(--space-2) var(--space-1) 0;\n border-bottom: 1px solid var(--border-subtle);\n color: var(--text-primary);\n}\n\n.scopeList {\n margin: 0;\n padding-left: var(--space-4);\n color: var(--text-secondary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n}\n\n.ladder {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n counter-reset: rung;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-secondary);\n}\n\n.ladder li {\n display: grid;\n grid-template-columns: 56px minmax(0, 1fr);\n gap: var(--space-2);\n}\n\n.ladderId {\n font-family: var(--font-mono);\n color: var(--text-primary);\n}\n\n.sheetFooter {\n display: flex;\n flex-direction: column;\n gap: var(--space-3);\n}\n\n.sheetFootnote {\n margin: 0;\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n}\n\n.sheetButtons {\n display: flex;\n justify-content: flex-end;\n gap: var(--space-2);\n}\n\n@media (prefers-reduced-motion: reduce) {\n button.pill,\n button.chip {\n transition: none;\n }\n}\n","/**\n * routes/verse/command/actions.tsx — how every write on the four surfaces\n * reaches the server (unit C7).\n *\n * Order is fixed and the same for a click, a key and the palette\n * (SPEC-310C §1 \"Guarded actions ask for confirmation, then the mutation\n * token\"):\n *\n * 1. a confirmation dialog, when the action asks for one (Stop, Veto,\n * Resume, every Needs-you approve / reject / veto);\n * 2. the mutation token, when none is held (useGuardedAction);\n * 3. the request, one at a time, with the server's own refusal sentence\n * shown on failure and read-only sessions explained, never errored.\n *\n * LOWERING needs no confirmation (SPEC-310B I1: \"lowering authority is\n * instant\") — callers simply omit `confirm` for the switch-down path.\n */\nimport { useCallback, useId, useRef, useState, type ReactNode } from 'react';\nimport { MutationTokenDialog } from '../../../components/auth/MutationTokenDialog.js';\nimport { Dialog } from '../../../components/primitives/Dialog.js';\nimport { Button } from '../../../components/primitives/Button.js';\nimport { useGuardedAction } from '../autonomy/use-guarded-action.js';\nimport styles from './command.module.css';\n\nexport interface ConfirmSpec {\n title: string;\n body: ReactNode;\n confirmLabel: string;\n destructive?: boolean;\n}\n\nexport function ConfirmDialog({ spec, onConfirm, onCancel }: { spec: ConfirmSpec | null; onConfirm: () => void; onCancel: () => void }) {\n const titleId = useId();\n const cancelRef = useRef<HTMLButtonElement>(null);\n const confirmRef = useRef<HTMLButtonElement>(null);\n return (\n <Dialog\n open={spec !== null}\n onClose={onCancel}\n titleId={titleId}\n title={spec?.title ?? ''}\n // A destructive confirm starts on Cancel, so a stray Enter never stops the fleet.\n initialFocusRef={spec?.destructive ? cancelRef : confirmRef}\n >\n <div className={styles.confirmBody}>{spec?.body}</div>\n <div className={styles.confirmActions}>\n <Button ref={cancelRef} variant=\"ghost\" onClick={onCancel}>\n Cancel\n </Button>\n <Button ref={confirmRef} variant={spec?.destructive ? 'danger' : 'primary'} onClick={onConfirm}>\n {spec?.confirmLabel ?? 'Confirm'}\n </Button>\n </div>\n </Dialog>\n );\n}\n\nexport interface SurfaceActions {\n /** Confirm (when asked), then token (when needed), then run `fn`. */\n act: <T>(fn: () => Promise<T>, reason: string, options?: { confirm?: ConfirmSpec; onDone?: (result: T) => void }) => void;\n busy: boolean;\n error: string | null;\n clearError: () => void;\n readOnly: boolean;\n /** Render once per surface. */\n dialogs: ReactNode;\n}\n\nexport function useSurfaceActions(): SurfaceActions {\n const guard = useGuardedAction();\n const [pending, setPending] = useState<{ spec: ConfirmSpec; run: () => void } | null>(null);\n const { request } = guard;\n\n const act = useCallback(\n <T,>(fn: () => Promise<T>, reason: string, options: { confirm?: ConfirmSpec; onDone?: (result: T) => void } = {}) => {\n const run = () => request(fn, reason, options.onDone);\n if (options.confirm) setPending({ spec: options.confirm, run });\n else run();\n },\n [request],\n );\n\n const dialogs = (\n <>\n <ConfirmDialog\n spec={pending?.spec ?? null}\n onCancel={() => setPending(null)}\n onConfirm={() => {\n const next = pending;\n setPending(null);\n next?.run();\n }}\n />\n <MutationTokenDialog open={guard.tokenOpen} onClose={guard.closeToken} reason={guard.tokenReason} tokenHelp=\"the mutation token ashlr verse printed\" />\n </>\n );\n\n return { act, busy: guard.busy, error: guard.error, clearError: guard.clearError, readOnly: guard.readOnly, dialogs };\n}\n\n/** The error / read-only line a surface shows under its top bar. */\nexport function ActionStatus({ actions }: { actions: Pick<SurfaceActions, 'error' | 'clearError' | 'readOnly'> }) {\n if (actions.readOnly) {\n return (\n <p className={styles.actionNote} role=\"status\">\n Read-only session: this server was started without dispatch, so switching, stopping and vetoing are unavailable. Everything shown is live.\n </p>\n );\n }\n if (!actions.error) return null;\n return (\n <p className={styles.actionError} role=\"alert\">\n {actions.error}\n <button type=\"button\" className={styles.linkButton} onClick={actions.clearError}>\n Dismiss\n </button>\n </p>\n );\n}\n"],"mappings":"8oFC+BA,SAAgB,EAAc,CAAE,OAAM,YAAW,YAAuF,CACtI,IAAM,GAAA,EAAU,EAAA,MAAA,CAAM,EAChB,GAAA,EAAY,EAAA,OAAA,CAA0B,IAAI,EAC1C,GAAA,EAAa,EAAA,OAAA,CAA0B,IAAI,EACjD,OACE,EAAA,EAAA,KAAA,CAAC,EAAD,CACE,KAAM,IAAS,KACf,QAAS,EACA,UACT,MAAO,GAAM,OAAS,GAEtB,gBAAiB,GAAM,YAAc,EAAY,EANnD,SAAA,EAQE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAO,YAAc,SAAA,GAAM,IAAU,CAAA,GACrD,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAO,eAAvB,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAQ,IAAK,EAAW,QAAQ,QAAQ,QAAS,EAAU,SAAA,QAEnD,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,EAAD,CAAQ,IAAK,EAAY,QAAS,GAAM,YAAc,SAAW,UAAW,QAAS,EAClF,SAAA,GAAM,cAAgB,SACjB,CAAA,CACL,CACC,CAAA,CAAA,GAEZ,CAaA,SAAgB,GAAoC,CAClD,IAAM,EAAQ,EAAiB,EACzB,CAAC,EAAS,IAAA,EAAc,EAAA,SAAA,CAAwD,IAAI,EACpF,CAAE,WAAY,EAEd,GAAA,EAAM,EAAA,YAAA,EACL,EAAsB,EAAgB,EAAmE,CAAC,IAAM,CACnH,IAAM,MAAY,EAAQ,EAAI,EAAQ,EAAQ,MAAM,EAChD,EAAQ,QAAS,EAAW,CAAE,KAAM,EAAQ,QAAS,KAAI,CAAC,EACzD,EAAI,CACX,EACA,CAAC,CAAO,CACV,EAEM,GACJ,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,KAAM,GAAS,MAAQ,KACvB,aAAgB,EAAW,IAAI,EAC/B,cAAiB,CACf,IAAM,EAAO,EACb,EAAW,IAAI,EACf,GAAM,IAAI,CACZ,CACD,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,EAAD,CAAqB,KAAM,EAAM,UAAW,QAAS,EAAM,WAAY,OAAQ,EAAM,YAAa,UAAU,wCAA0C,CAAA,CACtJ,CAAA,CAAA,EAGJ,MAAO,CAAE,MAAK,KAAM,EAAM,KAAM,MAAO,EAAM,MAAO,WAAY,EAAM,WAAY,SAAU,EAAM,SAAU,SAAQ,CACtH,CAGA,SAAgB,EAAa,CAAE,WAAmF,CAShH,OARI,EAAQ,UAER,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAW,EAAO,WAAY,KAAK,SAAS,SAAA,4IAE5C,CAAA,EAGF,EAAQ,OAEX,EAAA,EAAA,KAAA,CAAC,IAAD,CAAG,UAAW,EAAO,YAAa,KAAK,QAAvC,SAAA,CACG,EAAQ,OACT,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,KAAK,SAAS,UAAW,EAAO,WAAY,QAAS,EAAQ,WAAY,SAAA,SAEzE,CAAA,CACP,IAPsB,IAS7B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._lead_i2poc_8{gap:var(--space-3);flex-direction:column;display:flex}._bar_i2poc_14{align-items:center;gap:var(--space-2) var(--space-3);min-height:var(--control-h);flex-wrap:wrap;display:flex}._barSpacer_i2poc_22{flex:1}._barSecondary_i2poc_26{gap:var(--space-2);flex-wrap:wrap;display:flex}._switchWrap_i2poc_32{align-items:center;gap:var(--space-2);display:inline-flex}._barLabel_i2poc_38,._pillLabel_i2poc_39{font-family:var(--font-display);font-size:var(--text-2xs-size);line-height:var(--text-2xs-line);letter-spacing:var(--tracking-label);text-transform:uppercase;color:var(--text-tertiary)}._switchOption_i2poc_48{align-items:center;gap:var(--space-1);display:inline-flex}._touchMark_i2poc_54{color:var(--text-tertiary)}._pill_i2poc_39,._chip_i2poc_59{align-items:center;gap:var(--space-2);min-height:var(--control-h-sm);padding:0 var(--space-3);border:1px solid var(--border-default);border-radius:var(--radius-full);background:var(--bg-surface);color:var(--text-primary);font-family:var(--font-ui);font-size:var(--text-xs-size);line-height:var(--text-xs-line);white-space:nowrap;display:inline-flex}button._pill_i2poc_39,button._chip_i2poc_59{cursor:pointer;transition:background-color var(--duration-fast) var(--ease-standard)}button._pill_i2poc_39:hover,button._chip_i2poc_59:hover{background:var(--bg-hover)}._pill_i2poc_39:focus-visible,._chip_i2poc_59:focus-visible,._linkButton_i2poc_88:focus-visible,._moreLink_i2poc_89:focus-visible{outline:2px solid var(--border-focus);outline-offset:2px}._chip_i2poc_59[data-tone=warning]{border-color:var(--status-warning-solid)}._chip_i2poc_59[data-tone=danger]{border-color:var(--status-danger-solid);color:var(--status-danger-fg)}._dot_i2poc_103{border-radius:var(--radius-full);background:var(--status-neutral-solid);flex:none;width:8px;height:8px}._dot_i2poc_103[data-tone=success]{background:var(--status-success-solid)}._dot_i2poc_103[data-tone=warning]{background:var(--status-warning-solid)}._dot_i2poc_103[data-tone=danger]{background:var(--status-danger-solid)}._dot_i2poc_103[data-tone=unknown]{background:var(--chart-unknown-hatch);border:1px solid var(--status-unknown-solid)}._verdict_i2poc_126{font-size:var(--text-lg-size);line-height:var(--text-lg-line);font-weight:var(--font-weight-medium);color:var(--text-primary);font-variant-numeric:tabular-nums;margin:0}._verdictPart_i2poc_135[data-tone=danger]{color:var(--status-danger-fg)}._verdictPart_i2poc_135[data-tone=warning]{color:var(--status-warning-fg)}._verdictPart_i2poc_135[data-tone=success]{color:var(--status-success-fg)}._verdictPart_i2poc_135[data-tone=unknown]{color:var(--status-unknown-fg);font-style:italic}._verdictSep_i2poc_149{color:var(--text-tertiary)}._since_i2poc_153{align-items:center;gap:var(--space-2);font-size:var(--text-xs-size);line-height:var(--text-xs-line);flex-wrap:wrap;display:flex}._sinceLead_i2poc_162,._sinceEmpty_i2poc_166{color:var(--text-tertiary)}._sinceChip_i2poc_170{padding:1px var(--space-2);border-radius:var(--radius-full);background:var(--status-neutral-bg);color:var(--status-neutral-fg);font-variant-numeric:tabular-nums;align-items:center;display:inline-flex}._sinceChip_i2poc_170[data-tone=success]{background:var(--status-success-bg);color:var(--status-success-fg)}._sinceChip_i2poc_170[data-tone=danger]{background:var(--status-danger-bg);color:var(--status-danger-fg)}._sinceChip_i2poc_170[data-tone=warning]{background:var(--status-warning-bg);color:var(--status-warning-fg)}._sinceChip_i2poc_170[data-tone=info]{background:var(--status-info-bg);color:var(--status-info-fg)}._actionNote_i2poc_196,._actionError_i2poc_197{padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);font-size:var(--text-sm-size);line-height:var(--text-sm-line);margin:0}._actionNote_i2poc_196{background:var(--bg-hover);color:var(--text-secondary)}._actionError_i2poc_197{align-items:baseline;gap:var(--space-3);background:var(--status-danger-bg);color:var(--status-danger-fg);display:flex}._linkButton_i2poc_88,._moreLink_i2poc_89{align-items:center;gap:var(--space-1);color:var(--text-link);font:inherit;font-size:var(--text-xs-size);line-height:var(--text-xs-line);cursor:pointer;white-space:nowrap;background:0 0;border:0;padding:0;text-decoration:none;display:inline-flex}._linkButton_i2poc_88:hover,._moreLink_i2poc_89:hover{text-decoration:underline}._moreLink_i2poc_89{align-self:flex-start}._moreLink_i2poc_89:disabled{color:var(--text-disabled);cursor:default;text-decoration:none}._kbd_i2poc_251{padding:0 var(--space-1);border:1px solid var(--border-subtle);border-radius:var(--radius-xs);color:var(--text-tertiary);font-family:var(--font-mono);font-size:var(--text-2xs-size)}._muted_i2poc_260{color:var(--text-tertiary);font-size:var(--text-xs-size);line-height:var(--text-xs-line);margin:0}._mono_i2poc_267{font-family:var(--font-mono);font-size:var(--text-xs-size)}._num_i2poc_272{text-align:right;font-variant-numeric:tabular-nums}._confirmBody_i2poc_277{color:var(--text-secondary);font-size:var(--text-sm-size);line-height:var(--text-sm-line-relaxed)}._confirmActions_i2poc_283{justify-content:flex-end;gap:var(--space-2);margin-top:var(--space-5);display:flex}._needsList_i2poc_291{flex-direction:column;margin:0;padding:0;list-style:none;display:flex}._needsRow_i2poc_299{align-items:start;gap:var(--space-2) var(--space-3);padding:var(--space-2) 0;border-top:1px solid var(--border-subtle);grid-template-columns:auto minmax(0,1fr) auto;display:grid}._needsRow_i2poc_299:first-child{border-top:0;padding-top:0}._sevDot_i2poc_313{border-radius:var(--radius-full);background:var(--status-info-solid);width:8px;height:8px;margin-top:6px}._sevDot_i2poc_313[data-severity=warn]{background:var(--status-warning-solid)}._sevDot_i2poc_313[data-severity=high]{background:var(--status-danger-solid)}._needsText_i2poc_327{flex-direction:column;gap:2px;min-width:0;display:flex}._needsTitle_i2poc_334{color:var(--text-primary);font-size:var(--text-sm-size);line-height:var(--text-sm-line);overflow-wrap:anywhere}._needsDetail_i2poc_341{color:var(--text-secondary);font-size:var(--text-xs-size);line-height:var(--text-xs-line);overflow-wrap:anywhere}._needsMeta_i2poc_348{color:var(--text-tertiary);font-family:var(--font-mono);font-size:var(--text-2xs-size);line-height:var(--text-2xs-line)}._needsActions_i2poc_355{justify-content:flex-end;align-items:center;gap:var(--space-2);flex-wrap:wrap;display:flex}._allClear_i2poc_363{gap:var(--space-1);padding:var(--space-4) 0;flex-direction:column;display:flex}._allClearTitle_i2poc_370{font-family:var(--font-display);font-size:var(--text-md-size);line-height:var(--text-md-line);font-weight:var(--font-weight-semibold);color:var(--text-primary)}._allClearBody_i2poc_378{color:var(--text-secondary);font-size:var(--text-sm-size)}._memo_i2poc_384{gap:var(--space-2);flex-direction:column;margin:0;display:flex}._memoRow_i2poc_391{gap:var(--space-3);grid-template-columns:96px minmax(0,1fr);align-items:baseline;display:grid}._memoRow_i2poc_391 dd{margin:0}._memoText_i2poc_402{color:var(--text-primary);font-size:var(--text-base-size);line-height:var(--text-base-line)}._delta_i2poc_408{margin-left:var(--space-2);padding:0 var(--space-2);border-radius:var(--radius-full);background:var(--status-info-bg);color:var(--status-info-fg);font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);font-variant-numeric:tabular-nums;white-space:nowrap;display:inline-block}._dryRun_i2poc_421{font-family:var(--font-display);padding:0 var(--space-2);border:1px dashed var(--border-strong);border-radius:var(--radius-full);color:var(--text-secondary);font-size:var(--text-2xs-size);line-height:var(--text-xs-line);text-transform:uppercase;letter-spacing:var(--tracking-label)}._actionList_i2poc_433{border-top:1px solid var(--border-subtle);flex-direction:column;margin:0;padding:0;list-style:none;display:flex}._actionRow_i2poc_442{gap:var(--space-3);padding:var(--space-2) 0;border-bottom:1px solid var(--border-subtle);grid-template-columns:auto minmax(0,1fr) auto;align-items:center;display:grid}._actionRow_i2poc_442[data-status=vetoed] ._actionSummary_i2poc_451{color:var(--text-tertiary);text-decoration:line-through}._classBadge_i2poc_456{border:1px solid var(--border-default);border-radius:var(--radius-sm);width:20px;height:20px;color:var(--text-secondary);font-family:var(--font-display);font-size:var(--text-2xs-size);font-weight:var(--font-weight-semibold);justify-content:center;align-items:center;display:inline-flex}._classBadge_i2poc_456[data-class=B]{border-color:var(--status-warning-solid);color:var(--status-warning-fg)}._classBadge_i2poc_456[data-class=C]{border-style:dashed}._actionText_i2poc_479{flex-direction:column;min-width:0;display:flex}._actionSummary_i2poc_451{color:var(--text-primary);font-size:var(--text-sm-size);line-height:var(--text-sm-line);overflow-wrap:anywhere}._actionWhy_i2poc_492{color:var(--text-tertiary);font-size:var(--text-xs-size);line-height:var(--text-xs-line);overflow-wrap:anywhere}._actionState_i2poc_499{align-items:center;gap:var(--space-2);display:inline-flex}._statusWord_i2poc_505{color:var(--text-tertiary);font-size:var(--text-xs-size);white-space:nowrap}._statusWord_i2poc_505[data-status=escalated]{color:var(--status-warning-fg)}._statusWord_i2poc_505[data-status=failed],._statusWord_i2poc_505[data-status=refused]{color:var(--status-danger-fg)}._vetoChip_i2poc_520{border:1px solid var(--border-default)}._ring_i2poc_524{align-items:center;gap:var(--space-1);color:var(--status-warning-fg);font-size:var(--text-xs-size);font-variant-numeric:tabular-nums;white-space:nowrap;display:inline-flex}._ringTrack_i2poc_534{fill:none;stroke:var(--border-subtle);stroke-width:2.5px}._ringFill_i2poc_540{fill:none;stroke:var(--status-warning-solid);stroke-width:2.5px;stroke-linecap:round}._ringText_i2poc_547{min-width:4ch}._kpis_i2poc_552{gap:var(--surface-gap);grid-template-columns:repeat(5,minmax(0,1fr));align-items:start;display:grid}[data-viewport=medium] ._kpis_i2poc_552{grid-template-columns:repeat(3,minmax(0,1fr))}[data-viewport=compact] ._kpis_i2poc_552{grid-template-columns:repeat(2,minmax(0,1fr))}._burnGrid_i2poc_567{gap:var(--surface-gap);grid-template-columns:repeat(4,minmax(0,1fr));align-items:start;display:grid}[data-viewport=medium] ._burnGrid_i2poc_567{grid-template-columns:repeat(2,minmax(0,1fr))}._burnStrip_i2poc_579{gap:var(--space-3);overscroll-behavior-x:contain;scroll-snap-type:x mandatory;padding-bottom:var(--space-1);grid-auto-columns:86%;grid-auto-flow:column;display:grid;overflow-x:auto}._burnStrip_i2poc_579>._burnItem_i2poc_590{scroll-snap-align:start}._burnItem_i2poc_590{min-width:0}._freeSeat_i2poc_598{gap:var(--space-2);padding:var(--card-pad);border:1px solid var(--border-subtle);border-radius:var(--radius-lg);background:var(--bg-surface);flex-direction:column;display:flex}._freeHead_i2poc_608{align-items:center;gap:var(--space-2);display:inline-flex}._freeTitle_i2poc_614{font-size:var(--text-sm-size);line-height:var(--text-sm-line);font-weight:var(--font-weight-semibold);color:var(--text-primary)}._freeValue_i2poc_621{font-size:var(--text-2xl-size);line-height:var(--text-2xl-line);font-weight:var(--font-weight-semibold);color:var(--text-secondary)}._freeBody_i2poc_628{color:var(--text-tertiary);font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed)}._scope_i2poc_635{gap:var(--space-5);flex-direction:column;display:flex}._scopeBlock_i2poc_641{gap:var(--space-2);flex-direction:column;display:flex}._scopeLead_i2poc_647{color:var(--text-primary);font-size:var(--text-base-size);line-height:var(--text-base-line);margin:0}._scopeMeta_i2poc_654{color:var(--text-tertiary);font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);margin:0}._scopeTable_i2poc_661{border-collapse:collapse;width:100%;font-size:var(--text-xs-size)}._scopeTable_i2poc_661 th{padding:var(--space-1) var(--space-2) var(--space-1) 0;border-bottom:1px solid var(--border-subtle);color:var(--text-tertiary);font-weight:var(--font-weight-medium);text-align:left}._scopeTable_i2poc_661 td{padding:var(--space-1) var(--space-2) var(--space-1) 0;border-bottom:1px solid var(--border-subtle);color:var(--text-primary)}._scopeList_i2poc_681{padding-left:var(--space-4);color:var(--text-secondary);font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);margin:0}._ladder_i2poc_689{gap:var(--space-2);counter-reset:rung;font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);color:var(--text-secondary);flex-direction:column;margin:0;padding:0;list-style:none;display:flex}._ladder_i2poc_689 li{gap:var(--space-2);grid-template-columns:56px minmax(0,1fr);display:grid}._ladderId_i2poc_708{font-family:var(--font-mono);color:var(--text-primary)}._sheetFooter_i2poc_713{gap:var(--space-3);flex-direction:column;display:flex}._sheetFootnote_i2poc_719{color:var(--text-tertiary);font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);margin:0}._sheetButtons_i2poc_726{justify-content:flex-end;gap:var(--space-2);display:flex}@media (prefers-reduced-motion:reduce){button._pill_i2poc_39,button._chip_i2poc_59{transition:none}}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./workbench-types-DzN-5trg.js";import{r as t}from"./verse-model-E98kXngO.js";import{t as n}from"./seat-subscription-CrWOV4Qc.js";function r(e,t){if(!e)return null;for(let n of e)if(n.seatId===t)return n;return null}function i(e,t=Date.now()){if(typeof e!=`string`||e.length===0)return null;let n=Date.parse(e);if(!Number.isFinite(n))return null;let r=new Date(n),i=r.toLocaleTimeString([],{hour:`numeric`,minute:`2-digit`});return new Date(t).toDateString()===r.toDateString()?`today ${i}`:n>t&&n-t<5184e5?`${r.toLocaleDateString([],{weekday:`short`})} ${i}`:`${r.toLocaleDateString([],{month:`short`,day:`numeric`})}, ${i}`}function a(e){return(e.capacity?.binding??null)?.resetDescription??null}function o(e,t,n=Date.now()){let r=null,o=null;if(t!==null)(t.connection===`signed-out`||t.connection===`exhausted`)&&(r=t.connection,o=t.resetAt);else if(e.engine!==`local`){let t=e.capacity?.usability;(t===`signed-out`||t===`exhausted`)&&(r=t,o=t===`exhausted`?e.capacity?.binding?.resetsAt??null:null)}if(r===null)return null;if(r===`signed-out`)return{connection:r,resetAt:null,reason:`${e.label} is signed out — reconnect it to use this seat.`};let s=i(o,n),c=s===null?a(e):null,l=s===null?c===null?``:` — ${c}`:` — resets ${s}`;return{connection:r,resetAt:o,reason:`${e.label} is out of usage${l}.`}}function s(e){return e.models.some(e=>!e.unavailableReason)}function c(e){return e.engine===`local`?2:e.capacity?.usability===`ready`?0:1}function l(e){let t=e.capacity?.binding?.usedPercent;return typeof t==`number`&&Number.isFinite(t)?t:101}function u(e,t,n){return!(!s(e)||e.health.state===`unavailable`||o(e,t,n)!==null||e.engine===`local`&&t!==null&&t.connection===`unknown`&&t.reasons.length>0)}function d(e,t,n,i=Date.now()){let a=t.find(t=>t.id===e)??null,o=t.map((e,t)=>({seat:e,index:t})).filter(({seat:t})=>t.id!==e&&u(t,r(n,t.id),i));return o.sort((e,t)=>{let n=c(e.seat)-c(t.seat);if(n!==0)return n;if(a!==null){let n=e.seat.engine===a.engine?0:1,r=t.seat.engine===a.engine?0:1;if(n!==r)return n-r}let r=l(e.seat)-l(t.seat);return r===0?e.index-t.index:r}),o.slice(0,5).map(({seat:e})=>e.id)}Object.freeze({"all-in":Object.freeze({claude:Object.freeze({enabled:!0,reservePercent:0}),codex:Object.freeze({enabled:!1,reservePercent:0}),grok:Object.freeze({enabled:!0,reservePercent:0}),local:Object.freeze({enabled:!0,reservePercent:0})}),balanced:Object.freeze({claude:Object.freeze({enabled:!0,reservePercent:40,maxSessionWindowPercent:70}),codex:Object.freeze({enabled:!1,reservePercent:40,maxSessionWindowPercent:70}),grok:Object.freeze({enabled:!0,reservePercent:0}),local:Object.freeze({enabled:!0,reservePercent:0})}),reserve:Object.freeze({claude:Object.freeze({enabled:!0,reservePercent:85,maxSessionWindowPercent:50}),codex:Object.freeze({enabled:!1,reservePercent:85,maxSessionWindowPercent:50}),grok:Object.freeze({enabled:!0,reservePercent:85}),local:Object.freeze({enabled:!0,reservePercent:0})})});var f=Object.freeze({"all-in":`Autonomy may use all available usage on every enabled seat.`,balanced:`Autonomy stops at each seat’s reserve, so you keep headroom for your own sessions.`,reserve:`Autonomy runs on free local models, plus only a small slice of paid seats.`}),p={eligible:`Eligible`,held:`Held back`,off:`Off`,unknown:`No reading`},m=[{value:`reserve`,label:`Reserve`,description:f.reserve},{value:`balanced`,label:`Balanced`,description:f.balanced},{value:`all-in`,label:`All-in`,description:f[`all-in`]}];function h(e,t){if(!t)return!1;let n=e=>m.findIndex(t=>t.value===e);return n(e)>n(t)}function g(e){return Math.round(e)}function _(e,t,n){return t.enabled?n?.eligibleForAutonomy?`eligible`:!e&&(n===null||n.sessionUsedPercent===null&&n.weeklyUsedPercent===null)?`unknown`:`held`:`off`}function v(e,t,n,r){if(t||r===null)return[];let i=[],a=100-n.reservePercent,o=r.weeklyUsedPercent!==null||e===`claude`||e===`grok`;if(o){let t=r.weeklyUsedPercent;i.push({kind:`weekly`,label:e===`grok`?`Billing period`:`Weekly`,usedPercent:t,ceilingPercent:a,binding:r.bindingWindow===`weekly`,description:t===null?`Weekly window: no reading.`:`Weekly window ${g(t)}% used; autonomy stops at ${g(a)}%, ${g(n.reservePercent)}% kept for you.`})}if(r.sessionUsedPercent!==null||e===`claude`){let e=r.sessionUsedPercent,t=n.maxSessionWindowPercent??100,s=o?t:Math.min(t,a);i.push({kind:`session`,label:`5-hour`,usedPercent:e,ceilingPercent:s,binding:r.bindingWindow===`session`,description:e===null?`5-hour window: no reading.`:`5-hour window ${g(e)}% used; ${s>=100?`no autonomy ceiling`:`autonomy stops at ${g(s)}%`}.`})}return i}function y(e){let t=new Map(e.headroom.map(e=>[e.seatId,e]));return e.seatInfo.map(n=>{let r=e.effective[n.seatId]??{seatId:n.seatId,enabled:!1,reservePercent:100},i=t.get(n.seatId)??null,a=i?.reasons??[];return{seatId:n.seatId,label:n.label,engine:n.engine,free:n.free,policy:r,headroom:i,status:_(n.free,r,i),why:a[0]??(n.free?`Local model — free.`:`No reading yet.`),more:a.slice(1),bars:v(n.engine,n.free,r,i),hasSessionCeiling:!n.free&&(n.engine===`claude`||n.engine===`codex`)}})}function b(e){let t=e.filter(e=>e.status===`eligible`).length,n=e.length;if(n===0)return{eligible:t,total:n,sentence:`No seats are known yet.`};let r=e.filter(e=>e.status===`eligible`&&!e.free).length,i=t-r,a=[];return r>0&&a.push(`${r} paid`),i>0&&a.push(`${i} local`),{eligible:t,total:n,sentence:t===0?`No seat can take autonomous work right now.`:`${t} of ${n} seats can take autonomous work (${a.join(`, `)}).`}}function x(e,t){let n=Date.parse(e);if(!Number.isFinite(n))return`unknown`;let r=Math.max(0,Math.round((t-n)/6e4));return r<1?`just now`:r<120?`${r} min ago`:`${Math.round(r/60)} h ago`}function S(e,t=0,n=100){return Number.isFinite(e)?Math.max(t,Math.min(n,Math.round(e))):t}var C={connected:`connected`,expiring:`sign-in expiring`,"signed-out":`signed out`,exhausted:`out of usage`,"binary-skew":`older CLI pinned`,unknown:`not checked`},w={connected:`success`,expiring:`warning`,"signed-out":`danger`,exhausted:`danger`,"binary-skew":`warning`,unknown:`neutral`},T={"signed-out":0,exhausted:1,expiring:2,"binary-skew":3,unknown:4,connected:5};function E(e){return e.connection===`connected`?!1:e.connection!==`unknown`||e.reasons.length>0&&!e.reasons[0].includes(`has not reached this seat`)}function D(e,t=[],n=Date.now()){let r=new Map(t.map(e=>[e.id,e.label]));return e.filter(E).map(e=>{let t=i(e.resetAt,n);return{report:e,label:r.get(e.seatId)??e.seatId,word:C[e.connection],tone:w[e.connection],detail:e.reasons[0]??null,reset:t===null?null:`resets ${t}`}}).sort((e,t)=>T[e.report.connection]-T[t.report.connection])}function O(e){return e.map(e=>/^[A-Za-z0-9_@%+=:,./-]+$/.test(e)||e.startsWith(`~/`)&&/^[A-Za-z0-9_@%+=:,./~-]+$/.test(e)?e:e.startsWith(`~/`)?`~/'${e.slice(2).replaceAll(`'`,`'\\''`)}'`:`'${e.replaceAll(`'`,`'\\''`)}'`).join(` `)}function k(e){if(e.length===0)return`All seats are connected.`;let t=e.filter(e=>e.tone===`danger`).length;return t>0?t===1?`${e.find(e=>e.tone===`danger`).label} can't run turns right now.`:`${t} seats can't run turns right now.`:e.length===1?`${e[0].label} needs attention.`:`${e.length} seats need attention.`}var A={ready:`success`,tight:`warning`,blocked:`danger`,unread:`neutral`};function j(e){return A[e]}function M(e,t){return{id:e.id,label:e.label,usedPercent:e.usedPercent,limitReached:e.limitReached,resetText:e.resetText,binding:t}}function N(e){return e?{connection:e.connection,word:C[e.connection],tone:w[e.connection],reasons:[...e.reasons],fixKind:e.fix.kind,fixCommand:e.fix.command&&e.fix.command.length>0?[...e.fix.command]:null}:null}function P(e){if(!e||e.free)return null;let{policy:t}=e,n=Math.max(0,Math.min(100,Math.round(t.reservePercent))),r=t.enabled?n===0?`No reserve — autonomy may use all of it`:`Reserved for you ${n}%`:`Autonomy off — all yours`;return{percent:t.enabled?n:null,label:r,autonomy:e.status,autonomyWord:p[e.status],why:e.why}}function F(r,i,a){let o=n(r),s=[];o.binding&&s.push(M(o.binding,!0));for(let e of o.others){if(s.length>=3)break;s.push(M(e,!1))}let c=N(i.get(r.id)),l=c!==null&&(c.connection===`signed-out`||c.connection===`exhausted`);return{seatId:r.id,label:r.label,engine:r.engine,monogram:e[r.engine],kind:o.kind,plan:o.plan,cls:l?`blocked`:o.cls,word:l?t.blocked:o.word,summary:l?c.reasons[0]??c.word:o.summary,connection:c,windows:s,credits:o.credits,reserve:P(a.get(r.id)),notes:[...o.notes],localCount:1}}function I(t,r){let i=t.map(e=>n(e)),a=i.filter(e=>e.cls===`ready`).length,o=i.filter(e=>e.cls===`blocked`).length,s=a>0?`ready`:o===i.length?`blocked`:`unread`,c=t.map(e=>r.get(e.id)).find(e=>e!==void 0),l=t.length;return{seatId:`local`,label:`Local models`,engine:`local`,monogram:e.local,kind:`local`,plan:null,cls:s,word:i.find(e=>e.cls===s)?.word??`no reading`,summary:s===`ready`?`${l} ${l===1?`model`:`models`} on this machine · free`:s===`blocked`?i[0]?.summary??`local runtime unavailable`:`readiness not reported`,connection:N(c),windows:[],credits:null,reserve:null,notes:[],localCount:l}}function L(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}var R=e=>typeof e==`number`&&Number.isFinite(e)?e:null;function z(e){if(!L(e)||typeof e.seatId!=`string`)return null;let t=e.bindingWindow;return{seatId:e.seatId,sessionUsedPercent:R(e.sessionUsedPercent),weeklyUsedPercent:R(e.weeklyUsedPercent),bindingWindow:t===`session`||t===`weekly`?t:null,autonomyHeadroomPercent:R(e.autonomyHeadroomPercent),resetAt:typeof e.resetAt==`string`?e.resetAt:null,eligibleForAutonomy:e.eligibleForAutonomy===!0,reasons:Array.isArray(e.reasons)?e.reasons.filter(e=>typeof e==`string`):[]}}function B(e,t){if(!L(t)||typeof t.enabled!=`boolean`)return null;let n=t.reservePercent;if(typeof n!=`number`||!Number.isFinite(n))return null;let r={seatId:e,enabled:t.enabled,reservePercent:n},i=t.maxSessionWindowPercent;return typeof i==`number`&&Number.isFinite(i)&&(r.maxSessionWindowPercent=i),r}function V(e){if(!L(e)||!Array.isArray(e.seatInfo))return new Map;let t=L(e.effective)?e.effective:{},n={},r=[];for(let i of e.seatInfo){if(!L(i)||typeof i.seatId!=`string`)continue;let e=i.seatId,a=i.engine;if(a===`claude`||a===`codex`||a===`grok`||a===`local`){if(Object.prototype.hasOwnProperty.call(t,e)){let r=B(e,t[e]);if(r===null)continue;n[e]=r}r.push({seatId:e,label:typeof i.label==`string`?i.label:e,engine:a,free:i.free===!0})}}let i=Array.isArray(e.headroom)?e.headroom.map(z).filter(e=>e!==null):[],a={...e,seatInfo:r,effective:n,headroom:i};try{return new Map(y(a).map(e=>[e.seatId,e]))}catch{return new Map}}function H(e){let t=new Map;if(!Array.isArray(e))return t;for(let n of e){if(!L(n)||typeof n.seatId!=`string`)continue;let e=n.connection;if(typeof e!=`string`||!Object.prototype.hasOwnProperty.call(C,e))continue;let r=L(n.fix)?n.fix:{},i=r.kind,a=Array.isArray(r.command)&&r.command.every(e=>typeof e==`string`)?r.command:void 0;t.set(n.seatId,{...n,reasons:Array.isArray(n.reasons)?n.reasons.filter(e=>typeof e==`string`):[],fix:{kind:i===`reauth`||i===`repin`||i===`wait`?i:`none`,...a?{command:a}:{}}})}return t}function U(e,t={}){let n=H(t.health),r=V(t.budget),i=Array.isArray(e)?e.filter(e=>L(e)&&typeof e.id==`string`):[],a=t.local??`collapse`,o=i;if(t.seatIds){let e=new Map(i.map(e=>[e.id,e]));o=t.seatIds.map(t=>e.get(t)).filter(e=>e!==void 0)}let s=[],c=[],l=-1;for(let e of o){if(e.engine===`local`){if(a===`hide`)continue;if(a===`collapse`){l===-1&&(l=s.length),c.push(e);continue}}s.push(F(e,n,r))}if(c.length>0){let e=c.length===1?F(c[0],n,r):I(c,n);s.splice(l,0,e)}return s}function W(e){let t=e.filter(e=>e.kind===`subscription`),n=e.filter(e=>e.kind===`local`),r=t.filter(e=>e.cls===`ready`||e.cls===`tight`).length,i=t.filter(e=>e.cls===`unread`).length,a=[];return t.length===0?a.push(`No accounts connected`):a.push(`${r} of ${t.length} ${t.length===1?`account`:`accounts`} usable`),i>0&&a.push(`${i} not read yet`),n.some(e=>e.cls===`ready`)?a.push(`local models ready`):n.length>0&&a.push(`local models not ready`),a.join(` · `)}function G(e){let t=null;for(let n of e){if(n.kind!==`subscription`)continue;let e=n.windows.find(e=>e.binding)??null,r;if(n.cls===`blocked`||e?.limitReached)r=300;else if(e?.usedPercent!=null)r=(n.cls===`tight`?100:0)+e.usedPercent;else continue;(t===null||r>t.score)&&(t={row:n,score:r})}return t?.row??null}function K(e,t,n={}){return U(e,{...n,seatIds:[t],local:`each`})[0]??null}function q(e,t,n){let r=`${e.label} ${t.label}`,i=t.resetText===null?``:`, ${t.resetText}`;if(t.limitReached)return`${r}: limit reached${i}`;if(t.usedPercent===null)return`${r}: no reading${i}`;let a=n!==null&&n>0?`; ${n}% kept for you`:``;return`${r}: ${Math.round(t.usedPercent)}% used${a}${i}`}export{d as _,V as a,k as c,m as d,p as f,x as g,h,j as i,D as l,S as m,W as n,G as o,b as p,K as r,q as s,U as t,O as u,o as v};
|
|
2
|
-
//# sourceMappingURL=capacity-strip-model-BR539Ci8.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"capacity-strip-model-BR539Ci8.js","names":[],"sources":["../../../../../../src/core/verse/seat-readiness.ts","../../../../../../src/core/routing/policy.ts","../../../../../../src/web-ui/routes/verse/budget/budget-model.ts","../../../../../../src/web-ui/routes/verse/health/health-model.ts","../../../../../../src/web-ui/routes/verse/usage/capacity-strip-model.ts"],"sourcesContent":["/**\n * core/verse/seat-readiness.ts — \"can this seat run a turn right now, and if\n * not, where else can the operator go?\" (V3.10, unit A2).\n *\n * PURE and BROWSER-SAFE on purpose: the engine's admission gate\n * (`getSeatReadiness` in core/verse/seats.ts) and the Composer's block\n * (web-ui/routes/verse/health/ComposerSeatBlock.tsx) must give the SAME\n * answer, with the SAME ranked alternatives, or the UI would offer a seat the\n * server then refuses. One implementation, imported by both. Type-only\n * imports and `Intl` only — no node: modules.\n *\n * ── WHAT BLOCKS A SEAT ─────────────────────────────────────────────────────\n * Only POSITIVE evidence that a turn would fail at the provider:\n * - `signed-out` — the CLI said so (status command or the live collector).\n * - `exhausted` — every window that carried a reading is spent and no\n * Codex credit balance remains (`seatUsability` in seats.ts;\n * a spent per-model window beside a healthy account-wide\n * one is `tight`, not exhausted).\n * `unknown`, `expiring` and `binary-skew` are WARNINGS, never refusals: an\n * admission gate that refused on \"we could not read it\" would lock Mason out\n * of his own seats every time a probe hiccuped (docs/VERSE-TELEMETRY-V2.md —\n * no signal is not a verdict).\n *\n * ── HOW ALTERNATIVES ARE RANKED ────────────────────────────────────────────\n * (research r2/accounts.md, recommendation 4): other subscription seats with\n * measured headroom first, then subscription seats whose headroom is tight or\n * unread, then local models (free, always last because they are the weakest).\n * Inside a tier the SAME ENGINE leads (a Codex user blocked on one account most\n * likely wants the other Codex account), then the lower binding-window\n * percentage, then discovery order. A seat with no runnable model, a local\n * seat whose runtime is not answering, or a seat that is itself blocked is\n * never offered.\n */\nimport type { SeatConnection, SeatHealthReport, SeatReadiness } from './health-types.js';\nimport type { VerseSeat } from './types.js';\n\n/** The only connections that refuse a turn. Everything else is a warning. */\nexport const SEAT_BLOCKING_CONNECTIONS: ReadonlySet<SeatConnection> = new Set<SeatConnection>(['signed-out', 'exhausted']);\n\n/** At most this many alternatives are offered — a list, not a directory. */\nexport const SEAT_MAX_ALTERNATIVES = 5;\n\nexport interface SeatBlock {\n connection: 'signed-out' | 'exhausted';\n /** One plain sentence naming the seat and the fact (\"Personal Codex is out of usage — resets Fri 2:25 PM.\"). */\n reason: string;\n /** Machine-readable reset instant, when the provider gave one. */\n resetAt: string | null;\n}\n\nfunction reportFor(reports: readonly SeatHealthReport[] | null | undefined, seatId: string): SeatHealthReport | null {\n if (!reports) return null;\n for (const report of reports) if (report.seatId === seatId) return report;\n return null;\n}\n\n/**\n * A reset instant as a short local phrase (\"Fri 2:25 PM\", \"Sep 30, 2:25 PM\"),\n * or null when `iso` is not a valid instant. Only a MACHINE-READABLE instant\n * is ever formatted — Claude's prose reset never reaches this function.\n */\nexport function describeResetAt(iso: string | null | undefined, now: number = Date.now()): string | null {\n if (typeof iso !== 'string' || iso.length === 0) return null;\n const at = Date.parse(iso);\n if (!Number.isFinite(at)) return null;\n const date = new Date(at);\n const time = date.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });\n if (new Date(now).toDateString() === date.toDateString()) return `today ${time}`;\n // Within the coming week the weekday is the clearest name for a day.\n if (at > now && at - now < 6 * 24 * 60 * 60 * 1000) {\n return `${date.toLocaleDateString([], { weekday: 'short' })} ${time}`;\n }\n return `${date.toLocaleDateString([], { month: 'short', day: 'numeric' })}, ${time}`;\n}\n\n/** The provider's own reset wording for the seat's binding window (Claude publishes prose only). */\nfunction bindingResetDescription(seat: VerseSeat): string | null {\n const binding = seat.capacity?.binding ?? null;\n return binding?.resetDescription ?? null;\n}\n\n/**\n * Why `seat` cannot take a turn, or null when nothing positively blocks it.\n *\n * The health report (sweep + live telemetry) wins when present; without one\n * the seat's own `capacity.usability` — which is on every native seat the\n * server serves — is the fallback, so the seat picker can mark a blocked seat\n * before the health endpoint has ever been read.\n */\nexport function seatBlock(\n seat: VerseSeat,\n report: SeatHealthReport | null,\n now: number = Date.now(),\n): SeatBlock | null {\n let connection: SeatBlock['connection'] | null = null;\n let resetAt: string | null = null;\n if (report !== null) {\n if (report.connection === 'signed-out' || report.connection === 'exhausted') {\n connection = report.connection;\n resetAt = report.resetAt;\n }\n } else if (seat.engine !== 'local') {\n const usability = seat.capacity?.usability;\n if (usability === 'signed-out' || usability === 'exhausted') {\n connection = usability;\n resetAt = usability === 'exhausted' ? seat.capacity?.binding?.resetsAt ?? null : null;\n }\n }\n if (connection === null) return null;\n if (connection === 'signed-out') {\n return { connection, resetAt: null, reason: `${seat.label} is signed out — reconnect it to use this seat.` };\n }\n const when = describeResetAt(resetAt, now);\n const prose = when === null ? bindingResetDescription(seat) : null;\n const tail = when !== null ? ` — resets ${when}` : prose !== null ? ` — ${prose}` : '';\n return { connection, resetAt, reason: `${seat.label} is out of usage${tail}.` };\n}\n\nfunction hasRunnableModel(seat: VerseSeat): boolean {\n return seat.models.some((model) => !model.unavailableReason);\n}\n\n/** 0 = subscription seat with measured headroom, 1 = tight/unread subscription seat, 2 = local. */\nfunction tier(seat: VerseSeat): number {\n if (seat.engine === 'local') return 2;\n return seat.capacity?.usability === 'ready' ? 0 : 1;\n}\n\nfunction bindingPercent(seat: VerseSeat): number {\n const used = seat.capacity?.binding?.usedPercent;\n // Unread sorts after every reading: no signal is not \"0% used\".\n return typeof used === 'number' && Number.isFinite(used) ? used : 101;\n}\n\n/** Can `seat` be offered as somewhere else to go? */\nfunction offerable(seat: VerseSeat, report: SeatHealthReport | null, now: number): boolean {\n if (!hasRunnableModel(seat)) return false;\n if (seat.health.state === 'unavailable') return false;\n if (seatBlock(seat, report, now) !== null) return false;\n // A local seat is only worth offering while its runtime answers. `unknown`\n // with reasons is the sweep saying Ollama did not respond.\n if (seat.engine === 'local' && report !== null && report.connection === 'unknown' && report.reasons.length > 0) {\n return false;\n }\n return true;\n}\n\n/** Ranked ids of seats that could take the turn instead of `seatId` (see the file header). */\nexport function rankSeatAlternatives(\n seatId: string,\n seats: readonly VerseSeat[],\n reports: readonly SeatHealthReport[] | null | undefined,\n now: number = Date.now(),\n): string[] {\n const blocked = seats.find((seat) => seat.id === seatId) ?? null;\n const candidates = seats\n .map((seat, index) => ({ seat, index }))\n .filter(({ seat }) => seat.id !== seatId && offerable(seat, reportFor(reports, seat.id), now));\n candidates.sort((a, b) => {\n const byTier = tier(a.seat) - tier(b.seat);\n if (byTier !== 0) return byTier;\n if (blocked !== null) {\n const sameA = a.seat.engine === blocked.engine ? 0 : 1;\n const sameB = b.seat.engine === blocked.engine ? 0 : 1;\n if (sameA !== sameB) return sameA - sameB;\n }\n const byUse = bindingPercent(a.seat) - bindingPercent(b.seat);\n if (byUse !== 0) return byUse;\n return a.index - b.index;\n });\n return candidates.slice(0, SEAT_MAX_ALTERNATIVES).map(({ seat }) => seat.id);\n}\n\n/**\n * The admission answer for one seat. A seat that is not in `seats` at all is\n * reported READY with no reason: the readiness layer has no evidence about\n * it, and \"seat not found\" is the engine's own error to raise.\n */\nexport function seatReadiness(\n seatId: string,\n seats: readonly VerseSeat[],\n reports: readonly SeatHealthReport[] | null | undefined,\n now: number = Date.now(),\n): SeatReadiness {\n const seat = seats.find((candidate) => candidate.id === seatId) ?? null;\n if (seat === null) return { seatId, ready: true, reason: null, alternatives: [] };\n const block = seatBlock(seat, reportFor(reports, seatId), now);\n if (block === null) return { seatId, ready: true, reason: null, alternatives: [] };\n return { seatId, ready: false, reason: block.reason, alternatives: rankSeatAlternatives(seatId, seats, reports, now) };\n}\n","/**\n * Budget policy — mode defaults, effective per-seat policy, and strict update\n * parsing (V3.10 unit A9).\n *\n * THE MODEL (what a stored policy means)\n *\n * `policy.mode` picks a column of MODE_DEFAULTS below. `policy.seats` holds\n * the per-seat policies IN FORCE for that mode, but only for seats the\n * operator has touched; every other seat gets the mode's default for its\n * engine. So what the Budget panel shows is exactly what the router uses —\n * there is no hidden transform layered on top of a slider.\n *\n * Switching mode (`applyModeSwitch`) re-bases every stored seat on the new\n * mode's defaults and keeps only the two choices that are not \"how much\" but\n * \"whether at all\": `enabled` and a hard `dailyUsdCap`. A reserve tuned for\n * `balanced` would be meaningless in `all-in` (which by definition keeps\n * nothing back), so it is not carried across.\n *\n * DEFAULTS (Mason's decisions, recorded 2026-09-24 — binding):\n * balanced (default) — Claude keeps 40% of its weekly window for Mason and\n * is never touched while its 5-hour window is above 70%\n * (protects his live session). Grok 0% reserve. Local\n * unlimited. Codex OFF (no usage) until switched on.\n * all-in — autonomy may use all available usage (no reserve, no\n * session ceiling). Codex stays OFF by default.\n * reserve — free local models plus only a small paid cap: every\n * paid seat keeps 85% of its binding window back and a\n * 5-hour ceiling of 50%, and the router ranks local\n * first (router.ts).\n *\n * BROWSER-SAFE and PURE: no node: imports, no I/O. The Budget UI imports the\n * defaults from here so the \"reset to default\" hint can never drift from the\n * server.\n */\nimport {\n BUDGET_MODES,\n type BudgetMode,\n type BudgetPolicy,\n type BudgetResponse,\n type BudgetUpdateRequest,\n type SeatBudgetPolicy,\n} from './types.js';\n\n/** The engines a seat can belong to (mirrors `VerseEngine`, kept local so this file has no verse import). */\nexport type BudgetEngine = 'claude' | 'codex' | 'grok' | 'local';\n\nexport const BUDGET_ENGINES: readonly BudgetEngine[] = ['claude', 'codex', 'grok', 'local'];\n\n/** Same spelling rule the seat catalog and preferences use for seat ids. */\nexport const BUDGET_SEAT_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._:@/+-]{0,199}$/;\n\n/** Registry bound — a blast radius for a runaway client, not a UI limit. */\nexport const BUDGET_MAX_SEATS = 64;\n\n/** Upper bound on a daily USD cap; anything larger is a typo, not a budget. */\nexport const BUDGET_MAX_DAILY_USD = 10_000;\n\nexport const DEFAULT_BUDGET_MODE: BudgetMode = 'balanced';\n\n/** Who a seat is, for the Budget panel (headroom rows carry only the id). */\nexport interface BudgetSeatInfo {\n seatId: string;\n label: string;\n engine: BudgetEngine;\n /** True for local seats: $0, no provider window. */\n free: boolean;\n}\n\n/**\n * The body `GET/POST /api/verse/budget` actually serves: the frozen\n * `BudgetResponse` plus two ADDITIVE fields the panel needs to render a seat\n * it has never stored a policy for. `seats` stays the stored policy (only the\n * seats the operator touched); `effective` is what the router applies to\n * every seat it currently knows.\n */\nexport interface BudgetView extends BudgetResponse {\n seatInfo: BudgetSeatInfo[];\n effective: Record<string, SeatBudgetPolicy>;\n /** How old a reading may be before autonomy stops spending against it. */\n readingMaxAgeMs: number;\n /** When the seat readings behind `headroom` were sampled. */\n sampledAt: string;\n}\n\n/** Per-engine default in one mode; `seatId` is filled in by `defaultSeatPolicy`. */\ntype EngineDefault = Omit<SeatBudgetPolicy, 'seatId'>;\n\n/**\n * Mode × engine defaults. Frozen so a caller can never mutate the table the\n * whole process reads.\n *\n * Codex is `enabled: false` in every mode on purpose: on 2026-09-24 both Codex\n * accounts were at 100% with resets days away, and Mason turned Codex OFF for\n * autonomy \"until usage returns\". That is a standing choice, not a function of\n * the mode, so a mode switch must not silently turn it back on.\n */\nexport const MODE_DEFAULTS: Readonly<Record<BudgetMode, Readonly<Record<BudgetEngine, Readonly<EngineDefault>>>>> =\n Object.freeze({\n 'all-in': Object.freeze({\n claude: Object.freeze({ enabled: true, reservePercent: 0 }),\n codex: Object.freeze({ enabled: false, reservePercent: 0 }),\n grok: Object.freeze({ enabled: true, reservePercent: 0 }),\n local: Object.freeze({ enabled: true, reservePercent: 0 }),\n }),\n balanced: Object.freeze({\n claude: Object.freeze({ enabled: true, reservePercent: 40, maxSessionWindowPercent: 70 }),\n codex: Object.freeze({ enabled: false, reservePercent: 40, maxSessionWindowPercent: 70 }),\n grok: Object.freeze({ enabled: true, reservePercent: 0 }),\n local: Object.freeze({ enabled: true, reservePercent: 0 }),\n }),\n reserve: Object.freeze({\n claude: Object.freeze({ enabled: true, reservePercent: 85, maxSessionWindowPercent: 50 }),\n codex: Object.freeze({ enabled: false, reservePercent: 85, maxSessionWindowPercent: 50 }),\n grok: Object.freeze({ enabled: true, reservePercent: 85 }),\n local: Object.freeze({ enabled: true, reservePercent: 0 }),\n }),\n });\n\n/** Plain-language one-liners for the mode control (UI + API `why` text share them). */\nexport const MODE_DESCRIPTIONS: Readonly<Record<BudgetMode, string>> = Object.freeze({\n 'all-in': 'Autonomy may use all available usage on every enabled seat.',\n balanced: 'Autonomy stops at each seat’s reserve, so you keep headroom for your own sessions.',\n reserve: 'Autonomy runs on free local models, plus only a small slice of paid seats.',\n});\n\nexport function isBudgetMode(value: unknown): value is BudgetMode {\n return typeof value === 'string' && (BUDGET_MODES as readonly string[]).includes(value);\n}\n\n/**\n * Which engine a seat id belongs to, when the caller has no seat record.\n *\n * Seat ids are account ids from connections.json (`claude`, `codex-personal`,\n * `grok`) or `local:<tag>` for Ollama. An id that names no known engine is\n * treated as `claude`-class — the most protected default — rather than as\n * free local capacity: guessing \"free\" for an unknown seat would be the\n * fail-open this module exists to close.\n */\nexport function engineOfSeatId(seatId: string): BudgetEngine {\n const id = seatId.toLowerCase();\n if (id === 'local' || id.startsWith('local:')) return 'local';\n if (id.startsWith('codex')) return 'codex';\n if (id.startsWith('grok')) return 'grok';\n return 'claude';\n}\n\nexport function defaultSeatPolicy(mode: BudgetMode, seatId: string, engine: BudgetEngine = engineOfSeatId(seatId)): SeatBudgetPolicy {\n const base = MODE_DEFAULTS[mode][engine];\n const out: SeatBudgetPolicy = { seatId, enabled: base.enabled, reservePercent: base.reservePercent };\n if (base.maxSessionWindowPercent !== undefined) out.maxSessionWindowPercent = base.maxSessionWindowPercent;\n if (base.dailyUsdCap !== undefined) out.dailyUsdCap = base.dailyUsdCap;\n return out;\n}\n\n/** The policy the router applies to one seat: the stored one, or the mode default. */\nexport function effectiveSeatPolicy(policy: BudgetPolicy, seatId: string, engine?: BudgetEngine): SeatBudgetPolicy {\n const stored = policy.seats[seatId];\n if (stored) return { ...stored, seatId };\n return defaultSeatPolicy(policy.mode, seatId, engine ?? engineOfSeatId(seatId));\n}\n\n/** The policy a fresh install starts with: balanced, no per-seat deviations. */\nexport function defaultBudgetPolicy(): BudgetPolicy {\n // Epoch, not \"now\": nothing was ever decided here, and a timestamp that\n // moves on every read would claim a change that never happened.\n return { mode: DEFAULT_BUDGET_MODE, seats: {}, updatedAt: new Date(0).toISOString() };\n}\n\n// ---------------------------------------------------------------------------\n// Validation (shared by the store's lenient load and the API's strict update)\n// ---------------------------------------------------------------------------\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isPercent(value: unknown, low = 0): value is number {\n return typeof value === 'number' && Number.isFinite(value) && value >= low && value <= 100;\n}\n\nfunction isUsd(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value) && value >= 0 && value <= BUDGET_MAX_DAILY_USD;\n}\n\n/** Whole percents only: a 40.000001% reserve is noise, and integers diff cleanly. */\nfunction wholePercent(value: number): number {\n return Math.round(value);\n}\n\n/** Cents are the finest a USD cap means anything at. */\nfunction cents(value: number): number {\n return Math.round(value * 100) / 100;\n}\n\n/**\n * Salvage one stored seat entry, or null when it is unusable. Lenient on\n * purpose (the file is ours but may be hand-edited): an invalid optional field\n * is dropped, an invalid required field drops the entry — which then falls\n * back to the mode default, the conservative outcome.\n */\nexport function sanitizeSeatPolicy(seatId: string, raw: unknown): SeatBudgetPolicy | null {\n if (!BUDGET_SEAT_ID_RE.test(seatId) || !isObject(raw)) return null;\n if (typeof raw['enabled'] !== 'boolean' || !isPercent(raw['reservePercent'])) return null;\n const out: SeatBudgetPolicy = {\n seatId,\n enabled: raw['enabled'],\n reservePercent: wholePercent(raw['reservePercent']),\n };\n if (isPercent(raw['maxSessionWindowPercent'], 1)) {\n out.maxSessionWindowPercent = wholePercent(raw['maxSessionWindowPercent']);\n }\n if (isUsd(raw['dailyUsdCap'])) out.dailyUsdCap = cents(raw['dailyUsdCap']);\n return out;\n}\n\n/** Field-by-field salvage of a whole stored policy. Never throws. */\nexport function sanitizeBudgetPolicy(raw: unknown): BudgetPolicy {\n const out = defaultBudgetPolicy();\n if (!isObject(raw)) return out;\n if (isBudgetMode(raw['mode'])) out.mode = raw['mode'];\n const updatedAt = raw['updatedAt'];\n if (typeof updatedAt === 'string' && Number.isFinite(Date.parse(updatedAt))) {\n out.updatedAt = new Date(Date.parse(updatedAt)).toISOString();\n }\n const seats = raw['seats'];\n if (isObject(seats)) {\n let kept = 0;\n for (const seatId of Object.keys(seats).sort()) {\n if (kept >= BUDGET_MAX_SEATS) break;\n const entry = sanitizeSeatPolicy(seatId, seats[seatId]);\n if (!entry) continue;\n out.seats[seatId] = entry;\n kept += 1;\n }\n }\n return out;\n}\n\n/** The error the budget module throws for a bad request (duck-typed by `code`, like VerseServiceError). */\nexport class BudgetPolicyError extends Error {\n readonly code: 'VERSE_INVALID' | 'VERSE_TOO_LARGE';\n readonly status: 400 | 413;\n\n constructor(code: 'VERSE_INVALID' | 'VERSE_TOO_LARGE', message: string) {\n super(message);\n this.name = 'BudgetPolicyError';\n this.code = code;\n this.status = code === 'VERSE_TOO_LARGE' ? 413 : 400;\n }\n}\n\n/**\n * A validated per-seat patch. `null` on an optional field means \"clear it\"\n * (JSON has no `undefined`): `maxSessionWindowPercent: null` removes the\n * session ceiling, `dailyUsdCap: null` removes the cap.\n */\nexport interface SeatPolicyPatch {\n enabled?: boolean;\n reservePercent?: number;\n maxSessionWindowPercent?: number | null;\n dailyUsdCap?: number | null;\n}\n\nexport type ParsedBudgetUpdate =\n | { kind: 'mode'; mode: BudgetMode }\n | { kind: 'seat'; seatId: string; patch: SeatPolicyPatch };\n\nconst SEAT_PATCH_KEYS: ReadonlySet<string> = new Set([\n 'enabled',\n 'reservePercent',\n 'maxSessionWindowPercent',\n 'dailyUsdCap',\n]);\n\nfunction sameKeys(value: Record<string, unknown>, keys: readonly string[]): boolean {\n const own = Object.keys(value);\n return own.length === keys.length && keys.every((key) => Object.prototype.hasOwnProperty.call(value, key));\n}\n\n/**\n * Validate a POST body against EXACTLY one `BudgetUpdateRequest` form, so a\n * body can never change more than the operator clicked. Unknown keys are\n * refused (a misspelt `reservepercent` silently dropped would \"succeed\" and\n * change nothing).\n */\nexport function parseBudgetUpdate(value: unknown): ParsedBudgetUpdate {\n if (!isObject(value)) throw new BudgetPolicyError('VERSE_INVALID', 'budget update must be a JSON object');\n\n if (sameKeys(value, ['mode'])) {\n if (!isBudgetMode(value['mode'])) {\n throw new BudgetPolicyError('VERSE_INVALID', `mode must be one of: ${BUDGET_MODES.join(', ')}`);\n }\n return { kind: 'mode', mode: value['mode'] };\n }\n\n if (sameKeys(value, ['seatId', 'policy'])) {\n const seatId = value['seatId'];\n if (typeof seatId !== 'string' || !BUDGET_SEAT_ID_RE.test(seatId)) {\n throw new BudgetPolicyError('VERSE_INVALID', 'seatId must be a seat id');\n }\n const policy = value['policy'];\n if (!isObject(policy)) throw new BudgetPolicyError('VERSE_INVALID', 'policy must be an object');\n const keys = Object.keys(policy);\n if (keys.length === 0) throw new BudgetPolicyError('VERSE_INVALID', 'policy must change at least one field');\n for (const key of keys) {\n if (!SEAT_PATCH_KEYS.has(key)) throw new BudgetPolicyError('VERSE_INVALID', `unknown policy key: ${key}`);\n }\n const patch: SeatPolicyPatch = {};\n if ('enabled' in policy) {\n if (typeof policy['enabled'] !== 'boolean') throw new BudgetPolicyError('VERSE_INVALID', 'enabled must be a boolean');\n patch.enabled = policy['enabled'];\n }\n if ('reservePercent' in policy) {\n if (!isPercent(policy['reservePercent'])) {\n throw new BudgetPolicyError('VERSE_INVALID', 'reservePercent must be a number from 0 to 100');\n }\n patch.reservePercent = wholePercent(policy['reservePercent']);\n }\n if ('maxSessionWindowPercent' in policy) {\n const v = policy['maxSessionWindowPercent'];\n if (v !== null && !isPercent(v, 1)) {\n throw new BudgetPolicyError('VERSE_INVALID', 'maxSessionWindowPercent must be a number from 1 to 100, or null');\n }\n patch.maxSessionWindowPercent = v === null ? null : wholePercent(v);\n }\n if ('dailyUsdCap' in policy) {\n const v = policy['dailyUsdCap'];\n if (v !== null && !isUsd(v)) {\n throw new BudgetPolicyError('VERSE_INVALID', `dailyUsdCap must be a number from 0 to ${BUDGET_MAX_DAILY_USD}, or null`);\n }\n patch.dailyUsdCap = v === null ? null : cents(v);\n }\n return { kind: 'seat', seatId, patch };\n }\n\n throw new BudgetPolicyError('VERSE_INVALID', 'budget update must be exactly one of {mode} or {seatId, policy}');\n}\n\n/**\n * Re-base every stored seat on `mode`'s defaults, keeping `enabled` and a hard\n * `dailyUsdCap` (see the file header for why reserves are not carried).\n */\nexport function applyModeSwitch(\n policy: BudgetPolicy,\n mode: BudgetMode,\n nowIso: string,\n engineOf?: (seatId: string) => BudgetEngine | undefined,\n): BudgetPolicy {\n const seats: Record<string, SeatBudgetPolicy> = {};\n for (const seatId of Object.keys(policy.seats).sort()) {\n const stored = policy.seats[seatId]!;\n const next = defaultSeatPolicy(mode, seatId, engineOf?.(seatId) ?? engineOfSeatId(seatId));\n next.enabled = stored.enabled;\n if (stored.dailyUsdCap !== undefined) next.dailyUsdCap = stored.dailyUsdCap;\n seats[seatId] = next;\n }\n return { mode, seats, updatedAt: nowIso };\n}\n\n/** Apply one validated per-seat patch on top of the seat's effective policy. */\nexport function applySeatPatch(\n policy: BudgetPolicy,\n seatId: string,\n patch: SeatPolicyPatch,\n nowIso: string,\n engine?: BudgetEngine,\n): BudgetPolicy {\n if (!(seatId in policy.seats) && Object.keys(policy.seats).length >= BUDGET_MAX_SEATS) {\n throw new BudgetPolicyError('VERSE_TOO_LARGE', `at most ${BUDGET_MAX_SEATS} seats can carry a budget policy`);\n }\n const next = effectiveSeatPolicy(policy, seatId, engine);\n if (patch.enabled !== undefined) next.enabled = patch.enabled;\n if (patch.reservePercent !== undefined) next.reservePercent = patch.reservePercent;\n if (patch.maxSessionWindowPercent !== undefined) {\n if (patch.maxSessionWindowPercent === null) delete next.maxSessionWindowPercent;\n else next.maxSessionWindowPercent = patch.maxSessionWindowPercent;\n }\n if (patch.dailyUsdCap !== undefined) {\n if (patch.dailyUsdCap === null) delete next.dailyUsdCap;\n else next.dailyUsdCap = patch.dailyUsdCap;\n }\n const seats: Record<string, SeatBudgetPolicy> = { ...policy.seats, [seatId]: next };\n const sorted: Record<string, SeatBudgetPolicy> = {};\n for (const id of Object.keys(seats).sort()) sorted[id] = seats[id]!;\n return { mode: policy.mode, seats: sorted, updatedAt: nowIso };\n}\n\n/** Apply exactly one update form. Pure — the caller persists. */\nexport function applyBudgetUpdate(\n policy: BudgetPolicy,\n update: BudgetUpdateRequest | ParsedBudgetUpdate,\n nowIso: string,\n engineOf?: (seatId: string) => BudgetEngine | undefined,\n): BudgetPolicy {\n const parsed: ParsedBudgetUpdate = 'kind' in update ? update : parseBudgetUpdate(update);\n if (parsed.kind === 'mode') return applyModeSwitch(policy, parsed.mode, nowIso, engineOf);\n return applySeatPatch(policy, parsed.seatId, parsed.patch, nowIso, engineOf?.(parsed.seatId));\n}\n","/**\n * routes/verse/budget/budget-model.ts — pure view-model for the Budget panel.\n *\n * Turns a `BudgetView` (GET /api/verse/budget) into one row per seat: who it\n * is, the policy in force, a one-line verdict, and the geometry of its\n * headroom bars. No React, no fetch — so every honesty rule is unit-tested\n * here rather than asserted through the DOM.\n *\n * HONESTY RULES (docs/VERSE-TELEMETRY-V2.md):\n * - Unknown is not zero. A window with no reading renders as `unknown`\n * (dashed track + words), never an empty bar (\"plenty left\") or a full one\n * (\"exhausted\").\n * - The verdict is always a WORD (Eligible / Held back / Off / No reading);\n * colour only reinforces it.\n * - The \"why\" line is the server's own sentence, verbatim.\n */\nimport {\n MODE_DESCRIPTIONS,\n type BudgetEngine,\n type BudgetView,\n} from '../../../../core/routing/policy.js';\nimport type { BudgetMode, SeatBudgetPolicy, SeatHeadroom } from '../../../../core/routing/types.js';\n\nexport type BudgetSeatStatus = 'eligible' | 'held' | 'off' | 'unknown';\n\nexport const STATUS_WORDS: Readonly<Record<BudgetSeatStatus, string>> = {\n eligible: 'Eligible',\n held: 'Held back',\n off: 'Off',\n unknown: 'No reading',\n};\n\n/** One horizontal headroom bar (a usage window against its autonomy ceiling). */\nexport interface BudgetBar {\n kind: 'weekly' | 'session';\n label: string;\n /** 0–100, or null when this window has no reading. */\n usedPercent: number | null;\n /** Where autonomy stops (0–100). 100 = no ceiling. */\n ceilingPercent: number;\n /** Plain-language summary for screen readers and the table view. */\n description: string;\n /** True when this bar is the one binding autonomy right now. */\n binding: boolean;\n}\n\nexport interface BudgetSeatRow {\n seatId: string;\n label: string;\n engine: BudgetEngine;\n free: boolean;\n policy: SeatBudgetPolicy;\n headroom: SeatHeadroom | null;\n status: BudgetSeatStatus;\n /** First server reason, verbatim. */\n why: string;\n /** Remaining server reasons, verbatim. */\n more: string[];\n bars: BudgetBar[];\n /** Whether the 5-hour ceiling control applies (subscription seats with a short window). */\n hasSessionCeiling: boolean;\n}\n\nexport const BUDGET_MODE_OPTIONS: ReadonlyArray<{ value: BudgetMode; label: string; description: string }> = [\n { value: 'reserve', label: 'Reserve', description: MODE_DESCRIPTIONS.reserve },\n { value: 'balanced', label: 'Balanced', description: MODE_DESCRIPTIONS.balanced },\n { value: 'all-in', label: 'All-in', description: MODE_DESCRIPTIONS['all-in'] },\n];\n\n/**\n * Whether `mode` is above a grant's ceiling. Rank is the order of\n * BUDGET_MODE_OPTIONS (reserve < balanced < all-in) — the same order as\n * core/authority BUDGET_MODE_RANK, restated here so the budget panel does not\n * import the authority module into the web bundle. No ceiling (null) = no\n * mode is above it.\n */\nexport function modeAboveCeiling(mode: BudgetMode, ceiling: BudgetMode | null | undefined): boolean {\n if (!ceiling) return false;\n const rank = (m: BudgetMode) => BUDGET_MODE_OPTIONS.findIndex((o) => o.value === m);\n return rank(mode) > rank(ceiling);\n}\n\nfunction round(n: number): number {\n return Math.round(n);\n}\n\nfunction statusOf(free: boolean, policy: SeatBudgetPolicy, headroom: SeatHeadroom | null): BudgetSeatStatus {\n if (!policy.enabled) return 'off';\n if (headroom?.eligibleForAutonomy) return 'eligible';\n if (!free && (headroom === null || (headroom.sessionUsedPercent === null && headroom.weeklyUsedPercent === null))) {\n return 'unknown';\n }\n return 'held';\n}\n\nfunction barsFor(engine: BudgetEngine, free: boolean, policy: SeatBudgetPolicy, h: SeatHeadroom | null): BudgetBar[] {\n if (free || h === null) return [];\n const bars: BudgetBar[] = [];\n const reserveCeiling = 100 - policy.reservePercent;\n const hasWeekly = h.weeklyUsedPercent !== null || engine === 'claude' || engine === 'grok';\n if (hasWeekly) {\n const used = h.weeklyUsedPercent;\n bars.push({\n kind: 'weekly',\n label: engine === 'grok' ? 'Billing period' : 'Weekly',\n usedPercent: used,\n ceilingPercent: reserveCeiling,\n binding: h.bindingWindow === 'weekly',\n description: used === null\n ? 'Weekly window: no reading.'\n : `Weekly window ${round(used)}% used; autonomy stops at ${round(reserveCeiling)}%, ${round(policy.reservePercent)}% kept for you.`,\n });\n }\n if (h.sessionUsedPercent !== null || engine === 'claude') {\n const used = h.sessionUsedPercent;\n const sessionCeiling = policy.maxSessionWindowPercent ?? 100;\n const ceiling = hasWeekly ? sessionCeiling : Math.min(sessionCeiling, reserveCeiling);\n bars.push({\n kind: 'session',\n label: '5-hour',\n usedPercent: used,\n ceilingPercent: ceiling,\n binding: h.bindingWindow === 'session',\n description: used === null\n ? '5-hour window: no reading.'\n : `5-hour window ${round(used)}% used; ${ceiling >= 100 ? 'no autonomy ceiling' : `autonomy stops at ${round(ceiling)}%`}.`,\n });\n }\n return bars;\n}\n\n/** Rows in the server's seat order (which lists the operator's preferred local tags first). */\nexport function buildBudgetRows(view: BudgetView): BudgetSeatRow[] {\n const headroomById = new Map(view.headroom.map((h) => [h.seatId, h]));\n return view.seatInfo.map((info) => {\n const policy = view.effective[info.seatId] ?? { seatId: info.seatId, enabled: false, reservePercent: 100 };\n const headroom = headroomById.get(info.seatId) ?? null;\n const reasons = headroom?.reasons ?? [];\n return {\n seatId: info.seatId,\n label: info.label,\n engine: info.engine,\n free: info.free,\n policy,\n headroom,\n status: statusOf(info.free, policy, headroom),\n why: reasons[0] ?? (info.free ? 'Local model — free.' : 'No reading yet.'),\n more: reasons.slice(1),\n bars: barsFor(info.engine, info.free, policy, headroom),\n hasSessionCeiling: !info.free && (info.engine === 'claude' || info.engine === 'codex'),\n };\n });\n}\n\n/** Headline counts for the panel summary (\"3 of 7 seats can take autonomous work\"). */\nexport function budgetSummary(rows: readonly BudgetSeatRow[]): { eligible: number; total: number; sentence: string } {\n const eligible = rows.filter((r) => r.status === 'eligible').length;\n const total = rows.length;\n if (total === 0) return { eligible, total, sentence: 'No seats are known yet.' };\n const paid = rows.filter((r) => r.status === 'eligible' && !r.free).length;\n const free = eligible - paid;\n const parts: string[] = [];\n if (paid > 0) parts.push(`${paid} paid`);\n if (free > 0) parts.push(`${free} local`);\n return {\n eligible,\n total,\n sentence: eligible === 0\n ? 'No seat can take autonomous work right now.'\n : `${eligible} of ${total} seats can take autonomous work (${parts.join(', ')}).`,\n };\n}\n\n/** Human age of the readings, e.g. \"just now\", \"4 min ago\". */\nexport function readingAge(sampledAt: string, nowMs: number): string {\n const t = Date.parse(sampledAt);\n if (!Number.isFinite(t)) return 'unknown';\n const minutes = Math.max(0, Math.round((nowMs - t) / 60_000));\n if (minutes < 1) return 'just now';\n if (minutes < 120) return `${minutes} min ago`;\n return `${Math.round(minutes / 60)} h ago`;\n}\n\n/** Clamp a slider value to the range the API accepts. */\nexport function clampPercent(value: number, low = 0, high = 100): number {\n if (!Number.isFinite(value)) return low;\n return Math.max(low, Math.min(high, Math.round(value)));\n}\n","/**\n * routes/verse/health/health-model.ts — how a seat health report reads on\n * screen (V3.10, unit A2). Pure: no React, no I/O.\n *\n * Every surface that shows seat health (the banner, the Composer block, the\n * seat picker) takes its words from here so one seat is never described two\n * ways. State is never carried by colour alone: every tone comes with a word.\n */\nimport type { SeatConnection, SeatHealthReport } from '../../../../core/verse/health-types.js';\nimport { describeResetAt } from '../../../../core/verse/seat-readiness.js';\nimport type { VerseSeat } from '../../../data/api-types.js';\n\nexport type HealthTone = 'danger' | 'warning' | 'neutral' | 'success';\n\nexport const CONNECTION_WORD: Record<SeatConnection, string> = {\n connected: 'connected',\n expiring: 'sign-in expiring',\n 'signed-out': 'signed out',\n exhausted: 'out of usage',\n 'binary-skew': 'older CLI pinned',\n unknown: 'not checked',\n};\n\nexport const CONNECTION_TONE: Record<SeatConnection, HealthTone> = {\n connected: 'success',\n expiring: 'warning',\n 'signed-out': 'danger',\n exhausted: 'danger',\n 'binary-skew': 'warning',\n unknown: 'neutral',\n};\n\n/** Most urgent first: what blocks work, then what will, then what could be better. */\nconst SEVERITY: Record<SeatConnection, number> = {\n 'signed-out': 0,\n exhausted: 1,\n expiring: 2,\n 'binary-skew': 3,\n unknown: 4,\n connected: 5,\n};\n\nexport interface SeatHealthIssue {\n report: SeatHealthReport;\n /** The seat's human label (falls back to the id when the seat is not in the roster). */\n label: string;\n word: string;\n tone: HealthTone;\n /** The first, most specific reason, or null. */\n detail: string | null;\n /** \"resets Fri 2:25 PM\" when the provider gave an instant. */\n reset: string | null;\n}\n\n/**\n * Is this report worth interrupting the operator for? Every non-connected\n * state is, EXCEPT an `unknown` with nothing to say (a sweep that has not run\n * yet is not a fault, and saying \"not checked\" about every seat at boot would\n * teach the operator to ignore the banner).\n */\nexport function needsAttention(report: SeatHealthReport): boolean {\n if (report.connection === 'connected') return false;\n if (report.connection === 'unknown') {\n return report.reasons.length > 0 && !report.reasons[0]!.includes('has not reached this seat');\n }\n return true;\n}\n\nexport function seatHealthIssues(\n reports: readonly SeatHealthReport[],\n seats: readonly VerseSeat[] = [],\n now: number = Date.now(),\n): SeatHealthIssue[] {\n const labels = new Map(seats.map((seat) => [seat.id, seat.label]));\n return reports\n .filter(needsAttention)\n .map((report) => {\n const when = describeResetAt(report.resetAt, now);\n return {\n report,\n label: labels.get(report.seatId) ?? report.seatId,\n word: CONNECTION_WORD[report.connection],\n tone: CONNECTION_TONE[report.connection],\n detail: report.reasons[0] ?? null,\n reset: when === null ? null : `resets ${when}`,\n };\n })\n .sort((a, b) => SEVERITY[a.report.connection] - SEVERITY[b.report.connection]);\n}\n\n/**\n * An argv rendered for copy-paste into a POSIX shell. Plain words stay bare;\n * anything else is single-quoted. A leading `~/` stays OUTSIDE the quotes so\n * the shell still expands it.\n */\nexport function shellCommandText(argv: readonly string[]): string {\n return argv.map((arg) => {\n if (/^[A-Za-z0-9_@%+=:,./-]+$/.test(arg)) return arg;\n if (arg.startsWith('~/') && /^[A-Za-z0-9_@%+=:,./~-]+$/.test(arg)) return arg;\n if (arg.startsWith('~/')) return `~/'${arg.slice(2).replaceAll(\"'\", \"'\\\\''\")}'`;\n return `'${arg.replaceAll(\"'\", \"'\\\\''\")}'`;\n }).join(' ');\n}\n\n/** One line summarising the whole roster for a collapsed banner. */\nexport function issuesHeadline(issues: readonly SeatHealthIssue[]): string {\n if (issues.length === 0) return 'All seats are connected.';\n const blocked = issues.filter((issue) => issue.tone === 'danger').length;\n if (blocked > 0) {\n return blocked === 1 ? `${issues.find((i) => i.tone === 'danger')!.label} can't run turns right now.`\n : `${blocked} seats can't run turns right now.`;\n }\n return issues.length === 1 ? `${issues[0]!.label} needs attention.` : `${issues.length} seats need attention.`;\n}\n","/**\n * routes/verse/usage/capacity-strip-model.ts — ONE projection of \"how much of\n * each seat is left, what is it tied to, and how much is kept for me\", for\n * every surface that shows seat capacity (SPEC-310C §4: Apps & Accounts,\n * Usage, Resources, NewChatDialog, onboarding; the rail foot's capacity ring\n * and the composer's seat chip read `scarcestSeat` / `capacityRowFor`).\n *\n * Three sources, each already cached app-wide, each read HERE and nowhere\n * else so a seat is never described two ways:\n * - the seat itself (`VerseSeat`, from bootstrap / the /seats poll) — plan,\n * windows, resets, credits, through `seat-subscription.ts`, which owns the\n * honesty rules (binding window leads, no reading ≠ zero, the sentinel 100\n * is a flag, prose resets stay prose);\n * - A2's health report — connected / expiring / signed out / older CLI, and\n * the command that fixes it;\n * - A9's budget view — the reserve kept for Mason and whether autonomy may\n * use the seat right now, through `budget-model.ts`'s own rows.\n * Any of the last two may be missing; the row then says less, never more.\n *\n * Pure: no React, no I/O.\n */\nimport type { BudgetView } from '../../../../core/routing/policy.js';\nimport type { SeatBudgetPolicy, SeatHeadroom } from '../../../../core/routing/types.js';\nimport type { SeatConnection, SeatFixKind, SeatHealthReport } from '../../../../core/verse/health-types.js';\nimport { ENGINE_MONOGRAM } from '../../../../core/verse/workbench-types.js';\nimport type { VerseEngine, VerseSeat } from '../../../data/api-types.js';\nimport { buildBudgetRows, STATUS_WORDS, type BudgetSeatStatus } from '../budget/budget-model.js';\nimport { CONNECTION_TONE, CONNECTION_WORD, type HealthTone } from '../health/health-model.js';\nimport { seatSubscription, type SeatCapacityClass, type SeatWindowView } from '../seat-subscription.js';\nimport { SEAT_CAPACITY_WORD } from '../verse-model.js';\n\nexport type { SeatCapacityClass };\n\ntype BudgetRow = ReturnType<typeof buildBudgetRows>[number];\n\n/** Rows show at most this many windows: the binding one and the next two. */\nexport const CAPACITY_MAX_WINDOWS = 3;\n\nexport interface CapacityWindowRow {\n id: string;\n /** \"5-hour window\", \"weekly window\", \"weekly fable window\". */\n label: string;\n /** 0–100, or null = no reading (never a substituted zero). */\n usedPercent: number | null;\n /** The provider flagged the limit; no percentage exists. */\n limitReached: boolean;\n /** Provider prose verbatim, or a formatted instant; null when neither. */\n resetText: string | null;\n /** True for the window that constrains work right now. */\n binding: boolean;\n}\n\nexport interface CapacityConnection {\n connection: SeatConnection;\n word: string;\n tone: HealthTone;\n /** Plain, already-scrubbed reasons; empty when connected. */\n reasons: string[];\n fixKind: SeatFixKind;\n /** argv; null when nothing fixes it from a terminal. */\n fixCommand: string[] | null;\n}\n\nexport interface CapacityReserve {\n /** Share of the binding window kept for Mason; null when autonomy is off for this seat. */\n percent: number | null;\n /** \"Reserved for you 40%\", \"Autonomy off — all yours\", \"No reserve\". */\n label: string;\n autonomy: BudgetSeatStatus;\n /** \"Eligible\", \"Held back\", \"Off\", \"No reading\". */\n autonomyWord: string;\n /** The router's own first reason, verbatim. */\n why: string;\n}\n\nexport interface CapacityRow {\n /** A seat id, or `local` for the collapsed local row. */\n seatId: string;\n label: string;\n engine: VerseEngine;\n monogram: string;\n kind: 'subscription' | 'local';\n plan: string | null;\n cls: SeatCapacityClass;\n /** usable / tight / blocked / no reading. */\n word: string;\n /** One phrase: \"62% of 5-hour window used\", \"signed out — reconnect this account\". */\n summary: string;\n connection: CapacityConnection | null;\n windows: CapacityWindowRow[];\n credits: string | null;\n reserve: CapacityReserve | null;\n notes: string[];\n /** For the collapsed local row: how many local seats it stands for. */\n localCount: number;\n}\n\nexport interface CapacityInputs {\n health?: readonly SeatHealthReport[] | null;\n budget?: BudgetView | null;\n /**\n * Local seats: `collapse` (default) folds every Ollama tag into one row —\n * they share one machine and one readiness, and twelve identical rows are\n * noise; `each` lists them; `hide` drops them.\n */\n local?: 'collapse' | 'each' | 'hide';\n /** Only these seats, in this order (the new-chat dialog passes the chosen one). */\n seatIds?: readonly string[];\n}\n\nconst TONE_OF_CLASS: Record<SeatCapacityClass, HealthTone> = {\n ready: 'success',\n tight: 'warning',\n blocked: 'danger',\n unread: 'neutral',\n};\n\n/** How a capacity class reads as a tone (a word always rides with it). */\nexport function capacityTone(cls: SeatCapacityClass): HealthTone {\n return TONE_OF_CLASS[cls];\n}\n\nfunction windowRow(w: SeatWindowView, binding: boolean): CapacityWindowRow {\n return { id: w.id, label: w.label, usedPercent: w.usedPercent, limitReached: w.limitReached, resetText: w.resetText, binding };\n}\n\nfunction connectionOf(report: SeatHealthReport | undefined): CapacityConnection | null {\n if (!report) return null;\n return {\n connection: report.connection,\n word: CONNECTION_WORD[report.connection],\n tone: CONNECTION_TONE[report.connection],\n reasons: [...report.reasons],\n fixKind: report.fix.kind,\n fixCommand: report.fix.command && report.fix.command.length > 0 ? [...report.fix.command] : null,\n };\n}\n\nfunction reserveOf(budgetRow: BudgetRow | undefined): CapacityReserve | null {\n if (!budgetRow || budgetRow.free) return null;\n const { policy } = budgetRow;\n const pct = Math.max(0, Math.min(100, Math.round(policy.reservePercent)));\n const label = !policy.enabled\n ? 'Autonomy off — all yours'\n : pct === 0\n ? 'No reserve — autonomy may use all of it'\n : `Reserved for you ${pct}%`;\n return {\n percent: policy.enabled ? pct : null,\n label,\n autonomy: budgetRow.status,\n autonomyWord: STATUS_WORDS[budgetRow.status],\n why: budgetRow.why,\n };\n}\n\nfunction seatRow(\n seat: VerseSeat,\n health: ReadonlyMap<string, SeatHealthReport>,\n budget: ReadonlyMap<string, BudgetRow>,\n): CapacityRow {\n const view = seatSubscription(seat);\n const windows: CapacityWindowRow[] = [];\n if (view.binding) windows.push(windowRow(view.binding, true));\n for (const w of view.others) {\n if (windows.length >= CAPACITY_MAX_WINDOWS) break;\n windows.push(windowRow(w, false));\n }\n const connection = connectionOf(health.get(seat.id));\n // A seat A2 found signed out or out of usage cannot run a turn, whatever\n // its last window reading says (the engine's readiness gate refuses it —\n // seat-readiness.ts SEAT_BLOCKING_CONNECTIONS). Counting it \"usable\"\n // would promise a chat the engine will refuse.\n const blockedByHealth = connection !== null && (connection.connection === 'signed-out' || connection.connection === 'exhausted');\n return {\n seatId: seat.id,\n label: seat.label,\n engine: seat.engine,\n monogram: ENGINE_MONOGRAM[seat.engine],\n kind: view.kind,\n plan: view.plan,\n cls: blockedByHealth ? 'blocked' : view.cls,\n word: blockedByHealth ? SEAT_CAPACITY_WORD.blocked : view.word,\n summary: blockedByHealth ? (connection.reasons[0] ?? connection.word) : view.summary,\n connection,\n windows,\n credits: view.credits,\n reserve: reserveOf(budget.get(seat.id)),\n notes: [...view.notes],\n localCount: 1,\n };\n}\n\nfunction collapsedLocal(seats: readonly VerseSeat[], health: ReadonlyMap<string, SeatHealthReport>): CapacityRow {\n const rows = seats.map((s) => seatSubscription(s));\n const ready = rows.filter((r) => r.cls === 'ready').length;\n const blocked = rows.filter((r) => r.cls === 'blocked').length;\n const cls: SeatCapacityClass = ready > 0 ? 'ready' : blocked === rows.length ? 'blocked' : 'unread';\n // One runtime behind every tag: the first report that says anything speaks for it.\n const report = seats.map((s) => health.get(s.id)).find((r) => r !== undefined);\n const count = seats.length;\n return {\n seatId: 'local',\n label: 'Local models',\n engine: 'local',\n monogram: ENGINE_MONOGRAM.local,\n kind: 'local',\n plan: null,\n cls,\n word: rows.find((r) => r.cls === cls)?.word ?? 'no reading',\n summary: cls === 'ready'\n ? `${count} ${count === 1 ? 'model' : 'models'} on this machine · free`\n : cls === 'blocked'\n ? (rows[0]?.summary ?? 'local runtime unavailable')\n : 'readiness not reported',\n connection: connectionOf(report),\n windows: [],\n credits: null,\n reserve: null,\n notes: [],\n localCount: count,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Tolerant readers\n// ---------------------------------------------------------------------------\n//\n// WHY THESE EXIST. The strip is mounted on five surfaces (Apps, Usage,\n// onboarding, NewChatDialog, the rail ring via scarcestSeat) and renders\n// synchronously from three cached server reads. The types say what a healthy\n// server sends, but the cache holds whatever arrived: a `{}` from a budget\n// route that has not landed on an older sidecar, a half-written health file,\n// a future field shape. One `undefined.map` inside `useMemo` takes the whole\n// surface down with it (INT6 found exactly that with `/api/verse/budget` →\n// `{}`). So each optional source is checked HERE, at the one boundary every\n// view shares, and the rule is the module's own: a source that cannot be\n// read makes the row say LESS, never crash and never invent. A bad entry is\n// dropped on its own; the rest of the source still speaks.\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nconst nullablePercent = (v: unknown): number | null => (typeof v === 'number' && Number.isFinite(v) ? v : null);\n\nfunction readHeadroom(value: unknown): SeatHeadroom | null {\n if (!isRecord(value) || typeof value['seatId'] !== 'string') return null;\n const binding = value['bindingWindow'];\n return {\n seatId: value['seatId'],\n sessionUsedPercent: nullablePercent(value['sessionUsedPercent']),\n weeklyUsedPercent: nullablePercent(value['weeklyUsedPercent']),\n bindingWindow: binding === 'session' || binding === 'weekly' ? binding : null,\n autonomyHeadroomPercent: nullablePercent(value['autonomyHeadroomPercent']),\n resetAt: typeof value['resetAt'] === 'string' ? value['resetAt'] : null,\n // Only an explicit `true` makes a seat eligible — a garbled flag is \"not known to be eligible\".\n eligibleForAutonomy: value['eligibleForAutonomy'] === true,\n reasons: Array.isArray(value['reasons']) ? value['reasons'].filter((r): r is string => typeof r === 'string') : [],\n };\n}\n\nfunction readPolicy(seatId: string, value: unknown): SeatBudgetPolicy | null {\n if (!isRecord(value) || typeof value['enabled'] !== 'boolean') return null;\n const reserve = value['reservePercent'];\n if (typeof reserve !== 'number' || !Number.isFinite(reserve)) return null;\n const out: SeatBudgetPolicy = { seatId, enabled: value['enabled'], reservePercent: reserve };\n const session = value['maxSessionWindowPercent'];\n if (typeof session === 'number' && Number.isFinite(session)) out.maxSessionWindowPercent = session;\n return out;\n}\n\n/**\n * The budget view → rows keyed by seat, or an empty map when the view cannot\n * be read. A seat whose policy entry is present but malformed is DROPPED\n * rather than handed to budget-model's \"no policy → off\" default: that default\n * is right for a seat the server genuinely has no policy for, but for a\n * garbled entry it would print \"Autonomy off — all yours\", a claim nobody\n * made.\n */\nexport function readBudgetRows(view: unknown): Map<string, BudgetRow> {\n if (!isRecord(view) || !Array.isArray(view['seatInfo'])) return new Map();\n const effectiveIn = isRecord(view['effective']) ? view['effective'] : {};\n const effective: Record<string, SeatBudgetPolicy> = {};\n const seatInfo: BudgetView['seatInfo'] = [];\n for (const info of view['seatInfo']) {\n if (!isRecord(info) || typeof info['seatId'] !== 'string') continue;\n const seatId = info['seatId'];\n const engine = info['engine'];\n if (engine !== 'claude' && engine !== 'codex' && engine !== 'grok' && engine !== 'local') continue;\n if (Object.prototype.hasOwnProperty.call(effectiveIn, seatId)) {\n const policy = readPolicy(seatId, effectiveIn[seatId]);\n if (policy === null) continue;\n effective[seatId] = policy;\n }\n seatInfo.push({\n seatId,\n label: typeof info['label'] === 'string' ? info['label'] : seatId,\n engine,\n free: info['free'] === true,\n });\n }\n const headroom = Array.isArray(view['headroom'])\n ? view['headroom'].map(readHeadroom).filter((h): h is SeatHeadroom => h !== null)\n : [];\n const safe = { ...(view as unknown as BudgetView), seatInfo, effective, headroom };\n try {\n return new Map(buildBudgetRows(safe).map((r) => [r.seatId, r]));\n } catch {\n // Belt and braces: budget-model is pure and the input is now well-typed,\n // but a reserve line is never worth a blank strip.\n return new Map();\n }\n}\n\n/** Health reports keyed by seat, keeping only reports that can be described honestly. */\nexport function readHealthReports(reports: unknown): Map<string, SeatHealthReport> {\n const out = new Map<string, SeatHealthReport>();\n if (!Array.isArray(reports)) return out;\n for (const r of reports) {\n if (!isRecord(r) || typeof r['seatId'] !== 'string') continue;\n const connection = r['connection'];\n // An unknown connection word has no tone or wording — describing it\n // would mean guessing; the row falls back to its window reading.\n if (typeof connection !== 'string' || !Object.prototype.hasOwnProperty.call(CONNECTION_WORD, connection)) continue;\n const fix = isRecord(r['fix']) ? r['fix'] : {};\n const kind = fix['kind'];\n const command = Array.isArray(fix['command']) && fix['command'].every((a) => typeof a === 'string')\n ? (fix['command'] as string[])\n : undefined;\n out.set(r['seatId'], {\n ...(r as unknown as SeatHealthReport),\n reasons: Array.isArray(r['reasons']) ? r['reasons'].filter((x): x is string => typeof x === 'string') : [],\n fix: {\n kind: kind === 'reauth' || kind === 'repin' || kind === 'wait' ? kind : 'none',\n ...(command ? { command } : {}),\n },\n });\n }\n return out;\n}\n\n/** Seats → rows, in the roster's own order (the server lists the operator's preferred seats first). */\nexport function buildCapacityRows(seats: readonly VerseSeat[], inputs: CapacityInputs = {}): CapacityRow[] {\n const health = readHealthReports(inputs.health);\n const budget = readBudgetRows(inputs.budget);\n // The roster comes from bootstrap; a malformed one reads as \"no seats yet\",\n // the strip's honest empty state, rather than a crash.\n const roster = Array.isArray(seats)\n ? seats.filter((s): s is VerseSeat => isRecord(s) && typeof (s as { id?: unknown }).id === 'string')\n : [];\n const localMode = inputs.local ?? 'collapse';\n let chosen: readonly VerseSeat[] = roster;\n if (inputs.seatIds) {\n const byId = new Map(roster.map((s) => [s.id, s]));\n chosen = inputs.seatIds.map((id) => byId.get(id)).filter((s): s is VerseSeat => s !== undefined);\n }\n const out: CapacityRow[] = [];\n const locals: VerseSeat[] = [];\n let localIndex = -1;\n for (const seat of chosen) {\n if (seat.engine === 'local') {\n if (localMode === 'hide') continue;\n if (localMode === 'collapse') {\n if (localIndex === -1) localIndex = out.length;\n locals.push(seat);\n continue;\n }\n }\n out.push(seatRow(seat, health, budget));\n }\n if (locals.length > 0) {\n // A single local seat keeps its own name; several fold into one row.\n const row = locals.length === 1 ? seatRow(locals[0]!, health, budget) : collapsedLocal(locals, health);\n out.splice(localIndex, 0, row);\n }\n return out;\n}\n\n/**\n * The strip's one sentence: how many paid seats are usable, and what local\n * adds. Counts only what was READ — an unread seat is named as unread, never\n * folded into \"blocked\".\n */\nexport function capacityHeadline(rows: readonly CapacityRow[]): string {\n const paid = rows.filter((r) => r.kind === 'subscription');\n const local = rows.filter((r) => r.kind === 'local');\n const usable = paid.filter((r) => r.cls === 'ready' || r.cls === 'tight').length;\n const unread = paid.filter((r) => r.cls === 'unread').length;\n const parts: string[] = [];\n if (paid.length === 0) parts.push('No accounts connected');\n else parts.push(`${usable} of ${paid.length} ${paid.length === 1 ? 'account' : 'accounts'} usable`);\n if (unread > 0) parts.push(`${unread} not read yet`);\n if (local.some((r) => r.cls === 'ready')) parts.push('local models ready');\n else if (local.length > 0) parts.push('local models not ready');\n return parts.join(' · ');\n}\n\n/**\n * The seat closest to running out — the rail foot's capacity ring (C1).\n * Blocked beats tight beats a measured percent; unread seats never win,\n * because an empty ring would claim headroom nobody measured.\n */\nexport function scarcestSeat(rows: readonly CapacityRow[]): CapacityRow | null {\n let best: { row: CapacityRow; score: number } | null = null;\n for (const row of rows) {\n if (row.kind !== 'subscription') continue;\n const binding = row.windows.find((w) => w.binding) ?? null;\n let score: number;\n if (row.cls === 'blocked' || binding?.limitReached) score = 300;\n else if (binding?.usedPercent != null) score = (row.cls === 'tight' ? 100 : 0) + binding.usedPercent;\n else continue;\n if (best === null || score > best.score) best = { row, score };\n }\n return best?.row ?? null;\n}\n\n/** One seat's row (the composer's seat chip, C3), or null when the seat is not in the roster. */\nexport function capacityRowFor(seats: readonly VerseSeat[], seatId: string, inputs: Omit<CapacityInputs, 'seatIds' | 'local'> = {}): CapacityRow | null {\n return buildCapacityRows(seats, { ...inputs, seatIds: [seatId], local: 'each' })[0] ?? null;\n}\n\n/** The accessible sentence for one window bar. */\nexport function windowSentence(row: Pick<CapacityRow, 'label'>, w: CapacityWindowRow, reservePercent: number | null): string {\n const head = `${row.label} ${w.label}`;\n const reset = w.resetText === null ? '' : `, ${w.resetText}`;\n if (w.limitReached) return `${head}: limit reached${reset}`;\n if (w.usedPercent === null) return `${head}: no reading${reset}`;\n const kept = reservePercent !== null && reservePercent > 0 ? `; ${reservePercent}% kept for you` : '';\n return `${head}: ${Math.round(w.usedPercent)}% used${kept}${reset}`;\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{a as e,n as t,s as n}from"./index-afDA8cwW.js";import"./useChartWidth-MEXvDxDL.js";import{a as r,c as i,g as a,t as o}from"./colors-B-vHsX1S.js";import"./Swimlane-BR40WVcj.js";import"./BurnDown-4P1LDoCL.js";import"./AreaTrend-gUVXkfhf.js";import"./Funnel-qX3Hlbce.js";import"./StepBand-B1W7rU70.js";import"./MatrixHeatmap-B_JWCjZx.js";var s={figure:`_figure_1si9v_1`,caption:`_caption_1si9v_12`,title:`_title_1si9v_20`,description:`_description_1si9v_26`,plot:`_plot_1si9v_31`,tableDisclosure:`_tableDisclosure_1si9v_36`,tableBody:`_tableBody_1si9v_61`,caveat:`_caveat_1si9v_65`,empty:`_empty_1si9v_75`},c=t();function l({title:e,description:t,caveat:n,children:r,table:i,empty:a,emptyMessage:o=`No data for this window.`}){return(0,c.jsxs)(`figure`,{className:s.figure,children:[(0,c.jsxs)(`figcaption`,{className:s.caption,children:[(0,c.jsx)(`span`,{className:s.title,children:e}),t?(0,c.jsx)(`span`,{className:s.description,children:t}):null]}),n?(0,c.jsx)(`p`,{className:s.caveat,role:`note`,children:n}):null,a?(0,c.jsx)(`p`,{className:s.empty,children:o}):(0,c.jsx)(`div`,{className:s.plot,children:r}),i?(0,c.jsxs)(`details`,{className:s.tableDisclosure,children:[(0,c.jsx)(`summary`,{children:`View as table`}),(0,c.jsx)(`div`,{className:s.tableBody,children:i})]}):null]})}var u={legend:`_legend_4pgvn_1`,item:`_item_4pgvn_10`,swatch:`_swatch_4pgvn_18`,swatchLine:`_swatchLine_4pgvn_25`};function d({items:e}){return e.length<2?null:(0,c.jsx)(`ul`,{className:u.legend,children:e.map(e=>(0,c.jsxs)(`li`,{className:u.item,children:[(0,c.jsx)(`span`,{className:e.kind===`line`?u.swatchLine:u.swatch,style:{background:e.color},"aria-hidden":`true`}),e.label]},e.label))})}var f=n(e(),1),p={svg:`_svg_djmd1_1`,gridline:`_gridline_djmd1_7`,axis:`_axis_djmd1_12`,axisLabel:`_axisLabel_djmd1_17`,line:`_line_djmd1_23`,area:`_area_djmd1_30`,marker:`_marker_djmd1_35`,endLabel:`_endLabel_djmd1_40`,crosshairLine:`_crosshairLine_djmd1_46`,overlay:`_overlay_djmd1_52`,wrap:`_wrap_djmd1_57`,tooltip:`_tooltip_djmd1_61`,tooltipDate:`_tooltipDate_djmd1_77`,tooltipRow:`_tooltipRow_djmd1_82`,tooltipKey:`_tooltipKey_djmd1_88`,tooltipValue:`_tooltipValue_djmd1_94`,tooltipGap:`_tooltipGap_djmd1_99`},m=640,h=44,g=12,_=12,v=24,y=4,b=6.4,x=4,S=150;function C(e){let t=[],n=[];for(let r of e){if(r.y===null){n.length&&t.push(n),n=[];continue}n.push({x:r.x,y:r.y})}return n.length&&t.push(n),t}function w(e,t,n){if(t<=e)return[e];let r=(t-e)/n;return Array.from({length:n+1},(t,n)=>e+r*n)}function T({series:e,height:t=200,area:n=!1,formatX:i=e=>String(e),formatY:s=e=>String(e),ariaLabel:l}){let u=(0,f.useRef)(null),[T,E]=(0,f.useState)(null),[D,O]=(0,f.useState)(null),k=e.flatMap(e=>e.points.map(e=>e.x)),A=e.flatMap(e=>e.points.map(e=>e.y)).filter(e=>e!==null);if(k.length===0)return(0,c.jsx)(`p`,{children:`No data.`});let j=Math.min(...k),M=Math.max(...k),N=Math.min(0,...A),P=Math.max(1e-4,...A),F=M-j||1,I=P-N||1,L=e.length>=1&&e.length<=4,R=L?Math.max(...e.map(e=>e.label.length))*b:0,z=L&&R<=S,B=g+(z?x+R:0),V=e.length>=2,H=596-B,U=t-_-v,W=e=>h+(e-j)/F*H,G=e=>_+U-(e-N)/I*U,K=w(N,P,y),q=Array.from(new Set(k)).sort((e,t)=>e-t);function J(e){let t=u.current;if(!t)return null;let n=t.getBoundingClientRect(),r=(e-n.left)/n.width*m,i=j+(r-h)/H*F,a=q[0],o=1/0;for(let e of q){let t=Math.abs(e-i);t<o&&(o=t,a=e)}return a}function Y(e){let t=J(e.clientX);if(t===null)return;E(t);let n=u.current;if(n){let e=n.getBoundingClientRect(),r=W(t)/m*e.width;O({left:r,top:0})}}let X=T===null?null:e.map(e=>({series:e,point:e.points.find(e=>e.x===T)??null}));return(0,c.jsxs)(`div`,{className:p.wrap,children:[(0,c.jsxs)(`svg`,{ref:u,className:p.svg,viewBox:`0 0 ${m} ${t}`,role:`img`,"aria-label":l,onPointerMove:Y,onPointerLeave:()=>E(null),children:[K.map((e,t)=>(0,c.jsxs)(`g`,{children:[(0,c.jsx)(`line`,{x1:h,x2:m-B,y1:G(e),y2:G(e),className:p.gridline,stroke:r}),(0,c.jsx)(`text`,{x:38,y:G(e),dy:`0.32em`,textAnchor:`end`,className:p.axisLabel,children:s(e)})]},t)),(0,c.jsx)(`line`,{x1:h,x2:m-B,y1:t-v,y2:t-v,className:p.axis,stroke:o}),q.length>1?[q[0],q[q.length-1]].map((e,n)=>(0,c.jsx)(`text`,{x:W(e),y:t-6,textAnchor:n===0?`start`:`end`,className:p.axisLabel,children:i(e)},n)):null,e.map((t,r)=>{let i=a(r),o=C(t.points);return(0,c.jsxs)(`g`,{children:[n&&e.length===1?o.map((e,t)=>{let n=e.map((e,t)=>`${t===0?`M`:`L`}${W(e.x)},${G(e.y)}`).join(` `)+` L${W(e[e.length-1].x)},${G(N)} L${W(e[0].x)},${G(N)} Z`;return(0,c.jsx)(`path`,{d:n,fill:i,className:p.area},t)}):null,o.map((e,t)=>(0,c.jsx)(`path`,{d:e.map((e,t)=>`${t===0?`M`:`L`}${W(e.x)},${G(e.y)}`).join(` `),stroke:i,className:p.line},t)),z&&o.length?(()=>{let e=o[o.length-1],n=e[e.length-1];return(0,c.jsx)(`text`,{x:W(n.x)+x,y:G(n.y),dy:`0.32em`,className:p.endLabel,fill:i,children:t.label})})():null]},t.id)}),T===null?null:(0,c.jsx)(`line`,{x1:W(T),x2:W(T),y1:_,y2:t-v,className:p.crosshairLine}),T===null?null:e.map((e,t)=>{let n=e.points.find(e=>e.x===T);return!n||n.y===null?null:(0,c.jsx)(`circle`,{cx:W(n.x),cy:G(n.y),r:4,fill:a(t),className:p.marker},e.id)}),(0,c.jsx)(`rect`,{x:h,y:_,width:H,height:U,className:p.overlay,onFocus:()=>E(q[q.length-1]??null)})]}),X&&D?(0,c.jsxs)(`div`,{className:p.tooltip,style:{left:D.left,top:D.top},children:[(0,c.jsx)(`div`,{className:p.tooltipDate,children:i(T)}),X.map(({series:e,point:t},n)=>(0,c.jsxs)(`div`,{className:p.tooltipRow,children:[(0,c.jsx)(`span`,{className:p.tooltipKey,style:{background:a(n)},"aria-hidden":`true`}),t&&t.y!==null?(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(`span`,{className:p.tooltipValue,children:s(t.y)}),V?(0,c.jsx)(`span`,{children:e.label}):null]}):(0,c.jsxs)(`span`,{className:p.tooltipGap,children:[`no data`,V?` — ${e.label}`:``]})]},e.id))]}):null,V?(0,c.jsx)(d,{items:e.map((e,t)=>({label:e.label,color:a(t),kind:`line`}))}):null]})}var E={svg:`_svg_o4jfa_1`,bar:`_bar_o4jfa_6`,baseline:`_baseline_o4jfa_15`,gridline:`_gridline_o4jfa_20`,axisLabel:`_axisLabel_o4jfa_25`,valueLabel:`_valueLabel_o4jfa_31`,categoryLabel:`_categoryLabel_o4jfa_38`,hitArea:`_hitArea_o4jfa_44`,tooltip:`_tooltip_o4jfa_49`,tooltipValue:`_tooltipValue_o4jfa_63`,tooltipLabel:`_tooltipLabel_o4jfa_68`,wrap:`_wrap_o4jfa_73`},D=24,O=10;function k({data:e,height:t=160,orientation:n=`vertical`,color:a=i,formatValue:s=e=>String(e),ariaLabel:l}){let u=(0,f.useId)(),[d,p]=(0,f.useState)(null),m=e.map(e=>e.value).filter(e=>e!==null),h=Math.max(0,...m,1e-4),g=Math.min(0,...m),_=h-g||1;if(n===`horizontal`){let n=Math.min(D,Math.max(14,Math.floor((t-O)/e.length)-O)),i=e.length*(n+O)+O;return(0,c.jsxs)(`div`,{className:E.wrap,children:[(0,c.jsxs)(`svg`,{className:E.svg,width:588,height:i,viewBox:`0 0 588 ${i}`,role:`img`,"aria-label":l,children:[(0,c.jsx)(`line`,{x1:120,y1:0,x2:120,y2:i,className:E.baseline,stroke:o}),e.map((e,t)=>{let i=O+t*(n+O),o=e.value===null?0:(e.value-g)/_*420;return(0,c.jsxs)(`g`,{children:[(0,c.jsx)(`text`,{x:112,y:i+n/2,dy:`0.32em`,textAnchor:`end`,className:E.categoryLabel,children:e.label.length>22?`${e.label.slice(0,21)}…`:e.label}),e.value===null?(0,c.jsx)(`line`,{x1:124,y1:i+n/2,x2:134,y2:i+n/2,stroke:r,strokeWidth:2,strokeDasharray:`2 2`}):(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(`rect`,{x:120,y:i,width:Math.max(2,o),height:n,rx:4,fill:a,className:E.bar}),(0,c.jsx)(`text`,{x:120+Math.max(2,o)+6,y:i+n/2,dy:`0.32em`,className:E.valueLabel,children:s(e.value)})]}),(0,c.jsx)(`rect`,{className:E.hitArea,x:0,y:i-O/2,width:588,height:n+O,tabIndex:0,role:`img`,"aria-label":`${e.label}: ${e.value===null?`no data`:s(e.value)}`,onPointerEnter:()=>p(t),onPointerLeave:()=>p(e=>e===t?null:e),onFocus:()=>p(t),onBlur:()=>p(e=>e===t?null:e)})]},e.label+t)})]}),d===null?null:(0,c.jsxs)(`div`,{className:E.tooltip,style:{left:128,top:O+d*(n+O)-4},children:[(0,c.jsx)(`span`,{className:E.tooltipValue,children:e[d].value===null?`no data`:s(e[d].value)}),(0,c.jsx)(`span`,{className:E.tooltipLabel,children:e[d].label})]})]})}let v=e.length?Math.max(D,0):D,y=Math.min(D,v),b=t,x=b+20+30,S=e.length*(y+O)+O,C=20+b-(0-g)/_*b;return(0,c.jsxs)(`div`,{className:E.wrap,children:[(0,c.jsxs)(`svg`,{className:E.svg,width:S,height:x,viewBox:`0 0 ${S} ${x}`,role:`img`,"aria-label":l,children:[(0,c.jsx)(`line`,{x1:0,y1:C,x2:S,y2:C,className:E.baseline,stroke:o}),e.map((e,t)=>{let n=O+t*(y+O),i=e.value===null?0:Math.abs(e.value-g)/_*b,o=e.value!==null&&e.value>=0?C-i:C;return(0,c.jsxs)(`g`,{children:[e.value===null?(0,c.jsx)(`line`,{x1:n+y/2-5,y1:C,x2:n+y/2+5,y2:C,stroke:r,strokeWidth:2,strokeDasharray:`2 2`}):(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(`rect`,{x:n,y:o,width:y,height:Math.max(2,i),rx:4,fill:a,className:E.bar}),(0,c.jsx)(`text`,{x:n+y/2,y:o-4,textAnchor:`middle`,className:E.valueLabel,children:s(e.value)})]}),(0,c.jsx)(`text`,{x:n+y/2,y:x-8,textAnchor:`middle`,className:E.axisLabel,children:e.label.length>10?`${e.label.slice(0,9)}…`:e.label}),(0,c.jsx)(`rect`,{className:E.hitArea,x:n-O/2,y:0,width:y+O,height:x,tabIndex:0,role:`img`,"aria-label":`${e.label}: ${e.value===null?`no data`:s(e.value)}`,onPointerEnter:()=>p(t),onPointerLeave:()=>p(e=>e===t?null:e),onFocus:()=>p(t),onBlur:()=>p(e=>e===t?null:e)})]},e.label+t)})]}),d===null?null:(0,c.jsxs)(`div`,{className:E.tooltip,style:{left:O+d*(y+O),top:0},id:`${u}-tooltip`,children:[(0,c.jsx)(`span`,{className:E.tooltipValue,children:e[d].value===null?`no data`:s(e[d].value)}),(0,c.jsx)(`span`,{className:E.tooltipLabel,children:e[d].label})]})]})}export{l as i,T as n,d as r,k as t};
|
|
2
|
-
//# sourceMappingURL=charts-D4NaLaXA.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"charts-D4NaLaXA.js","names":[],"sources":["../../../../../../src/web-ui/components/charts/ChartContainer.module.css","../../../../../../src/web-ui/components/charts/ChartContainer.tsx","../../../../../../src/web-ui/components/charts/Legend.module.css","../../../../../../src/web-ui/components/charts/Legend.tsx","../../../../../../src/web-ui/components/charts/LineChart.module.css","../../../../../../src/web-ui/components/charts/LineChart.tsx","../../../../../../src/web-ui/components/charts/BarChart.module.css","../../../../../../src/web-ui/components/charts/BarChart.tsx"],"sourcesContent":[".figure {\n margin: 0;\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-lg);\n background: var(--bg-surface);\n padding: var(--space-4);\n /* Fixed heights must include the axis-label band — this container instead\n grows with its content so a chart's x-axis labels never get clipped or\n forced into a nested scroll (dataviz anti-patterns). */\n}\n\n.caption {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--space-3);\n margin-bottom: var(--space-3);\n}\n\n.title {\n font-size: var(--text-sm-size);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n}\n\n.description {\n font-size: var(--text-xs-size);\n color: var(--text-tertiary);\n}\n\n.plot {\n width: 100%;\n overflow-x: auto;\n}\n\n.tableDisclosure {\n margin-top: var(--space-3);\n border-top: 1px solid var(--border-subtle);\n padding-top: var(--space-2);\n}\n\n.tableDisclosure > summary {\n cursor: pointer;\n font-size: var(--text-xs-size);\n color: var(--text-secondary);\n list-style: none;\n}\n\n.tableDisclosure > summary::-webkit-details-marker {\n display: none;\n}\n\n.tableDisclosure > summary::before {\n content: '▸ ';\n}\n\n.tableDisclosure[open] > summary::before {\n content: '▾ ';\n}\n\n.tableBody {\n margin-top: var(--space-2);\n}\n\n.caveat {\n margin: 0 0 var(--space-3);\n padding: var(--space-2) var(--space-3);\n border-radius: var(--radius-md);\n background: var(--status-unknown-bg);\n color: var(--status-unknown-fg);\n font-size: var(--text-xs-size);\n line-height: var(--text-sm-line);\n}\n\n.empty {\n color: var(--text-tertiary);\n font-size: var(--text-sm-size);\n padding: var(--space-6) 0;\n text-align: center;\n}\n","/**\n * components/charts/ChartContainer.tsx — the figure every chart mounts\n * inside: title/description, the plot itself, an optional caveat banner\n * (epistemic-honesty-adjacent: for a chart built on data with a known,\n * disclosed limitation — see ProductionView's judge-verdict caveat), an\n * optional table-view twin (the WCAG-clean accessibility equivalent every\n * chart should ship per the dataviz skill), and an empty state that never\n * lies about missing data.\n */\nimport type { ReactNode } from 'react';\nimport './chart-tokens.css';\nimport styles from './ChartContainer.module.css';\n\nexport interface ChartContainerProps {\n title: string;\n description?: string;\n /** A short, honest note about a known limitation of the data behind this\n * chart (e.g. \"counts may include X, not yet separable\"). Never omit a\n * caveat to make a chart look cleaner than the data actually is. */\n caveat?: string;\n /** The chart itself (SVG + legend). */\n children: ReactNode;\n /** The accessibility twin — same data as a real HTML table. Omit only\n * when the chart already IS a table. */\n table?: ReactNode;\n /** When true, renders the empty state instead of `children`. */\n empty?: boolean;\n emptyMessage?: string;\n}\n\nexport function ChartContainer({\n title,\n description,\n caveat,\n children,\n table,\n empty,\n emptyMessage = 'No data for this window.',\n}: ChartContainerProps) {\n return (\n <figure className={styles.figure}>\n <figcaption className={styles.caption}>\n <span className={styles.title}>{title}</span>\n {description ? <span className={styles.description}>{description}</span> : null}\n </figcaption>\n {caveat ? (\n <p className={styles.caveat} role=\"note\">\n {caveat}\n </p>\n ) : null}\n {empty ? (\n <p className={styles.empty}>{emptyMessage}</p>\n ) : (\n <div className={styles.plot}>{children}</div>\n )}\n {table ? (\n <details className={styles.tableDisclosure}>\n <summary>View as table</summary>\n <div className={styles.tableBody}>{table}</div>\n </details>\n ) : null}\n </figure>\n );\n}\n",".legend {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-1) var(--space-4);\n margin: var(--space-2) 0 0;\n padding: 0;\n list-style: none;\n}\n\n.item {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n font-size: var(--text-xs-size);\n color: var(--text-secondary);\n}\n\n.swatch {\n width: 10px;\n height: 10px;\n border-radius: var(--radius-full);\n flex: none;\n}\n\n.swatchLine {\n width: 14px;\n height: 2px;\n border-radius: var(--radius-full);\n flex: none;\n}\n","/**\n * components/charts/Legend.tsx — the dependable identity channel. A legend\n * is always present for two or more series (never rely on color-matching\n * alone); a single series needs no legend box because the chart's own title\n * already names it (see marks-and-anatomy.md \"Labels & legend\").\n */\nimport styles from './Legend.module.css';\n\nexport interface LegendItem {\n label: string;\n color: string;\n /** 'line' for line charts (a short stroke key), 'swatch' for bar/area. */\n kind?: 'line' | 'swatch';\n}\n\nexport function Legend({ items }: { items: LegendItem[] }) {\n if (items.length < 2) return null;\n return (\n <ul className={styles.legend}>\n {items.map((it) => (\n <li key={it.label} className={styles.item}>\n <span\n className={it.kind === 'line' ? styles.swatchLine : styles.swatch}\n style={{ background: it.color }}\n aria-hidden=\"true\"\n />\n {it.label}\n </li>\n ))}\n </ul>\n );\n}\n",".svg {\n display: block;\n width: 100%;\n height: auto;\n}\n\n.gridline {\n stroke: var(--chart-grid);\n stroke-width: 1;\n}\n\n.axis {\n stroke: var(--chart-axis);\n stroke-width: 1;\n}\n\n.axisLabel {\n font-size: var(--text-xs-size);\n fill: var(--text-tertiary);\n font-family: var(--font-ui);\n}\n\n.line {\n fill: none;\n stroke-width: 2;\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n\n.area {\n opacity: 0.1;\n stroke: none;\n}\n\n.marker {\n stroke: var(--chart-surface);\n stroke-width: 2;\n}\n\n.endLabel {\n font-size: var(--text-xs-size);\n font-family: var(--font-ui);\n font-weight: var(--font-weight-medium);\n}\n\n.crosshairLine {\n stroke: var(--chart-axis);\n stroke-width: 1;\n pointer-events: none;\n}\n\n.overlay {\n fill: transparent;\n cursor: crosshair;\n}\n\n.wrap {\n position: relative;\n}\n\n.tooltip {\n position: absolute;\n pointer-events: none;\n background: var(--chart-tooltip-bg);\n border: 1px solid var(--chart-tooltip-border);\n border-radius: var(--radius-sm);\n box-shadow: var(--shadow-md);\n padding: var(--space-2);\n font-size: var(--text-xs-size);\n color: var(--text-primary);\n white-space: nowrap;\n z-index: var(--z-dropdown);\n transform: translate(-50%, -100%);\n margin-top: -10px;\n}\n\n.tooltipDate {\n color: var(--text-tertiary);\n margin-bottom: var(--space-1);\n}\n\n.tooltipRow {\n display: flex;\n align-items: center;\n gap: var(--space-1);\n}\n\n.tooltipKey {\n width: 12px;\n height: 2px;\n flex: none;\n}\n\n.tooltipValue {\n font-weight: var(--font-weight-semibold);\n font-variant-numeric: tabular-nums;\n}\n\n.tooltipGap {\n color: var(--text-tertiary);\n font-style: italic;\n}\n","/**\n * components/charts/LineChart.tsx — trend over time. A gap (`null` y) is\n * split into a separate path segment so it renders as a visible break in\n * the line, never as a straight line through a missing value and never as\n * a silent zero. Single series gets an optional soft area fill; two-plus\n * series always render a legend (never color-matching alone).\n */\nimport { useRef, useState } from 'react';\nimport type { Series } from './types.js';\nimport { seriesColor, CHART_GRID, CHART_AXIS } from './colors.js';\nimport { Legend } from './Legend.js';\nimport './chart-tokens.css';\nimport styles from './LineChart.module.css';\n\nconst VBOX_W = 640;\nconst PAD_L = 44;\nconst PAD_R = 12;\nconst PAD_T = 12;\nconst PAD_B = 24;\nconst TICKS_Y = 4;\n/* Direct end-of-line labels need a gutter of their own. They are drawn in USER\n units — the viewBox scales the font along with the geometry, so a reserve\n measured in user units holds at every rendered width — and `--text-xs-size`\n resolves to 12 user units here, where the UI sans averages a shade over 6\n units per character at medium weight. 6.4 rounds that up so the reserve errs\n wide rather than clipping. Without the reserve the label was drawn at\n `VBOX_W - PAD_R + 4` with only PAD_R (12u) of room and the svg's own\n `overflow: hidden` cropped it to its first glyph — \"Estimated spend\"\n rendered as a lone \"E\". */\nconst END_LABEL_CH = 6.4;\nconst END_LABEL_GAP = 4;\n/* Past this the gutter would cost more plot than the label is worth, so the\n label is dropped rather than shrinking the chart around it. Nothing is lost:\n Legend.tsx deliberately renders nothing below two series because the panel\n heading already names a lone series, and two-plus series always have the\n legend regardless. */\nconst END_LABEL_MAX = 150;\n\ninterface Run {\n x: number;\n y: number;\n}\n\nfunction splitRuns(points: Series['points']): Run[][] {\n const runs: Run[][] = [];\n let current: Run[] = [];\n for (const p of points) {\n if (p.y === null) {\n if (current.length) runs.push(current);\n current = [];\n continue;\n }\n current.push({ x: p.x, y: p.y });\n }\n if (current.length) runs.push(current);\n return runs;\n}\n\nfunction niceTicks(min: number, max: number, count: number): number[] {\n if (max <= min) return [min];\n const step = (max - min) / count;\n return Array.from({ length: count + 1 }, (_, i) => min + step * i);\n}\n\nexport function LineChart({\n series,\n height = 200,\n area = false,\n formatX = (x: number) => String(x),\n formatY = (y: number) => String(y),\n ariaLabel,\n}: {\n series: Series[];\n height?: number;\n area?: boolean;\n formatX?: (x: number) => string;\n formatY?: (y: number) => string;\n ariaLabel: string;\n}) {\n const svgRef = useRef<SVGSVGElement>(null);\n const [hoverX, setHoverX] = useState<number | null>(null);\n const [tooltipPos, setTooltipPos] = useState<{ left: number; top: number } | null>(null);\n\n const allX = series.flatMap((s) => s.points.map((p) => p.x));\n const knownY = series.flatMap((s) => s.points.map((p) => p.y)).filter((y): y is number => y !== null);\n if (allX.length === 0) {\n return <p>No data.</p>;\n }\n const xMin = Math.min(...allX);\n const xMax = Math.max(...allX);\n const yMin = Math.min(0, ...knownY);\n const yMax = Math.max(0.0001, ...knownY);\n const xRange = xMax - xMin || 1;\n const yRange = yMax - yMin || 1;\n\n /* Decided before the scales, because the reserved gutter is what plotW is\n measured against — and the gridlines and x-axis stop at the same edge. */\n const wantEndLabels = series.length >= 1 && series.length <= 4;\n const endLabelW = wantEndLabels\n ? Math.max(...series.map((s) => s.label.length)) * END_LABEL_CH\n : 0;\n const showEndLabels = wantEndLabels && endLabelW <= END_LABEL_MAX;\n const padR = PAD_R + (showEndLabels ? END_LABEL_GAP + endLabelW : 0);\n const showLegend = series.length >= 2;\n\n const plotW = VBOX_W - PAD_L - padR;\n const plotH = height - PAD_T - PAD_B;\n const xScale = (x: number) => PAD_L + ((x - xMin) / xRange) * plotW;\n const yScale = (y: number) => PAD_T + plotH - ((y - yMin) / yRange) * plotH;\n\n const yTicks = niceTicks(yMin, yMax, TICKS_Y);\n\n // Nearest-x lookup across a reference axis (the union of all distinct x\n // values, since series may not share every point).\n const xAxis = Array.from(new Set(allX)).sort((a, b) => a - b);\n\n function nearestX(clientX: number): number | null {\n const svg = svgRef.current;\n if (!svg) return null;\n const rect = svg.getBoundingClientRect();\n const svgX = ((clientX - rect.left) / rect.width) * VBOX_W;\n const dataX = xMin + ((svgX - PAD_L) / plotW) * xRange;\n let nearest = xAxis[0];\n let best = Infinity;\n for (const x of xAxis) {\n const d = Math.abs(x - dataX);\n if (d < best) {\n best = d;\n nearest = x;\n }\n }\n return nearest;\n }\n\n function handleMove(e: React.PointerEvent<SVGSVGElement>) {\n const x = nearestX(e.clientX);\n if (x === null) return;\n setHoverX(x);\n const svg = svgRef.current;\n if (svg) {\n const rect = svg.getBoundingClientRect();\n const px = (xScale(x) / VBOX_W) * rect.width;\n setTooltipPos({ left: px, top: 0 });\n }\n }\n\n const hoverPoints =\n hoverX !== null\n ? series.map((s) => ({\n series: s,\n point: s.points.find((p) => p.x === hoverX) ?? null,\n }))\n : null;\n\n return (\n <div className={styles.wrap}>\n <svg\n ref={svgRef}\n className={styles.svg}\n viewBox={`0 0 ${VBOX_W} ${height}`}\n role=\"img\"\n aria-label={ariaLabel}\n onPointerMove={handleMove}\n onPointerLeave={() => setHoverX(null)}\n >\n {yTicks.map((t, i) => (\n <g key={i}>\n <line\n x1={PAD_L}\n x2={VBOX_W - padR}\n y1={yScale(t)}\n y2={yScale(t)}\n className={styles.gridline}\n stroke={CHART_GRID}\n />\n <text x={PAD_L - 6} y={yScale(t)} dy=\"0.32em\" textAnchor=\"end\" className={styles.axisLabel}>\n {formatY(t)}\n </text>\n </g>\n ))}\n <line\n x1={PAD_L}\n x2={VBOX_W - padR}\n y1={height - PAD_B}\n y2={height - PAD_B}\n className={styles.axis}\n stroke={CHART_AXIS}\n />\n {xAxis.length > 1\n ? [xAxis[0], xAxis[xAxis.length - 1]].map((x, i) => (\n <text\n key={i}\n x={xScale(x)}\n y={height - 6}\n textAnchor={i === 0 ? 'start' : 'end'}\n className={styles.axisLabel}\n >\n {formatX(x)}\n </text>\n ))\n : null}\n\n {series.map((s, si) => {\n const color = seriesColor(si);\n const runs = splitRuns(s.points);\n return (\n <g key={s.id}>\n {area && series.length === 1\n ? runs.map((run, ri) => {\n const d =\n run.map((p, j) => `${j === 0 ? 'M' : 'L'}${xScale(p.x)},${yScale(p.y)}`).join(' ') +\n ` L${xScale(run[run.length - 1].x)},${yScale(yMin)} L${xScale(run[0].x)},${yScale(yMin)} Z`;\n return <path key={ri} d={d} fill={color} className={styles.area} />;\n })\n : null}\n {runs.map((run, ri) => (\n <path\n key={ri}\n d={run.map((p, j) => `${j === 0 ? 'M' : 'L'}${xScale(p.x)},${yScale(p.y)}`).join(' ')}\n stroke={color}\n className={styles.line}\n />\n ))}\n {showEndLabels && runs.length ? (\n (() => {\n const lastRun = runs[runs.length - 1];\n const last = lastRun[lastRun.length - 1];\n return (\n <text\n x={xScale(last.x) + END_LABEL_GAP}\n y={yScale(last.y)}\n dy=\"0.32em\"\n className={styles.endLabel}\n fill={color}\n >\n {s.label}\n </text>\n );\n })()\n ) : null}\n </g>\n );\n })}\n\n {hoverX !== null ? (\n <line\n x1={xScale(hoverX)}\n x2={xScale(hoverX)}\n y1={PAD_T}\n y2={height - PAD_B}\n className={styles.crosshairLine}\n />\n ) : null}\n {hoverX !== null\n ? series.map((s, si) => {\n const p = s.points.find((pt) => pt.x === hoverX);\n if (!p || p.y === null) return null;\n return (\n <circle\n key={s.id}\n cx={xScale(p.x)}\n cy={yScale(p.y)}\n r={4}\n fill={seriesColor(si)}\n className={styles.marker}\n />\n );\n })\n : null}\n\n <rect\n x={PAD_L}\n y={PAD_T}\n width={plotW}\n height={plotH}\n className={styles.overlay}\n onFocus={() => setHoverX(xAxis[xAxis.length - 1] ?? null)}\n />\n </svg>\n {hoverPoints && tooltipPos ? (\n <div className={styles.tooltip} style={{ left: tooltipPos.left, top: tooltipPos.top }}>\n <div className={styles.tooltipDate}>{formatX(hoverX as number)}</div>\n {hoverPoints.map(({ series: s, point }, i) => (\n <div className={styles.tooltipRow} key={s.id}>\n <span className={styles.tooltipKey} style={{ background: seriesColor(i) }} aria-hidden=\"true\" />\n {point && point.y !== null ? (\n <>\n <span className={styles.tooltipValue}>{formatY(point.y)}</span>\n {showLegend ? <span>{s.label}</span> : null}\n </>\n ) : (\n <span className={styles.tooltipGap}>no data{showLegend ? ` — ${s.label}` : ''}</span>\n )}\n </div>\n ))}\n </div>\n ) : null}\n {showLegend ? (\n <Legend items={series.map((s, i) => ({ label: s.label, color: seriesColor(i), kind: 'line' }))} />\n ) : null}\n </div>\n );\n}\n",".svg {\n display: block;\n overflow: visible;\n}\n\n.bar {\n transition: opacity var(--duration-fast) var(--ease-standard);\n}\n\n.bar:hover,\n.bar:focus-visible {\n opacity: 0.82;\n}\n\n.baseline {\n stroke: var(--chart-axis);\n stroke-width: 1;\n}\n\n.gridline {\n stroke: var(--chart-grid);\n stroke-width: 1;\n}\n\n.axisLabel {\n font-size: 10px;\n fill: var(--text-tertiary);\n font-family: var(--font-ui);\n}\n\n.valueLabel {\n font-size: 10px;\n fill: var(--text-secondary);\n font-family: var(--font-ui);\n font-variant-numeric: tabular-nums;\n}\n\n.categoryLabel {\n font-size: 10px;\n fill: var(--text-secondary);\n font-family: var(--font-ui);\n}\n\n.hitArea {\n fill: transparent;\n cursor: pointer;\n}\n\n.tooltip {\n position: absolute;\n pointer-events: none;\n background: var(--chart-tooltip-bg);\n border: 1px solid var(--chart-tooltip-border);\n border-radius: var(--radius-sm);\n box-shadow: var(--shadow-md);\n padding: var(--space-1) var(--space-2);\n font-size: var(--text-xs-size);\n color: var(--text-primary);\n white-space: nowrap;\n z-index: var(--z-dropdown);\n}\n\n.tooltipValue {\n font-weight: var(--font-weight-semibold);\n font-variant-numeric: tabular-nums;\n}\n\n.tooltipLabel {\n color: var(--text-tertiary);\n margin-left: var(--space-1);\n}\n\n.wrap {\n position: relative;\n}\n","/**\n * components/charts/BarChart.tsx — categorical magnitude comparison.\n * Single hue by default (nominal categories never get a value-ramp — see\n * dataviz anti-patterns \"a value-ramp on nominal categories\"). Vertical for\n * a handful of short-named categories, horizontal for many or long-named\n * ones (dataviz choosing-a-form.md). Null values render as an explicit\n * \"no data\" dash, never a silent zero-height bar indistinguishable from a\n * real zero.\n */\nimport { useId, useState } from 'react';\nimport type { CategoricalDatum } from './types.js';\nimport { CHART_SEQUENTIAL, CHART_AXIS, CHART_GRID } from './colors.js';\nimport './chart-tokens.css';\nimport styles from './BarChart.module.css';\n\nconst BAR_MAX = 24;\nconst GAP = 10;\n\nexport function BarChart({\n data,\n height = 160,\n orientation = 'vertical',\n color = CHART_SEQUENTIAL,\n formatValue = (v: number) => String(v),\n ariaLabel,\n}: {\n data: CategoricalDatum[];\n height?: number;\n orientation?: 'vertical' | 'horizontal';\n color?: string;\n formatValue?: (v: number) => string;\n ariaLabel: string;\n}) {\n const uid = useId();\n const [hover, setHover] = useState<number | null>(null);\n\n const known = data.map((d) => d.value).filter((v): v is number => v !== null);\n const maxVal = Math.max(0, ...known, 0.0001);\n const minVal = Math.min(0, ...known);\n const range = maxVal - minVal || 1;\n\n if (orientation === 'horizontal') {\n const LABEL_W = 120;\n const PAD_R = 48;\n const rowH = Math.min(BAR_MAX, Math.max(14, Math.floor((height - GAP) / data.length) - GAP));\n const plotW = 420;\n const svgH = data.length * (rowH + GAP) + GAP;\n const svgW = LABEL_W + plotW + PAD_R;\n\n return (\n <div className={styles.wrap}>\n <svg\n className={styles.svg}\n width={svgW}\n height={svgH}\n viewBox={`0 0 ${svgW} ${svgH}`}\n role=\"img\"\n aria-label={ariaLabel}\n >\n <line x1={LABEL_W} y1={0} x2={LABEL_W} y2={svgH} className={styles.baseline} stroke={CHART_AXIS} />\n {data.map((d, i) => {\n const y = GAP + i * (rowH + GAP);\n const barW = d.value !== null ? ((d.value - minVal) / range) * plotW : 0;\n return (\n <g key={d.label + i}>\n <text\n x={LABEL_W - 8}\n y={y + rowH / 2}\n dy=\"0.32em\"\n textAnchor=\"end\"\n className={styles.categoryLabel}\n >\n {d.label.length > 22 ? `${d.label.slice(0, 21)}…` : d.label}\n </text>\n {d.value === null ? (\n <line\n x1={LABEL_W + 4}\n y1={y + rowH / 2}\n x2={LABEL_W + 14}\n y2={y + rowH / 2}\n stroke={CHART_GRID}\n strokeWidth={2}\n strokeDasharray=\"2 2\"\n />\n ) : (\n <>\n <rect\n x={LABEL_W}\n y={y}\n width={Math.max(2, barW)}\n height={rowH}\n rx={4}\n fill={color}\n className={styles.bar}\n />\n <text\n x={LABEL_W + Math.max(2, barW) + 6}\n y={y + rowH / 2}\n dy=\"0.32em\"\n className={styles.valueLabel}\n >\n {formatValue(d.value)}\n </text>\n </>\n )}\n <rect\n className={styles.hitArea}\n x={0}\n y={y - GAP / 2}\n width={svgW}\n height={rowH + GAP}\n tabIndex={0}\n role=\"img\"\n aria-label={`${d.label}: ${d.value === null ? 'no data' : formatValue(d.value)}`}\n onPointerEnter={() => setHover(i)}\n onPointerLeave={() => setHover((h) => (h === i ? null : h))}\n onFocus={() => setHover(i)}\n onBlur={() => setHover((h) => (h === i ? null : h))}\n />\n </g>\n );\n })}\n </svg>\n {hover !== null ? (\n <div\n className={styles.tooltip}\n style={{ left: LABEL_W + 8, top: GAP + hover * (rowH + GAP) - 4 }}\n >\n <span className={styles.tooltipValue}>\n {data[hover].value === null ? 'no data' : formatValue(data[hover].value as number)}\n </span>\n <span className={styles.tooltipLabel}>{data[hover].label}</span>\n </div>\n ) : null}\n </div>\n );\n }\n\n // Vertical orientation.\n const barSlot = data.length ? Math.max(BAR_MAX, 0) : BAR_MAX;\n const barW = Math.min(BAR_MAX, barSlot);\n const PAD_T = 20;\n const PAD_B = 30;\n const plotH = height;\n const svgH = plotH + PAD_T + PAD_B;\n const svgW = data.length * (barW + GAP) + GAP;\n const zeroY = PAD_T + plotH - ((0 - minVal) / range) * plotH;\n\n return (\n <div className={styles.wrap}>\n <svg\n className={styles.svg}\n width={svgW}\n height={svgH}\n viewBox={`0 0 ${svgW} ${svgH}`}\n role=\"img\"\n aria-label={ariaLabel}\n >\n <line x1={0} y1={zeroY} x2={svgW} y2={zeroY} className={styles.baseline} stroke={CHART_AXIS} />\n {data.map((d, i) => {\n const x = GAP + i * (barW + GAP);\n const barH = d.value !== null ? (Math.abs(d.value - minVal) / range) * plotH : 0;\n const top = d.value !== null && d.value >= 0 ? zeroY - barH : zeroY;\n return (\n <g key={d.label + i}>\n {d.value === null ? (\n <line\n x1={x + barW / 2 - 5}\n y1={zeroY}\n x2={x + barW / 2 + 5}\n y2={zeroY}\n stroke={CHART_GRID}\n strokeWidth={2}\n strokeDasharray=\"2 2\"\n />\n ) : (\n <>\n <rect\n x={x}\n y={top}\n width={barW}\n height={Math.max(2, barH)}\n rx={4}\n fill={color}\n className={styles.bar}\n />\n <text x={x + barW / 2} y={top - 4} textAnchor=\"middle\" className={styles.valueLabel}>\n {formatValue(d.value)}\n </text>\n </>\n )}\n <text\n x={x + barW / 2}\n y={svgH - 8}\n textAnchor=\"middle\"\n className={styles.axisLabel}\n >\n {d.label.length > 10 ? `${d.label.slice(0, 9)}…` : d.label}\n </text>\n <rect\n className={styles.hitArea}\n x={x - GAP / 2}\n y={0}\n width={barW + GAP}\n height={svgH}\n tabIndex={0}\n role=\"img\"\n aria-label={`${d.label}: ${d.value === null ? 'no data' : formatValue(d.value)}`}\n onPointerEnter={() => setHover(i)}\n onPointerLeave={() => setHover((h) => (h === i ? null : h))}\n onFocus={() => setHover(i)}\n onBlur={() => setHover((h) => (h === i ? null : h))}\n />\n </g>\n );\n })}\n </svg>\n {hover !== null ? (\n <div\n className={styles.tooltip}\n style={{ left: GAP + hover * (barW + GAP), top: 0 }}\n id={`${uid}-tooltip`}\n >\n <span className={styles.tooltipValue}>\n {data[hover].value === null ? 'no data' : formatValue(data[hover].value as number)}\n </span>\n <span className={styles.tooltipLabel}>{data[hover].label}</span>\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
var e=`var(--chart-neutral)`;function t(t){return!Number.isInteger(t)||t<0||t>=6?e:`var(--chart-series-${t+1})`}var n=`var(--chart-sequential)`,r=`var(--chart-sequential-soft)`;function i(e){return`var(--chart-seq-${Number.isFinite(e)?Math.max(1,Math.min(7,Math.round(e))):1})`}function a(e){return i(1+Math.max(0,Math.min(1,e))*6)}var o=`var(--chart-diverging-pos)`,s=`var(--chart-diverging-neg)`,c=`var(--chart-diverging-mid)`,l=`var(--chart-grid)`,u=`var(--chart-axis)`;function d(e){return`var(--status-${e}-solid)`}function f(e){return`var(--chart-heat-${Math.max(0,Math.min(4,Math.round(e)))})`}var p=`var(--chart-track)`,m=Object.freeze({size:6,angle:45,strokeWidth:1.5,stroke:`var(--chart-unknown)`});function h(e){return`chart-hatch-${e.replace(/[^A-Za-z0-9_-]/g,``)}`}var g=`var(--chart-queued-outline)`;function _(e){return`var(--engine-${e})`}export{d as _,l as a,n as c,m as d,_ as f,t as g,a as h,o as i,r as l,f as m,c as n,e as o,h as p,s as r,g as s,u as t,p as u};
|
|
2
|
-
//# sourceMappingURL=colors-B-vHsX1S.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"colors-B-vHsX1S.js","names":[],"sources":["../../../../../../src/web-ui/components/charts/colors.ts"],"sourcesContent":["/**\n * components/charts/colors.ts — the one place a chart asks for a colour\n * (owner: unit C0, with chart-tokens.css; the chart components are C7's).\n * Every value is a `var(--chart-*)` / `var(--engine-*)` / `var(--status-*)`\n * reference, never a literal hex, so theming is automatic and light and dark\n * can never drift apart. The roles — quantity, categorical, unknown, queued,\n * engine, status — are explained in chart-tokens.css's header.\n */\n\n/**\n * Identity slots in the categorical rotation. SIX (V3.10): the palette is\n * derived to stay clear of every engine, status and quantity hue, and no\n * seventh family clears that bar — see design/tokens.css.\n */\nexport const SERIES_SLOT_COUNT = 6;\n\n/** The \"Other\"/overflow bucket colour — never part of the identity rotation. */\nexport const CHART_NEUTRAL = 'var(--chart-neutral)';\n\n/**\n * Fixed-order categorical colour for series `slot` (0-based). Colour follows\n * the entity, never its row number: assign each series its slot once (e.g.\n * by a stable sort) and keep it even when others are filtered out — never\n * re-pack slots to \"fill the gap\" (dataviz anti-pattern: recolor-on-filter).\n *\n * Past the sixth slot this answers the NEUTRAL \"Other\" colour instead of\n * cycling: a repeated colour would tell the reader two series are one. A\n * chart with more than six series should fold its tail into \"Other\" and say\n * so in the legend and the table.\n */\nexport function seriesColor(slot: number): string {\n if (!Number.isInteger(slot) || slot < 0 || slot >= SERIES_SLOT_COUNT) return CHART_NEUTRAL;\n return `var(--chart-series-${slot + 1})`;\n}\n\n/** Default single hue for magnitude (sequential) and for one nominal series. */\nexport const CHART_SEQUENTIAL = 'var(--chart-sequential)';\nexport const CHART_SEQUENTIAL_SOFT = 'var(--chart-sequential-soft)';\n\n/** Steps in the quantity ramp (`--chart-seq-1..7`, azure 214°). */\nexport const SEQ_STEP_COUNT = 7;\n\n/** Quantity ramp step 1..7 (1 = least). Out-of-range steps clamp. */\nexport function seqColor(step: number): string {\n const n = Number.isFinite(step) ? Math.max(1, Math.min(SEQ_STEP_COUNT, Math.round(step))) : 1;\n return `var(--chart-seq-${n})`;\n}\n\n/**\n * A magnitude in [0, 1] → its quantity step. For a known value only: an\n * unknown (null / NaN) is the hatch below, never the lightest step — a pale\n * azure cell would claim \"a little\", which is a measurement nobody made.\n */\nexport function quantityColor(fraction: number): string {\n const f = Math.max(0, Math.min(1, fraction));\n return seqColor(1 + f * (SEQ_STEP_COUNT - 1));\n}\n\nexport const CHART_DIVERGING_POS = 'var(--chart-diverging-pos)';\nexport const CHART_DIVERGING_NEG = 'var(--chart-diverging-neg)';\nexport const CHART_DIVERGING_MID = 'var(--chart-diverging-mid)';\n\nexport const CHART_GRID = 'var(--chart-grid)';\nexport const CHART_AXIS = 'var(--chart-axis)';\n\n/** Status tones (the StatusBadge vocabulary). Status colours carry STATE, never\n * identity, and always travel with a text label (legend, tooltip, table). */\nexport type ChartTone = 'neutral' | 'info' | 'running' | 'success' | 'warning' | 'danger' | 'unknown';\n\nexport function toneColor(tone: ChartTone): string {\n return `var(--status-${tone}-solid)`;\n}\n\n/** Sequential heat steps 0..4 (0 = a true zero, not \"no data\"). */\nexport function heatColor(step: number): string {\n const n = Math.max(0, Math.min(4, Math.round(step)));\n return `var(--chart-heat-${n})`;\n}\n\n/** Unfilled meter/gauge track: the lightest step of the quantity ramp, not a gray. */\nexport const CHART_TRACK = 'var(--chart-track)';\n\n// ---------------------------------------------------------------------------\n// Unknown, queued / parked\n// ---------------------------------------------------------------------------\n\n/** The unknown gray — for the hatch stroke and the outline around it. */\nexport const CHART_UNKNOWN = 'var(--chart-unknown)';\n\n/** A CSS background that draws the 45° unknown hatch (HTML bars, tiles, cells). */\nexport const CHART_UNKNOWN_HATCH = 'var(--chart-unknown-hatch)';\n\n/**\n * The SVG version of the same hatch, as data: render it once per chart as\n *\n * <pattern id={id} width={size} height={size} patternUnits=\"userSpaceOnUse\"\n * patternTransform={`rotate(${angle})`}>\n * <line x1={0} y1={0} x2={0} y2={size} stroke={stroke} strokeWidth={strokeWidth} />\n * </pattern>\n *\n * with `id` from `hatchPatternId(useId())` — ids are document-global, so a\n * shared literal id would let one chart's unmount blank another's hatch —\n * and fill unknown marks with `url(#id)` plus a CHART_UNKNOWN outline.\n */\nexport const UNKNOWN_HATCH = Object.freeze({\n size: 6,\n angle: 45,\n strokeWidth: 1.5,\n stroke: CHART_UNKNOWN,\n});\n\n/** A document-safe pattern id from React's `useId()` (which contains `:`). */\nexport function hatchPatternId(reactId: string): string {\n return `chart-hatch-${reactId.replace(/[^A-Za-z0-9_-]/g, '')}`;\n}\n\n/** Queued / parked work: an outline in this colour, no fill. */\nexport const CHART_QUEUED_OUTLINE = 'var(--chart-queued-outline)';\n\n// ---------------------------------------------------------------------------\n// Engines (identity only)\n// ---------------------------------------------------------------------------\n\nexport type ChartEngine = 'claude' | 'codex' | 'grok' | 'local';\n\n/**\n * An engine's identity colour. ONLY for charts that show nothing but engines\n * (runs by engine, usage bars) and the 2px tick beside a lane label — pass it\n * explicitly per series; a chart never picks engine colours by index. When\n * status colour is on screen, show engines by position and monogram instead.\n */\nexport function engineColor(engine: ChartEngine): string {\n return `var(--engine-${engine})`;\n}\n"],"mappings":"AAiBA,IAAa,EAAgB,uBAa7B,SAAgB,EAAY,EAAsB,CAEhD,MADI,CAAC,OAAO,UAAU,CAAI,GAAK,EAAO,GAAK,GAAA,EAAkC,EACtE,sBAAsB,EAAO,EAAE,EACxC,CAGA,IAAa,EAAmB,0BACnB,EAAwB,+BAMrC,SAAgB,EAAS,EAAsB,CAE7C,MAAO,mBADG,OAAO,SAAS,CAAI,EAAI,KAAK,IAAI,EAAG,KAAK,IAAA,EAAoB,KAAK,MAAM,CAAI,CAAC,CAAC,EAAI,EAChE,EAC9B,CAOA,SAAgB,EAAc,EAA0B,CAEtD,OAAO,EAAS,EADN,KAAK,IAAI,EAAG,KAAK,IAAI,EAAG,CAAQ,CACtB,EAAK,CAAmB,CAC9C,CAEA,IAAa,EAAsB,6BACtB,EAAsB,6BACtB,EAAsB,6BAEtB,EAAa,oBACb,EAAa,oBAM1B,SAAgB,EAAU,EAAyB,CACjD,MAAO,gBAAgB,EAAK,QAC9B,CAGA,SAAgB,EAAU,EAAsB,CAE9C,MAAO,oBADG,KAAK,IAAI,EAAG,KAAK,IAAI,EAAG,KAAK,MAAM,CAAI,CAAC,CACvB,EAAE,EAC/B,CAGA,IAAa,EAAc,qBAwBd,EAAgB,OAAO,OAAO,CACzC,KAAM,EACN,MAAO,GACP,YAAa,IACb,OAAQ,sBACV,CAAC,EAGD,SAAgB,EAAe,EAAyB,CACtD,MAAO,eAAe,EAAQ,QAAQ,kBAAmB,EAAE,GAC7D,CAGA,IAAa,EAAuB,8BAcpC,SAAgB,EAAY,EAA6B,CACvD,MAAO,gBAAgB,EAAO,EAChC"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
var e=`ashlr:command`,t={"open-settings":`section.settings`,"toggle-theme":`appearance.toggle-theme`,"open-needs-you":`needs-you.open`,"new-chat":`chat.new`,"focus-composer":`app.summon`},n=/^open-session:([A-Za-z0-9._-]{1,128})$/;function r(e){if(typeof e!=`string`)return null;if(Object.prototype.hasOwnProperty.call(t,e)){let n=e;return{kind:`command`,name:n,commandId:t[n]}}let r=n.exec(e);return r?{kind:`open-session`,sessionId:r[1]}:null}var i=[{id:`needs-you`,label:`Needs you`},{id:`chats`,label:`Chats`},{id:`actions`,label:`Actions`},{id:`go-to`,label:`Go to`},{id:`seats-apps`,label:`Seats & Apps`},{id:`projects`,label:`Projects`}],a={">":`actions`,"#":`chats`},o=[`Surfaces`,`Navigation`,`Chat`,`Dock`,`Composer`,`Needs you`,`Charts`,`App`],s={confirm:{title:`Stop every running chat?`,body:`Each running turn is cancelled. Queued follow-ups are held, not sent.`,confirmLabel:`Stop chats`,destructive:!0},token:!0},c={confirm:{title:`Stop the fleet?`,body:`Autonomous work halts within one tick and stays stopped until you resume it. Chats keep running.`,confirmLabel:`Stop fleet`,destructive:!0},token:!0},l=(e,t,n)=>({id:`surface.${t}`,title:`Go to ${n}`,scope:`global`,keys:[{key:String(e),mod:!0}],group:`go-to`,section:`Surfaces`,keywords:[n.toLowerCase()]}),u=[l(1,`command`,`Command`),l(2,`fleet`,`Fleet`),l(3,`growth`,`Growth`),l(4,`mind`,`Mind`),l(5,`chat`,`Chat`),{id:`section.settings`,title:`Open Settings`,scope:`global`,keys:[{key:`,`,mod:!0}],group:`go-to`,section:`Surfaces`,keywords:[`preferences`,`appearance`],native:{kind:`menu`,desktopCommand:`open-settings`,accelerator:`CmdOrCtrl+,`}},{id:`section.apps`,title:`Open Apps & Accounts`,scope:`global`,keys:[],group:`go-to`,section:`Surfaces`,keywords:[`mcp`,`accounts`,`seats`,`integrations`,`ollama`]},{id:`section.usage`,title:`Open Usage`,scope:`global`,keys:[],group:`go-to`,section:`Surfaces`,keywords:[`capacity`,`spend`,`limits`]},{id:`palette.open`,title:`Command palette`,scope:`global`,keys:[{key:`k`,mod:!0}],group:null,section:`Navigation`},{id:`needs-you.open`,title:`Open Needs you`,scope:`global`,keys:[{key:`j`,mod:!0}],group:`actions`,section:`Navigation`,keywords:[`approvals`,`inbox`,`triage`]},{id:`shortcuts.open`,title:`Keyboard shortcuts`,scope:`global`,keys:[{key:`/`,mod:!0}],group:`actions`,section:`Navigation`,keywords:[`keys`,`help`]},{id:`history.back`,title:`Back`,scope:`global`,keys:[{key:`[`,mod:!0}],group:null,section:`Navigation`,note:`through surfaces and chats`},{id:`history.forward`,title:`Forward`,scope:`global`,keys:[{key:`]`,mod:!0}],group:null,section:`Navigation`,note:`through surfaces and chats`},{id:`chat.recent-next`,title:`Next recent chat`,scope:`global`,keys:[{key:`tab`,ctrl:!0}],group:null,section:`Navigation`},{id:`chat.recent-prev`,title:`Previous recent chat`,scope:`global`,keys:[{key:`tab`,ctrl:!0,shift:!0}],group:null,section:`Navigation`},{id:`rail.toggle-labels`,title:`Show or hide rail labels`,scope:`global`,keys:[{key:`\\`,mod:!0,shift:!0}],group:`actions`,section:`Navigation`},{id:`chat.new`,title:`New chat`,scope:`global`,keys:[{key:`n`,mod:!0}],group:`actions`,section:`Chat`},{id:`chat.new-on`,title:`New chat on…`,scope:`global`,keys:[],group:`actions`,section:`Chat`,argument:{kind:`seat`,prompt:`Seat`},keywords:[`seat`,`account`,`engine`]},{id:`chat.sidebar`,title:`Show or hide the chat list`,scope:`chat`,keys:[{key:`b`,mod:!0}],group:`actions`,section:`Chat`},{id:`chat.find`,title:`Find in chat`,scope:`chat`,keys:[{key:`f`,mod:!0}],group:`actions`,section:`Chat`,keywords:[`search`]},{id:`chat.turn-prev`,title:`Previous turn`,scope:`chat`,keys:[{key:`arrowup`,alt:!0}],group:null,section:`Chat`},{id:`chat.turn-next`,title:`Next turn`,scope:`chat`,keys:[{key:`arrowdown`,alt:!0}],group:null,section:`Chat`},{id:`chats.stop-all`,title:`Stop running chats…`,scope:`global`,keys:[],group:`actions`,section:`Chat`,guard:s,keywords:[`cancel`,`halt`]},{id:`git.create-pr`,title:`Create pull request…`,scope:`chat`,keys:[],group:`actions`,section:`Chat`,keywords:[`pr`,`github`,`git`,`open pull request`]},{id:`git.merge-pr`,title:`Merge pull request…`,scope:`chat`,keys:[],group:`actions`,section:`Chat`,keywords:[`pr`,`github`,`git`,`land`,`ship`]},{id:`dock.toggle`,title:`Show or hide the dock`,scope:`chat`,keys:[{key:`\\`,mod:!0}],group:`actions`,section:`Dock`},{id:`dock.terminal`,title:`Terminal`,scope:`chat`,keys:[{key:"`",ctrl:!0}],group:`actions`,section:`Dock`,keywords:[`shell`,`console`]},{id:`dock.terminal-new`,title:`New terminal tab`,scope:`chat`,keys:[{key:"`",ctrl:!0,shift:!0}],group:`actions`,section:`Dock`},{id:`dock.preview`,title:`Preview`,scope:`chat`,keys:[{key:`b`,mod:!0,shift:!0}],group:`actions`,section:`Dock`,keywords:[`browser`,`dev server`]},{id:`dock.diff`,title:`Review changes`,scope:`chat`,keys:[{key:`d`,mod:!0,shift:!0}],group:`actions`,section:`Dock`,keywords:[`diff`,`git`]},{id:`composer.permission`,title:`Permission mode…`,scope:`chat`,keys:[{key:`m`,mod:!0,shift:!0}],group:`actions`,section:`Composer`,keywords:[`plan`,`bypass`,`auto`]},{id:`composer.model`,title:`Model…`,scope:`chat`,keys:[{key:`i`,mod:!0,shift:!0}],group:`actions`,section:`Composer`},{id:`composer.effort`,title:`Effort…`,scope:`chat`,keys:[{key:`e`,mod:!0,shift:!0}],group:`actions`,section:`Composer`,keywords:[`reasoning`,`thinking`]},{id:`composer.attach`,title:`Attach files…`,scope:`chat`,keys:[{key:`u`,mod:!0}],group:`actions`,section:`Composer`,keywords:[`upload`,`image`]},{id:`composer.send`,title:`Send`,scope:`composer`,keys:[{key:`enter`}],group:null,section:`Composer`,note:`queues while a turn runs (up to 3)`},{id:`composer.stop-and-send`,title:`Stop and send`,scope:`composer`,keys:[{key:`enter`,mod:!0,shift:!0}],group:null,section:`Composer`},{id:`composer.stop`,title:`Stop the running turn`,scope:`composer`,keys:[{key:`escape`}],group:null,section:`Composer`,note:`only from an empty composer with no overlay open`},{id:`drawer.next`,title:`Next item`,scope:`drawer`,keys:[{key:`j`}],group:null,section:`Needs you`},{id:`drawer.prev`,title:`Previous item`,scope:`drawer`,keys:[{key:`k`}],group:null,section:`Needs you`},{id:`drawer.open`,title:`Open item`,scope:`drawer`,keys:[{key:`enter`}],group:null,section:`Needs you`},{id:`drawer.approve`,title:`Approve`,scope:`drawer`,keys:[{key:`a`}],group:null,section:`Needs you`,note:`confirms, then asks for the token`},{id:`drawer.reject`,title:`Reject`,scope:`drawer`,keys:[{key:`r`}],group:null,section:`Needs you`,note:`confirms, then asks for the token`},{id:`drawer.veto`,title:`Veto`,scope:`drawer`,keys:[{key:`v`}],group:null,section:`Needs you`,note:`confirms, then asks for the token`},{id:`drawer.done`,title:`Mark done`,scope:`drawer`,keys:[{key:`e`}],group:null,section:`Needs you`},{id:`drawer.split-prev`,title:`Previous split`,scope:`drawer`,keys:[{key:`h`}],group:null,section:`Needs you`},{id:`drawer.split-next`,title:`Next split`,scope:`drawer`,keys:[{key:`l`}],group:null,section:`Needs you`},{id:`chart.table`,title:`Show as a table`,scope:`chart`,keys:[{key:`t`}],group:null,section:`Charts`,note:`when a chart card has focus`},{id:`appearance.toggle-theme`,title:`Toggle light / dark`,scope:`global`,keys:[{key:`l`,mod:!0,shift:!0}],group:`actions`,section:`App`,keywords:[`theme`,`dark mode`],native:{kind:`menu`,desktopCommand:`toggle-theme`,accelerator:`Shift+CmdOrCtrl+L`}},{id:`app.summon`,title:`Show Verse and focus the composer`,scope:`global`,keys:[{key:`space`,ctrl:!0,alt:!0}],group:null,section:`App`,note:`system-wide; turn on in Settings ▸ Desktop`,native:{kind:`global-hotkey`,accelerator:`Control+Alt+Space`}},{id:`fleet.stop`,title:`Stop the fleet…`,scope:`global`,keys:[],group:`actions`,section:`App`,guard:c,keywords:[`kill`,`halt`,`autonomy`]}],d=new Map(u.map(e=>[e.id,e]));function f(e){return d.get(e)??null}function p(e){return u.filter(t=>t.group===e)}function m(){let e=u.filter(e=>e.keys.length>0);return o.map(t=>({section:t,commands:e.filter(e=>e.section===t)})).filter(e=>e.commands.length>0)}function h(){if(typeof navigator>`u`)return`mac`;let e=navigator,t=e.userAgentData?.platform??e.platform??``;return/mac|iphone|ipad|ipod/i.test(t)?`mac`:`other`}var g={Backslash:`\\`,Backquote:"`",BracketLeft:`[`,BracketRight:`]`,Slash:`/`,Comma:`,`,Period:`.`,Semicolon:`;`,Quote:`'`,Minus:`-`,Equal:`=`,Space:`space`},_={" ":`space`,spacebar:`space`,esc:`escape`,return:`enter`,up:`arrowup`,down:`arrowdown`,left:`arrowleft`,right:`arrowright`};function v(e){let t=e.key??``;if(/^[a-z]$/i.test(t))return t.toLowerCase();let n=e.code??``;if(/^Digit[0-9]$/.test(n))return n.slice(5);if(g[n])return g[n];if(/^Key[A-Z]$/.test(n))return n.slice(3).toLowerCase();let r=t.toLowerCase();return _[r]??r}function y(e,t,n=h()){if(n===`mac`){if(!!t.mod!==e.metaKey||!!t.ctrl!==e.ctrlKey)return!1}else if(e.metaKey||!!(t.mod||t.ctrl)!==e.ctrlKey)return!1;return!!t.shift!==e.shiftKey||!!t.alt!==e.altKey?!1:v(e)===t.key}function b(e,t,n=h()){for(let r of t)for(let t of u)if(t.scope===r&&t.native?.kind!==`global-hotkey`&&t.keys.some(t=>y(e,t,n)))return t;return null}var x={enter:`↩`,escape:`Esc`,tab:`⇥`,space:`Space`,arrowup:`↑`,arrowdown:`↓`,arrowleft:`←`,arrowright:`→`,backspace:`⌫`},S={enter:`Enter`,escape:`Esc`,tab:`Tab`,space:`Space`,arrowup:`↑`,arrowdown:`↓`,arrowleft:`←`,arrowright:`→`,backspace:`Backspace`};function C(e,t=h()){let n=e.key.length===1?e.key.toUpperCase():(t===`mac`?x:S)[e.key]??e.key;return t===`mac`?`${e.ctrl?`⌃`:``}${e.alt?`⌥`:``}${e.shift?`⇧`:``}${e.mod?`⌘`:``}${n}`:[e.mod||e.ctrl?`Ctrl`:``,e.alt?`Alt`:``,e.shift?`Shift`:``,n].filter(Boolean).join(`+`)}export{h as a,C as c,r as d,m as f,y as i,b as l,a as n,v as o,e as r,f as s,i as t,p as u};
|
|
2
|
-
//# sourceMappingURL=command-catalog-s3W6Z96D.js.map
|