@ashlr/hub 3.11.0 → 3.11.2
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 +96 -0
- package/dist/authority-surface.json +12 -7
- package/dist/build-identity.json +2 -2
- package/dist/core/universe/builtins/preparation/manifest.json +1 -1
- package/dist/core/universe/builtins/preparation/preparation-bridge.mjs +5 -4
- package/dist/core/universe/builtins/preparation/preparation-verification-fixtures.mjs +4 -3
- package/dist/core/universe/campaign.js +9 -1
- package/dist/core/universe/campaign.js.map +1 -1
- package/dist/core/universe/runner.d.ts +3 -0
- package/dist/core/universe/runner.js +7 -3
- package/dist/core/universe/runner.js.map +1 -1
- package/dist/core/verse/compaction-point.d.ts +55 -0
- package/dist/core/verse/compaction-point.js +75 -0
- package/dist/core/verse/compaction-point.js.map +1 -0
- package/dist/core/verse/context-math.d.ts +1 -38
- package/dist/core/verse/context-math.js +5 -59
- package/dist/core/verse/context-math.js.map +1 -1
- package/dist/core/web/public/next/assets/{ActionMenu-CQvNJvHY.js → ActionMenu-_DhtX2gO.js} +2 -2
- package/dist/core/web/public/next/assets/{ActionMenu-CQvNJvHY.js.map → ActionMenu-_DhtX2gO.js.map} +1 -1
- package/dist/core/web/public/next/assets/Advanced-CAAfaBke.js +2 -0
- package/dist/core/web/public/next/assets/{Advanced-DEM93sKI.js.map → Advanced-CAAfaBke.js.map} +1 -1
- package/dist/core/web/public/next/assets/App-BAywyjE8.js +7 -0
- package/dist/core/web/public/next/assets/{App-CimXmK0L.js.map → App-BAywyjE8.js.map} +1 -1
- package/dist/core/web/public/next/assets/AppsSection-CUypKeog.js +2 -0
- package/dist/core/web/public/next/assets/{AppsSection-D6U-dSj6.js.map → AppsSection-CUypKeog.js.map} +1 -1
- package/dist/core/web/public/next/assets/{AreaTrend-LD9lCPkT.js → AreaTrend-CblDqC8Q.js} +2 -2
- package/dist/core/web/public/next/assets/{AreaTrend-LD9lCPkT.js.map → AreaTrend-CblDqC8Q.js.map} +1 -1
- package/dist/core/web/public/next/assets/AutonomySection-D3d8lYO3.js +2 -0
- package/dist/core/web/public/next/assets/{AutonomySection-3V9pUyxm.js.map → AutonomySection-D3d8lYO3.js.map} +1 -1
- package/dist/core/web/public/next/assets/BranchBar-DU0jAV1E.js +2 -0
- package/dist/core/web/public/next/assets/{BranchBar-U8UdpfEB.js.map → BranchBar-DU0jAV1E.js.map} +1 -1
- package/dist/core/web/public/next/assets/{BudgetControl-DOTlMSmW.js → BudgetControl-Mm1ZL4u6.js} +2 -2
- package/dist/core/web/public/next/assets/{BudgetControl-DOTlMSmW.js.map → BudgetControl-Mm1ZL4u6.js.map} +1 -1
- package/dist/core/web/public/next/assets/{BurnDown-x4PWH9JF.js → BurnDown-C1fgcFqo.js} +2 -2
- package/dist/core/web/public/next/assets/{BurnDown-x4PWH9JF.js.map → BurnDown-C1fgcFqo.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Button-DYv_KKxr.js → Button-DqgLUZvd.js} +2 -2
- package/dist/core/web/public/next/assets/{Button-DYv_KKxr.js.map → Button-DqgLUZvd.js.map} +1 -1
- package/dist/core/web/public/next/assets/CapacityStrip-nWFHvqFB.js +2 -0
- package/dist/core/web/public/next/assets/CapacityStrip-nWFHvqFB.js.map +1 -0
- package/dist/core/web/public/next/assets/ChatSection-DUZNpiVr.js +3 -0
- package/dist/core/web/public/next/assets/ChatSection-DUZNpiVr.js.map +1 -0
- package/dist/core/web/public/next/assets/{CloudBudgetForm-DJeJvBEu.js → CloudBudgetForm-2OW38o_C.js} +2 -2
- package/dist/core/web/public/next/assets/{CloudBudgetForm-DJeJvBEu.js.map → CloudBudgetForm-2OW38o_C.js.map} +1 -1
- package/dist/core/web/public/next/assets/CommandPalette-C5w2o1-r.js +2 -0
- package/dist/core/web/public/next/assets/{CommandPalette-FiD4N8XD.js.map → CommandPalette-C5w2o1-r.js.map} +1 -1
- package/dist/core/web/public/next/assets/CommandSection-Bx2knNqY.js +2 -0
- package/dist/core/web/public/next/assets/{CommandSection-DN8KwH-X.js.map → CommandSection-Bx2knNqY.js.map} +1 -1
- package/dist/core/web/public/next/assets/ConfirmDialog-B7ZwCQOX.js +2 -0
- package/dist/core/web/public/next/assets/ConfirmDialog-B7ZwCQOX.js.map +1 -0
- package/dist/core/web/public/next/assets/ConfirmDialog-Dx15x0Ho.css +1 -0
- package/dist/core/web/public/next/assets/Dialog-BpgcEW6b.js +2 -0
- package/dist/core/web/public/next/assets/Dialog-BpgcEW6b.js.map +1 -0
- package/dist/core/web/public/next/assets/Dialog-tQ8kFulD.css +1 -0
- package/dist/core/web/public/next/assets/{DiffPane-DLJ3gGGK.js → DiffPane-DpqRUtCx.js} +2 -2
- package/dist/core/web/public/next/assets/{DiffPane-DLJ3gGGK.js.map → DiffPane-DpqRUtCx.js.map} +1 -1
- package/dist/core/web/public/next/assets/{DiffViewer-B7NWPjIO.js → DiffViewer-CoV5-nUf.js} +2 -2
- package/dist/core/web/public/next/assets/{DiffViewer-B7NWPjIO.js.map → DiffViewer-CoV5-nUf.js.map} +1 -1
- package/dist/core/web/public/next/assets/DockHost-C0Pq7Jak.js +2 -0
- package/dist/core/web/public/next/assets/{DockHost-DvR-hPhZ.js.map → DockHost-C0Pq7Jak.js.map} +1 -1
- package/dist/core/web/public/next/assets/{EmptyState-DhNgDDrF.js → EmptyState-DYW29ncw.js} +2 -2
- package/dist/core/web/public/next/assets/{EmptyState-DhNgDDrF.js.map → EmptyState-DYW29ncw.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Epistemic-uARPnx9x.js → Epistemic-DVx6oHzp.js} +2 -2
- package/dist/core/web/public/next/assets/{Epistemic-uARPnx9x.js.map → Epistemic-DVx6oHzp.js.map} +1 -1
- package/dist/core/web/public/next/assets/FleetSection-DSETviPK.js +3 -0
- package/dist/core/web/public/next/assets/{FleetSection-D_zRBCub.js.map → FleetSection-DSETviPK.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Funnel-CL8uHONq.js → Funnel-DxiGqJrt.js} +2 -2
- package/dist/core/web/public/next/assets/{Funnel-CL8uHONq.js.map → Funnel-DxiGqJrt.js.map} +1 -1
- package/dist/core/web/public/next/assets/GearTray-C3I89sIt.js +2 -0
- package/dist/core/web/public/next/assets/{GearTray-C7k4l_BW.js.map → GearTray-C3I89sIt.js.map} +1 -1
- package/dist/core/web/public/next/assets/{GrowthSection-DwdNSGj8.js → GrowthSection-C3m2bPEz.js} +2 -2
- package/dist/core/web/public/next/assets/{GrowthSection-DwdNSGj8.js.map → GrowthSection-C3m2bPEz.js.map} +1 -1
- package/dist/core/web/public/next/assets/HandoffDialog-Bjb96a0N.js +2 -0
- package/dist/core/web/public/next/assets/{HandoffDialog-FPVOqOMN.js.map → HandoffDialog-Bjb96a0N.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Input-B9-VLcHS.js → Input-ekTehVaH.js} +2 -2
- package/dist/core/web/public/next/assets/{Input-B9-VLcHS.js.map → Input-ekTehVaH.js.map} +1 -1
- package/dist/core/web/public/next/assets/LeaderCard-85VBbbaZ.js +2 -0
- package/dist/core/web/public/next/assets/{LeaderCard-4R0BhDzT.js.map → LeaderCard-85VBbbaZ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{MatrixHeatmap-DiuushcS.js → MatrixHeatmap-Bo8j0QPC.js} +2 -2
- package/dist/core/web/public/next/assets/{MatrixHeatmap-DiuushcS.js.map → MatrixHeatmap-Bo8j0QPC.js.map} +1 -1
- package/dist/core/web/public/next/assets/McpSection-DvHFaVyp.js +2 -0
- package/dist/core/web/public/next/assets/{McpSection-CJ__OJKl.js.map → McpSection-DvHFaVyp.js.map} +1 -1
- package/dist/core/web/public/next/assets/{MessageMarkdown-qWKyJvAQ.js → MessageMarkdown-fsY_ltVa.js} +3 -3
- package/dist/core/web/public/next/assets/{MessageMarkdown-qWKyJvAQ.js.map → MessageMarkdown-fsY_ltVa.js.map} +1 -1
- package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-x05TrsrW.js → MessageMarkdownRenderer-DDdtu82l.js} +2 -2
- package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-x05TrsrW.js.map → MessageMarkdownRenderer-DDdtu82l.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Meter-D-hncpkO.js → Meter-CeGDXdDM.js} +2 -2
- package/dist/core/web/public/next/assets/{Meter-D-hncpkO.js.map → Meter-CeGDXdDM.js.map} +1 -1
- package/dist/core/web/public/next/assets/MindSection-CDVhHvXl.js +2 -0
- package/dist/core/web/public/next/assets/{MindSection-BjXHkQPS.js.map → MindSection-CDVhHvXl.js.map} +1 -1
- package/dist/core/web/public/next/assets/MutationTokenDialog-CrfJ0PdD.css +1 -0
- package/dist/core/web/public/next/assets/MutationTokenDialog-DTQzEOHR.js +2 -0
- package/dist/core/web/public/next/assets/MutationTokenDialog-DTQzEOHR.js.map +1 -0
- package/dist/core/web/public/next/assets/NeedsYouDrawer-6AuN0BF3.js +2 -0
- package/dist/core/web/public/next/assets/{NeedsYouDrawer-rSd1ZHAR.js.map → NeedsYouDrawer-6AuN0BF3.js.map} +1 -1
- package/dist/core/web/public/next/assets/{NeedsYouList-CG-nB1tr.js → NeedsYouList-ChnRmbSk.js} +2 -2
- package/dist/core/web/public/next/assets/{NeedsYouList-CG-nB1tr.js.map → NeedsYouList-ChnRmbSk.js.map} +1 -1
- package/dist/core/web/public/next/assets/NewChatDialog-B06E7sqg.js +3 -0
- package/dist/core/web/public/next/assets/{NewChatDialog-BeDQ1eW3.js.map → NewChatDialog-B06E7sqg.js.map} +1 -1
- package/dist/core/web/public/next/assets/OnboardingFlow-C2M3zov9.js +2 -0
- package/dist/core/web/public/next/assets/{OnboardingFlow-CkTZtt-m.js.map → OnboardingFlow-C2M3zov9.js.map} +1 -1
- package/dist/core/web/public/next/assets/PreviewPane-Bd6HsX1k.js +2 -0
- package/dist/core/web/public/next/assets/{PreviewPane-kzbbSK4u.js.map → PreviewPane-Bd6HsX1k.js.map} +1 -1
- package/dist/core/web/public/next/assets/ProviderLogo-Bz7KR5j3.js +2 -0
- package/dist/core/web/public/next/assets/ProviderLogo-Bz7KR5j3.js.map +1 -0
- package/dist/core/web/public/next/assets/{RailStatus-D-t2gPae.js → RailStatus-CctCuuLy.js} +2 -2
- package/dist/core/web/public/next/assets/{RailStatus-D-t2gPae.js.map → RailStatus-CctCuuLy.js.map} +1 -1
- package/dist/core/web/public/next/assets/{RefreshIndicator-BLnr9IOM.js → RefreshIndicator-CKY5BGdD.js} +2 -2
- package/dist/core/web/public/next/assets/{RefreshIndicator-BLnr9IOM.js.map → RefreshIndicator-CKY5BGdD.js.map} +1 -1
- package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-CM_8pJs6.css → ResourcePoolConsoleApp-BX9JLkT4.css} +1 -1
- package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-BeG0gBif.js → ResourcePoolConsoleApp-CspIsW_G.js} +5 -5
- package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-BeG0gBif.js.map → ResourcePoolConsoleApp-CspIsW_G.js.map} +1 -1
- package/dist/core/web/public/next/assets/ResourcesChrome-B7fHZ6zX.js +3 -0
- package/dist/core/web/public/next/assets/ResourcesChrome-B7fHZ6zX.js.map +1 -0
- package/dist/core/web/public/next/assets/ResourcesChrome-uZEqC2EM.css +1 -0
- package/dist/core/web/public/next/assets/ResourcesDrawer-B7-N9n7-.js +2 -0
- package/dist/core/web/public/next/assets/ResourcesDrawer-B7-N9n7-.js.map +1 -0
- package/dist/core/web/public/next/assets/RouteErrorBoundary-C_B11J0s.js +2 -0
- package/dist/core/web/public/next/assets/RouteErrorBoundary-C_B11J0s.js.map +1 -0
- package/dist/core/web/public/next/assets/RouteErrorBoundary-DdxhTdZ6.css +1 -0
- package/dist/core/web/public/next/assets/{RunInCloudAction-C3LBp7C4.js → RunInCloudAction-_juw4EXd.js} +2 -2
- package/dist/core/web/public/next/assets/{RunInCloudAction-C3LBp7C4.js.map → RunInCloudAction-_juw4EXd.js.map} +1 -1
- package/dist/core/web/public/next/assets/SeatSelector-D_YXvkPy.js +3 -0
- package/dist/core/web/public/next/assets/{SeatSelector-DpvvbjNm.js.map → SeatSelector-D_YXvkPy.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Segmented-BL40udoO.js → Segmented-DnKP6rr7.js} +2 -2
- package/dist/core/web/public/next/assets/{Segmented-BL40udoO.js.map → Segmented-DnKP6rr7.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Select-FWLnAw_j.js → Select-DlbUupTX.js} +2 -2
- package/dist/core/web/public/next/assets/{Select-FWLnAw_j.js.map → Select-DlbUupTX.js.map} +1 -1
- package/dist/core/web/public/next/assets/SessionGate-DnuTZACL.js +2 -0
- package/dist/core/web/public/next/assets/SessionGate-DnuTZACL.js.map +1 -0
- package/dist/core/web/public/next/assets/SessionGate-DvMpXNpJ.css +1 -0
- package/dist/core/web/public/next/assets/SessionInsightChip-C33-k-Q5.js +2 -0
- package/dist/core/web/public/next/assets/{SessionInsightChip-CWye87Ju.js.map → SessionInsightChip-C33-k-Q5.js.map} +1 -1
- package/dist/core/web/public/next/assets/{SessionSearch-YvCHFUuN.js → SessionSearch-DhhR9Csg.js} +2 -2
- package/dist/core/web/public/next/assets/{SessionSearch-YvCHFUuN.js.map → SessionSearch-DhhR9Csg.js.map} +1 -1
- package/dist/core/web/public/next/assets/SettingsSection-C0xQvCz3.js +2 -0
- package/dist/core/web/public/next/assets/SettingsSection-C0xQvCz3.js.map +1 -0
- package/dist/core/web/public/next/assets/Sheet-BvNYOYv5.js +2 -0
- package/dist/core/web/public/next/assets/{Sheet-DZKcQXQg.js.map → Sheet-BvNYOYv5.js.map} +1 -1
- package/dist/core/web/public/next/assets/ShortcutsOverlay-1nUBVO-Z.js +2 -0
- package/dist/core/web/public/next/assets/{ShortcutsOverlay-BpDimdPq.js.map → ShortcutsOverlay-1nUBVO-Z.js.map} +1 -1
- package/dist/core/web/public/next/assets/Sidebar-YrVvvBNM.js +3 -0
- package/dist/core/web/public/next/assets/{Sidebar-BoBzBEFX.js.map → Sidebar-YrVvvBNM.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Slider-DUMo9HDD.js → Slider-B2c-dbQb.js} +2 -2
- package/dist/core/web/public/next/assets/{Slider-DUMo9HDD.js.map → Slider-B2c-dbQb.js.map} +1 -1
- package/dist/core/web/public/next/assets/{StatusBadge-BwnBNFQr.js → StatusBadge-Q9YYkijx.js} +2 -2
- package/dist/core/web/public/next/assets/{StatusBadge-BwnBNFQr.js.map → StatusBadge-Q9YYkijx.js.map} +1 -1
- package/dist/core/web/public/next/assets/{StepBand-PDXMIlRk.js → StepBand-Ci-C0GUG.js} +2 -2
- package/dist/core/web/public/next/assets/{StepBand-PDXMIlRk.js.map → StepBand-Ci-C0GUG.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Surface-B3TZVoER.js → Surface-DBovMq4P.js} +2 -2
- package/dist/core/web/public/next/assets/{Surface-B3TZVoER.js.map → Surface-DBovMq4P.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Swimlane-DR4OgON_.js → Swimlane-Cdc4TqDe.js} +2 -2
- package/dist/core/web/public/next/assets/{Swimlane-DR4OgON_.js.map → Swimlane-Cdc4TqDe.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Switch-CcR5Llk5.js → Switch-CUrvzO2k.js} +2 -2
- package/dist/core/web/public/next/assets/{Switch-CcR5Llk5.js.map → Switch-CUrvzO2k.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Tag-_-K1h7Hk.js → Tag-Bv8u6APt.js} +2 -2
- package/dist/core/web/public/next/assets/{Tag-_-K1h7Hk.js.map → Tag-Bv8u6APt.js.map} +1 -1
- package/dist/core/web/public/next/assets/TerminalPane-BE4Xlqi5.js +7 -0
- package/dist/core/web/public/next/assets/{TerminalPane-_1aH4ndN.js.map → TerminalPane-BE4Xlqi5.js.map} +1 -1
- package/dist/core/web/public/next/assets/UniverseConsoleApp-BGwejf0m.js +2 -0
- package/dist/core/web/public/next/assets/{UniverseConsoleApp-BUsq-inZ.js.map → UniverseConsoleApp-BGwejf0m.js.map} +1 -1
- package/dist/core/web/public/next/assets/{UniverseConsoleApp-Dh7A-hLD.css → UniverseConsoleApp-DfuT-wFw.css} +1 -1
- package/dist/core/web/public/next/assets/{UniverseView-Dogy_dsB.js → UniverseView-CgKa-WXC.js} +4 -4
- package/dist/core/web/public/next/assets/{UniverseView-Dogy_dsB.js.map → UniverseView-CgKa-WXC.js.map} +1 -1
- package/dist/core/web/public/next/assets/UsageSection-CazsHm1f.js +2 -0
- package/dist/core/web/public/next/assets/{UsageSection-DiX_dTyo.js.map → UsageSection-CazsHm1f.js.map} +1 -1
- package/dist/core/web/public/next/assets/VerseConsoleApp-CTF3Shs0.js +3 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-CTF3Shs0.js.map +1 -0
- package/dist/core/web/public/next/assets/Workspace-CgdyXiEV.js +10 -0
- package/dist/core/web/public/next/assets/Workspace-CgdyXiEV.js.map +1 -0
- package/dist/core/web/public/next/assets/Workspace-Dwri2jFJ.css +1 -0
- package/dist/core/web/public/next/assets/actions-MtxBGS5B.js +2 -0
- package/dist/core/web/public/next/assets/{actions-s2lfm_5k.js.map → actions-MtxBGS5B.js.map} +1 -1
- package/dist/core/web/public/next/assets/budget-queries-CP7hgR-p.js +2 -0
- package/dist/core/web/public/next/assets/{budget-queries-wUshcovN.js.map → budget-queries-CP7hgR-p.js.map} +1 -1
- package/dist/core/web/public/next/assets/{capacity-strip-model-Bj_9ztzs.js → capacity-strip-model-fHfu5cph.js} +2 -2
- package/dist/core/web/public/next/assets/{capacity-strip-model-Bj_9ztzs.js.map → capacity-strip-model-fHfu5cph.js.map} +1 -1
- package/dist/core/web/public/next/assets/{charts-CMSgAUKn.js → charts-Bis9WSiS.js} +2 -2
- package/dist/core/web/public/next/assets/{charts-CMSgAUKn.js.map → charts-Bis9WSiS.js.map} +1 -1
- package/dist/core/web/public/next/assets/cloud-queries-BsOepFz6.js +2 -0
- package/dist/core/web/public/next/assets/{cloud-queries-CnV1yaNG.js.map → cloud-queries-BsOepFz6.js.map} +1 -1
- package/dist/core/web/public/next/assets/{cloud.module-CiwatLj3.js → cloud.module-DoFnr8ZH.js} +2 -2
- package/dist/core/web/public/next/assets/{cloud.module-CiwatLj3.js.map → cloud.module-DoFnr8ZH.js.map} +1 -1
- package/dist/core/web/public/next/assets/{command-bus-DqimKCUY.js → command-bus-CMvbYP5K.js} +2 -2
- package/dist/core/web/public/next/assets/{command-bus-DqimKCUY.js.map → command-bus-CMvbYP5K.js.map} +1 -1
- package/dist/core/web/public/next/assets/command-catalog-Bb_PxC5w.js +2 -0
- package/dist/core/web/public/next/assets/command-catalog-Bb_PxC5w.js.map +1 -0
- package/dist/core/web/public/next/assets/compaction-point-VL9oegWS.js +2 -0
- package/dist/core/web/public/next/assets/compaction-point-VL9oegWS.js.map +1 -0
- package/dist/core/web/public/next/assets/{composer-keys-DBRymxQn.js → composer-keys-su0g1h9o.js} +2 -2
- package/dist/core/web/public/next/assets/{composer-keys-DBRymxQn.js.map → composer-keys-su0g1h9o.js.map} +1 -1
- package/dist/core/web/public/next/assets/context-model-Ci3Ch9t5.js +2 -0
- package/dist/core/web/public/next/assets/{context-model-Dwd49-dp.js.map → context-model-Ci3Ch9t5.js.map} +1 -1
- package/dist/core/web/public/next/assets/context-model-CjiJTnf1.js +2 -0
- package/dist/core/web/public/next/assets/{context-model-MT17V86_.js.map → context-model-CjiJTnf1.js.map} +1 -1
- package/dist/core/web/public/next/assets/context-queries-BDXT6LQ3.js +2 -0
- package/dist/core/web/public/next/assets/{context-queries-xVKIeynP.js.map → context-queries-BDXT6LQ3.js.map} +1 -1
- package/dist/core/web/public/next/assets/control-queries-Dv-h1Clu.js +2 -0
- package/dist/core/web/public/next/assets/{control-queries-DOZR-D8G.js.map → control-queries-Dv-h1Clu.js.map} +1 -1
- package/dist/core/web/public/next/assets/{dock-icons-8EtARwUm.js → dock-icons-t--Eugrd.js} +2 -2
- package/dist/core/web/public/next/assets/{dock-icons-8EtARwUm.js.map → dock-icons-t--Eugrd.js.map} +1 -1
- package/dist/core/web/public/next/assets/{dock-store-BA1cHOYA.js → dock-store-qIu7kSQE.js} +2 -2
- package/dist/core/web/public/next/assets/{dock-store-BA1cHOYA.js.map → dock-store-qIu7kSQE.js.map} +1 -1
- package/dist/core/web/public/next/assets/{fleet-model-CNe8Wh-s.js → fleet-model-IRbwfhkR.js} +2 -2
- package/dist/core/web/public/next/assets/{fleet-model-CNe8Wh-s.js.map → fleet-model-IRbwfhkR.js.map} +1 -1
- package/dist/core/web/public/next/assets/fleet-queries-7FVNByX1.js +2 -0
- package/dist/core/web/public/next/assets/{fleet-queries-BSdRlUwJ.js.map → fleet-queries-7FVNByX1.js.map} +1 -1
- package/dist/core/web/public/next/assets/focus-trap-QqQxQdvH.js +2 -0
- package/dist/core/web/public/next/assets/focus-trap-QqQxQdvH.js.map +1 -0
- package/dist/core/web/public/next/assets/{format-B8DAVcn2.js → format-CaMmVQCn.js} +2 -2
- package/dist/core/web/public/next/assets/{format-B8DAVcn2.js.map → format-CaMmVQCn.js.map} +1 -1
- package/dist/core/web/public/next/assets/git-model-B4S_GUNA.js +5 -0
- package/dist/core/web/public/next/assets/{git-model-CivuBY_D.js.map → git-model-B4S_GUNA.js.map} +1 -1
- package/dist/core/web/public/next/assets/global-BkNl4e6E.js +2 -0
- package/dist/core/web/public/next/assets/global-BkNl4e6E.js.map +1 -0
- package/dist/core/web/public/next/assets/global-BlI2BYa1.css +1 -0
- package/dist/core/web/public/next/assets/guarded-action-DHiL8tY5.js +3 -0
- package/dist/core/web/public/next/assets/guarded-action-DHiL8tY5.js.map +1 -0
- package/dist/core/web/public/next/assets/guarded-runners-DmGEkM2P.js +2 -0
- package/dist/core/web/public/next/assets/guarded-runners-DmGEkM2P.js.map +1 -0
- package/dist/core/web/public/next/assets/icon-base-NtFmP2yB.js +2 -0
- package/dist/core/web/public/next/assets/icon-base-NtFmP2yB.js.map +1 -0
- package/dist/core/web/public/next/assets/icons-C5EFt_Ts.js +2 -0
- package/dist/core/web/public/next/assets/icons-C5EFt_Ts.js.map +1 -0
- package/dist/core/web/public/next/assets/{index-oAAq8XJa.js → index-DbDw9UAs.js} +3 -3
- package/dist/core/web/public/next/assets/{index-oAAq8XJa.js.map → index-DbDw9UAs.js.map} +1 -1
- package/dist/core/web/public/next/assets/{live-model-DCw_IFRI.js → live-model-DEwrl7_A.js} +2 -2
- package/dist/core/web/public/next/assets/{live-model-DCw_IFRI.js.map → live-model-DEwrl7_A.js.map} +1 -1
- package/dist/core/web/public/next/assets/{mind.module-vnuJcwvD.js → mind.module-CLhqMQak.js} +2 -2
- package/dist/core/web/public/next/assets/{mind.module-vnuJcwvD.js.map → mind.module-CLhqMQak.js.map} +1 -1
- package/dist/core/web/public/next/assets/mutations-Kvzsg-iK.js +2 -0
- package/dist/core/web/public/next/assets/{mutations-Dpsql5t7.js.map → mutations-Kvzsg-iK.js.map} +1 -1
- package/dist/core/web/public/next/assets/nav-C0IunEYF.js +2 -0
- package/dist/core/web/public/next/assets/nav-C0IunEYF.js.map +1 -0
- package/dist/core/web/public/next/assets/overnight-queries-C_AfcL7q.js +2 -0
- package/dist/core/web/public/next/assets/{overnight-queries-X-44Gsw5.js.map → overnight-queries-C_AfcL7q.js.map} +1 -1
- package/dist/core/web/public/next/assets/preloaded-CctOitLu.js +2 -0
- package/dist/core/web/public/next/assets/preloaded-CctOitLu.js.map +1 -0
- package/dist/core/web/public/next/assets/primitives-CbAGCNKt.js +1 -0
- package/dist/core/web/public/next/assets/{queries-BA4rNGD-.js → queries-THD05gHP.js} +2 -2
- package/dist/core/web/public/next/assets/{queries-BA4rNGD-.js.map → queries-THD05gHP.js.map} +1 -1
- package/dist/core/web/public/next/assets/reasoning-pref-BVPu0SME.js +2 -0
- package/dist/core/web/public/next/assets/{reasoning-pref-B9-DJUXP.js.map → reasoning-pref-BVPu0SME.js.map} +1 -1
- package/dist/core/web/public/next/assets/reveal-anchor-wCT5b4m3.js +2 -0
- package/dist/core/web/public/next/assets/reveal-anchor-wCT5b4m3.js.map +1 -0
- package/dist/core/web/public/next/assets/seat-subscription-CR_VylsK.js +2 -0
- package/dist/core/web/public/next/assets/{seat-subscription-CH6fW4fJ.js.map → seat-subscription-CR_VylsK.js.map} +1 -1
- package/dist/core/web/public/next/assets/{section-visibility-qFqc_d4Z.js → section-visibility-B0xXUQJ0.js} +2 -2
- package/dist/core/web/public/next/assets/{section-visibility-qFqc_d4Z.js.map → section-visibility-B0xXUQJ0.js.map} +1 -1
- package/dist/core/web/public/next/assets/{sidebar-model-M1GaQU5l.js → sidebar-model-C5wVXGpb.js} +2 -2
- package/dist/core/web/public/next/assets/{sidebar-model-M1GaQU5l.js.map → sidebar-model-C5wVXGpb.js.map} +1 -1
- package/dist/core/web/public/next/assets/slots-DDd8cEoh.js +3 -0
- package/dist/core/web/public/next/assets/{slots-Ds9ZIqUL.js.map → slots-DDd8cEoh.js.map} +1 -1
- package/dist/core/web/public/next/assets/surface-data-BFxAlefI.js +2 -0
- package/dist/core/web/public/next/assets/{surface-data-J52iIGMD.js.map → surface-data-BFxAlefI.js.map} +1 -1
- package/dist/core/web/public/next/assets/surface-prefetch-CHusyO9q.js +2 -0
- package/dist/core/web/public/next/assets/{surface-prefetch-CgZ-LEJK.js.map → surface-prefetch-CHusyO9q.js.map} +1 -1
- package/dist/core/web/public/next/assets/{tasks-model-ent8f0jZ.js → tasks-model-DvkWveXs.js} +2 -2
- package/dist/core/web/public/next/assets/{tasks-model-ent8f0jZ.js.map → tasks-model-DvkWveXs.js.map} +1 -1
- package/dist/core/web/public/next/assets/{terminal-icons-DJTK7QpR.js → terminal-icons-Dp6pJgV2.js} +2 -2
- package/dist/core/web/public/next/assets/{terminal-icons-DJTK7QpR.js.map → terminal-icons-Dp6pJgV2.js.map} +1 -1
- package/dist/core/web/public/next/assets/{usage-queries-Bn8ccqyN.js → usage-queries-CUTmnegA.js} +2 -2
- package/dist/core/web/public/next/assets/{usage-queries-Bn8ccqyN.js.map → usage-queries-CUTmnegA.js.map} +1 -1
- package/dist/core/web/public/next/assets/use-guarded-action-UCX2u1t1.js +2 -0
- package/dist/core/web/public/next/assets/{use-guarded-action-C2HlSzkz.js.map → use-guarded-action-UCX2u1t1.js.map} +1 -1
- package/dist/core/web/public/next/assets/{use-ticker-BNc1H4ZC.js → use-ticker-OXAjob3y.js} +2 -2
- package/dist/core/web/public/next/assets/{use-ticker-BNc1H4ZC.js.map → use-ticker-OXAjob3y.js.map} +1 -1
- package/dist/core/web/public/next/assets/use-token-gate-CDDRAoKH.js +2 -0
- package/dist/core/web/public/next/assets/{use-token-gate-B3IJL6bf.js.map → use-token-gate-CDDRAoKH.js.map} +1 -1
- package/dist/core/web/public/next/assets/useChartWidth-BW6SwYIK.css +1 -0
- package/dist/core/web/public/next/assets/useChartWidth-D9M7kUw7.js +2 -0
- package/dist/core/web/public/next/assets/{useChartWidth-lZ9PrQn0.js.map → useChartWidth-D9M7kUw7.js.map} +1 -1
- package/dist/core/web/public/next/assets/{useSeatsRefresh-CG4jczeL.js → useSeatsRefresh-B2dCVcj9.js} +2 -2
- package/dist/core/web/public/next/assets/{useSeatsRefresh-CG4jczeL.js.map → useSeatsRefresh-B2dCVcj9.js.map} +1 -1
- package/dist/core/web/public/next/assets/useVerseTranscript-BL3CljSI.js +2 -0
- package/dist/core/web/public/next/assets/useVerseTranscript-BL3CljSI.js.map +1 -0
- package/dist/core/web/public/next/assets/verse-icons-DASWdYuE.js +2 -0
- package/dist/core/web/public/next/assets/verse-icons-DASWdYuE.js.map +1 -0
- package/dist/core/web/public/next/assets/verse-model-BQ0Y2CSr.js +2 -0
- package/dist/core/web/public/next/assets/verse-model-BQ0Y2CSr.js.map +1 -0
- package/dist/core/web/public/next/assets/verse-store-b_Lek_c5.js +3 -0
- package/dist/core/web/public/next/assets/verse-store-b_Lek_c5.js.map +1 -0
- package/dist/core/web/public/next/assets/verse-ui-store-D7YXi63q.js +3 -0
- package/dist/core/web/public/next/assets/{verse-ui-store-zafyzXKD.js.map → verse-ui-store-D7YXi63q.js.map} +1 -1
- package/dist/core/web/public/next/assets/{viewport-BEqGUoTA.js → viewport-BYGH5EgA.js} +2 -2
- package/dist/core/web/public/next/assets/{viewport-BEqGUoTA.js.map → viewport-BYGH5EgA.js.map} +1 -1
- package/dist/core/web/public/next/assets/warmup-AsqwWCUi.js +3 -0
- package/dist/core/web/public/next/assets/{warmup-BR6pxAKs.js.map → warmup-AsqwWCUi.js.map} +1 -1
- package/dist/core/web/public/next/assets/{workspace-model-D_tWD5Wt.js → workspace-model-CXorJr0G.js} +2 -2
- package/dist/core/web/public/next/assets/{workspace-model-D_tWD5Wt.js.map → workspace-model-CXorJr0G.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 +5 -2
- package/dist/cli/activation.d.ts +0 -41
- package/dist/cli/activation.js +0 -485
- package/dist/cli/activation.js.map +0 -1
- package/dist/core/fleet/generated-repair-resolution.d.ts +0 -36
- package/dist/core/fleet/generated-repair-resolution.js +0 -245
- package/dist/core/fleet/generated-repair-resolution.js.map +0 -1
- package/dist/core/local-runtime/llama/port.d.ts +0 -17
- package/dist/core/local-runtime/llama/port.js +0 -47
- package/dist/core/local-runtime/llama/port.js.map +0 -1
- package/dist/core/local-runtime/llama/proxy-host.d.ts +0 -54
- package/dist/core/local-runtime/llama/proxy-host.js +0 -159
- package/dist/core/local-runtime/llama/proxy-host.js.map +0 -1
- package/dist/core/local-runtime/llama/proxy-process.d.ts +0 -148
- package/dist/core/local-runtime/llama/proxy-process.js +0 -250
- package/dist/core/local-runtime/llama/proxy-process.js.map +0 -1
- package/dist/core/local-runtime/llama/proxy-record.d.ts +0 -40
- package/dist/core/local-runtime/llama/proxy-record.js +0 -133
- package/dist/core/local-runtime/llama/proxy-record.js.map +0 -1
- package/dist/core/local-runtime/llama/proxy-supervisor.d.ts +0 -118
- package/dist/core/local-runtime/llama/proxy-supervisor.js +0 -511
- package/dist/core/local-runtime/llama/proxy-supervisor.js.map +0 -1
- package/dist/core/web/public/next/assets/Advanced-DEM93sKI.js +0 -2
- package/dist/core/web/public/next/assets/App-CimXmK0L.js +0 -7
- package/dist/core/web/public/next/assets/AppsSection-D6U-dSj6.js +0 -2
- package/dist/core/web/public/next/assets/AutonomySection-3V9pUyxm.js +0 -2
- package/dist/core/web/public/next/assets/BranchBar-U8UdpfEB.js +0 -2
- package/dist/core/web/public/next/assets/CapacityStrip-C667yQe8.js +0 -2
- package/dist/core/web/public/next/assets/CapacityStrip-C667yQe8.js.map +0 -1
- package/dist/core/web/public/next/assets/ChatSection-CCcIPpOq.js +0 -3
- package/dist/core/web/public/next/assets/ChatSection-CCcIPpOq.js.map +0 -1
- package/dist/core/web/public/next/assets/CommandPalette-FiD4N8XD.js +0 -2
- package/dist/core/web/public/next/assets/CommandSection-DN8KwH-X.js +0 -2
- package/dist/core/web/public/next/assets/DockHost-DvR-hPhZ.js +0 -2
- package/dist/core/web/public/next/assets/FleetSection-D_zRBCub.js +0 -3
- package/dist/core/web/public/next/assets/GearTray-C7k4l_BW.js +0 -2
- package/dist/core/web/public/next/assets/HandoffDialog-FPVOqOMN.js +0 -2
- package/dist/core/web/public/next/assets/LeaderCard-4R0BhDzT.js +0 -2
- package/dist/core/web/public/next/assets/McpSection-CJ__OJKl.js +0 -2
- package/dist/core/web/public/next/assets/MindSection-BjXHkQPS.js +0 -2
- package/dist/core/web/public/next/assets/MutationTokenDialog-Cum_DqQZ.css +0 -1
- package/dist/core/web/public/next/assets/MutationTokenDialog-SkRxqV_I.js +0 -2
- package/dist/core/web/public/next/assets/MutationTokenDialog-SkRxqV_I.js.map +0 -1
- package/dist/core/web/public/next/assets/NeedsYouDrawer-rSd1ZHAR.js +0 -2
- package/dist/core/web/public/next/assets/NewChatDialog-BeDQ1eW3.js +0 -3
- package/dist/core/web/public/next/assets/OnboardingFlow-CkTZtt-m.js +0 -2
- package/dist/core/web/public/next/assets/PreviewPane-kzbbSK4u.js +0 -2
- package/dist/core/web/public/next/assets/ResourcesChrome-B3Z3O98t.css +0 -1
- package/dist/core/web/public/next/assets/ResourcesChrome-BzV6bkIa.js +0 -3
- package/dist/core/web/public/next/assets/ResourcesChrome-BzV6bkIa.js.map +0 -1
- package/dist/core/web/public/next/assets/ResourcesDrawer-o4ILHdep.js +0 -2
- package/dist/core/web/public/next/assets/ResourcesDrawer-o4ILHdep.js.map +0 -1
- package/dist/core/web/public/next/assets/RouteErrorBoundary-6RMd_aZg.css +0 -1
- package/dist/core/web/public/next/assets/RouteErrorBoundary-C5SxA2Dg.js +0 -2
- package/dist/core/web/public/next/assets/RouteErrorBoundary-C5SxA2Dg.js.map +0 -1
- package/dist/core/web/public/next/assets/SeatSelector-DpvvbjNm.js +0 -3
- package/dist/core/web/public/next/assets/SessionInsightChip-CWye87Ju.js +0 -2
- package/dist/core/web/public/next/assets/SettingsSection-Dr18upeE.js +0 -2
- package/dist/core/web/public/next/assets/SettingsSection-Dr18upeE.js.map +0 -1
- package/dist/core/web/public/next/assets/Sheet-DZKcQXQg.js +0 -2
- package/dist/core/web/public/next/assets/ShortcutsOverlay-BpDimdPq.js +0 -2
- package/dist/core/web/public/next/assets/Sidebar-BoBzBEFX.js +0 -3
- package/dist/core/web/public/next/assets/TerminalPane-_1aH4ndN.js +0 -7
- package/dist/core/web/public/next/assets/UniverseConsoleApp-BUsq-inZ.js +0 -2
- package/dist/core/web/public/next/assets/UsageSection-DiX_dTyo.js +0 -2
- package/dist/core/web/public/next/assets/VerseConsoleApp-WVeyJnW7.js +0 -3
- package/dist/core/web/public/next/assets/VerseConsoleApp-WVeyJnW7.js.map +0 -1
- package/dist/core/web/public/next/assets/Workspace-BYW9dm90.css +0 -1
- package/dist/core/web/public/next/assets/Workspace-BbxZHwQd.js +0 -10
- package/dist/core/web/public/next/assets/Workspace-BbxZHwQd.js.map +0 -1
- package/dist/core/web/public/next/assets/actions-s2lfm_5k.js +0 -2
- package/dist/core/web/public/next/assets/budget-queries-wUshcovN.js +0 -2
- package/dist/core/web/public/next/assets/cloud-queries-CnV1yaNG.js +0 -2
- package/dist/core/web/public/next/assets/command-catalog-BdtDH93o.js +0 -2
- package/dist/core/web/public/next/assets/command-catalog-BdtDH93o.js.map +0 -1
- package/dist/core/web/public/next/assets/context-model-Dwd49-dp.js +0 -2
- package/dist/core/web/public/next/assets/context-model-MT17V86_.js +0 -2
- package/dist/core/web/public/next/assets/context-queries-xVKIeynP.js +0 -2
- package/dist/core/web/public/next/assets/control-queries-DOZR-D8G.js +0 -2
- package/dist/core/web/public/next/assets/dock-panes-UKS-mXhr.js +0 -2
- package/dist/core/web/public/next/assets/dock-panes-UKS-mXhr.js.map +0 -1
- package/dist/core/web/public/next/assets/fleet-queries-BSdRlUwJ.js +0 -2
- package/dist/core/web/public/next/assets/git-model-CivuBY_D.js +0 -5
- package/dist/core/web/public/next/assets/global-Di2PUgj4.js +0 -2
- package/dist/core/web/public/next/assets/global-Di2PUgj4.js.map +0 -1
- package/dist/core/web/public/next/assets/global-_tOCFt9y.css +0 -1
- package/dist/core/web/public/next/assets/guarded-action-CvOHcqyH.js +0 -2
- package/dist/core/web/public/next/assets/guarded-action-CvOHcqyH.js.map +0 -1
- package/dist/core/web/public/next/assets/icons-B_yuAgdN.js +0 -2
- package/dist/core/web/public/next/assets/icons-B_yuAgdN.js.map +0 -1
- package/dist/core/web/public/next/assets/mutations-Dpsql5t7.js +0 -2
- package/dist/core/web/public/next/assets/overnight-queries-X-44Gsw5.js +0 -2
- package/dist/core/web/public/next/assets/primitives-BDIcUvob.js +0 -1
- package/dist/core/web/public/next/assets/reasoning-pref-B9-DJUXP.js +0 -2
- package/dist/core/web/public/next/assets/seat-subscription-CH6fW4fJ.js +0 -2
- package/dist/core/web/public/next/assets/slots-Ds9ZIqUL.js +0 -3
- package/dist/core/web/public/next/assets/surface-data-J52iIGMD.js +0 -2
- package/dist/core/web/public/next/assets/surface-prefetch-CgZ-LEJK.js +0 -2
- package/dist/core/web/public/next/assets/use-guarded-action-C2HlSzkz.js +0 -2
- package/dist/core/web/public/next/assets/use-token-gate-B3IJL6bf.js +0 -2
- package/dist/core/web/public/next/assets/useActivity-Bk3XgXjL.js +0 -2
- package/dist/core/web/public/next/assets/useActivity-Bk3XgXjL.js.map +0 -1
- package/dist/core/web/public/next/assets/useChartWidth-BAtVgn2n.css +0 -1
- package/dist/core/web/public/next/assets/useChartWidth-lZ9PrQn0.js +0 -2
- package/dist/core/web/public/next/assets/verse-model-D7NZQFAR.js +0 -2
- package/dist/core/web/public/next/assets/verse-model-D7NZQFAR.js.map +0 -1
- package/dist/core/web/public/next/assets/verse-queries-DvIJcn6Z.js +0 -2
- package/dist/core/web/public/next/assets/verse-queries-DvIJcn6Z.js.map +0 -1
- package/dist/core/web/public/next/assets/verse-store-DjBWj04q.js +0 -3
- package/dist/core/web/public/next/assets/verse-store-DjBWj04q.js.map +0 -1
- package/dist/core/web/public/next/assets/verse-ui-store-zafyzXKD.js +0 -3
- package/dist/core/web/public/next/assets/warmup-BR6pxAKs.js +0 -3
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{_ as e,o as t}from"./colors-BZ3a9wFf.js";import{y as n}from"./format-
|
|
2
|
-
//# sourceMappingURL=live-model-
|
|
1
|
+
import{_ as e,o as t}from"./colors-BZ3a9wFf.js";import{y as n}from"./format-CaMmVQCn.js";var r=new Set([`headroom`,`switched-off`,`signed-out`,`unreachable`,`spent`,`reserve`,`session-ceiling`,`unknown-usage`,`spend-cap`,`model-window`,`context`,`grant`,`lane`,`demoted`,`other`]);function i(e){let t=e.trim().replace(/[\s;,:]+$/,``);return t?/[.!?…]$/.test(t)?t:`${t}.`:``}function a(e){return e.map(i).filter(Boolean).join(` `)}function o(e){return e.length<=1?e[0]??``:`${e.slice(0,-1).join(`, `)} and ${e[e.length-1]}`}var s=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/,c=/\b\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d{1,9})?)?(?:Z|[+-]\d{2}:?\d{2})?(?![\w:])/g;function l(e,t=Date.now()){return e.replace(c,e=>n(e,t)??e)}function u(e){return typeof e==`string`&&s.test(e)&&Number.isFinite(Date.parse(e))}function d(e){return/^autonomy is switched off/i.test(e)?`switched-off`:/^signed out/i.test(e)?`signed-out`:/not reachable/i.test(e)?`unreachable`:/limits that model only/.test(e)?`model-window`:/ is spent — /.test(e)?`spent`:/is kept for you, so autonomy stops at/.test(e)?`reserve`:/used; autonomy stops at .* to protect your live session/.test(e)?`session-ceiling`:/unknown usage is not headroom|too stale to spend against|too uncertain to spend against/.test(e)?`unknown-usage`:/daily cap/.test(e)?`spend-cap`:/tokens of context/.test(e)?`context`:/is demoted/.test(e)?`demoted`:/\bgrant\b/i.test(e)?`grant`:/\blanes?\b|\bslots?\b|producer slice is held/i.test(e)?`lane`:`other`}var f=[[/(?<![\w-])grok-cli(?![\w-])/g,`Grok`],[/(?<![\w-])claude-cli(?![\w-])/g,`Claude`],[/(?<![\w-])codex(?![\w-])/g,`Codex`]];function p(e){let t=e.trim();t=t.replace(/^Codex lanes stay off until the Leader enables them\b/,`Codex stays off until the Leader turns it on`),t=t.replace(/\s*\(an? class-([A-Za-z])\s+action\)/g,(e,t)=>/^[ab]$/i.test(t)?` (you can veto it)`:``),t=t.replace(/\b(\d+)((?:\s+[A-Za-z-]+)*?)\s+([A-Za-z]+)\(s\)/g,(e,t,n,r)=>`${t}${n} ${r}${Number(t)===1?``:`s`}`),t=t.replace(/\b([A-Za-z]+)\(s\)/g,`$1s`);for(let[e,n]of f)t=t.replace(e,n);return t}function m(e){let t=e.trim(),n=/^([\s\S]*?) \(resets ([\s\S]+)\)\.?$/.exec(t),r=n?`${n[1]}.`:t,i=n?n[2].trim():null,a=u(i)?i:null,o=/ is demoted until (\S+): /.exec(r);return o&&u(o[1])&&(a=o[1],r=r.replace(` until ${o[1]}:`,`:`)),{kind:d(r),text:r,resetsAt:a,resetDescription:i!==null&&!u(i)?i:null}}function h(e){return Array.isArray(e.details)&&(e.details.length>0||e.reasons.length===0)?e.details.map(e=>r.has(e.kind)?e:{...e,kind:`other`}):e.reasons.map(m)}function g(e){return a(h(e).filter(e=>e.kind!==`headroom`).map(e=>e.kind===`lane`?p(e.text):e.text))}var _={"switched-off":`you switch autonomy on for this seat`,"signed-out":`you reconnect this account`,unreachable:`it is reachable again`,"unknown-usage":`a fresh usage reading arrives`,"spend-cap":`its daily spend cap resets`,grant:`the standing grant allows it`,lane:`its lane has a free slot`},v=new Set([`spent`,`reserve`,`session-ceiling`,`demoted`]);function y(e){return e.trim().replace(/^resets\s+/i,``)}function b(e){let t=[],n=[],r=null,i=!1,a=null;for(let o of h(e)){if(o.kind===`context`){a=`not for this task — it needs a larger context window than this seat has`;continue}let e=_[o.kind];if(e&&!t.includes(e)&&t.push(e),v.has(o.kind)){if(u(o.resetsAt))(r===null||Date.parse(o.resetsAt)>Date.parse(r))&&(r=o.resetsAt);else if(o.resetDescription){let e=y(o.resetDescription);n.includes(e)||n.push(e)}else i=!0}}return r===null&&n.length===0&&u(e.nextEligibleAt)&&(r=e.nextEligibleAt,i=!1),{conditions:t,at:r,prose:n,timeUnknown:i,never:a}}function x(e,t=Date.now()){if(e.never)return e.never;let r=[...e.at?[n(e.at,t)??e.at]:[],...e.prose],i=r.length>0?r.join(` and `):null,a=e.conditions.length>0?`when ${o(e.conditions)}`:null;return a&&i?`${a}, not before ${i}`:a||i||`unknown`}var S=/^Routed (?:autonomous )?[\w-]+-difficulty \w+ work to (.+?) \(([^()]+)\)(?: with (\d+)% of its (5-hour|weekly) window left for autonomy| (at no cost))?: ([\w-]+) mode prefers (.+?) first for this work(?:; held back [\s\S]*)?\.$/,C=/^(No seat (?:the grant lets produce )?can take [\s\S]*?) \([\s\S]*\)(?:; the earliest known reopening is \S+)?\.$/;function w(e){let t=e.trim(),n=S.exec(t);if(n){let[,e,,t,r,i,a,o]=n,s=t?` — ${t}% of its ${r} window left`:i?` — free, no usage window`:``;return s?`${e}${s}; ${a} mode prefers ${o} for this work.`:`${e} — ${a} mode prefers ${o} for this work.`}let r=C.exec(t);return r?`${r[1]}.`:t}function T(e){let t=i(e.summary??w(e.why)),n=e.exclusions.length;return n===0?t:`${t} ${n===1?`1 seat`:`${n} seats`} held back.`}var E={local:`local`,"grok-cli":`grok`,"claude-cli":`claude`,codex:`codex`},D={local:`Local`,"grok-cli":`Grok`,"claude-cli":`Claude`,codex:`Codex`};function O(e){return{name:D[e.lane],slots:e.slots===0?`off`:`${e.busy}/${e.slots}`}}function k(e){let t=e.capReason?.trim();return t?p(t):null}function A(e){let t=new Map;for(let n of e){let e=k(n);if(!e)continue;let r=t.get(e)??[];r.push(n.lane),t.set(e,r)}return[...t.entries()].map(([t,n])=>({lanes:n,all:n.length===e.length&&e.length>1,reason:t}))}function j(e){return e.phase===`queued`||e.phase===`parked`?e.phase:e.phase===`reverting`?`reverting`:e.outcome??e.phase}var M={producing:`running`,verifying:`running`,judging:`running`,landing:`running`,watching:`info`,reverting:`danger`,merged:`success`,proposed:`info`,"owner-lane":`warning`,refused:`warning`,failed:`danger`,reverted:`danger`,cancelled:`neutral`,queued:`neutral`,parked:`neutral`};function N(e){return M[e]??`unknown`}function P(e){let t=Date.parse(e.startedAt??e.phaseStartedAt??``);return Number.isFinite(t)?t:null}function F(e){if(!e.endedAt)return null;let t=Date.parse(e.endedAt);return Number.isFinite(t)?t:null}function I(e){return[e.repo.includes(`/`)?e.repo.split(`/`)[1]:e.repo,e.title,e.model,e.prNumber?`PR #${e.prNumber}`:null].filter(Boolean).join(` · `)}var L=[`local`,`grok-cli`,`claude-cli`,`codex`,`none`];function R(e,t,n,r={}){let i=r.includeParked??!0,a=new Map;for(let r of e){if(!i&&r.phase===`parked`)continue;let e=P(r);if(e===null||(F(r)??n)<t||e>n)continue;let o=r.lane??`none`;a.has(o)||a.set(o,[]),a.get(o).push(r)}let o=[];for(let e of L){let t=a.get(e);if(!t?.length)continue;t.sort((e,t)=>P(e)-P(t));let r=[],i=[];for(let e of t){let t=P(e),a=F(e)??n,o=r.findIndex(e=>e<=t);o===-1?(o=r.length,r.push(a),i.push([])):r[o]=a,i[o].push(e)}let s=e===`none`?`Unassigned`:D[e];i.forEach((t,n)=>{o.push({id:`${e}:${n}`,label:i.length>1?`${s} · ${n+1}`:s,...e===`none`?{}:{engine:E[e]},items:t.map(e=>({id:e.id,start:P(e),end:F(e),status:j(e),detail:I(e)}))})})}return o}function z(e,t){let n=e.filter(e=>e.phase===`parked`||e.hold!==null),r=n.map(e=>e.hold?.nextEligibleAt?Date.parse(e.hold.nextEligibleAt):NaN).filter(Number.isFinite),i=n.map(e=>P(e)??t),a=Math.min(t-36e5,...i),o=Math.min(t+1728e5,Math.max(t+72e5,...r)),s=0;return{lanes:n.map(e=>{let n=e.hold?.nextEligibleAt?Date.parse(e.hold.nextEligibleAt):NaN;Number.isFinite(n)||s++;let r=e.repo.includes(`/`)?e.repo.split(`/`)[1]:e.repo;return{id:e.id,label:`${r}: ${e.title}`,...e.lane?{engine:E[e.lane]}:{},items:[{id:e.id,start:P(e)??t,end:Number.isFinite(n)?n:null,status:e.hold?.kind===`split`?`split`:`parked`,outline:!0,detail:`${l(e.hold?.reason??`parked`,t)}${Number.isFinite(n)?``:` · release time unknown`}`}]}}),from:a,to:o,unknownRelease:s}}var B={G0:`Authority`,G1:`Protected paths`,G1b:`Tamper`,G2:`Scope`,G3:`Verify`,G4:`Claims`,G5:`Blast radius`,G6:`Judge`,G7:`GitHub checks`};function V(e){return!e||e.stages.length===0?[]:[{id:`entered`,label:`Proposals`,value:e.stages[0].entered},...e.stages.map(e=>({id:e.gate,label:`${e.gate} ${B[e.gate]??``}`.trim(),value:e.passed}))]}function H(n,r=5){if(!n)return{categories:[],segments:[],values:[],total:0};let i=new Map;for(let e of n.stages)for(let t of e.refusals){let e=i.get(t.code);i.set(t.code,{reason:e?.reason??t.reason,count:(e?.count??0)+t.count})}let a=[...i.entries()].sort((e,t)=>t[1].count-e[1].count||e[0].localeCompare(t[0])),o=a.slice(0,r).map(([e])=>e),s=a.length>r,c=[...o.map((t,n)=>({id:t,label:i.get(t).reason,color:e(n)})),...s?[{id:`__other`,label:`Other reasons`,color:t}]:[]],l=n.stages.filter(e=>e.refusals.length>0||e.entered!==e.passed);return{categories:l.map(e=>e.gate),segments:c,values:l.map(e=>{let t=o.map(t=>e.refusals.find(e=>e.code===t)?.count??0);return s&&t.push(e.refusals.filter(e=>!o.includes(e.code)).reduce((e,t)=>e+t.count,0)),t}),total:a.reduce((e,[,t])=>e+t.count,0)}}function U(e){if(!e)return null;let t=e.runs.filter(e=>e.seatDecision!==null);if(!t.length)return null;t.sort((e,t)=>(P(t)??0)-(P(e)??0));let n=t[0];return{decision:n.seatDecision,run:n}}export{l as _,A as a,U as c,N as d,i as f,g,b as h,O as i,z as l,x as m,D as n,k as o,T as p,V as r,R as s,E as t,H as u,m as v};
|
|
2
|
+
//# sourceMappingURL=live-model-DEwrl7_A.js.map
|
package/dist/core/web/public/next/assets/{live-model-DCw_IFRI.js.map → live-model-DEwrl7_A.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"live-model-DCw_IFRI.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/fleet/why-seat-model.ts","../../../../../../src/web-ui/routes/verse/fleet/live-model.ts"],"sourcesContent":["/**\n * routes/verse/fleet/why-seat-model.ts — \"Why this seat\" in words (3.10.1).\n *\n * The card used to print the router's log sentence verbatim — one run-on with\n * every held-back seat's first reason in nested parentheses and a literal\n * \"…\" — and each HELD BACK entry as `reasons.join('; ')` (hence \".;\"), with\n * raw UTC instants and \"eligible again: unknown\" for seats whose reset was\n * known all along. Now:\n *\n * - the headline is one short sentence (`SeatDecision.summary`, or the\n * same words recovered from a 3.10.0 `why`) plus \"N seats held back.\";\n * - each held-back seat lists its reasons as prose sentences, without the\n * reset clauses — those move to \"eligible again\";\n * - \"eligible again\" is derived from the reasons AS DATA: every condition\n * that must change first (\"when you switch autonomy on for this seat\")\n * and the time every time-bound blocker has lifted, in the viewer's zone\n * (\"Fri 11:46 PM\") or, for Claude, the provider's own words verbatim.\n * \"unknown\" only when nothing says.\n *\n * Records written before 3.10.1 carry only sentences; `parseLegacyReason`\n * recovers the same data from them.\n *\n * Framework-free; tested directly.\n */\nimport type { SeatDecision, SeatExclusion, SeatReason, SeatReasonKind } from '../../../../core/routing/types.js';\nimport { describeResetAt } from '../../../../core/verse/seat-readiness.js';\n\nconst KINDS: ReadonlySet<string> = new Set<SeatReasonKind>([\n 'headroom', 'switched-off', 'signed-out', 'unreachable', 'spent', 'reserve', 'session-ceiling',\n 'unknown-usage', 'spend-cap', 'model-window', 'context', 'grant', 'lane', 'demoted', 'other',\n]);\n\n// ---------------------------------------------------------------------------\n// Sentences\n// ---------------------------------------------------------------------------\n\n/**\n * One sentence: trimmed and closed by exactly one full stop (a trailing \";\"\n * or \",\" is dropped). Never re-cased — a sentence may open on a seat id.\n */\nexport function asSentence(text: string): string {\n const t = text.trim().replace(/[\\s;,:]+$/, '');\n if (!t) return '';\n return /[.!?…]$/.test(t) ? t : `${t}.`;\n}\n\n/** Sentences as prose — \"A. B.\" — never \"A.; B\" and never \"A.. B\". */\nexport function joinSentences(texts: readonly string[]): string {\n return texts.map(asSentence).filter(Boolean).join(' ');\n}\n\n/** \"a\", \"a and b\", \"a, b and c\". */\nfunction listWords(words: readonly string[]): string {\n if (words.length <= 1) return words[0] ?? '';\n return `${words.slice(0, -1).join(', ')} and ${words[words.length - 1]}`;\n}\n\n// ---------------------------------------------------------------------------\n// Reasons as data\n// ---------------------------------------------------------------------------\n\nconst ISO_INSTANT = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}/;\nconst ISO_IN_TEXT = /\\b\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{1,9})?)?(?:Z|[+-]\\d{2}:?\\d{2})?(?![\\w:])/g;\n\n/**\n * Server prose with every ISO instant in it shown in the viewer's zone (\"the\n * earliest known reopening is Fri 2:25 PM\") — for sentences the server keeps\n * machine-exact for its logs, like a park hold's reason.\n */\nexport function localTimes(text: string, now: number = Date.now()): string {\n return text.replace(ISO_IN_TEXT, (iso) => describeResetAt(iso, now) ?? iso);\n}\n\nfunction isInstant(text: string | null | undefined): text is string {\n return typeof text === 'string' && ISO_INSTANT.test(text) && Number.isFinite(Date.parse(text));\n}\n\nfunction legacyKind(text: string): SeatReasonKind {\n if (/^autonomy is switched off/i.test(text)) return 'switched-off';\n if (/^signed out/i.test(text)) return 'signed-out';\n if (/not reachable/i.test(text)) return 'unreachable';\n if (/limits that model only/.test(text)) return 'model-window';\n if (/ is spent — /.test(text)) return 'spent';\n if (/is kept for you, so autonomy stops at/.test(text)) return 'reserve';\n if (/used; autonomy stops at .* to protect your live session/.test(text)) return 'session-ceiling';\n if (/unknown usage is not headroom|too stale to spend against|too uncertain to spend against/.test(text)) return 'unknown-usage';\n if (/daily cap/.test(text)) return 'spend-cap';\n if (/tokens of context/.test(text)) return 'context';\n if (/is demoted/.test(text)) return 'demoted';\n if (/\\bgrant\\b/i.test(text)) return 'grant';\n // A lane cap, as 3.10.0's router wrote it into exclusions: \"Codex lanes\n // stay off until…\", \"The Leader set 0 grok-cli lanes.\", \"The local runtime\n // serves 0 slot(s).\", \"…the Claude producer slice is held for your own\n // session.\" (3.10.1 sends these as `kind: 'lane'`.)\n if (/\\blanes?\\b|\\bslots?\\b|producer slice is held/i.test(text)) return 'lane';\n return 'other';\n}\n\n// ---------------------------------------------------------------------------\n// Lane cap reasons in operator words\n// ---------------------------------------------------------------------------\n\n/** Lane ids as the operator reads them — never inside a seat id (`codex-cmp`). */\nconst LANE_WORDS: ReadonlyArray<readonly [RegExp, string]> = [\n [/(?<![\\w-])grok-cli(?![\\w-])/g, 'Grok'],\n [/(?<![\\w-])claude-cli(?![\\w-])/g, 'Claude'],\n [/(?<![\\w-])codex(?![\\w-])/g, 'Codex'],\n];\n\n/**\n * A lane cap reason (the router's `capReason`, also a held-back seat's lane\n * reason) in plain words. The router words these for its log: \"The local\n * runtime serves 2 slot(s).\", \"A harness experiment is using 1 local\n * slot(s).\", \"Codex lanes stay off until the Leader enables them after the\n * usage reset (a class-B action).\", \"The Leader set 0 grok-cli lanes.\" The\n * operator reads \"2 slots\", \"1 local slot\", \"Codex stays off until the Leader\n * turns it on after the usage reset (you can veto it)\" and \"0 Grok lanes\".\n * Anything it does not recognise passes through unchanged.\n */\nexport function laneReasonText(reason: string): string {\n let text = reason.trim();\n text = text.replace(/^Codex lanes stay off until the Leader enables them\\b/, 'Codex stays off until the Leader turns it on');\n // A class-A/B Leader action waits out a veto window; class C does not.\n text = text.replace(/\\s*\\(an? class-([A-Za-z])\\s+action\\)/g, (_m, cls: string) => (/^[ab]$/i.test(cls) ? ' (you can veto it)' : ''));\n // \"2 slot(s)\" → \"2 slots\"; \"1 local slot(s)\" → \"1 local slot\".\n text = text.replace(/\\b(\\d+)((?:\\s+[A-Za-z-]+)*?)\\s+([A-Za-z]+)\\(s\\)/g, (_m, n: string, mid: string, word: string) => `${n}${mid} ${word}${Number(n) === 1 ? '' : 's'}`);\n text = text.replace(/\\b([A-Za-z]+)\\(s\\)/g, '$1s');\n for (const [re, word] of LANE_WORDS) text = text.replace(re, word);\n return text;\n}\n\n/**\n * A pre-3.10.1 reason sentence, back into data: the \" (resets …)\" clause the\n * server appended is split off (an instant → `resetsAt`, Claude's prose →\n * `resetDescription`), as is a demotion's \"until <instant>\".\n */\nexport function parseLegacyReason(sentence: string): SeatReason {\n const trimmed = sentence.trim();\n const clause = /^([\\s\\S]*?) \\(resets ([\\s\\S]+)\\)\\.?$/.exec(trimmed);\n let text = clause ? `${clause[1]}.` : trimmed;\n const reset = clause ? clause[2]!.trim() : null;\n let resetsAt: string | null = isInstant(reset) ? reset : null;\n const demoted = / is demoted until (\\S+): /.exec(text);\n if (demoted && isInstant(demoted[1])) {\n resetsAt = demoted[1];\n text = text.replace(` until ${demoted[1]}:`, ':');\n }\n return {\n kind: legacyKind(text),\n text,\n resetsAt,\n resetDescription: reset !== null && !isInstant(reset) ? reset : null,\n };\n}\n\n/** An exclusion's reasons as data: its 3.10.1 `details`, or its sentences parsed. */\nexport function exclusionReasons(x: SeatExclusion): SeatReason[] {\n if (Array.isArray(x.details) && (x.details.length > 0 || x.reasons.length === 0)) {\n // A newer server may add kinds; anything unrecognised reads as `other`.\n return x.details.map((r) => (KINDS.has(r.kind) ? r : { ...r, kind: 'other' as const }));\n }\n return x.reasons.map(parseLegacyReason);\n}\n\n/** The reasons a HELD BACK row prints: blockers and notes, never the \"N% left\" line; lane caps in plain words. */\nexport function heldBackText(x: SeatExclusion): string {\n return joinSentences(exclusionReasons(x).filter((r) => r.kind !== 'headroom').map((r) => (r.kind === 'lane' ? laneReasonText(r.text) : r.text)));\n}\n\n// ---------------------------------------------------------------------------\n// Eligible again\n// ---------------------------------------------------------------------------\n\n/** What must change before the seat can take this work again. */\nexport interface EligibleAgain {\n /** Conditions a person or the fleet must meet first, in words. */\n conditions: string[];\n /** The instant every time-bound blocker has lifted (the LATEST reset among them); null when none is known. */\n at: string | null;\n /** Provider reset wording with no instant (Claude), verbatim. */\n prose: string[];\n /** A time-bound blocker whose lift time nobody reported. */\n timeUnknown: boolean;\n /** Set when the seat can never take THIS work (it does not fit). */\n never: string | null;\n}\n\nconst CONDITION: Partial<Record<SeatReasonKind, string>> = {\n 'switched-off': 'you switch autonomy on for this seat',\n 'signed-out': 'you reconnect this account',\n unreachable: 'it is reachable again',\n 'unknown-usage': 'a fresh usage reading arrives',\n 'spend-cap': 'its daily spend cap resets',\n grant: 'the standing grant allows it',\n lane: 'its lane has a free slot',\n};\n\n/** Blockers that lift on their own at a time: a window reset, a demotion's end. */\nconst TIMED: ReadonlySet<SeatReasonKind> = new Set<SeatReasonKind>(['spent', 'reserve', 'session-ceiling', 'demoted']);\n\n/** Claude's wording, without the \"resets\" some sources lead with. */\nfunction resetWords(text: string): string {\n return text.trim().replace(/^resets\\s+/i, '');\n}\n\nexport function eligibleAgain(x: SeatExclusion): EligibleAgain {\n const conditions: string[] = [];\n const prose: string[] = [];\n let at: string | null = null;\n let timeUnknown = false;\n let never: string | null = null;\n for (const r of exclusionReasons(x)) {\n if (r.kind === 'context') {\n never = 'not for this task — it needs a larger context window than this seat has';\n continue;\n }\n const condition = CONDITION[r.kind];\n if (condition && !conditions.includes(condition)) conditions.push(condition);\n if (!TIMED.has(r.kind)) continue;\n // The seat is free only once EVERY time-bound blocker has lifted.\n if (isInstant(r.resetsAt)) {\n if (at === null || Date.parse(r.resetsAt) > Date.parse(at)) at = r.resetsAt;\n } else if (r.resetDescription) {\n const words = resetWords(r.resetDescription);\n if (!prose.includes(words)) prose.push(words);\n } else {\n timeUnknown = true;\n }\n }\n // The server's own estimate, when the reasons themselves carried no time.\n if (at === null && prose.length === 0 && isInstant(x.nextEligibleAt)) {\n at = x.nextEligibleAt;\n timeUnknown = false;\n }\n return { conditions, at, prose, timeUnknown, never };\n}\n\n/**\n * \"Fri 11:46 PM\"; \"when you switch autonomy on for this seat, not before Fri\n * 11:46 PM\"; \"Sep 25 at 6:59pm (America/New_York)\" (Claude's words); and\n * \"unknown\" only when nothing says.\n */\nexport function describeEligibleAgain(e: EligibleAgain, now: number = Date.now()): string {\n if (e.never) return e.never;\n const times = [...(e.at ? [describeResetAt(e.at, now) ?? e.at] : []), ...e.prose];\n const time = times.length > 0 ? times.join(' and ') : null;\n const when = e.conditions.length > 0 ? `when ${listWords(e.conditions)}` : null;\n if (when && time) return `${when}, not before ${time}`;\n if (when) return when;\n if (time) return time;\n return 'unknown';\n}\n\n// ---------------------------------------------------------------------------\n// Headline\n// ---------------------------------------------------------------------------\n\nconst ROUTED = /^Routed (?:autonomous )?[\\w-]+-difficulty \\w+ work to (.+?) \\(([^()]+)\\)(?: with (\\d+)% of its (5-hour|weekly) window left for autonomy| (at no cost))?: ([\\w-]+) mode prefers (.+?) first for this work(?:; held back [\\s\\S]*)?\\.$/;\nconst NOTHING = /^(No seat (?:the grant lets produce )?can take [\\s\\S]*?) \\([\\s\\S]*\\)(?:; the earliest known reopening is \\S+)?\\.$/;\n\n/**\n * The short headline recovered from a 3.10.0 `why` — the same words a 3.10.1\n * router writes as `summary` (\"Grok — 94% of its weekly window left; balanced\n * mode prefers Grok for this work.\"). Anything unrecognised is returned as is.\n */\nexport function legacySummary(why: string): string {\n const text = why.trim();\n const routed = ROUTED.exec(text);\n if (routed) {\n const [, label, , room, windowWord, free, mode, engine] = routed;\n const lead = room ? ` — ${room}% of its ${windowWord} window left` : free ? ' — free, no usage window' : '';\n return lead ? `${label}${lead}; ${mode} mode prefers ${engine} for this work.` : `${label} — ${mode} mode prefers ${engine} for this work.`;\n }\n const nothing = NOTHING.exec(text);\n if (nothing) return `${nothing[1]}.`;\n return text;\n}\n\n/** The card's one-line headline: the choice and why, then how many seats were held back. */\nexport function decisionSummary(d: SeatDecision): string {\n const lead = asSentence(d.summary ?? legacySummary(d.why));\n const n = d.exclusions.length;\n return n === 0 ? lead : `${lead} ${n === 1 ? '1 seat' : `${n} seats`} held back.`;\n}\n","/**\n * routes/verse/fleet/live-model.ts — FleetLiveSnapshotV1 → chart props\n * (unit C7; SPEC-310B §6 Fleet, SPEC-310C §5). Shared by Command's 12 h\n * swimlane and every Fleet card, so both make the same decisions:\n *\n * - rows are LANES × SLOTS: runs overlapping in one lane stack into\n * numbered slot rows (\"Grok · 2\"), so a bar never hides behind another;\n * - bar colour is STATUS (running amber, merged green, reverted red …);\n * the lane's ENGINE is the tick + monogram beside its label;\n * - queued and parked work draws as an outline (it holds a place; nothing\n * runs) — the Parked Gantt runs from \"parked since\" to `nextEligibleAt`,\n * and an unknown `nextEligibleAt` stays open-ended with \"unknown\" in words.\n *\n * Framework-free; tested directly.\n */\nimport type { FleetEngine, FleetGateFunnel, FleetLaneState, FleetLiveRun, FleetLiveSnapshotV1 } from '../../../../core/fleet/fleet-types.js';\nimport type { SeatDecision } from '../../../../core/routing/types.js';\nimport type { ChartEngine, ChartTone } from '../../../components/charts/colors.js';\nimport { CHART_NEUTRAL, seriesColor } from '../../../components/charts/colors.js';\nimport type { SwimlaneLane } from '../../../components/charts/Swimlane.js';\nimport type { FunnelStage } from '../../../components/charts/Funnel.js';\nimport type { BarStackSegment } from '../../../components/charts/BarStack.js';\nimport { laneReasonText, localTimes } from './why-seat-model.js';\n\nexport const LANE_ENGINE: Readonly<Record<FleetEngine, ChartEngine>> = {\n local: 'local',\n 'grok-cli': 'grok',\n 'claude-cli': 'claude',\n codex: 'codex',\n};\n\nexport const LANE_LABEL: Readonly<Record<FleetEngine, string>> = {\n local: 'Local',\n 'grok-cli': 'Grok',\n 'claude-cli': 'Claude',\n codex: 'Codex',\n};\n\n/** A lane chip's words: \"Local · off\", \"Grok · 1/2\". The why is a separate line (`laneNotes`). */\nexport function laneChipText(lane: FleetLaneState): { name: string; slots: string } {\n return { name: LANE_LABEL[lane.lane], slots: lane.slots === 0 ? 'off' : `${lane.busy}/${lane.slots}` };\n}\n\nexport interface LaneNote {\n /** The lanes this reason applies to, in strip order. */\n lanes: FleetEngine[];\n /** True when every lane shares it — then it is said once, without names. */\n all: boolean;\n reason: string;\n}\n\n/** A lane's cap reason as the operator reads it (`laneReasonText`); null when it has none. */\nexport function laneReason(lane: FleetLaneState): string | null {\n const reason = lane.capReason?.trim();\n return reason ? laneReasonText(reason) : null;\n}\n\n/**\n * Each distinct lane cap reason ONCE, with the lanes it covers, in plain\n * words (the router's \"slot(s)\" and \"class-B action\" never reach the\n * operator). A dark fleet gives every lane the same sentence; 3.10.0\n * repeated it inside every chip and truncated it there.\n */\nexport function laneNotes(lanes: readonly FleetLaneState[]): LaneNote[] {\n const byReason = new Map<string, FleetEngine[]>();\n for (const lane of lanes) {\n const reason = laneReason(lane);\n if (!reason) continue;\n const list = byReason.get(reason) ?? [];\n list.push(lane.lane);\n byReason.set(reason, list);\n }\n return [...byReason.entries()].map(([reason, covered]) => ({\n lanes: covered,\n all: covered.length === lanes.length && lanes.length > 1,\n reason,\n }));\n}\n\n/** The word a bar is labelled with: the outcome once it ended, else the phase. */\nexport function runStatus(run: FleetLiveRun): string {\n if (run.phase === 'queued' || run.phase === 'parked') return run.phase;\n if (run.phase === 'reverting') return 'reverting';\n return run.outcome ?? run.phase;\n}\n\nconst TONES: Readonly<Record<string, ChartTone>> = {\n producing: 'running',\n verifying: 'running',\n judging: 'running',\n landing: 'running',\n watching: 'info',\n reverting: 'danger',\n merged: 'success',\n proposed: 'info',\n 'owner-lane': 'warning',\n refused: 'warning',\n failed: 'danger',\n reverted: 'danger',\n cancelled: 'neutral',\n queued: 'neutral',\n parked: 'neutral',\n};\n\nexport function runTone(status: string): ChartTone {\n return TONES[status] ?? 'unknown';\n}\n\nfunction startOf(run: FleetLiveRun): number | null {\n const t = Date.parse(run.startedAt ?? run.phaseStartedAt ?? '');\n return Number.isFinite(t) ? t : null;\n}\n\nfunction endOf(run: FleetLiveRun): number | null {\n if (!run.endedAt) return null;\n const t = Date.parse(run.endedAt);\n return Number.isFinite(t) ? t : null;\n}\n\nfunction runDetail(run: FleetLiveRun): string {\n const where = run.repo.includes('/') ? run.repo.split('/')[1] : run.repo;\n return [where, run.title, run.model, run.prNumber ? `PR #${run.prNumber}` : null].filter(Boolean).join(' · ');\n}\n\nconst LANE_ORDER: readonly (FleetEngine | 'none')[] = ['local', 'grok-cli', 'claude-cli', 'codex', 'none'];\n\n/**\n * Runs within [from, now] packed into lane × slot rows. `parkedAsGantt`\n * leaves parked runs out (the Fleet surface draws them in their own Gantt);\n * Command keeps them in, as outlines.\n */\nexport function laneRows(runs: readonly FleetLiveRun[], from: number, now: number, opts: { includeParked?: boolean } = {}): SwimlaneLane[] {\n const includeParked = opts.includeParked ?? true;\n const byLane = new Map<FleetEngine | 'none', FleetLiveRun[]>();\n for (const run of runs) {\n if (!includeParked && run.phase === 'parked') continue;\n const s = startOf(run);\n if (s === null) continue;\n const e = endOf(run) ?? now;\n if (e < from || s > now) continue;\n const key = run.lane ?? 'none';\n if (!byLane.has(key)) byLane.set(key, []);\n byLane.get(key)!.push(run);\n }\n const lanes: SwimlaneLane[] = [];\n for (const key of LANE_ORDER) {\n const list = byLane.get(key);\n if (!list?.length) continue;\n list.sort((a, b) => startOf(a)! - startOf(b)!);\n const slotEnds: number[] = [];\n const slotItems: FleetLiveRun[][] = [];\n for (const run of list) {\n const s = startOf(run)!;\n const e = endOf(run) ?? now;\n let slot = slotEnds.findIndex((end) => end <= s);\n if (slot === -1) {\n slot = slotEnds.length;\n slotEnds.push(e);\n slotItems.push([]);\n } else {\n slotEnds[slot] = e;\n }\n slotItems[slot]!.push(run);\n }\n const name = key === 'none' ? 'Unassigned' : LANE_LABEL[key];\n slotItems.forEach((items, i) => {\n lanes.push({\n id: `${key}:${i}`,\n label: slotItems.length > 1 ? `${name} · ${i + 1}` : name,\n ...(key === 'none' ? {} : { engine: LANE_ENGINE[key] }),\n items: items.map((run) => ({\n id: run.id,\n start: startOf(run)!,\n end: endOf(run),\n status: runStatus(run),\n detail: runDetail(run),\n })),\n });\n });\n }\n return lanes;\n}\n\nexport interface GanttRow {\n lanes: SwimlaneLane[];\n from: number;\n to: number;\n /** Rows whose release time is unknown (drawn open-ended). */\n unknownRelease: number;\n}\n\n/**\n * The Parked Gantt: one row per parked item, from when it parked to when its\n * seat should free up. The window always shows \"now\" plus the furthest known\n * release (capped at 48 h — a week-long wait still reads, it just runs off\n * the right edge and the table carries the exact time).\n */\nexport function parkedGantt(runs: readonly FleetLiveRun[], now: number): GanttRow {\n const parked = runs.filter((r) => r.phase === 'parked' || r.hold !== null);\n const releases = parked.map((r) => (r.hold?.nextEligibleAt ? Date.parse(r.hold.nextEligibleAt) : NaN)).filter(Number.isFinite);\n const starts = parked.map((r) => startOf(r) ?? now);\n const from = Math.min(now - 60 * 60_000, ...starts);\n const to = Math.min(now + 48 * 3_600_000, Math.max(now + 2 * 3_600_000, ...releases));\n let unknownRelease = 0;\n const lanes: SwimlaneLane[] = parked.map((r) => {\n const release = r.hold?.nextEligibleAt ? Date.parse(r.hold.nextEligibleAt) : NaN;\n if (!Number.isFinite(release)) unknownRelease++;\n const where = r.repo.includes('/') ? r.repo.split('/')[1] : r.repo;\n return {\n id: r.id,\n label: `${where}: ${r.title}`,\n ...(r.lane ? { engine: LANE_ENGINE[r.lane] } : {}),\n items: [{\n id: r.id,\n start: startOf(r) ?? now,\n end: Number.isFinite(release) ? release : null,\n status: r.hold?.kind === 'split' ? 'split' : 'parked',\n outline: true,\n detail: `${localTimes(r.hold?.reason ?? 'parked', now)}${Number.isFinite(release) ? '' : ' · release time unknown'}`,\n }],\n };\n });\n return { lanes, from, to, unknownRelease };\n}\n\n// ---------------------------------------------------------------------------\n// Gate funnel + refusal reasons\n// ---------------------------------------------------------------------------\n\n/** Gate names in operator words (the funnel's stage labels). */\nexport const GATE_LABEL: Readonly<Record<string, string>> = {\n G0: 'Authority',\n G1: 'Protected paths',\n G1b: 'Tamper',\n G2: 'Scope',\n G3: 'Verify',\n G4: 'Claims',\n G5: 'Blast radius',\n G6: 'Judge',\n G7: 'GitHub checks',\n};\n\n/** Entered G0, then how many passed each gate — a strictly narrowing pipeline. */\nexport function funnelStages(funnel: FleetGateFunnel | null): FunnelStage[] {\n if (!funnel || funnel.stages.length === 0) return [];\n return [\n { id: 'entered', label: 'Proposals', value: funnel.stages[0]!.entered },\n ...funnel.stages.map((s) => ({ id: s.gate, label: `${s.gate} ${GATE_LABEL[s.gate] ?? ''}`.trim(), value: s.passed })),\n ];\n}\n\nexport interface RefusalStack {\n categories: string[];\n segments: BarStackSegment[];\n values: (number | null)[][];\n total: number;\n}\n\n/**\n * Refusals per gate, stacked by reason. The top five reasons (by count over\n * the window) keep FIXED identity slots — a reason's colour never changes\n * when another is filtered out — and the rest fold into a neutral \"Other\".\n */\nexport function refusalStack(funnel: FleetGateFunnel | null, topN = 5): RefusalStack {\n if (!funnel) return { categories: [], segments: [], values: [], total: 0 };\n const totals = new Map<string, { reason: string; count: number }>();\n for (const s of funnel.stages) for (const r of s.refusals) {\n const prev = totals.get(r.code);\n totals.set(r.code, { reason: prev?.reason ?? r.reason, count: (prev?.count ?? 0) + r.count });\n }\n const ranked = [...totals.entries()].sort((a, b) => b[1].count - a[1].count || a[0].localeCompare(b[0]));\n const top = ranked.slice(0, topN).map(([code]) => code);\n const hasOther = ranked.length > topN;\n const segments: BarStackSegment[] = [\n ...top.map((code, i) => ({ id: code, label: totals.get(code)!.reason, color: seriesColor(i) })),\n ...(hasOther ? [{ id: '__other', label: 'Other reasons', color: CHART_NEUTRAL }] : []),\n ];\n const stages = funnel.stages.filter((s) => s.refusals.length > 0 || s.entered !== s.passed);\n return {\n categories: stages.map((s) => s.gate),\n segments,\n values: stages.map((s) => {\n const row = top.map((code) => s.refusals.find((r) => r.code === code)?.count ?? 0);\n if (hasOther) row.push(s.refusals.filter((r) => !top.includes(r.code)).reduce((n, r) => n + r.count, 0));\n return row;\n }),\n total: ranked.reduce((n, [, v]) => n + v.count, 0),\n };\n}\n\n/** The newest seat decision behind a live dispatch (\"why this seat\"). */\nexport function latestDecision(fleet: FleetLiveSnapshotV1 | null): { decision: SeatDecision; run: FleetLiveRun } | null {\n if (!fleet) return null;\n const withDecision = fleet.runs.filter((r) => r.seatDecision !== null);\n if (!withDecision.length) return null;\n withDecision.sort((a, b) => (startOf(b) ?? 0) - (startOf(a) ?? 0));\n const run = withDecision[0]!;\n return { decision: run.seatDecision!, run };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"live-model-DEwrl7_A.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/fleet/why-seat-model.ts","../../../../../../src/web-ui/routes/verse/fleet/live-model.ts"],"sourcesContent":["/**\n * routes/verse/fleet/why-seat-model.ts — \"Why this seat\" in words (3.10.1).\n *\n * The card used to print the router's log sentence verbatim — one run-on with\n * every held-back seat's first reason in nested parentheses and a literal\n * \"…\" — and each HELD BACK entry as `reasons.join('; ')` (hence \".;\"), with\n * raw UTC instants and \"eligible again: unknown\" for seats whose reset was\n * known all along. Now:\n *\n * - the headline is one short sentence (`SeatDecision.summary`, or the\n * same words recovered from a 3.10.0 `why`) plus \"N seats held back.\";\n * - each held-back seat lists its reasons as prose sentences, without the\n * reset clauses — those move to \"eligible again\";\n * - \"eligible again\" is derived from the reasons AS DATA: every condition\n * that must change first (\"when you switch autonomy on for this seat\")\n * and the time every time-bound blocker has lifted, in the viewer's zone\n * (\"Fri 11:46 PM\") or, for Claude, the provider's own words verbatim.\n * \"unknown\" only when nothing says.\n *\n * Records written before 3.10.1 carry only sentences; `parseLegacyReason`\n * recovers the same data from them.\n *\n * Framework-free; tested directly.\n */\nimport type { SeatDecision, SeatExclusion, SeatReason, SeatReasonKind } from '../../../../core/routing/types.js';\nimport { describeResetAt } from '../../../../core/verse/seat-readiness.js';\n\nconst KINDS: ReadonlySet<string> = new Set<SeatReasonKind>([\n 'headroom', 'switched-off', 'signed-out', 'unreachable', 'spent', 'reserve', 'session-ceiling',\n 'unknown-usage', 'spend-cap', 'model-window', 'context', 'grant', 'lane', 'demoted', 'other',\n]);\n\n// ---------------------------------------------------------------------------\n// Sentences\n// ---------------------------------------------------------------------------\n\n/**\n * One sentence: trimmed and closed by exactly one full stop (a trailing \";\"\n * or \",\" is dropped). Never re-cased — a sentence may open on a seat id.\n */\nexport function asSentence(text: string): string {\n const t = text.trim().replace(/[\\s;,:]+$/, '');\n if (!t) return '';\n return /[.!?…]$/.test(t) ? t : `${t}.`;\n}\n\n/** Sentences as prose — \"A. B.\" — never \"A.; B\" and never \"A.. B\". */\nexport function joinSentences(texts: readonly string[]): string {\n return texts.map(asSentence).filter(Boolean).join(' ');\n}\n\n/** \"a\", \"a and b\", \"a, b and c\". */\nfunction listWords(words: readonly string[]): string {\n if (words.length <= 1) return words[0] ?? '';\n return `${words.slice(0, -1).join(', ')} and ${words[words.length - 1]}`;\n}\n\n// ---------------------------------------------------------------------------\n// Reasons as data\n// ---------------------------------------------------------------------------\n\nconst ISO_INSTANT = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}/;\nconst ISO_IN_TEXT = /\\b\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{1,9})?)?(?:Z|[+-]\\d{2}:?\\d{2})?(?![\\w:])/g;\n\n/**\n * Server prose with every ISO instant in it shown in the viewer's zone (\"the\n * earliest known reopening is Fri 2:25 PM\") — for sentences the server keeps\n * machine-exact for its logs, like a park hold's reason.\n */\nexport function localTimes(text: string, now: number = Date.now()): string {\n return text.replace(ISO_IN_TEXT, (iso) => describeResetAt(iso, now) ?? iso);\n}\n\nfunction isInstant(text: string | null | undefined): text is string {\n return typeof text === 'string' && ISO_INSTANT.test(text) && Number.isFinite(Date.parse(text));\n}\n\nfunction legacyKind(text: string): SeatReasonKind {\n if (/^autonomy is switched off/i.test(text)) return 'switched-off';\n if (/^signed out/i.test(text)) return 'signed-out';\n if (/not reachable/i.test(text)) return 'unreachable';\n if (/limits that model only/.test(text)) return 'model-window';\n if (/ is spent — /.test(text)) return 'spent';\n if (/is kept for you, so autonomy stops at/.test(text)) return 'reserve';\n if (/used; autonomy stops at .* to protect your live session/.test(text)) return 'session-ceiling';\n if (/unknown usage is not headroom|too stale to spend against|too uncertain to spend against/.test(text)) return 'unknown-usage';\n if (/daily cap/.test(text)) return 'spend-cap';\n if (/tokens of context/.test(text)) return 'context';\n if (/is demoted/.test(text)) return 'demoted';\n if (/\\bgrant\\b/i.test(text)) return 'grant';\n // A lane cap, as 3.10.0's router wrote it into exclusions: \"Codex lanes\n // stay off until…\", \"The Leader set 0 grok-cli lanes.\", \"The local runtime\n // serves 0 slot(s).\", \"…the Claude producer slice is held for your own\n // session.\" (3.10.1 sends these as `kind: 'lane'`.)\n if (/\\blanes?\\b|\\bslots?\\b|producer slice is held/i.test(text)) return 'lane';\n return 'other';\n}\n\n// ---------------------------------------------------------------------------\n// Lane cap reasons in operator words\n// ---------------------------------------------------------------------------\n\n/** Lane ids as the operator reads them — never inside a seat id (`codex-cmp`). */\nconst LANE_WORDS: ReadonlyArray<readonly [RegExp, string]> = [\n [/(?<![\\w-])grok-cli(?![\\w-])/g, 'Grok'],\n [/(?<![\\w-])claude-cli(?![\\w-])/g, 'Claude'],\n [/(?<![\\w-])codex(?![\\w-])/g, 'Codex'],\n];\n\n/**\n * A lane cap reason (the router's `capReason`, also a held-back seat's lane\n * reason) in plain words. The router words these for its log: \"The local\n * runtime serves 2 slot(s).\", \"A harness experiment is using 1 local\n * slot(s).\", \"Codex lanes stay off until the Leader enables them after the\n * usage reset (a class-B action).\", \"The Leader set 0 grok-cli lanes.\" The\n * operator reads \"2 slots\", \"1 local slot\", \"Codex stays off until the Leader\n * turns it on after the usage reset (you can veto it)\" and \"0 Grok lanes\".\n * Anything it does not recognise passes through unchanged.\n */\nexport function laneReasonText(reason: string): string {\n let text = reason.trim();\n text = text.replace(/^Codex lanes stay off until the Leader enables them\\b/, 'Codex stays off until the Leader turns it on');\n // A class-A/B Leader action waits out a veto window; class C does not.\n text = text.replace(/\\s*\\(an? class-([A-Za-z])\\s+action\\)/g, (_m, cls: string) => (/^[ab]$/i.test(cls) ? ' (you can veto it)' : ''));\n // \"2 slot(s)\" → \"2 slots\"; \"1 local slot(s)\" → \"1 local slot\".\n text = text.replace(/\\b(\\d+)((?:\\s+[A-Za-z-]+)*?)\\s+([A-Za-z]+)\\(s\\)/g, (_m, n: string, mid: string, word: string) => `${n}${mid} ${word}${Number(n) === 1 ? '' : 's'}`);\n text = text.replace(/\\b([A-Za-z]+)\\(s\\)/g, '$1s');\n for (const [re, word] of LANE_WORDS) text = text.replace(re, word);\n return text;\n}\n\n/**\n * A pre-3.10.1 reason sentence, back into data: the \" (resets …)\" clause the\n * server appended is split off (an instant → `resetsAt`, Claude's prose →\n * `resetDescription`), as is a demotion's \"until <instant>\".\n */\nexport function parseLegacyReason(sentence: string): SeatReason {\n const trimmed = sentence.trim();\n const clause = /^([\\s\\S]*?) \\(resets ([\\s\\S]+)\\)\\.?$/.exec(trimmed);\n let text = clause ? `${clause[1]}.` : trimmed;\n const reset = clause ? clause[2]!.trim() : null;\n let resetsAt: string | null = isInstant(reset) ? reset : null;\n const demoted = / is demoted until (\\S+): /.exec(text);\n if (demoted && isInstant(demoted[1])) {\n resetsAt = demoted[1];\n text = text.replace(` until ${demoted[1]}:`, ':');\n }\n return {\n kind: legacyKind(text),\n text,\n resetsAt,\n resetDescription: reset !== null && !isInstant(reset) ? reset : null,\n };\n}\n\n/** An exclusion's reasons as data: its 3.10.1 `details`, or its sentences parsed. */\nexport function exclusionReasons(x: SeatExclusion): SeatReason[] {\n if (Array.isArray(x.details) && (x.details.length > 0 || x.reasons.length === 0)) {\n // A newer server may add kinds; anything unrecognised reads as `other`.\n return x.details.map((r) => (KINDS.has(r.kind) ? r : { ...r, kind: 'other' as const }));\n }\n return x.reasons.map(parseLegacyReason);\n}\n\n/** The reasons a HELD BACK row prints: blockers and notes, never the \"N% left\" line; lane caps in plain words. */\nexport function heldBackText(x: SeatExclusion): string {\n return joinSentences(exclusionReasons(x).filter((r) => r.kind !== 'headroom').map((r) => (r.kind === 'lane' ? laneReasonText(r.text) : r.text)));\n}\n\n// ---------------------------------------------------------------------------\n// Eligible again\n// ---------------------------------------------------------------------------\n\n/** What must change before the seat can take this work again. */\nexport interface EligibleAgain {\n /** Conditions a person or the fleet must meet first, in words. */\n conditions: string[];\n /** The instant every time-bound blocker has lifted (the LATEST reset among them); null when none is known. */\n at: string | null;\n /** Provider reset wording with no instant (Claude), verbatim. */\n prose: string[];\n /** A time-bound blocker whose lift time nobody reported. */\n timeUnknown: boolean;\n /** Set when the seat can never take THIS work (it does not fit). */\n never: string | null;\n}\n\nconst CONDITION: Partial<Record<SeatReasonKind, string>> = {\n 'switched-off': 'you switch autonomy on for this seat',\n 'signed-out': 'you reconnect this account',\n unreachable: 'it is reachable again',\n 'unknown-usage': 'a fresh usage reading arrives',\n 'spend-cap': 'its daily spend cap resets',\n grant: 'the standing grant allows it',\n lane: 'its lane has a free slot',\n};\n\n/** Blockers that lift on their own at a time: a window reset, a demotion's end. */\nconst TIMED: ReadonlySet<SeatReasonKind> = new Set<SeatReasonKind>(['spent', 'reserve', 'session-ceiling', 'demoted']);\n\n/** Claude's wording, without the \"resets\" some sources lead with. */\nfunction resetWords(text: string): string {\n return text.trim().replace(/^resets\\s+/i, '');\n}\n\nexport function eligibleAgain(x: SeatExclusion): EligibleAgain {\n const conditions: string[] = [];\n const prose: string[] = [];\n let at: string | null = null;\n let timeUnknown = false;\n let never: string | null = null;\n for (const r of exclusionReasons(x)) {\n if (r.kind === 'context') {\n never = 'not for this task — it needs a larger context window than this seat has';\n continue;\n }\n const condition = CONDITION[r.kind];\n if (condition && !conditions.includes(condition)) conditions.push(condition);\n if (!TIMED.has(r.kind)) continue;\n // The seat is free only once EVERY time-bound blocker has lifted.\n if (isInstant(r.resetsAt)) {\n if (at === null || Date.parse(r.resetsAt) > Date.parse(at)) at = r.resetsAt;\n } else if (r.resetDescription) {\n const words = resetWords(r.resetDescription);\n if (!prose.includes(words)) prose.push(words);\n } else {\n timeUnknown = true;\n }\n }\n // The server's own estimate, when the reasons themselves carried no time.\n if (at === null && prose.length === 0 && isInstant(x.nextEligibleAt)) {\n at = x.nextEligibleAt;\n timeUnknown = false;\n }\n return { conditions, at, prose, timeUnknown, never };\n}\n\n/**\n * \"Fri 11:46 PM\"; \"when you switch autonomy on for this seat, not before Fri\n * 11:46 PM\"; \"Sep 25 at 6:59pm (America/New_York)\" (Claude's words); and\n * \"unknown\" only when nothing says.\n */\nexport function describeEligibleAgain(e: EligibleAgain, now: number = Date.now()): string {\n if (e.never) return e.never;\n const times = [...(e.at ? [describeResetAt(e.at, now) ?? e.at] : []), ...e.prose];\n const time = times.length > 0 ? times.join(' and ') : null;\n const when = e.conditions.length > 0 ? `when ${listWords(e.conditions)}` : null;\n if (when && time) return `${when}, not before ${time}`;\n if (when) return when;\n if (time) return time;\n return 'unknown';\n}\n\n// ---------------------------------------------------------------------------\n// Headline\n// ---------------------------------------------------------------------------\n\nconst ROUTED = /^Routed (?:autonomous )?[\\w-]+-difficulty \\w+ work to (.+?) \\(([^()]+)\\)(?: with (\\d+)% of its (5-hour|weekly) window left for autonomy| (at no cost))?: ([\\w-]+) mode prefers (.+?) first for this work(?:; held back [\\s\\S]*)?\\.$/;\nconst NOTHING = /^(No seat (?:the grant lets produce )?can take [\\s\\S]*?) \\([\\s\\S]*\\)(?:; the earliest known reopening is \\S+)?\\.$/;\n\n/**\n * The short headline recovered from a 3.10.0 `why` — the same words a 3.10.1\n * router writes as `summary` (\"Grok — 94% of its weekly window left; balanced\n * mode prefers Grok for this work.\"). Anything unrecognised is returned as is.\n */\nexport function legacySummary(why: string): string {\n const text = why.trim();\n const routed = ROUTED.exec(text);\n if (routed) {\n const [, label, , room, windowWord, free, mode, engine] = routed;\n const lead = room ? ` — ${room}% of its ${windowWord} window left` : free ? ' — free, no usage window' : '';\n return lead ? `${label}${lead}; ${mode} mode prefers ${engine} for this work.` : `${label} — ${mode} mode prefers ${engine} for this work.`;\n }\n const nothing = NOTHING.exec(text);\n if (nothing) return `${nothing[1]}.`;\n return text;\n}\n\n/** The card's one-line headline: the choice and why, then how many seats were held back. */\nexport function decisionSummary(d: SeatDecision): string {\n const lead = asSentence(d.summary ?? legacySummary(d.why));\n const n = d.exclusions.length;\n return n === 0 ? lead : `${lead} ${n === 1 ? '1 seat' : `${n} seats`} held back.`;\n}\n","/**\n * routes/verse/fleet/live-model.ts — FleetLiveSnapshotV1 → chart props\n * (unit C7; SPEC-310B §6 Fleet, SPEC-310C §5). Shared by Command's 12 h\n * swimlane and every Fleet card, so both make the same decisions:\n *\n * - rows are LANES × SLOTS: runs overlapping in one lane stack into\n * numbered slot rows (\"Grok · 2\"), so a bar never hides behind another;\n * - bar colour is STATUS (running amber, merged green, reverted red …);\n * the lane's ENGINE is the tick + monogram beside its label;\n * - queued and parked work draws as an outline (it holds a place; nothing\n * runs) — the Parked Gantt runs from \"parked since\" to `nextEligibleAt`,\n * and an unknown `nextEligibleAt` stays open-ended with \"unknown\" in words.\n *\n * Framework-free; tested directly.\n */\nimport type { FleetEngine, FleetGateFunnel, FleetLaneState, FleetLiveRun, FleetLiveSnapshotV1 } from '../../../../core/fleet/fleet-types.js';\nimport type { SeatDecision } from '../../../../core/routing/types.js';\nimport type { ChartEngine, ChartTone } from '../../../components/charts/colors.js';\nimport { CHART_NEUTRAL, seriesColor } from '../../../components/charts/colors.js';\nimport type { SwimlaneLane } from '../../../components/charts/Swimlane.js';\nimport type { FunnelStage } from '../../../components/charts/Funnel.js';\nimport type { BarStackSegment } from '../../../components/charts/BarStack.js';\nimport { laneReasonText, localTimes } from './why-seat-model.js';\n\nexport const LANE_ENGINE: Readonly<Record<FleetEngine, ChartEngine>> = {\n local: 'local',\n 'grok-cli': 'grok',\n 'claude-cli': 'claude',\n codex: 'codex',\n};\n\nexport const LANE_LABEL: Readonly<Record<FleetEngine, string>> = {\n local: 'Local',\n 'grok-cli': 'Grok',\n 'claude-cli': 'Claude',\n codex: 'Codex',\n};\n\n/** A lane chip's words: \"Local · off\", \"Grok · 1/2\". The why is a separate line (`laneNotes`). */\nexport function laneChipText(lane: FleetLaneState): { name: string; slots: string } {\n return { name: LANE_LABEL[lane.lane], slots: lane.slots === 0 ? 'off' : `${lane.busy}/${lane.slots}` };\n}\n\nexport interface LaneNote {\n /** The lanes this reason applies to, in strip order. */\n lanes: FleetEngine[];\n /** True when every lane shares it — then it is said once, without names. */\n all: boolean;\n reason: string;\n}\n\n/** A lane's cap reason as the operator reads it (`laneReasonText`); null when it has none. */\nexport function laneReason(lane: FleetLaneState): string | null {\n const reason = lane.capReason?.trim();\n return reason ? laneReasonText(reason) : null;\n}\n\n/**\n * Each distinct lane cap reason ONCE, with the lanes it covers, in plain\n * words (the router's \"slot(s)\" and \"class-B action\" never reach the\n * operator). A dark fleet gives every lane the same sentence; 3.10.0\n * repeated it inside every chip and truncated it there.\n */\nexport function laneNotes(lanes: readonly FleetLaneState[]): LaneNote[] {\n const byReason = new Map<string, FleetEngine[]>();\n for (const lane of lanes) {\n const reason = laneReason(lane);\n if (!reason) continue;\n const list = byReason.get(reason) ?? [];\n list.push(lane.lane);\n byReason.set(reason, list);\n }\n return [...byReason.entries()].map(([reason, covered]) => ({\n lanes: covered,\n all: covered.length === lanes.length && lanes.length > 1,\n reason,\n }));\n}\n\n/** The word a bar is labelled with: the outcome once it ended, else the phase. */\nexport function runStatus(run: FleetLiveRun): string {\n if (run.phase === 'queued' || run.phase === 'parked') return run.phase;\n if (run.phase === 'reverting') return 'reverting';\n return run.outcome ?? run.phase;\n}\n\nconst TONES: Readonly<Record<string, ChartTone>> = {\n producing: 'running',\n verifying: 'running',\n judging: 'running',\n landing: 'running',\n watching: 'info',\n reverting: 'danger',\n merged: 'success',\n proposed: 'info',\n 'owner-lane': 'warning',\n refused: 'warning',\n failed: 'danger',\n reverted: 'danger',\n cancelled: 'neutral',\n queued: 'neutral',\n parked: 'neutral',\n};\n\nexport function runTone(status: string): ChartTone {\n return TONES[status] ?? 'unknown';\n}\n\nfunction startOf(run: FleetLiveRun): number | null {\n const t = Date.parse(run.startedAt ?? run.phaseStartedAt ?? '');\n return Number.isFinite(t) ? t : null;\n}\n\nfunction endOf(run: FleetLiveRun): number | null {\n if (!run.endedAt) return null;\n const t = Date.parse(run.endedAt);\n return Number.isFinite(t) ? t : null;\n}\n\nfunction runDetail(run: FleetLiveRun): string {\n const where = run.repo.includes('/') ? run.repo.split('/')[1] : run.repo;\n return [where, run.title, run.model, run.prNumber ? `PR #${run.prNumber}` : null].filter(Boolean).join(' · ');\n}\n\nconst LANE_ORDER: readonly (FleetEngine | 'none')[] = ['local', 'grok-cli', 'claude-cli', 'codex', 'none'];\n\n/**\n * Runs within [from, now] packed into lane × slot rows. `parkedAsGantt`\n * leaves parked runs out (the Fleet surface draws them in their own Gantt);\n * Command keeps them in, as outlines.\n */\nexport function laneRows(runs: readonly FleetLiveRun[], from: number, now: number, opts: { includeParked?: boolean } = {}): SwimlaneLane[] {\n const includeParked = opts.includeParked ?? true;\n const byLane = new Map<FleetEngine | 'none', FleetLiveRun[]>();\n for (const run of runs) {\n if (!includeParked && run.phase === 'parked') continue;\n const s = startOf(run);\n if (s === null) continue;\n const e = endOf(run) ?? now;\n if (e < from || s > now) continue;\n const key = run.lane ?? 'none';\n if (!byLane.has(key)) byLane.set(key, []);\n byLane.get(key)!.push(run);\n }\n const lanes: SwimlaneLane[] = [];\n for (const key of LANE_ORDER) {\n const list = byLane.get(key);\n if (!list?.length) continue;\n list.sort((a, b) => startOf(a)! - startOf(b)!);\n const slotEnds: number[] = [];\n const slotItems: FleetLiveRun[][] = [];\n for (const run of list) {\n const s = startOf(run)!;\n const e = endOf(run) ?? now;\n let slot = slotEnds.findIndex((end) => end <= s);\n if (slot === -1) {\n slot = slotEnds.length;\n slotEnds.push(e);\n slotItems.push([]);\n } else {\n slotEnds[slot] = e;\n }\n slotItems[slot]!.push(run);\n }\n const name = key === 'none' ? 'Unassigned' : LANE_LABEL[key];\n slotItems.forEach((items, i) => {\n lanes.push({\n id: `${key}:${i}`,\n label: slotItems.length > 1 ? `${name} · ${i + 1}` : name,\n ...(key === 'none' ? {} : { engine: LANE_ENGINE[key] }),\n items: items.map((run) => ({\n id: run.id,\n start: startOf(run)!,\n end: endOf(run),\n status: runStatus(run),\n detail: runDetail(run),\n })),\n });\n });\n }\n return lanes;\n}\n\nexport interface GanttRow {\n lanes: SwimlaneLane[];\n from: number;\n to: number;\n /** Rows whose release time is unknown (drawn open-ended). */\n unknownRelease: number;\n}\n\n/**\n * The Parked Gantt: one row per parked item, from when it parked to when its\n * seat should free up. The window always shows \"now\" plus the furthest known\n * release (capped at 48 h — a week-long wait still reads, it just runs off\n * the right edge and the table carries the exact time).\n */\nexport function parkedGantt(runs: readonly FleetLiveRun[], now: number): GanttRow {\n const parked = runs.filter((r) => r.phase === 'parked' || r.hold !== null);\n const releases = parked.map((r) => (r.hold?.nextEligibleAt ? Date.parse(r.hold.nextEligibleAt) : NaN)).filter(Number.isFinite);\n const starts = parked.map((r) => startOf(r) ?? now);\n const from = Math.min(now - 60 * 60_000, ...starts);\n const to = Math.min(now + 48 * 3_600_000, Math.max(now + 2 * 3_600_000, ...releases));\n let unknownRelease = 0;\n const lanes: SwimlaneLane[] = parked.map((r) => {\n const release = r.hold?.nextEligibleAt ? Date.parse(r.hold.nextEligibleAt) : NaN;\n if (!Number.isFinite(release)) unknownRelease++;\n const where = r.repo.includes('/') ? r.repo.split('/')[1] : r.repo;\n return {\n id: r.id,\n label: `${where}: ${r.title}`,\n ...(r.lane ? { engine: LANE_ENGINE[r.lane] } : {}),\n items: [{\n id: r.id,\n start: startOf(r) ?? now,\n end: Number.isFinite(release) ? release : null,\n status: r.hold?.kind === 'split' ? 'split' : 'parked',\n outline: true,\n detail: `${localTimes(r.hold?.reason ?? 'parked', now)}${Number.isFinite(release) ? '' : ' · release time unknown'}`,\n }],\n };\n });\n return { lanes, from, to, unknownRelease };\n}\n\n// ---------------------------------------------------------------------------\n// Gate funnel + refusal reasons\n// ---------------------------------------------------------------------------\n\n/** Gate names in operator words (the funnel's stage labels). */\nexport const GATE_LABEL: Readonly<Record<string, string>> = {\n G0: 'Authority',\n G1: 'Protected paths',\n G1b: 'Tamper',\n G2: 'Scope',\n G3: 'Verify',\n G4: 'Claims',\n G5: 'Blast radius',\n G6: 'Judge',\n G7: 'GitHub checks',\n};\n\n/** Entered G0, then how many passed each gate — a strictly narrowing pipeline. */\nexport function funnelStages(funnel: FleetGateFunnel | null): FunnelStage[] {\n if (!funnel || funnel.stages.length === 0) return [];\n return [\n { id: 'entered', label: 'Proposals', value: funnel.stages[0]!.entered },\n ...funnel.stages.map((s) => ({ id: s.gate, label: `${s.gate} ${GATE_LABEL[s.gate] ?? ''}`.trim(), value: s.passed })),\n ];\n}\n\nexport interface RefusalStack {\n categories: string[];\n segments: BarStackSegment[];\n values: (number | null)[][];\n total: number;\n}\n\n/**\n * Refusals per gate, stacked by reason. The top five reasons (by count over\n * the window) keep FIXED identity slots — a reason's colour never changes\n * when another is filtered out — and the rest fold into a neutral \"Other\".\n */\nexport function refusalStack(funnel: FleetGateFunnel | null, topN = 5): RefusalStack {\n if (!funnel) return { categories: [], segments: [], values: [], total: 0 };\n const totals = new Map<string, { reason: string; count: number }>();\n for (const s of funnel.stages) for (const r of s.refusals) {\n const prev = totals.get(r.code);\n totals.set(r.code, { reason: prev?.reason ?? r.reason, count: (prev?.count ?? 0) + r.count });\n }\n const ranked = [...totals.entries()].sort((a, b) => b[1].count - a[1].count || a[0].localeCompare(b[0]));\n const top = ranked.slice(0, topN).map(([code]) => code);\n const hasOther = ranked.length > topN;\n const segments: BarStackSegment[] = [\n ...top.map((code, i) => ({ id: code, label: totals.get(code)!.reason, color: seriesColor(i) })),\n ...(hasOther ? [{ id: '__other', label: 'Other reasons', color: CHART_NEUTRAL }] : []),\n ];\n const stages = funnel.stages.filter((s) => s.refusals.length > 0 || s.entered !== s.passed);\n return {\n categories: stages.map((s) => s.gate),\n segments,\n values: stages.map((s) => {\n const row = top.map((code) => s.refusals.find((r) => r.code === code)?.count ?? 0);\n if (hasOther) row.push(s.refusals.filter((r) => !top.includes(r.code)).reduce((n, r) => n + r.count, 0));\n return row;\n }),\n total: ranked.reduce((n, [, v]) => n + v.count, 0),\n };\n}\n\n/** The newest seat decision behind a live dispatch (\"why this seat\"). */\nexport function latestDecision(fleet: FleetLiveSnapshotV1 | null): { decision: SeatDecision; run: FleetLiveRun } | null {\n if (!fleet) return null;\n const withDecision = fleet.runs.filter((r) => r.seatDecision !== null);\n if (!withDecision.length) return null;\n withDecision.sort((a, b) => (startOf(b) ?? 0) - (startOf(a) ?? 0));\n const run = withDecision[0]!;\n return { decision: run.seatDecision!, run };\n}\n"],"mappings":"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"}
|
package/dist/core/web/public/next/assets/{mind.module-vnuJcwvD.js → mind.module-CLhqMQak.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{v as e}from"./colors-BZ3a9wFf.js";import{a as t}from"./workspace-model-
|
|
2
|
-
//# sourceMappingURL=mind.module-
|
|
1
|
+
import{v as e}from"./colors-BZ3a9wFf.js";import{a as t}from"./workspace-model-CXorJr0G.js";import{t as n}from"./calendar-day-BxBYHfX1.js";function r(e){let t=e.trim().replace(/\\/g,`/`).replace(/\/+$/,``);return t=t.replace(/^\/private(?=\/(?:tmp|var)(?:\/|$))/,``),t=t.replace(/^(?:\/Users\/[^/]+|\/home\/[^/]+|[A-Za-z]:\/Users\/[^/]+)(?=\/|$)/,`~`),t||`/`}var i=[/^\/tmp(?:\/|$)/,/^\/var\/tmp(?:\/|$)/,/^\/var\/folders\/[^/]+\/[^/]+\/T(?:\/|$)/,/^[A-Za-z]:\/Windows\/Temp(?:\/|$)/i,/\/AppData\/Local\/Temp(?:\/|$)/i];function a(e){let t=r(e);return i.some(e=>e.test(t))}function o(e,t){let n=new Map,i=(e,t)=>{let i=r(e),a=t.trim();i!==`/`&&i!==`~`&&a&&!n.has(i)&&n.set(i,a)};for(let t of e??[])for(let e of t.roots)i(e.path,t.name);for(let e of t??[])i(e.path,e.name);return n}function s(e,t){let n=r(e),i=t.get(n);if(i!==void 0)return i;let a=null;for(let[e,r]of t)n.startsWith(`${e}/`)&&(!a||e.length>a.root.length)&&(a={root:e,name:r});return a?.name??null}function c(e,n=new Map){return{label:s(e,n)??t(e),full:e,scratch:a(e)}}var l=e=>e.length>14?`${e.slice(0,13)}…`:e;function u(e,t){let n=new Map(e.map(e=>[e,e.split(`/`).filter(Boolean).reverse()])),r=new Map;for(let i of e){let a=n.get(i),o=null,s=null;for(let r=0;r<a.length&&s===null;r++){let c=a[r];c!==t&&c!==`~`&&(o??=c,e.every(e=>e===i||n.get(e)[r]!==c)&&(s=c))}r.set(i,s??o)}return r}function d(e,t=new Map){let n=new Map;for(let t of[...new Set(e)].sort()){let e=r(t);n.set(e,[...n.get(e)??[],t])}let i=new Map;for(let[e,r]of n){let n=c(r[0],t).label;i.set(n,[...i.get(n)??[],e])}let o=new Map,s=new Map;for(let[e,t]of i){let n=t.length>1?u(t,e):null;for(let r of t){let t=n?.get(r)??null;o.set(r,t?`${e} (${l(t)})`:e),t&&l(t)!==t&&s.set(r,`${e} (${t})`)}}let d=new Map;for(let e of o.values())d.set(e,(d.get(e)??0)+1);let f=new Set,p=new Map;for(let e of[...o.keys()].sort()){let t=o.get(e),n=d.get(t)>1?s.get(e)??t:t,r=n;for(let e=2;f.has(r);e++)r=`${n} #${e}`;f.add(r),p.set(e,r)}let m=new Map;for(let[e,t]of n)for(let n of t)m.set(n,{label:p.get(e),full:n,scratch:a(n)});return m}var f=[`loop`,`struggle`,`verification-gap`,`uncertainty`,`backtrack`,`win`],p={loop:`Loops`,struggle:`Repeated failures`,"verification-gap":`Edits without tests`,uncertainty:`Uncertainty`,backtrack:`Backtracking`,win:`Wins`},m={claude:`Claude`,codex:`Codex`,grok:`Grok`,local:`Local`},h=[`claude`,`codex`,`grok`,`local`];function g(e){return h.includes(e)?e:null}function _(e){if(!e)return[];let t=new Map;for(let n of e.insights){if(!n.repo)continue;let e=r(n.repo),i=t.get(e)??{total:0,spellings:new Map};i.total+=n.count,i.spellings.set(n.repo,(i.spellings.get(n.repo)??0)+n.count),t.set(e,i)}let n=(e,t)=>t[1]-e[1]||e[0].localeCompare(t[0]);return[...t.values()].map(e=>[[...e.spellings.entries()].sort(n)[0][0],e.total]).sort(n).map(([e])=>e)}function v(e,t){return!!e&&(e===t||r(e)===r(t))}function y(e,t){let n=f.map(e=>({id:e,label:p[e]}));if(!e)return{rows:n,columns:[],values:[]};let r=[...new Set([...Object.keys(e.totals.byEngine),...e.insights.map(e=>e.engine).filter(e=>!!e)])].sort((e,t)=>{let n=h.indexOf(e),r=h.indexOf(t);return(n===-1?99:n)-(r===-1?99:r)||e.localeCompare(t)}),i=r.map(e=>{let t=g(e);return{id:e,label:m[e]??e,...t?{engine:t}:{}}}),a=e.insights.filter(e=>t===null||v(e.repo,t));return{rows:n,columns:i,values:f.map(t=>r.map(n=>{let r=(e.totals.byEngine[n]??0)>0,i=a.filter(e=>e.kind===t&&e.engine===n).reduce((e,t)=>e+t.count,0);return r||i>0?i:null}))}}function b(e,t=3){if(!e)return[];let n={high:0,warn:1,info:2};return e.insights.filter(e=>e.kind!==`win`).sort((e,t)=>n[e.severity]-n[t.severity]||Date.parse(t.lastAt)-Date.parse(e.lastAt)).slice(0,t)}function x(t){if(!t)return[];let r=e=>t.trends.map(t=>({x:n(t.day),y:t.steps===0?null:e(t)}));return[{id:`struggles`,label:`Struggles`,color:e(`warning`),points:r(e=>e.struggles)},{id:`wins`,label:`Wins`,color:e(`success`),points:r(e=>e.wins)}]}var S=new Set([`loop`,`struggle`]);function C(e,t){return e.evidence.some(e=>e.ref.startsWith(`session:${t}#`)||e.ref.startsWith(`verse:${t}:`))}function w(e,t){return!e||!t?[]:e.insights.filter(e=>S.has(e.kind)&&C(e,t)).sort((e,t)=>Date.parse(t.lastAt)-Date.parse(e.lastAt))}var T={stack:`_stack_1bdwr_5`,muted:`_muted_1bdwr_11`,link:`_link_1bdwr_17`,veto:`_veto_1bdwr_33`,chip:`_chip_1bdwr_34`,timeline:`_timeline_1bdwr_40`,memo:`_memo_1bdwr_48`,memoDay:`_memoDay_1bdwr_62`,mark:`_mark_1bdwr_69`,memoBody:`_memoBody_1bdwr_92`,memoMove:`_memoMove_1bdwr_99`,memoWhy:`_memoWhy_1bdwr_106`,memoMeta:`_memoMeta_1bdwr_113`,standards:`_standards_1bdwr_157`,standardRule:`_standardRule_1bdwr_172`,standardMeta:`_standardMeta_1bdwr_178`,insights:`_insights_1bdwr_184`,insight:`_insight_1bdwr_184`,insightKind:`_insightKind_1bdwr_213`,insightSeverity:`_insightSeverity_1bdwr_220`,insightTitle:`_insightTitle_1bdwr_233`,insightMeta:`_insightMeta_1bdwr_240`,insightPlace:`_insightPlace_1bdwr_248`,scratchTag:`_scratchTag_1bdwr_254`,log:`_log_1bdwr_266`,facet:`_facet_1bdwr_274`,chipWrap:`_chipWrap_1bdwr_294`,chipDot:`_chipDot_1bdwr_321`,chipMore:`_chipMore_1bdwr_332`,chipPanel:`_chipPanel_1bdwr_336`,chipList:`_chipList_1bdwr_352`};export{x as a,c,_ as i,d as l,p as n,w as o,y as r,b as s,T as t,o as u};
|
|
2
|
+
//# sourceMappingURL=mind.module-CLhqMQak.js.map
|
package/dist/core/web/public/next/assets/{mind.module-vnuJcwvD.js.map → mind.module-CLhqMQak.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mind.module-vnuJcwvD.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/mind/project-label.ts","../../../../../../src/web-ui/routes/verse/mind/mind-model.ts","../../../../../../src/web-ui/routes/verse/mind/mind.module.css"],"sourcesContent":["/**\n * routes/verse/mind/project-label.ts — how Mind names the place a reasoning\n * insight happened.\n *\n * A7 keys insights by the workspace path the engine ran in, verbatim, so the\n * cards used to read \"/private/tmp/claude-501/-Users-…/9d28bdb1-…/scratchpad/\n * grokpad · grok · 1×\". The card now shows a human label:\n *\n * 1. the REGISTERED name — a saved project (Chat → Projects) whose root is\n * that folder or contains it, else a project Verse knows from bootstrap;\n * 2. otherwise the folder's own name (`grokpad`), the same rule a saved\n * project uses when the operator names nothing (defaultWorkspaceName).\n *\n * The full path is never dropped: it rides in the tooltip. A folder under the\n * OS temp directory (an agent's scratchpad, a test fixture) is tagged\n * `scratch` rather than hidden — the insight is real, the place is throwaway.\n * The browser cannot ask the OS for its temp dir, so the well-known locations\n * are matched instead (macOS /tmp, /private/tmp and the per-user\n * /var/folders/…/T; Linux /tmp and /var/tmp; Windows …\\AppData\\Local\\Temp).\n *\n * Two different folders that would read the same (two agents' `scratchpad`s)\n * get a short distinguisher appended, so the Repo facet never offers two\n * identical choices; two spellings of ONE folder share one label.\n *\n * Framework-free; tested directly.\n */\nimport type { VerseProject, VerseWorkspace } from '../../../data/api-types.js';\nimport { defaultWorkspaceName } from '../workspace-model.js';\n\nexport interface ProjectLabel {\n /** What the card draws: the registered name, else the folder's own name. */\n label: string;\n /** The path (or slug) exactly as recorded — the tooltip. */\n full: string;\n /** Lives under the OS temp directory: a scratch folder, not a project. */\n scratch: boolean;\n}\n\n/** Registered names keyed by `pathKey(root)`. */\nexport type ProjectNames = ReadonlyMap<string, string>;\n\n/**\n * A comparable form of a path: `/` separators, no trailing separator, the\n * macOS `/private` alias folded (`/tmp` and `/var` are symlinks into it, and\n * the same folder is recorded either way), a home directory as `~` (a project\n * saved as `~/dev/hub` still runs in `/Users/me/dev/hub`).\n */\nexport function pathKey(path: string): string {\n let p = path.trim().replace(/\\\\/g, '/').replace(/\\/+$/, '');\n p = p.replace(/^\\/private(?=\\/(?:tmp|var)(?:\\/|$))/, '');\n p = p.replace(/^(?:\\/Users\\/[^/]+|\\/home\\/[^/]+|[A-Za-z]:\\/Users\\/[^/]+)(?=\\/|$)/, '~');\n return p || '/';\n}\n\nconst SCRATCH_ROOTS: readonly RegExp[] = [\n /^\\/tmp(?:\\/|$)/, // also /private/tmp, folded by pathKey\n /^\\/var\\/tmp(?:\\/|$)/,\n /^\\/var\\/folders\\/[^/]+\\/[^/]+\\/T(?:\\/|$)/, // macOS per-user $TMPDIR\n /^[A-Za-z]:\\/Windows\\/Temp(?:\\/|$)/i,\n /\\/AppData\\/Local\\/Temp(?:\\/|$)/i,\n];\n\n/** Is this folder under the OS temp directory? */\nexport function isScratchPath(path: string): boolean {\n const key = pathKey(path);\n return SCRATCH_ROOTS.some((re) => re.test(key));\n}\n\n/**\n * Registered names by root. Saved projects win (the operator named them),\n * then Verse's known projects; every root of a multi-folder project maps to\n * that project's name.\n */\nexport function projectNames(\n workspaces: readonly { name: VerseWorkspace['name']; roots: readonly { path: string }[] }[] | null | undefined,\n projects: readonly Pick<VerseProject, 'name' | 'path'>[] | null | undefined,\n): Map<string, string> {\n const names = new Map<string, string>();\n const add = (path: string, name: string) => {\n const key = pathKey(path);\n const label = name.trim();\n if (key !== '/' && key !== '~' && label && !names.has(key)) names.set(key, label);\n };\n for (const w of workspaces ?? []) for (const r of w.roots) add(r.path, w.name);\n for (const p of projects ?? []) add(p.path, p.name);\n return names;\n}\n\n/** The registered name for `path`: its own root, else the longest registered root containing it. */\nfunction registeredName(path: string, names: ProjectNames): string | null {\n const key = pathKey(path);\n const exact = names.get(key);\n if (exact !== undefined) return exact;\n let best: { root: string; name: string } | null = null;\n for (const [root, name] of names) {\n if (key.startsWith(`${root}/`) && (!best || root.length > best.root.length)) best = { root, name };\n }\n return best?.name ?? null;\n}\n\n/** One insight's place, as the card draws it. */\nexport function projectLabel(repo: string, names: ProjectNames = new Map()): ProjectLabel {\n return { label: registeredName(repo, names) ?? defaultWorkspaceName(repo), full: repo, scratch: isScratchPath(repo) };\n}\n\nconst short = (name: string) => (name.length > 14 ? `${name.slice(0, 13)}…` : name);\n\n/**\n * What tells same-label folders apart, per folder (keyed by `pathKey`):\n * walking up from the folder itself, the NEAREST path segment that no other\n * folder in the group has at that same depth — `grokpad (9d28bdb1-4c1e…)` for\n * two agents' `…/<uuid>/scratchpad/grokpad` (their parents are both\n * `scratchpad`), `Hub (a)` for two folders under one registered project. A\n * segment that only repeats the label (or is the home `~`) says nothing and\n * is skipped. When no single segment is unique, the nearest informative one\n * is returned and `projectLabels` settles whatever still collides.\n */\nfunction distinguishers(keys: readonly string[], label: string): Map<string, string | null> {\n const parts = new Map(keys.map((k) => [k, k.split('/').filter(Boolean).reverse()]));\n const out = new Map<string, string | null>();\n for (const key of keys) {\n const mine = parts.get(key)!;\n let nearest: string | null = null;\n let unique: string | null = null;\n for (let depth = 0; depth < mine.length && unique === null; depth++) {\n const seg = mine[depth]!;\n if (seg === label || seg === '~') continue;\n nearest ??= seg;\n if (keys.every((other) => other === key || parts.get(other)![depth] !== seg)) unique = seg;\n }\n out.set(key, unique ?? nearest);\n }\n return out;\n}\n\n/**\n * Labels for every repo on a surface at once, so the cards and the Repo facet\n * agree — and two different folders NEVER read the same:\n *\n * 1. spellings of one folder (`/tmp/x` and `/private/tmp/x`: one `pathKey`)\n * share one label; each keeps its own `full` path for the tooltip;\n * 2. different folders that would read the same get their nearest\n * distinguishing ancestor appended, shortened (`distinguishers`);\n * 3. whatever still collides — two ancestors that shorten alike, a folder\n * with nothing left to tell it apart — is settled by construction: the\n * whole segment instead of the shortened one, then an ordinal (\"#2\").\n */\nexport function projectLabels(repos: readonly string[], names: ProjectNames = new Map()): Map<string, ProjectLabel> {\n // One entry per folder, in a stable order: the labels never depend on the\n // order the insights arrived in.\n const spellings = new Map<string, string[]>();\n for (const repo of [...new Set(repos)].sort()) {\n const key = pathKey(repo);\n spellings.set(key, [...(spellings.get(key) ?? []), repo]);\n }\n const byLabel = new Map<string, string[]>();\n for (const [key, list] of spellings) {\n const label = projectLabel(list[0]!, names).label;\n byLabel.set(label, [...(byLabel.get(label) ?? []), key]);\n }\n\n const wanted = new Map<string, string>();\n const whole = new Map<string, string>();\n for (const [label, keys] of byLabel) {\n const extra = keys.length > 1 ? distinguishers(keys, label) : null;\n for (const key of keys) {\n const seg = extra?.get(key) ?? null;\n wanted.set(key, seg ? `${label} (${short(seg)})` : label);\n if (seg && short(seg) !== seg) whole.set(key, `${label} (${seg})`);\n }\n }\n\n const shared = new Map<string, number>();\n for (const l of wanted.values()) shared.set(l, (shared.get(l) ?? 0) + 1);\n const taken = new Set<string>();\n const labelOf = new Map<string, string>();\n for (const key of [...wanted.keys()].sort()) {\n const first = wanted.get(key)!;\n const pick = shared.get(first)! > 1 ? (whole.get(key) ?? first) : first;\n let label = pick;\n for (let n = 2; taken.has(label); n++) label = `${pick} #${n}`;\n taken.add(label);\n labelOf.set(key, label);\n }\n\n const out = new Map<string, ProjectLabel>();\n for (const [key, list] of spellings) {\n for (const repo of list) out.set(repo, { label: labelOf.get(key)!, full: repo, scratch: isScratchPath(repo) });\n }\n return out;\n}\n","/**\n * routes/verse/mind/mind-model.ts — the reasoning digest (A7) as Mind's\n * charts and cards, plus the chat-header chip's matching rule (unit C7;\n * SPEC-310B §6 Mind, SPEC-310C §5).\n *\n * The matrix is insight KIND × ENGINE, faceted by repo. A cell is:\n * - a count of insight occurrences when that engine produced reasoning in\n * the window (0 is a real zero: it reasoned and nothing was flagged);\n * - UNKNOWN (null) when that engine recorded no reasoning at all — nothing\n * was measured, so nothing can be said (hatched, never a pale zero).\n *\n * Framework-free; tested directly.\n */\nimport type { ReasoningDigest, ReasoningInsight, ReasoningInsightKind } from '../../../../core/reasoning/types.js';\nimport type { ChartEngine } from '../../../components/charts/colors.js';\nimport type { MatrixAxisItem } from '../../../components/charts/MatrixHeatmap.js';\nimport type { AreaTrendSeries } from '../../../components/charts/AreaTrend.js';\nimport { toneColor } from '../../../components/charts/colors.js';\nimport { calendarDayStart } from '../growth/calendar-day.js';\nimport { pathKey } from './project-label.js';\n\nexport const INSIGHT_KINDS: readonly ReasoningInsightKind[] = ['loop', 'struggle', 'verification-gap', 'uncertainty', 'backtrack', 'win'];\n\nexport const KIND_LABEL: Readonly<Record<ReasoningInsightKind, string>> = {\n loop: 'Loops',\n struggle: 'Repeated failures',\n 'verification-gap': 'Edits without tests',\n uncertainty: 'Uncertainty',\n backtrack: 'Backtracking',\n win: 'Wins',\n};\n\nconst ENGINE_LABEL: Readonly<Record<string, string>> = { claude: 'Claude', codex: 'Codex', grok: 'Grok', local: 'Local' };\nconst KNOWN_ENGINES: readonly ChartEngine[] = ['claude', 'codex', 'grok', 'local'];\n\nfunction asEngine(name: string): ChartEngine | null {\n return (KNOWN_ENGINES as readonly string[]).includes(name) ? (name as ChartEngine) : null;\n}\n\n/**\n * Repos that appear in the digest's insights, most insight occurrences first\n * — ONE per folder: two spellings of the same folder (`/tmp/x` and\n * `/private/tmp/x`, which `pathKey` treats as one) are one Repo facet entry,\n * named by the spelling recorded most often.\n */\nexport function insightRepos(digest: ReasoningDigest | null): string[] {\n if (!digest) return [];\n const folders = new Map<string, { total: number; spellings: Map<string, number> }>();\n for (const i of digest.insights) {\n if (!i.repo) continue;\n const key = pathKey(i.repo);\n const f = folders.get(key) ?? { total: 0, spellings: new Map<string, number>() };\n f.total += i.count;\n f.spellings.set(i.repo, (f.spellings.get(i.repo) ?? 0) + i.count);\n folders.set(key, f);\n }\n const byCount = (a: [string, number], b: [string, number]) => b[1] - a[1] || a[0].localeCompare(b[0]);\n return [...folders.values()]\n .map((f) => [[...f.spellings.entries()].sort(byCount)[0]![0], f.total] as [string, number])\n .sort(byCount)\n .map(([r]) => r);\n}\n\n/** Does insight `repo` name the same folder as facet `facet` (any spelling)? */\nfunction sameFolder(repo: string | null | undefined, facet: string): boolean {\n return !!repo && (repo === facet || pathKey(repo) === pathKey(facet));\n}\n\nexport interface InsightMatrix {\n rows: MatrixAxisItem[];\n columns: MatrixAxisItem[];\n values: (number | null)[][];\n}\n\n/** `repo` null = every repo. */\nexport function insightMatrix(digest: ReasoningDigest | null, repo: string | null): InsightMatrix {\n const rows = INSIGHT_KINDS.map((k) => ({ id: k, label: KIND_LABEL[k] }));\n if (!digest) return { rows, columns: [], values: [] };\n // Columns: every engine that reasoned in the window, plus any engine an\n // insight names (so a count is never dropped), known engines first.\n const names = new Set<string>([...Object.keys(digest.totals.byEngine), ...digest.insights.map((i) => i.engine).filter((e): e is string => !!e)]);\n const ordered = [...names].sort((a, b) => {\n const ia = KNOWN_ENGINES.indexOf(a as ChartEngine);\n const ib = KNOWN_ENGINES.indexOf(b as ChartEngine);\n return (ia === -1 ? 99 : ia) - (ib === -1 ? 99 : ib) || a.localeCompare(b);\n });\n const columns: MatrixAxisItem[] = ordered.map((name) => {\n const engine = asEngine(name);\n return { id: name, label: ENGINE_LABEL[name] ?? name, ...(engine ? { engine } : {}) };\n });\n const insights = digest.insights.filter((i) => repo === null || sameFolder(i.repo, repo));\n const values = INSIGHT_KINDS.map((kind) =>\n ordered.map((engine) => {\n const measured = (digest.totals.byEngine[engine] ?? 0) > 0;\n const count = insights.filter((i) => i.kind === kind && i.engine === engine).reduce((n, i) => n + i.count, 0);\n return measured || count > 0 ? count : null;\n }),\n );\n return { rows, columns, values };\n}\n\n/** The three cards: most severe first, then most recent — wins are not problems. */\nexport function topInsights(digest: ReasoningDigest | null, n = 3): ReasoningInsight[] {\n if (!digest) return [];\n const rank = { high: 0, warn: 1, info: 2 } as const;\n return digest.insights\n .filter((i) => i.kind !== 'win')\n .sort((a, b) => rank[a.severity] - rank[b.severity] || Date.parse(b.lastAt) - Date.parse(a.lastAt))\n .slice(0, n);\n}\n\n/**\n * Struggles vs wins per day, for the trends card. Each day is stamped at the\n * viewer's LOCAL midnight (`calendarDayStart`), because the chart labels its\n * x values in the local zone: a UTC-midnight stamp read one day early west of\n * UTC (\"2026-09-24\" as \"Sep 23\").\n */\nexport function reasoningTrendSeries(digest: ReasoningDigest | null): AreaTrendSeries[] {\n if (!digest) return [];\n const pts = (pick: (d: ReasoningDigest['trends'][number]) => number) =>\n digest.trends.map((d) => ({ x: calendarDayStart(d.day), y: d.steps === 0 ? null : pick(d) }));\n return [\n { id: 'struggles', label: 'Struggles', color: toneColor('warning'), points: pts((d) => d.struggles) },\n { id: 'wins', label: 'Wins', color: toneColor('success'), points: pts((d) => d.wins) },\n ];\n}\n\n// ---------------------------------------------------------------------------\n// SessionInsightChip\n// ---------------------------------------------------------------------------\n\n/** The chip shows only the insight kinds that mean \"this chat is stuck\". */\nexport const CHIP_KINDS: ReadonlySet<ReasoningInsightKind> = new Set(['loop', 'struggle']);\n\n/**\n * Does `insight` cite chat `sessionId`? Verse evidence refs are\n * `session:<id>#<seq>` (tool / message events) or `verse:<id>:<turn|seq>`\n * (thinking steps) — A7's ingest-verse.ts. The id is matched exactly up to\n * its delimiter, so chat `s1` never matches `s12`.\n */\nexport function citesSession(insight: Pick<ReasoningInsight, 'evidence'>, sessionId: string): boolean {\n return insight.evidence.some((e) => e.ref.startsWith(`session:${sessionId}#`) || e.ref.startsWith(`verse:${sessionId}:`));\n}\n\nexport function sessionInsights(digest: ReasoningDigest | null, sessionId: string): ReasoningInsight[] {\n if (!digest || !sessionId) return [];\n return digest.insights\n .filter((i) => CHIP_KINDS.has(i.kind) && citesSession(i, sessionId))\n .sort((a, b) => Date.parse(b.lastAt) - Date.parse(a.lastAt));\n}\n","/*\n * routes/verse/mind/mind.module.css — Mind cards and the chat-header chip\n * (unit C7). Tokens only (style-scan-310).\n */\n.stack {\n display: flex;\n flex-direction: column;\n gap: var(--surface-gap);\n}\n\n.muted {\n margin: 0;\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n}\n\n.link {\n align-self: flex-start;\n padding: 0;\n border: 0;\n background: none;\n color: var(--text-link);\n font: inherit;\n font-size: var(--text-xs-size);\n cursor: pointer;\n}\n\n.link:hover {\n text-decoration: underline;\n}\n\n.link:focus-visible,\n.veto:focus-visible,\n.chip:focus-visible {\n outline: 2px solid var(--border-focus);\n outline-offset: 2px;\n}\n\n/* ---- memo timeline ---------------------------------------------------- */\n.timeline {\n display: flex;\n flex-direction: column;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.memo {\n display: grid;\n grid-template-columns: 88px 20px minmax(0, 1fr) auto;\n gap: var(--space-3);\n align-items: start;\n padding: var(--space-3) 0;\n border-top: 1px solid var(--border-subtle);\n}\n\n.memo:first-child {\n border-top: 0;\n padding-top: 0;\n}\n\n.memoDay {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-sm-line);\n font-variant-numeric: tabular-nums;\n}\n\n.mark {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border-radius: var(--radius-full);\n background: var(--status-neutral-bg);\n color: var(--status-neutral-fg);\n font-size: var(--text-xs-size);\n font-weight: var(--font-weight-semibold);\n}\n\n.mark[data-outcome='hit'] {\n background: var(--status-success-bg);\n color: var(--status-success-fg);\n}\n\n.mark[data-outcome='miss'] {\n background: var(--status-danger-bg);\n color: var(--status-danger-fg);\n}\n\n.memoBody {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.memoMove {\n color: var(--text-primary);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n overflow-wrap: anywhere;\n}\n\n.memoWhy {\n color: var(--text-secondary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n overflow-wrap: anywhere;\n}\n\n.memoMeta {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n\n.memoMeta [data-outcome='hit'] {\n color: var(--status-success-fg);\n}\n\n.memoMeta [data-outcome='miss'] {\n color: var(--status-danger-fg);\n}\n\n.veto {\n min-height: var(--control-h-sm);\n padding: 0 var(--space-3);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n background: transparent;\n color: var(--text-primary);\n font: inherit;\n font-size: var(--text-xs-size);\n cursor: pointer;\n}\n\n.veto:hover {\n background: var(--bg-hover);\n}\n\n.veto:disabled {\n color: var(--text-disabled);\n cursor: default;\n}\n\n[data-viewport='compact'] .memo {\n grid-template-columns: 20px minmax(0, 1fr) auto;\n}\n\n[data-viewport='compact'] .memoDay {\n grid-column: 1 / -1;\n}\n\n/* ---- standards -------------------------------------------------------- */\n.standards {\n display: flex;\n flex-direction: column;\n gap: var(--space-3);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.standards li {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.standardRule {\n color: var(--text-primary);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line-relaxed);\n}\n\n.standardMeta {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n}\n\n/* ---- insight cards ---------------------------------------------------- */\n.insights {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: var(--surface-gap);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n[data-viewport='compact'] .insights,\n[data-viewport='medium'] .insights {\n grid-template-columns: minmax(0, 1fr);\n}\n\n.insight {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n padding: var(--card-pad);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-lg);\n background: var(--bg-surface);\n box-shadow: inset 0 1px 0 var(--hairline-lift, transparent);\n}\n\n.insight[data-severity='high'] {\n border-color: var(--status-danger-solid);\n}\n\n.insightKind {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-2);\n}\n\n.insightSeverity {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n}\n\n.insightSeverity[data-severity='high'] {\n color: var(--status-danger-fg);\n}\n\n.insightSeverity[data-severity='warn'] {\n color: var(--status-warning-fg);\n}\n\n.insightTitle {\n color: var(--text-primary);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line-relaxed);\n overflow-wrap: anywhere;\n}\n\n.insightMeta {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n\n/* The project's name reads a step stronger than the rest of the meta line;\n the full path is its tooltip. */\n.insightPlace {\n color: var(--text-secondary);\n overflow-wrap: anywhere;\n}\n\n/* A folder under the OS temp dir: tagged, quietly — never hidden. */\n.scratchTag {\n display: inline-block;\n margin-left: var(--space-1);\n padding: 0 var(--space-1);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-sm);\n color: var(--text-tertiary);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n vertical-align: 1px;\n}\n\n.log {\n display: flex;\n flex-direction: column;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.facet {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n}\n\n.facet select {\n min-height: var(--control-h-xs);\n padding: 0 var(--space-2);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n background: var(--bg-input);\n color: var(--text-primary);\n font: inherit;\n font-size: var(--text-xs-size);\n}\n\n/* ---- chat-header chip ------------------------------------------------- */\n.chipWrap {\n position: relative;\n display: inline-flex;\n}\n\n.chip {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n min-height: var(--control-h-xs);\n padding: 0 var(--space-2);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-full);\n background: var(--bg-surface);\n color: var(--text-secondary);\n font: inherit;\n font-size: var(--text-xs-size);\n white-space: nowrap;\n cursor: pointer;\n}\n\n.chip:hover,\n.chip[aria-expanded='true'] {\n background: var(--bg-hover);\n color: var(--text-primary);\n}\n\n.chipDot {\n width: 6px;\n height: 6px;\n border-radius: var(--radius-full);\n background: var(--status-warning-solid);\n}\n\n.chipDot[data-severity='high'] {\n background: var(--status-danger-solid);\n}\n\n.chipMore {\n color: var(--text-tertiary);\n}\n\n.chipPanel {\n position: absolute;\n top: calc(100% + var(--space-1));\n right: 0;\n z-index: var(--z-dropdown);\n display: flex;\n flex-direction: column;\n gap: var(--space-3);\n width: min(320px, calc(100vw - var(--space-8)));\n padding: var(--space-3);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-md);\n background: var(--bg-surface-raised);\n box-shadow: var(--shadow-menu);\n}\n\n.chipList {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.chipList li {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mind.module-CLhqMQak.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/mind/project-label.ts","../../../../../../src/web-ui/routes/verse/mind/mind-model.ts","../../../../../../src/web-ui/routes/verse/mind/mind.module.css"],"sourcesContent":["/**\n * routes/verse/mind/project-label.ts — how Mind names the place a reasoning\n * insight happened.\n *\n * A7 keys insights by the workspace path the engine ran in, verbatim, so the\n * cards used to read \"/private/tmp/claude-501/-Users-…/9d28bdb1-…/scratchpad/\n * grokpad · grok · 1×\". The card now shows a human label:\n *\n * 1. the REGISTERED name — a saved project (Chat → Projects) whose root is\n * that folder or contains it, else a project Verse knows from bootstrap;\n * 2. otherwise the folder's own name (`grokpad`), the same rule a saved\n * project uses when the operator names nothing (defaultWorkspaceName).\n *\n * The full path is never dropped: it rides in the tooltip. A folder under the\n * OS temp directory (an agent's scratchpad, a test fixture) is tagged\n * `scratch` rather than hidden — the insight is real, the place is throwaway.\n * The browser cannot ask the OS for its temp dir, so the well-known locations\n * are matched instead (macOS /tmp, /private/tmp and the per-user\n * /var/folders/…/T; Linux /tmp and /var/tmp; Windows …\\AppData\\Local\\Temp).\n *\n * Two different folders that would read the same (two agents' `scratchpad`s)\n * get a short distinguisher appended, so the Repo facet never offers two\n * identical choices; two spellings of ONE folder share one label.\n *\n * Framework-free; tested directly.\n */\nimport type { VerseProject, VerseWorkspace } from '../../../data/api-types.js';\nimport { defaultWorkspaceName } from '../workspace-model.js';\n\nexport interface ProjectLabel {\n /** What the card draws: the registered name, else the folder's own name. */\n label: string;\n /** The path (or slug) exactly as recorded — the tooltip. */\n full: string;\n /** Lives under the OS temp directory: a scratch folder, not a project. */\n scratch: boolean;\n}\n\n/** Registered names keyed by `pathKey(root)`. */\nexport type ProjectNames = ReadonlyMap<string, string>;\n\n/**\n * A comparable form of a path: `/` separators, no trailing separator, the\n * macOS `/private` alias folded (`/tmp` and `/var` are symlinks into it, and\n * the same folder is recorded either way), a home directory as `~` (a project\n * saved as `~/dev/hub` still runs in `/Users/me/dev/hub`).\n */\nexport function pathKey(path: string): string {\n let p = path.trim().replace(/\\\\/g, '/').replace(/\\/+$/, '');\n p = p.replace(/^\\/private(?=\\/(?:tmp|var)(?:\\/|$))/, '');\n p = p.replace(/^(?:\\/Users\\/[^/]+|\\/home\\/[^/]+|[A-Za-z]:\\/Users\\/[^/]+)(?=\\/|$)/, '~');\n return p || '/';\n}\n\nconst SCRATCH_ROOTS: readonly RegExp[] = [\n /^\\/tmp(?:\\/|$)/, // also /private/tmp, folded by pathKey\n /^\\/var\\/tmp(?:\\/|$)/,\n /^\\/var\\/folders\\/[^/]+\\/[^/]+\\/T(?:\\/|$)/, // macOS per-user $TMPDIR\n /^[A-Za-z]:\\/Windows\\/Temp(?:\\/|$)/i,\n /\\/AppData\\/Local\\/Temp(?:\\/|$)/i,\n];\n\n/** Is this folder under the OS temp directory? */\nexport function isScratchPath(path: string): boolean {\n const key = pathKey(path);\n return SCRATCH_ROOTS.some((re) => re.test(key));\n}\n\n/**\n * Registered names by root. Saved projects win (the operator named them),\n * then Verse's known projects; every root of a multi-folder project maps to\n * that project's name.\n */\nexport function projectNames(\n workspaces: readonly { name: VerseWorkspace['name']; roots: readonly { path: string }[] }[] | null | undefined,\n projects: readonly Pick<VerseProject, 'name' | 'path'>[] | null | undefined,\n): Map<string, string> {\n const names = new Map<string, string>();\n const add = (path: string, name: string) => {\n const key = pathKey(path);\n const label = name.trim();\n if (key !== '/' && key !== '~' && label && !names.has(key)) names.set(key, label);\n };\n for (const w of workspaces ?? []) for (const r of w.roots) add(r.path, w.name);\n for (const p of projects ?? []) add(p.path, p.name);\n return names;\n}\n\n/** The registered name for `path`: its own root, else the longest registered root containing it. */\nfunction registeredName(path: string, names: ProjectNames): string | null {\n const key = pathKey(path);\n const exact = names.get(key);\n if (exact !== undefined) return exact;\n let best: { root: string; name: string } | null = null;\n for (const [root, name] of names) {\n if (key.startsWith(`${root}/`) && (!best || root.length > best.root.length)) best = { root, name };\n }\n return best?.name ?? null;\n}\n\n/** One insight's place, as the card draws it. */\nexport function projectLabel(repo: string, names: ProjectNames = new Map()): ProjectLabel {\n return { label: registeredName(repo, names) ?? defaultWorkspaceName(repo), full: repo, scratch: isScratchPath(repo) };\n}\n\nconst short = (name: string) => (name.length > 14 ? `${name.slice(0, 13)}…` : name);\n\n/**\n * What tells same-label folders apart, per folder (keyed by `pathKey`):\n * walking up from the folder itself, the NEAREST path segment that no other\n * folder in the group has at that same depth — `grokpad (9d28bdb1-4c1e…)` for\n * two agents' `…/<uuid>/scratchpad/grokpad` (their parents are both\n * `scratchpad`), `Hub (a)` for two folders under one registered project. A\n * segment that only repeats the label (or is the home `~`) says nothing and\n * is skipped. When no single segment is unique, the nearest informative one\n * is returned and `projectLabels` settles whatever still collides.\n */\nfunction distinguishers(keys: readonly string[], label: string): Map<string, string | null> {\n const parts = new Map(keys.map((k) => [k, k.split('/').filter(Boolean).reverse()]));\n const out = new Map<string, string | null>();\n for (const key of keys) {\n const mine = parts.get(key)!;\n let nearest: string | null = null;\n let unique: string | null = null;\n for (let depth = 0; depth < mine.length && unique === null; depth++) {\n const seg = mine[depth]!;\n if (seg === label || seg === '~') continue;\n nearest ??= seg;\n if (keys.every((other) => other === key || parts.get(other)![depth] !== seg)) unique = seg;\n }\n out.set(key, unique ?? nearest);\n }\n return out;\n}\n\n/**\n * Labels for every repo on a surface at once, so the cards and the Repo facet\n * agree — and two different folders NEVER read the same:\n *\n * 1. spellings of one folder (`/tmp/x` and `/private/tmp/x`: one `pathKey`)\n * share one label; each keeps its own `full` path for the tooltip;\n * 2. different folders that would read the same get their nearest\n * distinguishing ancestor appended, shortened (`distinguishers`);\n * 3. whatever still collides — two ancestors that shorten alike, a folder\n * with nothing left to tell it apart — is settled by construction: the\n * whole segment instead of the shortened one, then an ordinal (\"#2\").\n */\nexport function projectLabels(repos: readonly string[], names: ProjectNames = new Map()): Map<string, ProjectLabel> {\n // One entry per folder, in a stable order: the labels never depend on the\n // order the insights arrived in.\n const spellings = new Map<string, string[]>();\n for (const repo of [...new Set(repos)].sort()) {\n const key = pathKey(repo);\n spellings.set(key, [...(spellings.get(key) ?? []), repo]);\n }\n const byLabel = new Map<string, string[]>();\n for (const [key, list] of spellings) {\n const label = projectLabel(list[0]!, names).label;\n byLabel.set(label, [...(byLabel.get(label) ?? []), key]);\n }\n\n const wanted = new Map<string, string>();\n const whole = new Map<string, string>();\n for (const [label, keys] of byLabel) {\n const extra = keys.length > 1 ? distinguishers(keys, label) : null;\n for (const key of keys) {\n const seg = extra?.get(key) ?? null;\n wanted.set(key, seg ? `${label} (${short(seg)})` : label);\n if (seg && short(seg) !== seg) whole.set(key, `${label} (${seg})`);\n }\n }\n\n const shared = new Map<string, number>();\n for (const l of wanted.values()) shared.set(l, (shared.get(l) ?? 0) + 1);\n const taken = new Set<string>();\n const labelOf = new Map<string, string>();\n for (const key of [...wanted.keys()].sort()) {\n const first = wanted.get(key)!;\n const pick = shared.get(first)! > 1 ? (whole.get(key) ?? first) : first;\n let label = pick;\n for (let n = 2; taken.has(label); n++) label = `${pick} #${n}`;\n taken.add(label);\n labelOf.set(key, label);\n }\n\n const out = new Map<string, ProjectLabel>();\n for (const [key, list] of spellings) {\n for (const repo of list) out.set(repo, { label: labelOf.get(key)!, full: repo, scratch: isScratchPath(repo) });\n }\n return out;\n}\n","/**\n * routes/verse/mind/mind-model.ts — the reasoning digest (A7) as Mind's\n * charts and cards, plus the chat-header chip's matching rule (unit C7;\n * SPEC-310B §6 Mind, SPEC-310C §5).\n *\n * The matrix is insight KIND × ENGINE, faceted by repo. A cell is:\n * - a count of insight occurrences when that engine produced reasoning in\n * the window (0 is a real zero: it reasoned and nothing was flagged);\n * - UNKNOWN (null) when that engine recorded no reasoning at all — nothing\n * was measured, so nothing can be said (hatched, never a pale zero).\n *\n * Framework-free; tested directly.\n */\nimport type { ReasoningDigest, ReasoningInsight, ReasoningInsightKind } from '../../../../core/reasoning/types.js';\nimport type { ChartEngine } from '../../../components/charts/colors.js';\nimport type { MatrixAxisItem } from '../../../components/charts/MatrixHeatmap.js';\nimport type { AreaTrendSeries } from '../../../components/charts/AreaTrend.js';\nimport { toneColor } from '../../../components/charts/colors.js';\nimport { calendarDayStart } from '../growth/calendar-day.js';\nimport { pathKey } from './project-label.js';\n\nexport const INSIGHT_KINDS: readonly ReasoningInsightKind[] = ['loop', 'struggle', 'verification-gap', 'uncertainty', 'backtrack', 'win'];\n\nexport const KIND_LABEL: Readonly<Record<ReasoningInsightKind, string>> = {\n loop: 'Loops',\n struggle: 'Repeated failures',\n 'verification-gap': 'Edits without tests',\n uncertainty: 'Uncertainty',\n backtrack: 'Backtracking',\n win: 'Wins',\n};\n\nconst ENGINE_LABEL: Readonly<Record<string, string>> = { claude: 'Claude', codex: 'Codex', grok: 'Grok', local: 'Local' };\nconst KNOWN_ENGINES: readonly ChartEngine[] = ['claude', 'codex', 'grok', 'local'];\n\nfunction asEngine(name: string): ChartEngine | null {\n return (KNOWN_ENGINES as readonly string[]).includes(name) ? (name as ChartEngine) : null;\n}\n\n/**\n * Repos that appear in the digest's insights, most insight occurrences first\n * — ONE per folder: two spellings of the same folder (`/tmp/x` and\n * `/private/tmp/x`, which `pathKey` treats as one) are one Repo facet entry,\n * named by the spelling recorded most often.\n */\nexport function insightRepos(digest: ReasoningDigest | null): string[] {\n if (!digest) return [];\n const folders = new Map<string, { total: number; spellings: Map<string, number> }>();\n for (const i of digest.insights) {\n if (!i.repo) continue;\n const key = pathKey(i.repo);\n const f = folders.get(key) ?? { total: 0, spellings: new Map<string, number>() };\n f.total += i.count;\n f.spellings.set(i.repo, (f.spellings.get(i.repo) ?? 0) + i.count);\n folders.set(key, f);\n }\n const byCount = (a: [string, number], b: [string, number]) => b[1] - a[1] || a[0].localeCompare(b[0]);\n return [...folders.values()]\n .map((f) => [[...f.spellings.entries()].sort(byCount)[0]![0], f.total] as [string, number])\n .sort(byCount)\n .map(([r]) => r);\n}\n\n/** Does insight `repo` name the same folder as facet `facet` (any spelling)? */\nfunction sameFolder(repo: string | null | undefined, facet: string): boolean {\n return !!repo && (repo === facet || pathKey(repo) === pathKey(facet));\n}\n\nexport interface InsightMatrix {\n rows: MatrixAxisItem[];\n columns: MatrixAxisItem[];\n values: (number | null)[][];\n}\n\n/** `repo` null = every repo. */\nexport function insightMatrix(digest: ReasoningDigest | null, repo: string | null): InsightMatrix {\n const rows = INSIGHT_KINDS.map((k) => ({ id: k, label: KIND_LABEL[k] }));\n if (!digest) return { rows, columns: [], values: [] };\n // Columns: every engine that reasoned in the window, plus any engine an\n // insight names (so a count is never dropped), known engines first.\n const names = new Set<string>([...Object.keys(digest.totals.byEngine), ...digest.insights.map((i) => i.engine).filter((e): e is string => !!e)]);\n const ordered = [...names].sort((a, b) => {\n const ia = KNOWN_ENGINES.indexOf(a as ChartEngine);\n const ib = KNOWN_ENGINES.indexOf(b as ChartEngine);\n return (ia === -1 ? 99 : ia) - (ib === -1 ? 99 : ib) || a.localeCompare(b);\n });\n const columns: MatrixAxisItem[] = ordered.map((name) => {\n const engine = asEngine(name);\n return { id: name, label: ENGINE_LABEL[name] ?? name, ...(engine ? { engine } : {}) };\n });\n const insights = digest.insights.filter((i) => repo === null || sameFolder(i.repo, repo));\n const values = INSIGHT_KINDS.map((kind) =>\n ordered.map((engine) => {\n const measured = (digest.totals.byEngine[engine] ?? 0) > 0;\n const count = insights.filter((i) => i.kind === kind && i.engine === engine).reduce((n, i) => n + i.count, 0);\n return measured || count > 0 ? count : null;\n }),\n );\n return { rows, columns, values };\n}\n\n/** The three cards: most severe first, then most recent — wins are not problems. */\nexport function topInsights(digest: ReasoningDigest | null, n = 3): ReasoningInsight[] {\n if (!digest) return [];\n const rank = { high: 0, warn: 1, info: 2 } as const;\n return digest.insights\n .filter((i) => i.kind !== 'win')\n .sort((a, b) => rank[a.severity] - rank[b.severity] || Date.parse(b.lastAt) - Date.parse(a.lastAt))\n .slice(0, n);\n}\n\n/**\n * Struggles vs wins per day, for the trends card. Each day is stamped at the\n * viewer's LOCAL midnight (`calendarDayStart`), because the chart labels its\n * x values in the local zone: a UTC-midnight stamp read one day early west of\n * UTC (\"2026-09-24\" as \"Sep 23\").\n */\nexport function reasoningTrendSeries(digest: ReasoningDigest | null): AreaTrendSeries[] {\n if (!digest) return [];\n const pts = (pick: (d: ReasoningDigest['trends'][number]) => number) =>\n digest.trends.map((d) => ({ x: calendarDayStart(d.day), y: d.steps === 0 ? null : pick(d) }));\n return [\n { id: 'struggles', label: 'Struggles', color: toneColor('warning'), points: pts((d) => d.struggles) },\n { id: 'wins', label: 'Wins', color: toneColor('success'), points: pts((d) => d.wins) },\n ];\n}\n\n// ---------------------------------------------------------------------------\n// SessionInsightChip\n// ---------------------------------------------------------------------------\n\n/** The chip shows only the insight kinds that mean \"this chat is stuck\". */\nexport const CHIP_KINDS: ReadonlySet<ReasoningInsightKind> = new Set(['loop', 'struggle']);\n\n/**\n * Does `insight` cite chat `sessionId`? Verse evidence refs are\n * `session:<id>#<seq>` (tool / message events) or `verse:<id>:<turn|seq>`\n * (thinking steps) — A7's ingest-verse.ts. The id is matched exactly up to\n * its delimiter, so chat `s1` never matches `s12`.\n */\nexport function citesSession(insight: Pick<ReasoningInsight, 'evidence'>, sessionId: string): boolean {\n return insight.evidence.some((e) => e.ref.startsWith(`session:${sessionId}#`) || e.ref.startsWith(`verse:${sessionId}:`));\n}\n\nexport function sessionInsights(digest: ReasoningDigest | null, sessionId: string): ReasoningInsight[] {\n if (!digest || !sessionId) return [];\n return digest.insights\n .filter((i) => CHIP_KINDS.has(i.kind) && citesSession(i, sessionId))\n .sort((a, b) => Date.parse(b.lastAt) - Date.parse(a.lastAt));\n}\n","/*\n * routes/verse/mind/mind.module.css — Mind cards and the chat-header chip\n * (unit C7). Tokens only (style-scan-310).\n */\n.stack {\n display: flex;\n flex-direction: column;\n gap: var(--surface-gap);\n}\n\n.muted {\n margin: 0;\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n}\n\n.link {\n align-self: flex-start;\n padding: 0;\n border: 0;\n background: none;\n color: var(--text-link);\n font: inherit;\n font-size: var(--text-xs-size);\n cursor: pointer;\n}\n\n.link:hover {\n text-decoration: underline;\n}\n\n.link:focus-visible,\n.veto:focus-visible,\n.chip:focus-visible {\n outline: 2px solid var(--border-focus);\n outline-offset: 2px;\n}\n\n/* ---- memo timeline ---------------------------------------------------- */\n.timeline {\n display: flex;\n flex-direction: column;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.memo {\n display: grid;\n grid-template-columns: 88px 20px minmax(0, 1fr) auto;\n gap: var(--space-3);\n align-items: start;\n padding: var(--space-3) 0;\n border-top: 1px solid var(--border-subtle);\n}\n\n.memo:first-child {\n border-top: 0;\n padding-top: 0;\n}\n\n.memoDay {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-sm-line);\n font-variant-numeric: tabular-nums;\n}\n\n.mark {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border-radius: var(--radius-full);\n background: var(--status-neutral-bg);\n color: var(--status-neutral-fg);\n font-size: var(--text-xs-size);\n font-weight: var(--font-weight-semibold);\n}\n\n.mark[data-outcome='hit'] {\n background: var(--status-success-bg);\n color: var(--status-success-fg);\n}\n\n.mark[data-outcome='miss'] {\n background: var(--status-danger-bg);\n color: var(--status-danger-fg);\n}\n\n.memoBody {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.memoMove {\n color: var(--text-primary);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n overflow-wrap: anywhere;\n}\n\n.memoWhy {\n color: var(--text-secondary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n overflow-wrap: anywhere;\n}\n\n.memoMeta {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n\n.memoMeta [data-outcome='hit'] {\n color: var(--status-success-fg);\n}\n\n.memoMeta [data-outcome='miss'] {\n color: var(--status-danger-fg);\n}\n\n.veto {\n min-height: var(--control-h-sm);\n padding: 0 var(--space-3);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n background: transparent;\n color: var(--text-primary);\n font: inherit;\n font-size: var(--text-xs-size);\n cursor: pointer;\n}\n\n.veto:hover {\n background: var(--bg-hover);\n}\n\n.veto:disabled {\n color: var(--text-disabled);\n cursor: default;\n}\n\n[data-viewport='compact'] .memo {\n grid-template-columns: 20px minmax(0, 1fr) auto;\n}\n\n[data-viewport='compact'] .memoDay {\n grid-column: 1 / -1;\n}\n\n/* ---- standards -------------------------------------------------------- */\n.standards {\n display: flex;\n flex-direction: column;\n gap: var(--space-3);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.standards li {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.standardRule {\n color: var(--text-primary);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line-relaxed);\n}\n\n.standardMeta {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n}\n\n/* ---- insight cards ---------------------------------------------------- */\n.insights {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: var(--surface-gap);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n[data-viewport='compact'] .insights,\n[data-viewport='medium'] .insights {\n grid-template-columns: minmax(0, 1fr);\n}\n\n.insight {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n padding: var(--card-pad);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-lg);\n background: var(--bg-surface);\n box-shadow: inset 0 1px 0 var(--hairline-lift, transparent);\n}\n\n.insight[data-severity='high'] {\n border-color: var(--status-danger-solid);\n}\n\n.insightKind {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-2);\n}\n\n.insightSeverity {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n}\n\n.insightSeverity[data-severity='high'] {\n color: var(--status-danger-fg);\n}\n\n.insightSeverity[data-severity='warn'] {\n color: var(--status-warning-fg);\n}\n\n.insightTitle {\n color: var(--text-primary);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line-relaxed);\n overflow-wrap: anywhere;\n}\n\n.insightMeta {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n\n/* The project's name reads a step stronger than the rest of the meta line;\n the full path is its tooltip. */\n.insightPlace {\n color: var(--text-secondary);\n overflow-wrap: anywhere;\n}\n\n/* A folder under the OS temp dir: tagged, quietly — never hidden. */\n.scratchTag {\n display: inline-block;\n margin-left: var(--space-1);\n padding: 0 var(--space-1);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-sm);\n color: var(--text-tertiary);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n vertical-align: 1px;\n}\n\n.log {\n display: flex;\n flex-direction: column;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.facet {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n}\n\n.facet select {\n min-height: var(--control-h-xs);\n padding: 0 var(--space-2);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n background: var(--bg-input);\n color: var(--text-primary);\n font: inherit;\n font-size: var(--text-xs-size);\n}\n\n/* ---- chat-header chip ------------------------------------------------- */\n.chipWrap {\n position: relative;\n display: inline-flex;\n}\n\n.chip {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n min-height: var(--control-h-xs);\n padding: 0 var(--space-2);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-full);\n background: var(--bg-surface);\n color: var(--text-secondary);\n font: inherit;\n font-size: var(--text-xs-size);\n white-space: nowrap;\n cursor: pointer;\n}\n\n.chip:hover,\n.chip[aria-expanded='true'] {\n background: var(--bg-hover);\n color: var(--text-primary);\n}\n\n.chipDot {\n width: 6px;\n height: 6px;\n border-radius: var(--radius-full);\n background: var(--status-warning-solid);\n}\n\n.chipDot[data-severity='high'] {\n background: var(--status-danger-solid);\n}\n\n.chipMore {\n color: var(--text-tertiary);\n}\n\n.chipPanel {\n position: absolute;\n top: calc(100% + var(--space-1));\n right: 0;\n z-index: var(--z-dropdown);\n display: flex;\n flex-direction: column;\n gap: var(--space-3);\n width: min(320px, calc(100vw - var(--space-8)));\n padding: var(--space-3);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-md);\n background: var(--bg-surface-raised);\n box-shadow: var(--shadow-menu);\n}\n\n.chipList {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.chipList li {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n"],"mappings":"0IA+CA,SAAgB,EAAQ,EAAsB,CAC5C,IAAI,EAAI,EAAK,KAAK,CAAC,CAAC,QAAQ,MAAO,GAAG,CAAC,CAAC,QAAQ,OAAQ,EAAE,EAG1D,MAFA,GAAI,EAAE,QAAQ,sCAAuC,EAAE,EACvD,EAAI,EAAE,QAAQ,oEAAqE,GAAG,EAC/E,GAAK,GACd,CAEA,IAAM,EAAmC,CACvC,iBACA,sBACA,2CACA,qCACA,iCACF,EAGA,SAAgB,EAAc,EAAuB,CACnD,IAAM,EAAM,EAAQ,CAAI,EACxB,OAAO,EAAc,KAAM,GAAO,EAAG,KAAK,CAAG,CAAC,CAChD,CAOA,SAAgB,EACd,EACA,EACqB,CACrB,IAAM,EAAQ,IAAI,IACZ,GAAO,EAAc,IAAiB,CAC1C,IAAM,EAAM,EAAQ,CAAI,EAClB,EAAQ,EAAK,KAAK,EACpB,IAAQ,KAAO,IAAQ,KAAO,GAAS,CAAC,EAAM,IAAI,CAAG,GAAG,EAAM,IAAI,EAAK,CAAK,CAClF,EACA,IAAK,IAAM,KAAK,GAAc,CAAC,EAAG,IAAK,IAAM,KAAK,EAAE,MAAO,EAAI,EAAE,KAAM,EAAE,IAAI,EAC7E,IAAK,IAAM,KAAK,GAAY,CAAC,EAAG,EAAI,EAAE,KAAM,EAAE,IAAI,EAClD,OAAO,CACT,CAGA,SAAS,EAAe,EAAc,EAAoC,CACxE,IAAM,EAAM,EAAQ,CAAI,EAClB,EAAQ,EAAM,IAAI,CAAG,EAC3B,GAAI,IAAU,IAAA,GAAW,OAAO,EAChC,IAAI,EAA8C,KAClD,IAAK,GAAM,CAAC,EAAM,KAAS,EACrB,EAAI,WAAW,GAAG,EAAK,EAAE,IAAM,CAAC,GAAQ,EAAK,OAAS,EAAK,KAAK,UAAS,EAAO,CAAE,OAAM,MAAK,GAEnG,OAAO,GAAM,MAAQ,IACvB,CAGA,SAAgB,EAAa,EAAc,EAAsB,IAAI,IAAqB,CACxF,MAAO,CAAE,MAAO,EAAe,EAAM,CAAK,GAAK,EAAqB,CAAI,EAAG,KAAM,EAAM,QAAS,EAAc,CAAI,CAAE,CACtH,CAEA,IAAM,EAAS,GAAkB,EAAK,OAAS,GAAK,GAAG,EAAK,MAAM,EAAG,EAAE,EAAE,GAAK,EAY9E,SAAS,EAAe,EAAyB,EAA2C,CAC1F,IAAM,EAAQ,IAAI,IAAI,EAAK,IAAK,GAAM,CAAC,EAAG,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAC5E,EAAM,IAAI,IAChB,IAAK,IAAM,KAAO,EAAM,CACtB,IAAM,EAAO,EAAM,IAAI,CAAG,EACtB,EAAyB,KACzB,EAAwB,KAC5B,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAK,QAAU,IAAW,KAAM,IAAS,CACnE,IAAM,EAAM,EAAK,GACb,IAAQ,GAAS,IAAQ,MAC7B,IAAY,EACR,EAAK,MAAO,GAAU,IAAU,GAAO,EAAM,IAAI,CAAK,CAAC,CAAE,KAAW,CAAG,IAAG,EAAS,GACzF,CACA,EAAI,IAAI,EAAK,GAAU,CAAO,CAChC,CACA,OAAO,CACT,CAcA,SAAgB,EAAc,EAA0B,EAAsB,IAAI,IAAkC,CAGlH,IAAM,EAAY,IAAI,IACtB,IAAK,IAAM,IAAQ,CAAC,GAAG,IAAI,IAAI,CAAK,CAAC,CAAC,CAAC,KAAK,EAAG,CAC7C,IAAM,EAAM,EAAQ,CAAI,EACxB,EAAU,IAAI,EAAK,CAAC,GAAI,EAAU,IAAI,CAAG,GAAK,CAAC,EAAI,CAAI,CAAC,CAC1D,CACA,IAAM,EAAU,IAAI,IACpB,IAAK,GAAM,CAAC,EAAK,KAAS,EAAW,CACnC,IAAM,EAAQ,EAAa,EAAK,GAAK,CAAK,CAAC,CAAC,MAC5C,EAAQ,IAAI,EAAO,CAAC,GAAI,EAAQ,IAAI,CAAK,GAAK,CAAC,EAAI,CAAG,CAAC,CACzD,CAEA,IAAM,EAAS,IAAI,IACb,EAAQ,IAAI,IAClB,IAAK,GAAM,CAAC,EAAO,KAAS,EAAS,CACnC,IAAM,EAAQ,EAAK,OAAS,EAAI,EAAe,EAAM,CAAK,EAAI,KAC9D,IAAK,IAAM,KAAO,EAAM,CACtB,IAAM,EAAM,GAAO,IAAI,CAAG,GAAK,KAC/B,EAAO,IAAI,EAAK,EAAM,GAAG,EAAM,IAAI,EAAM,CAAG,EAAE,GAAK,CAAK,EACpD,GAAO,EAAM,CAAG,IAAM,GAAK,EAAM,IAAI,EAAK,GAAG,EAAM,IAAI,EAAI,EAAE,CACnE,CACF,CAEA,IAAM,EAAS,IAAI,IACnB,IAAK,IAAM,KAAK,EAAO,OAAO,EAAG,EAAO,IAAI,GAAI,EAAO,IAAI,CAAC,GAAK,GAAK,CAAC,EACvE,IAAM,EAAQ,IAAI,IACZ,EAAU,IAAI,IACpB,IAAK,IAAM,IAAO,CAAC,GAAG,EAAO,KAAK,CAAC,CAAC,CAAC,KAAK,EAAG,CAC3C,IAAM,EAAQ,EAAO,IAAI,CAAG,EACtB,EAAO,EAAO,IAAI,CAAK,EAAK,EAAK,EAAM,IAAI,CAAG,GAAK,EAAS,EAC9D,EAAQ,EACZ,IAAK,IAAI,EAAI,EAAG,EAAM,IAAI,CAAK,EAAG,IAAK,EAAQ,GAAG,EAAK,IAAI,IAC3D,EAAM,IAAI,CAAK,EACf,EAAQ,IAAI,EAAK,CAAK,CACxB,CAEA,IAAM,EAAM,IAAI,IAChB,IAAK,GAAM,CAAC,EAAK,KAAS,EACxB,IAAK,IAAM,KAAQ,EAAM,EAAI,IAAI,EAAM,CAAE,MAAO,EAAQ,IAAI,CAAG,EAAI,KAAM,EAAM,QAAS,EAAc,CAAI,CAAE,CAAC,EAE/G,OAAO,CACT,CCzKA,IAAa,EAAiD,CAAC,OAAQ,WAAY,mBAAoB,cAAe,YAAa,KAAK,EAE3H,EAA6D,CACxE,KAAM,QACN,SAAU,oBACV,mBAAoB,sBACpB,YAAa,cACb,UAAW,eACX,IAAK,MACP,EAEM,EAAiD,CAAE,OAAQ,SAAU,MAAO,QAAS,KAAM,OAAQ,MAAO,OAAQ,EAClH,EAAwC,CAAC,SAAU,QAAS,OAAQ,OAAO,EAEjF,SAAS,EAAS,EAAkC,CAClD,OAAQ,EAAoC,SAAS,CAAI,EAAK,EAAuB,IACvF,CAQA,SAAgB,EAAa,EAA0C,CACrE,GAAI,CAAC,EAAQ,MAAO,CAAC,EACrB,IAAM,EAAU,IAAI,IACpB,IAAK,IAAM,KAAK,EAAO,SAAU,CAC/B,GAAI,CAAC,EAAE,KAAM,SACb,IAAM,EAAM,EAAQ,EAAE,IAAI,EACpB,EAAI,EAAQ,IAAI,CAAG,GAAK,CAAE,MAAO,EAAG,UAAW,IAAI,GAAsB,EAC/E,EAAE,OAAS,EAAE,MACb,EAAE,UAAU,IAAI,EAAE,MAAO,EAAE,UAAU,IAAI,EAAE,IAAI,GAAK,GAAK,EAAE,KAAK,EAChE,EAAQ,IAAI,EAAK,CAAC,CACpB,CACA,IAAM,GAAW,EAAqB,IAAwB,EAAE,GAAK,EAAE,IAAM,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE,EACpG,MAAO,CAAC,GAAG,EAAQ,OAAO,CAAC,CAAC,CACzB,IAAK,GAAM,CAAC,CAAC,GAAG,EAAE,UAAU,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAO,CAAC,CAAC,EAAE,CAAE,GAAI,EAAE,KAAK,CAAqB,CAAC,CAC1F,KAAK,CAAO,CAAC,CACb,KAAK,CAAC,KAAO,CAAC,CACnB,CAGA,SAAS,EAAW,EAAiC,EAAwB,CAC3E,MAAO,CAAC,CAAC,IAAS,IAAS,GAAS,EAAQ,CAAI,IAAM,EAAQ,CAAK,EACrE,CASA,SAAgB,EAAc,EAAgC,EAAoC,CAChG,IAAM,EAAO,EAAc,IAAK,IAAO,CAAE,GAAI,EAAG,MAAO,EAAW,EAAG,EAAE,EACvE,GAAI,CAAC,EAAQ,MAAO,CAAE,OAAM,QAAS,CAAC,EAAG,OAAQ,CAAC,CAAE,EAIpD,IAAM,EAAU,CAAC,GAAG,IADF,IAAY,CAAC,GAAG,OAAO,KAAK,EAAO,OAAO,QAAQ,EAAG,GAAG,EAAO,SAAS,IAAK,GAAM,EAAE,MAAM,CAAC,CAAC,OAAQ,GAAmB,CAAC,CAAC,CAAC,CAAC,CAC1H,CAAK,CAAC,CAAC,MAAM,EAAG,IAAM,CACxC,IAAM,EAAK,EAAc,QAAQ,CAAgB,EAC3C,EAAK,EAAc,QAAQ,CAAgB,EACjD,OAAQ,IAAO,GAAK,GAAK,IAAO,IAAO,GAAK,GAAK,IAAO,EAAE,cAAc,CAAC,CAC3E,CAAC,EACK,EAA4B,EAAQ,IAAK,GAAS,CACtD,IAAM,EAAS,EAAS,CAAI,EAC5B,MAAO,CAAE,GAAI,EAAM,MAAO,EAAa,IAAS,EAAM,GAAI,EAAS,CAAE,QAAO,EAAI,CAAC,CAAG,CACtF,CAAC,EACK,EAAW,EAAO,SAAS,OAAQ,GAAM,IAAS,MAAQ,EAAW,EAAE,KAAM,CAAI,CAAC,EAQxF,MAAO,CAAE,OAAM,UAAS,OAPT,EAAc,IAAK,GAChC,EAAQ,IAAK,GAAW,CACtB,IAAM,GAAY,EAAO,OAAO,SAAS,IAAW,GAAK,EACnD,EAAQ,EAAS,OAAQ,GAAM,EAAE,OAAS,GAAQ,EAAE,SAAW,CAAM,CAAC,CAAC,QAAQ,EAAG,IAAM,EAAI,EAAE,MAAO,CAAC,EAC5G,OAAO,GAAY,EAAQ,EAAI,EAAQ,IACzC,CAAC,CAEqB,CAAO,CACjC,CAGA,SAAgB,EAAY,EAAgC,EAAI,EAAuB,CACrF,GAAI,CAAC,EAAQ,MAAO,CAAC,EACrB,IAAM,EAAO,CAAE,KAAM,EAAG,KAAM,EAAG,KAAM,CAAE,EACzC,OAAO,EAAO,SACX,OAAQ,GAAM,EAAE,OAAS,KAAK,CAAC,CAC/B,MAAM,EAAG,IAAM,EAAK,EAAE,UAAY,EAAK,EAAE,WAAa,KAAK,MAAM,EAAE,MAAM,EAAI,KAAK,MAAM,EAAE,MAAM,CAAC,CAAC,CAClG,MAAM,EAAG,CAAC,CACf,CAQA,SAAgB,EAAqB,EAAmD,CACtF,GAAI,CAAC,EAAQ,MAAO,CAAC,EACrB,IAAM,EAAO,GACX,EAAO,OAAO,IAAK,IAAO,CAAE,EAAG,EAAiB,EAAE,GAAG,EAAG,EAAG,EAAE,QAAU,EAAI,KAAO,EAAK,CAAC,CAAE,EAAE,EAC9F,MAAO,CACL,CAAE,GAAI,YAAa,MAAO,YAAa,MAAO,EAAU,SAAS,EAAG,OAAQ,EAAK,GAAM,EAAE,SAAS,CAAE,EACpG,CAAE,GAAI,OAAQ,MAAO,OAAQ,MAAO,EAAU,SAAS,EAAG,OAAQ,EAAK,GAAM,EAAE,IAAI,CAAE,CACvF,CACF,CAOA,IAAa,EAAgD,IAAI,IAAI,CAAC,OAAQ,UAAU,CAAC,EAQzF,SAAgB,EAAa,EAA6C,EAA4B,CACpG,OAAO,EAAQ,SAAS,KAAM,GAAM,EAAE,IAAI,WAAW,WAAW,EAAU,EAAE,GAAK,EAAE,IAAI,WAAW,SAAS,EAAU,EAAE,CAAC,CAC1H,CAEA,SAAgB,EAAgB,EAAgC,EAAuC,CAErG,MADI,CAAC,GAAU,CAAC,EAAkB,CAAC,EAC5B,EAAO,SACX,OAAQ,GAAM,EAAW,IAAI,EAAE,IAAI,GAAK,EAAa,EAAG,CAAS,CAAC,CAAC,CACnE,MAAM,EAAG,IAAM,KAAK,MAAM,EAAE,MAAM,EAAI,KAAK,MAAM,EAAE,MAAM,CAAC,CAC/D"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{D as e,F as t,U as n,W as r,l as i}from"./global-BkNl4e6E.js";var a=class extends Error{constructor(){super(`No mutation token held for this session yet.`),this.name=`MissingMutationTokenError`}};async function o(n,r){let o=e();if(!o)throw new a;let s=await i(n,r,o);return t(),s}async function s(){await o(`/api/fleet/pause`,{}),n(`dashboard-snapshot`),n(`control-snapshot`),n(`fleet`),n(`fleet-activity`)}async function c(){await o(`/api/fleet/resume`,{}),n(`dashboard-snapshot`),n(`control-snapshot`),n(`fleet`),n(`fleet-activity`)}async function l(e){await o(`/api/inbox/${encodeURIComponent(e)}/approve`,{}),n(`inbox`),n(`dashboard-snapshot`),n(`proposal-detail-${e}`),r(`inbox-list:`)}async function u(e){await o(`/api/inbox/${encodeURIComponent(e)}/reject`,{}),n(`inbox`),n(`dashboard-snapshot`),n(`proposal-detail-${e}`),r(`inbox-list:`)}export{c as i,s as n,u as r,l as t};
|
|
2
|
+
//# sourceMappingURL=mutations-Kvzsg-iK.js.map
|
package/dist/core/web/public/next/assets/{mutations-Dpsql5t7.js.map → mutations-Kvzsg-iK.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mutations-
|
|
1
|
+
{"version":3,"file":"mutations-Kvzsg-iK.js","names":[],"sources":["../../../../../../src/web-ui/data/mutations.ts"],"sourcesContent":["/**\n * data/mutations.ts — every mutating call the foundation ships with, each\n * wrapped so it (a) pulls the held mutation token from auth-store instead\n * of asking every call site to thread it through, (b) touches the hold on\n * success so a burst of approvals doesn't idle-expire mid-session, and\n * (c) invalidates whatever cache keys the mutation obviously affects so\n * views update without waiting for the next SSE tick.\n *\n * Routes mirror the mutating surface documented at the top of\n * src/core/web/api.ts. Every one of these 404s (not 401/403) when the\n * server was started without --allow-dispatch — apiPost maps that code-less\n * 404 to DispatchDisabledError (a 404 carrying a `code` stays an ApiError).\n */\nimport { apiPost } from './client.js';\nimport { getMutationToken, touchMutationHold } from './auth-store.js';\nimport { invalidate, invalidatePrefix } from './cache.js';\n\nclass MissingMutationTokenError extends Error {\n constructor() {\n super('No mutation token held for this session yet.');\n this.name = 'MissingMutationTokenError';\n }\n}\n\nasync function post<T>(path: string, body: unknown): Promise<T> {\n const token = getMutationToken();\n if (!token) throw new MissingMutationTokenError();\n const result = await apiPost<T>(path, body, token);\n touchMutationHold();\n return result;\n}\n\nexport async function pauseFleet(): Promise<void> {\n await post('/api/fleet/pause', {});\n invalidate('dashboard-snapshot');\n invalidate('control-snapshot');\n invalidate('fleet');\n invalidate('fleet-activity');\n}\n\nexport async function resumeFleet(): Promise<void> {\n await post('/api/fleet/resume', {});\n invalidate('dashboard-snapshot');\n invalidate('control-snapshot');\n invalidate('fleet');\n invalidate('fleet-activity');\n}\n\nexport async function approveProposal(id: string): Promise<void> {\n await post(`/api/inbox/${encodeURIComponent(id)}/approve`, {});\n invalidate('inbox');\n invalidate('dashboard-snapshot');\n invalidate(`proposal-detail-${id}`);\n invalidatePrefix('inbox-list:');\n}\n\nexport async function rejectProposal(id: string): Promise<void> {\n await post(`/api/inbox/${encodeURIComponent(id)}/reject`, {});\n invalidate('inbox');\n invalidate('dashboard-snapshot');\n invalidate(`proposal-detail-${id}`);\n invalidatePrefix('inbox-list:');\n}\n\nexport interface OpenTargetRequest {\n path: string;\n target: 'editor' | 'finder';\n}\n\nexport async function openTarget(req: OpenTargetRequest): Promise<void> {\n await post('/api/open', req);\n}\n"],"mappings":"qEAiBA,IAAM,EAAN,cAAwC,KAAM,CAC5C,aAAc,CACZ,MAAM,8CAA8C,EACpD,KAAK,KAAO,2BACd,CACF,EAEA,eAAe,EAAQ,EAAc,EAA2B,CAC9D,IAAM,EAAQ,EAAiB,EAC/B,GAAI,CAAC,EAAO,MAAM,IAAI,EACtB,IAAM,EAAS,MAAM,EAAW,EAAM,EAAM,CAAK,EAEjD,OADA,EAAkB,EACX,CACT,CAEA,eAAsB,GAA4B,CAChD,MAAM,EAAK,mBAAoB,CAAC,CAAC,EACjC,EAAW,oBAAoB,EAC/B,EAAW,kBAAkB,EAC7B,EAAW,OAAO,EAClB,EAAW,gBAAgB,CAC7B,CAEA,eAAsB,GAA6B,CACjD,MAAM,EAAK,oBAAqB,CAAC,CAAC,EAClC,EAAW,oBAAoB,EAC/B,EAAW,kBAAkB,EAC7B,EAAW,OAAO,EAClB,EAAW,gBAAgB,CAC7B,CAEA,eAAsB,EAAgB,EAA2B,CAC/D,MAAM,EAAK,cAAc,mBAAmB,CAAE,EAAE,UAAW,CAAC,CAAC,EAC7D,EAAW,OAAO,EAClB,EAAW,oBAAoB,EAC/B,EAAW,mBAAmB,GAAI,EAClC,EAAiB,aAAa,CAChC,CAEA,eAAsB,EAAe,EAA2B,CAC9D,MAAM,EAAK,cAAc,mBAAmB,CAAE,EAAE,SAAU,CAAC,CAAC,EAC5D,EAAW,OAAO,EAClB,EAAW,oBAAoB,EAC/B,EAAW,mBAAmB,GAAI,EAClC,EAAiB,aAAa,CAChC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{C as e,g as t,m as n}from"./verse-ui-store-D7YXi63q.js";function r(e=null){n(e?{focusId:e}:{})}function i(e){return`c7-anchor-${e.replace(/[^A-Za-z0-9_-]/g,`-`)}`}function a(e){let t=document.getElementById(i(e));t&&typeof t.scrollIntoView==`function`&&t.scrollIntoView({block:`center`,behavior:`smooth`})}function o(t,n=null){e(t),n&&requestAnimationFrame(()=>{document.getElementById(i(n))?a(n):requestAnimationFrame(()=>a(n))})}function s(e){t(e)}export{r as i,o as n,s as r,i as t};
|
|
2
|
+
//# sourceMappingURL=nav-C0IunEYF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nav-C0IunEYF.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/command/nav.ts"],"sourcesContent":["/**\n * routes/verse/command/nav.ts — how a surface card asks the shell to go\n * somewhere (unit C7). The shell (C1) owns navigation state; these are thin\n * wrappers over its store so every card words navigation the same way:\n *\n * openNeedsYou() ⌘J's drawer, optionally focused on one item;\n * goToSection(s, a) switch surface (keep-alive: the target keeps its\n * state) and, when `anchor` names a card or row on\n * it, scroll that into view once it is on screen;\n * openChat(sessionId) the chat a Needs-you item or insight is about.\n */\nimport type { WorkbenchSectionId } from '../../../../core/verse/workbench-types.js';\nimport { openVerseNeedsYou, openVerseSession, setVerseSection } from '../verse-ui-store.js';\n\nexport function openNeedsYou(focusId: string | null = null): void {\n openVerseNeedsYou(focusId ? { focusId } : {});\n}\n\n/** DOM id for an anchor (\"repo-ashlrai/binshield\" → \"c7-anchor-repo-ashlrai-binshield\"). */\nexport function anchorId(anchor: string): string {\n return `c7-anchor-${anchor.replace(/[^A-Za-z0-9_-]/g, '-')}`;\n}\n\nexport function scrollToAnchor(anchor: string): void {\n const el = document.getElementById(anchorId(anchor));\n if (el && typeof el.scrollIntoView === 'function') el.scrollIntoView({ block: 'center', behavior: 'smooth' });\n}\n\nexport function goToSection(section: WorkbenchSectionId, anchor: string | null = null): void {\n setVerseSection(section);\n if (!anchor) return;\n // The target surface may be mounting (lazy chunk) or un-hiding (keep-alive):\n // try on the next two frames, then give up quietly — a missing anchor is\n // never an error, the operator is already on the right surface.\n requestAnimationFrame(() => {\n if (document.getElementById(anchorId(anchor))) scrollToAnchor(anchor);\n else requestAnimationFrame(() => scrollToAnchor(anchor));\n });\n}\n\nexport function openChat(sessionId: string): void {\n openVerseSession(sessionId);\n}\n"],"mappings":"+DAcA,SAAgB,EAAa,EAAyB,KAAY,CAChE,EAAkB,EAAU,CAAE,SAAQ,EAAI,CAAC,CAAC,CAC9C,CAGA,SAAgB,EAAS,EAAwB,CAC/C,MAAO,aAAa,EAAO,QAAQ,kBAAmB,GAAG,GAC3D,CAEA,SAAgB,EAAe,EAAsB,CACnD,IAAM,EAAK,SAAS,eAAe,EAAS,CAAM,CAAC,EAC/C,GAAM,OAAO,EAAG,gBAAmB,YAAY,EAAG,eAAe,CAAE,MAAO,SAAU,SAAU,QAAS,CAAC,CAC9G,CAEA,SAAgB,EAAY,EAA6B,EAAwB,KAAY,CAC3F,EAAgB,CAAO,EAClB,GAIL,0BAA4B,CACtB,SAAS,eAAe,EAAS,CAAM,CAAC,EAAG,EAAe,CAAM,EAC/D,0BAA4B,EAAe,CAAM,CAAC,CACzD,CAAC,CACH,CAEA,SAAgB,EAAS,EAAyB,CAChD,EAAiB,CAAS,CAC5B"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as e,s as t}from"./index-DbDw9UAs.js";import{D as n,F as r,U as i,c as a,l as o,m as s,o as c}from"./global-BkNl4e6E.js";import{s as l}from"./format-CaMmVQCn.js";import{n as u,t as d}from"./control-queries-Dv-h1Clu.js";var f=t(e(),1);function p(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function m(e){return typeof e==`string`&&e.trim()!==``?e:null}function h(e){return typeof e==`boolean`?e:null}function g(e){return typeof e!=`number`||!Number.isFinite(e)||e<0?null:Math.floor(e)}function _(e){if(!p(e))return null;let t=m(e.kind);if(t===`until-paused`)return{kind:`until-paused`};if(t===`at-time`){let t=m(e.at);return t===null||Number.isNaN(Date.parse(t))?null:{kind:`at-time`,at:t}}if(t===`after-iterations`){let t=g(e.iterations);return t===null||t<=0?null:{kind:`after-iterations`,iterations:t}}return null}function v(e){if(!Array.isArray(e))return[];let t=[];for(let[n,r]of e.entries()){if(!p(r))continue;let e=m(r.repo);e!==null&&t.push({id:m(r.id)??`${e}:${n}`,repo:e,title:m(r.title)??`untitled change`,at:m(r.at),commit:m(r.commit)})}return t}function y(e){if(!Array.isArray(e))return[];let t=[];for(let[n,r]of e.entries()){if(!p(r))continue;let e=m(r.repo);e!==null&&t.push({id:m(r.id)??`${e}:${n}`,repo:e,title:m(r.title)??`untitled change`,at:m(r.at),reason:m(r.reason)??`no reason recorded`})}return t}function b(e){return p(e)?{tests:h(e.tests),lint:h(e.lint),typecheck:h(e.typecheck),autoMerge:h(e.autoMerge),branch:m(e.branch)}:null}function x(e){if(!p(e))return null;let t=m(e.runId);return t===null?null:{runId:t,startedAt:m(e.startedAt),stopRule:_(e.stopRule),iterationsDone:g(e.iterationsDone),repo:m(e.repo),activity:m(e.activity),merged:v(e.merged),discarded:y(e.discarded)}}function S(e){if(!p(e))return null;let t=h(e.armed);return t===null?null:{armed:t,run:x(e.run),repos:g(e.repos),...e.mirrors===void 0?{}:{mirrors:g(e.mirrors)},gate:b(e.gate)}}function C(e,t=new Date){let n=/^(\d{1,2}):(\d{2})$/.exec(e.trim());if(!n)return null;let r=Number(n[1]),i=Number(n[2]);if(!Number.isInteger(r)||!Number.isInteger(i)||r<0||r>23||i<0||i>59)return null;let a=new Date(t);return a.setHours(r,i,0,0),a.getTime()<=t.getTime()&&a.setDate(a.getDate()+1),a.toISOString()}function w(e){if(!e)return`—`;let t=Date.parse(e);return Number.isNaN(t)?`—`:new Date(t).toLocaleTimeString(void 0,{hour:`2-digit`,minute:`2-digit`})}function T(e,t=new Date){if(!e)return!1;let n=Date.parse(e);return!Number.isNaN(n)&&new Date(n).toDateString()!==t.toDateString()}function E(e,t=new Date){switch(e.kind){case`until-paused`:return`Runs until you pause it — no stop time, no iteration limit.`;case`at-time`:return`Stops at ${w(e.at)}${T(e.at,t)?` tomorrow`:``}.`;case`after-iterations`:return`Stops after ${e.iterations} ${e.iterations===1?`iteration`:`iterations`}.`}}function D(e,t,n=Date.now()){if(e===null)return{headline:`Stop rule not stated`,remaining:`—`,percent:null,reached:!1};if(e.kind===`until-paused`)return{headline:`Runs until you pause it`,remaining:`no stop time, no iteration limit`,percent:null,reached:!1};if(e.kind===`at-time`){let r=Date.parse(e.at);if(Number.isNaN(r))return{headline:`Stop time not readable`,remaining:`—`,percent:null,reached:!1};let i=`Stops at ${w(e.at)}`,a=r-n;if(a<=0)return{headline:i,remaining:`stop time reached`,percent:100,reached:!0};let o=t?.startedAt?Date.parse(t.startedAt):NaN,s=Number.isNaN(o)||r<=o?null:Math.min(100,Math.max(0,Math.round((n-o)/(r-o)*100)));return{headline:i,remaining:`${l(a)} left`,percent:s,reached:!1}}let r=t?.iterationsDone,i=`Stops after ${e.iterations} ${e.iterations===1?`iteration`:`iterations`}`;return typeof r==`number`?{headline:i,remaining:`${r} of ${e.iterations} done`,percent:Math.min(100,Math.round(r/e.iterations*100)),reached:r>=e.iterations}:{headline:i,remaining:`— of ${e.iterations} done`,percent:null,reached:!1}}function O(e,t=Date.now()){if(!e)return`—`;let n=Date.parse(e);return Number.isNaN(n)?`—`:l(Math.max(0,t-n))}function k(e){if(e===null)return[];let t=[];return e.tests===!0&&t.push(`tests`),e.lint===!0&&t.push(`lint`),e.typecheck===!0&&t.push(`typecheck`),t}function A(e){if(e===null)return[`tests`,`lint`,`typecheck`];let t=[];return e.tests===null&&t.push(`tests`),e.lint===null&&t.push(`lint`),e.typecheck===null&&t.push(`typecheck`),t}function j(e){return e.length===0?``:e.length===1?e[0]:`${e.slice(0,-1).join(`, `)} and ${e[e.length-1]}`}var M=`verse-overnight`,N=`/api/verse/overnight`;function P(e){return e instanceof c?e.status===404?`This build does not expose ${N}, so an overnight run cannot be armed from here. It is a missing route, not a run that refused to start.`:`${N} answered HTTP ${e.status}.`:`${N} could not be reached.`}var F={key:M,fetch:async e=>{try{let t=S(await a(N,e));return t===null?{value:null,available:!0,reason:`${N} answered in a shape this client does not recognise, so nothing is shown rather than guessed.`}:{value:t,available:!0,reason:null}}catch(e){if(e instanceof c&&e.status===401||e instanceof DOMException&&e.name===`AbortError`)throw e;return{value:null,available:!1,reason:P(e)}}}};async function I(e,t){let i=n();if(!i)throw new u;let a=await o(e,t,i);return r(),a}function L(){i(M),i(d)}async function R(e){let t=await I(N,{action:`arm`,stopRule:e});return L(),t}async function z(){let e=await I(N,{action:`disarm`});return L(),e}var B=15e3;function V(e,t=B){let n=s(F);(0,f.useEffect)(()=>{if(!e)return;let r=null,i=()=>{r===null&&(r=setInterval(n,t))},a=()=>{r!==null&&(clearInterval(r),r=null)},o=()=>{if(document.visibilityState===`hidden`){a();return}n(),i()};return document.visibilityState!==`hidden`&&i(),document.addEventListener(`visibilitychange`,o),()=>{a(),document.removeEventListener(`visibilitychange`,o)}},[e,t,n])}export{E as a,A as c,D as d,V as i,j as l,z as n,O as o,F as r,k as s,R as t,C as u};
|
|
2
|
+
//# sourceMappingURL=overnight-queries-C_AfcL7q.js.map
|