@ashlr/hub 3.12.0 → 3.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (719) hide show
  1. package/CHANGELOG.md +157 -0
  2. package/README.md +29 -16
  3. package/dist/authority-surface.json +274 -148
  4. package/dist/build-identity.json +2 -2
  5. package/dist/cli/authority.d.ts +145 -33
  6. package/dist/cli/authority.js +1292 -315
  7. package/dist/cli/authority.js.map +1 -1
  8. package/dist/cli/cloud.js +12 -3
  9. package/dist/cli/cloud.js.map +1 -1
  10. package/dist/cli/comms.d.ts +33 -19
  11. package/dist/cli/comms.js +128 -151
  12. package/dist/cli/comms.js.map +1 -1
  13. package/dist/cli/completions.js +1 -1
  14. package/dist/cli/completions.js.map +1 -1
  15. package/dist/cli/daemon.js +29 -0
  16. package/dist/cli/daemon.js.map +1 -1
  17. package/dist/cli/director.d.ts +8 -12
  18. package/dist/cli/director.js +17 -52
  19. package/dist/cli/director.js.map +1 -1
  20. package/dist/cli/fleet.js +4 -1
  21. package/dist/cli/fleet.js.map +1 -1
  22. package/dist/cli/help.js +1 -0
  23. package/dist/cli/help.js.map +1 -1
  24. package/dist/cli/leader.d.ts +27 -3
  25. package/dist/cli/leader.js +253 -4
  26. package/dist/cli/leader.js.map +1 -1
  27. package/dist/core/authority/protected-paths.js +11 -0
  28. package/dist/core/authority/protected-paths.js.map +1 -1
  29. package/dist/core/authority/resident.d.ts +101 -0
  30. package/dist/core/authority/resident.js +246 -0
  31. package/dist/core/authority/resident.js.map +1 -0
  32. package/dist/core/authority/server-enforcement.d.ts +110 -0
  33. package/dist/core/authority/server-enforcement.js +260 -0
  34. package/dist/core/authority/server-enforcement.js.map +1 -0
  35. package/dist/core/authority/standing-grant.d.ts +24 -4
  36. package/dist/core/authority/standing-grant.js +19 -3
  37. package/dist/core/authority/standing-grant.js.map +1 -1
  38. package/dist/core/authority/types.d.ts +43 -0
  39. package/dist/core/authority/types.js +6 -0
  40. package/dist/core/authority/types.js.map +1 -1
  41. package/dist/core/cloud/budget.js +11 -1
  42. package/dist/core/cloud/budget.js.map +1 -1
  43. package/dist/core/cloud/cloud-api.d.ts +25 -2
  44. package/dist/core/cloud/cloud-api.js +139 -5
  45. package/dist/core/cloud/cloud-api.js.map +1 -1
  46. package/dist/core/cloud/pr-actions.d.ts +93 -0
  47. package/dist/core/cloud/pr-actions.js +436 -0
  48. package/dist/core/cloud/pr-actions.js.map +1 -0
  49. package/dist/core/cloud/pr-preview.d.ts +128 -0
  50. package/dist/core/cloud/pr-preview.js +228 -0
  51. package/dist/core/cloud/pr-preview.js.map +1 -0
  52. package/dist/core/cloud/store.d.ts +2 -0
  53. package/dist/core/cloud/store.js +28 -0
  54. package/dist/core/cloud/store.js.map +1 -1
  55. package/dist/core/cloud/timeline-api.d.ts +24 -0
  56. package/dist/core/cloud/timeline-api.js +46 -0
  57. package/dist/core/cloud/timeline-api.js.map +1 -0
  58. package/dist/core/cloud/timeline-types.d.ts +62 -0
  59. package/dist/core/cloud/timeline-types.js +36 -0
  60. package/dist/core/cloud/timeline-types.js.map +1 -0
  61. package/dist/core/cloud/timeline.d.ts +102 -0
  62. package/dist/core/cloud/timeline.js +925 -0
  63. package/dist/core/cloud/timeline.js.map +1 -0
  64. package/dist/core/cloud/tracker.js +67 -0
  65. package/dist/core/cloud/tracker.js.map +1 -1
  66. package/dist/core/cloud/types.d.ts +38 -0
  67. package/dist/core/cloud/types.js +1 -1
  68. package/dist/core/cloud/types.js.map +1 -1
  69. package/dist/core/comms/change-digest.d.ts +130 -0
  70. package/dist/core/comms/change-digest.js +451 -0
  71. package/dist/core/comms/change-digest.js.map +1 -0
  72. package/dist/core/comms/director-prompt.d.ts +4 -5
  73. package/dist/core/comms/director-prompt.js +4 -71
  74. package/dist/core/comms/director-prompt.js.map +1 -1
  75. package/dist/core/comms/director.d.ts +24 -61
  76. package/dist/core/comms/director.js +29 -382
  77. package/dist/core/comms/director.js.map +1 -1
  78. package/dist/core/comms/dispatch.d.ts +37 -12
  79. package/dist/core/comms/dispatch.js +244 -177
  80. package/dist/core/comms/dispatch.js.map +1 -1
  81. package/dist/core/comms/elon-dialogue.d.ts +23 -15
  82. package/dist/core/comms/elon-dialogue.js +36 -307
  83. package/dist/core/comms/elon-dialogue.js.map +1 -1
  84. package/dist/core/comms/fleet-pulse.js +4 -7
  85. package/dist/core/comms/fleet-pulse.js.map +1 -1
  86. package/dist/core/comms/handlers.d.ts +10 -6
  87. package/dist/core/comms/handlers.js +14 -48
  88. package/dist/core/comms/handlers.js.map +1 -1
  89. package/dist/core/comms/migrations.d.ts +47 -0
  90. package/dist/core/comms/migrations.js +125 -0
  91. package/dist/core/comms/migrations.js.map +1 -0
  92. package/dist/core/comms/requests.d.ts +32 -5
  93. package/dist/core/comms/requests.js +101 -5
  94. package/dist/core/comms/requests.js.map +1 -1
  95. package/dist/core/comms/telegram-channel.d.ts +104 -0
  96. package/dist/core/comms/telegram-channel.js +622 -0
  97. package/dist/core/comms/telegram-channel.js.map +1 -0
  98. package/dist/core/comms/telegram-thread-map.d.ts +56 -0
  99. package/dist/core/comms/telegram-thread-map.js +144 -0
  100. package/dist/core/comms/telegram-thread-map.js.map +1 -0
  101. package/dist/core/daemon/capacity-publisher.d.ts +8 -1
  102. package/dist/core/daemon/capacity-publisher.js +40 -2
  103. package/dist/core/daemon/capacity-publisher.js.map +1 -1
  104. package/dist/core/daemon/loop.js +18 -4
  105. package/dist/core/daemon/loop.js.map +1 -1
  106. package/dist/core/daemon/service-install-authority.d.ts +10 -2
  107. package/dist/core/daemon/service-install-authority.js +14 -5
  108. package/dist/core/daemon/service-install-authority.js.map +1 -1
  109. package/dist/core/daemon/service.d.ts +15 -0
  110. package/dist/core/daemon/service.js +26 -0
  111. package/dist/core/daemon/service.js.map +1 -1
  112. package/dist/core/daemon/tick-deadline.d.ts +44 -0
  113. package/dist/core/daemon/tick-deadline.js +83 -0
  114. package/dist/core/daemon/tick-deadline.js.map +1 -0
  115. package/dist/core/daemon/tick-hooks.d.ts +7 -0
  116. package/dist/core/daemon/tick-hooks.js.map +1 -1
  117. package/dist/core/daemon/tick-progress.d.ts +39 -0
  118. package/dist/core/daemon/tick-progress.js +194 -0
  119. package/dist/core/daemon/tick-progress.js.map +1 -0
  120. package/dist/core/dashboard.js +3 -1
  121. package/dist/core/dashboard.js.map +1 -1
  122. package/dist/core/fleet/cloud-intake.d.ts +95 -0
  123. package/dist/core/fleet/cloud-intake.js +557 -0
  124. package/dist/core/fleet/cloud-intake.js.map +1 -0
  125. package/dist/core/fleet/dispatch-router.d.ts +13 -0
  126. package/dist/core/fleet/dispatch-router.js +32 -8
  127. package/dist/core/fleet/dispatch-router.js.map +1 -1
  128. package/dist/core/fleet/fleet-merge-state.d.ts +16 -0
  129. package/dist/core/fleet/fleet-merge-state.js.map +1 -1
  130. package/dist/core/fleet/host-merge.d.ts +14 -0
  131. package/dist/core/fleet/host-merge.js +24 -2
  132. package/dist/core/fleet/host-merge.js.map +1 -1
  133. package/dist/core/fleet/merge-gates.d.ts +21 -0
  134. package/dist/core/fleet/merge-gates.js +39 -5
  135. package/dist/core/fleet/merge-gates.js.map +1 -1
  136. package/dist/core/fleet/mirrors.d.ts +162 -6
  137. package/dist/core/fleet/mirrors.js +1051 -49
  138. package/dist/core/fleet/mirrors.js.map +1 -1
  139. package/dist/core/fleet/standing-merge-pass.d.ts +8 -0
  140. package/dist/core/fleet/standing-merge-pass.js +102 -1
  141. package/dist/core/fleet/standing-merge-pass.js.map +1 -1
  142. package/dist/core/fleet/status.d.ts +17 -0
  143. package/dist/core/fleet/status.js +22 -0
  144. package/dist/core/fleet/status.js.map +1 -1
  145. package/dist/core/fleet/tick-hooks-live.d.ts +10 -1
  146. package/dist/core/fleet/tick-hooks-live.js +57 -8
  147. package/dist/core/fleet/tick-hooks-live.js.map +1 -1
  148. package/dist/core/fleet/verify-check-run.d.ts +90 -0
  149. package/dist/core/fleet/verify-check-run.js +274 -0
  150. package/dist/core/fleet/verify-check-run.js.map +1 -0
  151. package/dist/core/git.d.ts +17 -0
  152. package/dist/core/git.js +124 -25
  153. package/dist/core/git.js.map +1 -1
  154. package/dist/core/goals/open-goals.d.ts +47 -0
  155. package/dist/core/goals/open-goals.js +33 -0
  156. package/dist/core/goals/open-goals.js.map +1 -0
  157. package/dist/core/inbox/merge.d.ts +5 -0
  158. package/dist/core/inbox/merge.js +58 -2
  159. package/dist/core/inbox/merge.js.map +1 -1
  160. package/dist/core/integrations/locus.d.ts +28 -0
  161. package/dist/core/integrations/locus.js +155 -30
  162. package/dist/core/integrations/locus.js.map +1 -1
  163. package/dist/core/integrations/telegram-format.d.ts +40 -0
  164. package/dist/core/integrations/telegram-format.js +123 -0
  165. package/dist/core/integrations/telegram-format.js.map +1 -0
  166. package/dist/core/integrations/telegram.d.ts +60 -4
  167. package/dist/core/integrations/telegram.js +161 -28
  168. package/dist/core/integrations/telegram.js.map +1 -1
  169. package/dist/core/mcp-registry.d.ts +12 -0
  170. package/dist/core/mcp-registry.js +70 -0
  171. package/dist/core/mcp-registry.js.map +1 -1
  172. package/dist/core/observability/rollup.d.ts +12 -10
  173. package/dist/core/observability/rollup.js +44 -17
  174. package/dist/core/observability/rollup.js.map +1 -1
  175. package/dist/core/resources/connection-monitor.d.ts +9 -0
  176. package/dist/core/resources/connection-monitor.js +19 -9
  177. package/dist/core/resources/connection-monitor.js.map +1 -1
  178. package/dist/core/resources/quota-refresh-lease.d.ts +17 -0
  179. package/dist/core/resources/quota-refresh-lease.js +34 -1
  180. package/dist/core/resources/quota-refresh-lease.js.map +1 -1
  181. package/dist/core/routing/budget-api.d.ts +18 -1
  182. package/dist/core/routing/budget-api.js +120 -10
  183. package/dist/core/routing/budget-api.js.map +1 -1
  184. package/dist/core/routing/budget-store.d.ts +22 -1
  185. package/dist/core/routing/budget-store.js +22 -8
  186. package/dist/core/routing/budget-store.js.map +1 -1
  187. package/dist/core/routing/readiness-types.d.ts +82 -0
  188. package/dist/core/routing/readiness-types.js +23 -0
  189. package/dist/core/routing/readiness-types.js.map +1 -0
  190. package/dist/core/routing/readiness.d.ts +103 -0
  191. package/dist/core/routing/readiness.js +480 -0
  192. package/dist/core/routing/readiness.js.map +1 -0
  193. package/dist/core/sandbox/confine.js +22 -1
  194. package/dist/core/sandbox/confine.js.map +1 -1
  195. package/dist/core/sandbox/policy.d.ts +23 -0
  196. package/dist/core/sandbox/policy.js +100 -0
  197. package/dist/core/sandbox/policy.js.map +1 -1
  198. package/dist/core/types.d.ts +13 -0
  199. package/dist/core/types.js.map +1 -1
  200. package/dist/core/universe/builtins/preparation/manifest.json +1 -1
  201. package/dist/core/universe/builtins/preparation/preparation-bridge.mjs +1204 -939
  202. package/dist/core/universe/builtins/preparation/preparation-verification-fixtures.mjs +1319 -1054
  203. package/dist/core/usage/frontier-usage.d.ts +20 -2
  204. package/dist/core/usage/frontier-usage.js +75 -17
  205. package/dist/core/usage/frontier-usage.js.map +1 -1
  206. package/dist/core/verse/account-health.js +9 -3
  207. package/dist/core/verse/account-health.js.map +1 -1
  208. package/dist/core/verse/accounts.d.ts +45 -0
  209. package/dist/core/verse/accounts.js +246 -17
  210. package/dist/core/verse/accounts.js.map +1 -1
  211. package/dist/core/verse/activity-api.d.ts +5 -1
  212. package/dist/core/verse/activity-api.js +62 -14
  213. package/dist/core/verse/activity-api.js.map +1 -1
  214. package/dist/core/verse/apps-api.js +23 -11
  215. package/dist/core/verse/apps-api.js.map +1 -1
  216. package/dist/core/verse/apps.d.ts +11 -9
  217. package/dist/core/verse/apps.js +2 -2
  218. package/dist/core/verse/apps.js.map +1 -1
  219. package/dist/core/verse/authority-api.d.ts +17 -3
  220. package/dist/core/verse/authority-api.js +122 -7
  221. package/dist/core/verse/authority-api.js.map +1 -1
  222. package/dist/core/verse/autonomy-ladder.d.ts +172 -0
  223. package/dist/core/verse/autonomy-ladder.js +251 -0
  224. package/dist/core/verse/autonomy-ladder.js.map +1 -0
  225. package/dist/core/verse/context-fit.js +7 -5
  226. package/dist/core/verse/context-fit.js.map +1 -1
  227. package/dist/core/verse/control-api.d.ts +23 -1
  228. package/dist/core/verse/control-api.js +117 -10
  229. package/dist/core/verse/control-api.js.map +1 -1
  230. package/dist/core/verse/fleet-live-api.js +13 -5
  231. package/dist/core/verse/fleet-live-api.js.map +1 -1
  232. package/dist/core/verse/folder-io.d.ts +50 -0
  233. package/dist/core/verse/folder-io.js +142 -0
  234. package/dist/core/verse/folder-io.js.map +1 -0
  235. package/dist/core/verse/git-api.js +5 -4
  236. package/dist/core/verse/git-api.js.map +1 -1
  237. package/dist/core/verse/git-ops.d.ts +10 -1
  238. package/dist/core/verse/git-ops.js +18 -2
  239. package/dist/core/verse/git-ops.js.map +1 -1
  240. package/dist/core/verse/github-api.d.ts +1 -1
  241. package/dist/core/verse/github-api.js +5 -4
  242. package/dist/core/verse/github-api.js.map +1 -1
  243. package/dist/core/verse/github-repo.js +118 -14
  244. package/dist/core/verse/github-repo.js.map +1 -1
  245. package/dist/core/verse/leader-api.d.ts +5 -4
  246. package/dist/core/verse/leader-api.js +237 -10
  247. package/dist/core/verse/leader-api.js.map +1 -1
  248. package/dist/core/verse/local-models.d.ts +10 -0
  249. package/dist/core/verse/local-models.js +10 -1
  250. package/dist/core/verse/local-models.js.map +1 -1
  251. package/dist/core/verse/login-path.d.ts +73 -0
  252. package/dist/core/verse/login-path.js +123 -14
  253. package/dist/core/verse/login-path.js.map +1 -1
  254. package/dist/core/verse/mcp-control-api.js +4 -4
  255. package/dist/core/verse/mcp-control-api.js.map +1 -1
  256. package/dist/core/verse/mcp-scope.d.ts +22 -0
  257. package/dist/core/verse/mcp-scope.js +41 -1
  258. package/dist/core/verse/mcp-scope.js.map +1 -1
  259. package/dist/core/verse/mcp-seat-view.d.ts +10 -0
  260. package/dist/core/verse/mcp-seat-view.js +30 -4
  261. package/dist/core/verse/mcp-seat-view.js.map +1 -1
  262. package/dist/core/verse/overnight-api.js +20 -2
  263. package/dist/core/verse/overnight-api.js.map +1 -1
  264. package/dist/core/verse/path-guard.d.ts +24 -0
  265. package/dist/core/verse/path-guard.js +91 -22
  266. package/dist/core/verse/path-guard.js.map +1 -1
  267. package/dist/core/verse/preview-api.js +22 -0
  268. package/dist/core/verse/preview-api.js.map +1 -1
  269. package/dist/core/verse/projects.d.ts +21 -0
  270. package/dist/core/verse/projects.js +82 -0
  271. package/dist/core/verse/projects.js.map +1 -1
  272. package/dist/core/verse/seat-readiness.d.ts +25 -0
  273. package/dist/core/verse/seat-readiness.js +43 -6
  274. package/dist/core/verse/seat-readiness.js.map +1 -1
  275. package/dist/core/verse/session-controls-api.js +5 -3
  276. package/dist/core/verse/session-controls-api.js.map +1 -1
  277. package/dist/core/verse/session-handoff.d.ts +26 -0
  278. package/dist/core/verse/session-handoff.js +90 -12
  279. package/dist/core/verse/session-handoff.js.map +1 -1
  280. package/dist/core/verse/terminal-api.js +7 -4
  281. package/dist/core/verse/terminal-api.js.map +1 -1
  282. package/dist/core/verse/terminal.js +9 -5
  283. package/dist/core/verse/terminal.js.map +1 -1
  284. package/dist/core/verse/verse-api.d.ts +3 -1
  285. package/dist/core/verse/verse-api.js +87 -27
  286. package/dist/core/verse/verse-api.js.map +1 -1
  287. package/dist/core/verse/workspaces.d.ts +51 -0
  288. package/dist/core/verse/workspaces.js +177 -47
  289. package/dist/core/verse/workspaces.js.map +1 -1
  290. package/dist/core/vision/leader-apply.d.ts +40 -0
  291. package/dist/core/vision/leader-apply.js +101 -30
  292. package/dist/core/vision/leader-apply.js.map +1 -1
  293. package/dist/core/vision/leader-cadence.d.ts +114 -0
  294. package/dist/core/vision/leader-cadence.js +127 -0
  295. package/dist/core/vision/leader-cadence.js.map +1 -0
  296. package/dist/core/vision/leader-goal-evidence.d.ts +25 -0
  297. package/dist/core/vision/leader-goal-evidence.js +36 -0
  298. package/dist/core/vision/leader-goal-evidence.js.map +1 -0
  299. package/dist/core/vision/leader-health.d.ts +53 -0
  300. package/dist/core/vision/leader-health.js +92 -0
  301. package/dist/core/vision/leader-health.js.map +1 -0
  302. package/dist/core/vision/leader-operator.d.ts +176 -0
  303. package/dist/core/vision/leader-operator.js +355 -0
  304. package/dist/core/vision/leader-operator.js.map +1 -0
  305. package/dist/core/vision/leader-run-chain.d.ts +41 -0
  306. package/dist/core/vision/leader-run-chain.js +54 -0
  307. package/dist/core/vision/leader-run-chain.js.map +1 -0
  308. package/dist/core/vision/leader-seat-plan.d.ts +68 -0
  309. package/dist/core/vision/leader-seat-plan.js +93 -0
  310. package/dist/core/vision/leader-seat-plan.js.map +1 -0
  311. package/dist/core/vision/leader-seat.d.ts +71 -5
  312. package/dist/core/vision/leader-seat.js +235 -33
  313. package/dist/core/vision/leader-seat.js.map +1 -1
  314. package/dist/core/vision/leader-thread-types.d.ts +104 -0
  315. package/dist/core/vision/leader-thread-types.js +9 -0
  316. package/dist/core/vision/leader-thread-types.js.map +1 -0
  317. package/dist/core/vision/leader-thread.d.ts +138 -0
  318. package/dist/core/vision/leader-thread.js +926 -0
  319. package/dist/core/vision/leader-thread.js.map +1 -0
  320. package/dist/core/vision/leader-types.d.ts +75 -1
  321. package/dist/core/vision/leader.d.ts +88 -18
  322. package/dist/core/vision/leader.js +269 -69
  323. package/dist/core/vision/leader.js.map +1 -1
  324. package/dist/core/web/public/next/assets/{ActionMenu-B4-39f2S.js → ActionMenu-CIiX2X8w.js} +2 -2
  325. package/dist/core/web/public/next/assets/{ActionMenu-B4-39f2S.js.map → ActionMenu-CIiX2X8w.js.map} +1 -1
  326. package/dist/core/web/public/next/assets/Advanced-DHsysoIL.js +2 -0
  327. package/dist/core/web/public/next/assets/{Advanced-B-LqYXvd.js.map → Advanced-DHsysoIL.js.map} +1 -1
  328. package/dist/core/web/public/next/assets/App-CMeAocmW.js +7 -0
  329. package/dist/core/web/public/next/assets/{App-E2zCDRxm.js.map → App-CMeAocmW.js.map} +1 -1
  330. package/dist/core/web/public/next/assets/AppsSection-DISYnMnc.js +2 -0
  331. package/dist/core/web/public/next/assets/{AppsSection-8wXPPhZb.js.map → AppsSection-DISYnMnc.js.map} +1 -1
  332. package/dist/core/web/public/next/assets/AreaTrend-DK2Y2TbZ.js +2 -0
  333. package/dist/core/web/public/next/assets/AreaTrend-DK2Y2TbZ.js.map +1 -0
  334. package/dist/core/web/public/next/assets/AutonomyOffState-CEPSZToP.js +3 -0
  335. package/dist/core/web/public/next/assets/AutonomyOffState-CEPSZToP.js.map +1 -0
  336. package/dist/core/web/public/next/assets/AutonomyOffState-CmSSTHVe.css +1 -0
  337. package/dist/core/web/public/next/assets/AutonomySection-DWc3ciAD.js +2 -0
  338. package/dist/core/web/public/next/assets/{AutonomySection-B46igJKR.js.map → AutonomySection-DWc3ciAD.js.map} +1 -1
  339. package/dist/core/web/public/next/assets/AutonomyStatus-CYaHjJ9U.js +2 -0
  340. package/dist/core/web/public/next/assets/AutonomyStatus-CYaHjJ9U.js.map +1 -0
  341. package/dist/core/web/public/next/assets/{BranchBar-BRkrEQGs.js → BranchBar-BxhdiIpx.js} +2 -2
  342. package/dist/core/web/public/next/assets/{BranchBar-BRkrEQGs.js.map → BranchBar-BxhdiIpx.js.map} +1 -1
  343. package/dist/core/web/public/next/assets/BudgetControl-C-0KhjRS.js +2 -0
  344. package/dist/core/web/public/next/assets/BudgetControl-C-0KhjRS.js.map +1 -0
  345. package/dist/core/web/public/next/assets/{Button-BhO-WKPp.js → Button-D90dzI_o.js} +2 -2
  346. package/dist/core/web/public/next/assets/{Button-BhO-WKPp.js.map → Button-D90dzI_o.js.map} +1 -1
  347. package/dist/core/web/public/next/assets/{CapacityStrip-CkFz5vq2.js → CapacityStrip-qKDBC65C.js} +2 -2
  348. package/dist/core/web/public/next/assets/{CapacityStrip-CkFz5vq2.js.map → CapacityStrip-qKDBC65C.js.map} +1 -1
  349. package/dist/core/web/public/next/assets/ChartFrame-DY-GVUb3.js +2 -0
  350. package/dist/core/web/public/next/assets/ChartFrame-DY-GVUb3.js.map +1 -0
  351. package/dist/core/web/public/next/assets/ChartFrame-DyjmyV8N.css +1 -0
  352. package/dist/core/web/public/next/assets/ChatSection-DlT4QU6a.js +3 -0
  353. package/dist/core/web/public/next/assets/ChatSection-DlT4QU6a.js.map +1 -0
  354. package/dist/core/web/public/next/assets/{CloudBudgetForm-Bd91iStN.js → CloudBudgetForm-BrNun_Yu.js} +2 -2
  355. package/dist/core/web/public/next/assets/{CloudBudgetForm-Bd91iStN.js.map → CloudBudgetForm-BrNun_Yu.js.map} +1 -1
  356. package/dist/core/web/public/next/assets/CommandPalette-C5lDDKN0.js +2 -0
  357. package/dist/core/web/public/next/assets/CommandPalette-C5lDDKN0.js.map +1 -0
  358. package/dist/core/web/public/next/assets/CommandSection-B0xuU-yZ.css +1 -0
  359. package/dist/core/web/public/next/assets/CommandSection-DXFvPgKp.js +3 -0
  360. package/dist/core/web/public/next/assets/CommandSection-DXFvPgKp.js.map +1 -0
  361. package/dist/core/web/public/next/assets/{ConfirmDialog-Bv4hdK2T.js → ConfirmDialog-BR4nZQ2D.js} +2 -2
  362. package/dist/core/web/public/next/assets/{ConfirmDialog-Bv4hdK2T.js.map → ConfirmDialog-BR4nZQ2D.js.map} +1 -1
  363. package/dist/core/web/public/next/assets/{DeleteChatDialog-CH1Ix8Eh.js → DeleteChatDialog-BCfP12GH.js} +2 -2
  364. package/dist/core/web/public/next/assets/{DeleteChatDialog-CH1Ix8Eh.js.map → DeleteChatDialog-BCfP12GH.js.map} +1 -1
  365. package/dist/core/web/public/next/assets/{Dialog-BSsIFNqD.js → Dialog-D3msQlCj.js} +2 -2
  366. package/dist/core/web/public/next/assets/{Dialog-BSsIFNqD.js.map → Dialog-D3msQlCj.js.map} +1 -1
  367. package/dist/core/web/public/next/assets/{DiffPane-BpNuJmth.js → DiffPane-Ix6hvXlY.js} +2 -2
  368. package/dist/core/web/public/next/assets/{DiffPane-BpNuJmth.js.map → DiffPane-Ix6hvXlY.js.map} +1 -1
  369. package/dist/core/web/public/next/assets/{DiffViewer-CJarUvs0.js → DiffViewer-C4WKsCIe.js} +2 -2
  370. package/dist/core/web/public/next/assets/{DiffViewer-CJarUvs0.js.map → DiffViewer-C4WKsCIe.js.map} +1 -1
  371. package/dist/core/web/public/next/assets/DockHost-aWP7liri.js +2 -0
  372. package/dist/core/web/public/next/assets/{DockHost-DW9q0NdR.js.map → DockHost-aWP7liri.js.map} +1 -1
  373. package/dist/core/web/public/next/assets/{EmptyState-DPrd2aak.js → EmptyState-D2IRy3Cg.js} +2 -2
  374. package/dist/core/web/public/next/assets/{EmptyState-DPrd2aak.js.map → EmptyState-D2IRy3Cg.js.map} +1 -1
  375. package/dist/core/web/public/next/assets/{Epistemic-D7MxSmED.js → Epistemic-DMr18muX.js} +2 -2
  376. package/dist/core/web/public/next/assets/{Epistemic-D7MxSmED.js.map → Epistemic-DMr18muX.js.map} +1 -1
  377. package/dist/core/web/public/next/assets/EvidenceTimeline-DXmmz6Fi.js +2 -0
  378. package/dist/core/web/public/next/assets/EvidenceTimeline-DXmmz6Fi.js.map +1 -0
  379. package/dist/core/web/public/next/assets/EvidenceTimeline-PBDAiSuG.css +1 -0
  380. package/dist/core/web/public/next/assets/FleetSection-BfplcwFU.js +3 -0
  381. package/dist/core/web/public/next/assets/FleetSection-BfplcwFU.js.map +1 -0
  382. package/dist/core/web/public/next/assets/Funnel-Dh2yVHws.js +2 -0
  383. package/dist/core/web/public/next/assets/Funnel-Dh2yVHws.js.map +1 -0
  384. package/dist/core/web/public/next/assets/{GearTray-CIPtzeIx.js → GearTray-Dt-ee32-.js} +2 -2
  385. package/dist/core/web/public/next/assets/{GearTray-CIPtzeIx.js.map → GearTray-Dt-ee32-.js.map} +1 -1
  386. package/dist/core/web/public/next/assets/GrowthSection-P9EUfGeA.js +2 -0
  387. package/dist/core/web/public/next/assets/{GrowthSection-iiQg6wvK.js.map → GrowthSection-P9EUfGeA.js.map} +1 -1
  388. package/dist/core/web/public/next/assets/{HandoffDialog-DrQ6ofuy.js → HandoffDialog-CLJQLe7M.js} +2 -2
  389. package/dist/core/web/public/next/assets/{HandoffDialog-DrQ6ofuy.js.map → HandoffDialog-CLJQLe7M.js.map} +1 -1
  390. package/dist/core/web/public/next/assets/{Input-C0MQxEM6.js → Input-D_KRJA9V.js} +2 -2
  391. package/dist/core/web/public/next/assets/{Input-C0MQxEM6.js.map → Input-D_KRJA9V.js.map} +1 -1
  392. package/dist/core/web/public/next/assets/LeaderCard-D-7DlJuR.js +2 -0
  393. package/dist/core/web/public/next/assets/LeaderCard-D-7DlJuR.js.map +1 -0
  394. package/dist/core/web/public/next/assets/LeaderCard-DNsbLwY3.css +1 -0
  395. package/dist/core/web/public/next/assets/LeaderConversation-DGZjWI-E.js +2 -0
  396. package/dist/core/web/public/next/assets/LeaderConversation-DGZjWI-E.js.map +1 -0
  397. package/dist/core/web/public/next/assets/LeaderConversation-DPHUTq6W.css +1 -0
  398. package/dist/core/web/public/next/assets/MatrixHeatmap-C7BCG2d7.js +2 -0
  399. package/dist/core/web/public/next/assets/MatrixHeatmap-C7BCG2d7.js.map +1 -0
  400. package/dist/core/web/public/next/assets/McpSection-DGbRcyv8.js +2 -0
  401. package/dist/core/web/public/next/assets/{McpSection-BRuCcTjT.js.map → McpSection-DGbRcyv8.js.map} +1 -1
  402. package/dist/core/web/public/next/assets/{MessageMarkdown-bRvD5nSc.js → MessageMarkdown-DFvk06qG.js} +3 -3
  403. package/dist/core/web/public/next/assets/{MessageMarkdown-bRvD5nSc.js.map → MessageMarkdown-DFvk06qG.js.map} +1 -1
  404. package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-FjjkPKA2.js → MessageMarkdownRenderer-BAv4oEUf.js} +2 -2
  405. package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-FjjkPKA2.js.map → MessageMarkdownRenderer-BAv4oEUf.js.map} +1 -1
  406. package/dist/core/web/public/next/assets/{Meter-CFNLpwA-.js → Meter-CMj-VafN.js} +2 -2
  407. package/dist/core/web/public/next/assets/{Meter-CFNLpwA-.js.map → Meter-CMj-VafN.js.map} +1 -1
  408. package/dist/core/web/public/next/assets/MindSection-C6kLPIjt.js +3 -0
  409. package/dist/core/web/public/next/assets/MindSection-C6kLPIjt.js.map +1 -0
  410. package/dist/core/web/public/next/assets/{MutationTokenDialog-T7gv3a9r.js → MutationTokenDialog-DbnO8aYi.js} +2 -2
  411. package/dist/core/web/public/next/assets/{MutationTokenDialog-T7gv3a9r.js.map → MutationTokenDialog-DbnO8aYi.js.map} +1 -1
  412. package/dist/core/web/public/next/assets/NeedsYouDrawer-crsiX-Nc.js +3 -0
  413. package/dist/core/web/public/next/assets/NeedsYouDrawer-crsiX-Nc.js.map +1 -0
  414. package/dist/core/web/public/next/assets/NeedsYouList-CCsijdWt.js +2 -0
  415. package/dist/core/web/public/next/assets/{NeedsYouList-BgH8ezqf.js.map → NeedsYouList-CCsijdWt.js.map} +1 -1
  416. package/dist/core/web/public/next/assets/NeedsYouList-CH6Mq-E_.css +1 -0
  417. package/dist/core/web/public/next/assets/NewChatDialog-BlCHtOIr.js +3 -0
  418. package/dist/core/web/public/next/assets/{NewChatDialog-Db5Xjrk8.js.map → NewChatDialog-BlCHtOIr.js.map} +1 -1
  419. package/dist/core/web/public/next/assets/OnboardingFlow-Cy9BA9eR.js +3 -0
  420. package/dist/core/web/public/next/assets/OnboardingFlow-Cy9BA9eR.js.map +1 -0
  421. package/dist/core/web/public/next/assets/OnboardingGate-BXpNFoLt.js +3 -0
  422. package/dist/core/web/public/next/assets/{OnboardingGate-C4VXn7BJ.js.map → OnboardingGate-BXpNFoLt.js.map} +1 -1
  423. package/dist/core/web/public/next/assets/PreviewPane-COid5A0f.js +2 -0
  424. package/dist/core/web/public/next/assets/{PreviewPane-BPBbcROb.js.map → PreviewPane-COid5A0f.js.map} +1 -1
  425. package/dist/core/web/public/next/assets/{ProviderLogo-CT2cSfkg.js → ProviderLogo-Cq-CYIwT.js} +2 -2
  426. package/dist/core/web/public/next/assets/{ProviderLogo-CT2cSfkg.js.map → ProviderLogo-Cq-CYIwT.js.map} +1 -1
  427. package/dist/core/web/public/next/assets/{RailStatus-Vgl0GYtd.js → RailStatus-Co5UB6We.js} +2 -2
  428. package/dist/core/web/public/next/assets/{RailStatus-Vgl0GYtd.js.map → RailStatus-Co5UB6We.js.map} +1 -1
  429. package/dist/core/web/public/next/assets/{RefreshIndicator-CSyqpY_q.js → RefreshIndicator-DO9ibnSq.js} +2 -2
  430. package/dist/core/web/public/next/assets/{RefreshIndicator-CSyqpY_q.js.map → RefreshIndicator-DO9ibnSq.js.map} +1 -1
  431. package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-Dr2WRgkq.js +7 -0
  432. package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-BX2nkdmZ.js.map → ResourcePoolConsoleApp-Dr2WRgkq.js.map} +1 -1
  433. package/dist/core/web/public/next/assets/ResourcesChrome-CwMnbqI1.js +3 -0
  434. package/dist/core/web/public/next/assets/ResourcesChrome-CwMnbqI1.js.map +1 -0
  435. package/dist/core/web/public/next/assets/ResourcesDrawer-B_Xp_JNc.js +2 -0
  436. package/dist/core/web/public/next/assets/ResourcesDrawer-B_Xp_JNc.js.map +1 -0
  437. package/dist/core/web/public/next/assets/ResourcesDrawer-DrGoO8KG.css +1 -0
  438. package/dist/core/web/public/next/assets/{RouteErrorBoundary-BaC7YVzR.js → RouteErrorBoundary-SkNhhUbt.js} +2 -2
  439. package/dist/core/web/public/next/assets/{RouteErrorBoundary-BaC7YVzR.js.map → RouteErrorBoundary-SkNhhUbt.js.map} +1 -1
  440. package/dist/core/web/public/next/assets/{RunInCloudAction-D5PDHJPE.js → RunInCloudAction-BXPlZwJQ.js} +2 -2
  441. package/dist/core/web/public/next/assets/{RunInCloudAction-D5PDHJPE.js.map → RunInCloudAction-BXPlZwJQ.js.map} +1 -1
  442. package/dist/core/web/public/next/assets/{SeatSelector-Cg75LInq.js → SeatSelector-J5R3zDkB.js} +3 -3
  443. package/dist/core/web/public/next/assets/{SeatSelector-Cg75LInq.js.map → SeatSelector-J5R3zDkB.js.map} +1 -1
  444. package/dist/core/web/public/next/assets/{Segmented-CametjLt.js → Segmented-CGh_-tBb.js} +2 -2
  445. package/dist/core/web/public/next/assets/{Segmented-CametjLt.js.map → Segmented-CGh_-tBb.js.map} +1 -1
  446. package/dist/core/web/public/next/assets/{Select-De52fghU.js → Select-CWnmUzs3.js} +2 -2
  447. package/dist/core/web/public/next/assets/{Select-De52fghU.js.map → Select-CWnmUzs3.js.map} +1 -1
  448. package/dist/core/web/public/next/assets/{SessionGate-CzlcNq3O.js → SessionGate-sp4KsnUo.js} +2 -2
  449. package/dist/core/web/public/next/assets/{SessionGate-CzlcNq3O.js.map → SessionGate-sp4KsnUo.js.map} +1 -1
  450. package/dist/core/web/public/next/assets/{SessionInsightChip-Bk_Owa7u.js → SessionInsightChip-DLFAzdbi.js} +2 -2
  451. package/dist/core/web/public/next/assets/{SessionInsightChip-Bk_Owa7u.js.map → SessionInsightChip-DLFAzdbi.js.map} +1 -1
  452. package/dist/core/web/public/next/assets/{SessionSearch-C6C8DHN8.js → SessionSearch-DbFjwR1h.js} +2 -2
  453. package/dist/core/web/public/next/assets/{SessionSearch-C6C8DHN8.js.map → SessionSearch-DbFjwR1h.js.map} +1 -1
  454. package/dist/core/web/public/next/assets/{SettingsSection-mI9wQYZg.js → SettingsSection-Ch23msJ5.js} +2 -2
  455. package/dist/core/web/public/next/assets/SettingsSection-Ch23msJ5.js.map +1 -0
  456. package/dist/core/web/public/next/assets/SetupChecklist-Bd76MBAR.js +2 -0
  457. package/dist/core/web/public/next/assets/SetupChecklist-Bd76MBAR.js.map +1 -0
  458. package/dist/core/web/public/next/assets/SetupChecklist-BhZpFLsj.css +1 -0
  459. package/dist/core/web/public/next/assets/ShadowDecisions-C5RAY91f.js +3 -0
  460. package/dist/core/web/public/next/assets/ShadowDecisions-C5RAY91f.js.map +1 -0
  461. package/dist/core/web/public/next/assets/{Sheet-CJhK9Dqv.js → Sheet-BZ2AG4Eo.js} +2 -2
  462. package/dist/core/web/public/next/assets/{Sheet-CJhK9Dqv.js.map → Sheet-BZ2AG4Eo.js.map} +1 -1
  463. package/dist/core/web/public/next/assets/{ShortcutsOverlay-DDW-i9Fc.js → ShortcutsOverlay-C8n8y3zf.js} +2 -2
  464. package/dist/core/web/public/next/assets/{ShortcutsOverlay-DDW-i9Fc.js.map → ShortcutsOverlay-C8n8y3zf.js.map} +1 -1
  465. package/dist/core/web/public/next/assets/Sidebar-DN--cPYN.js +3 -0
  466. package/dist/core/web/public/next/assets/Sidebar-DN--cPYN.js.map +1 -0
  467. package/dist/core/web/public/next/assets/{Slider-Bwd9HfXl.js → Slider-KVoJLDD6.js} +2 -2
  468. package/dist/core/web/public/next/assets/{Slider-Bwd9HfXl.js.map → Slider-KVoJLDD6.js.map} +1 -1
  469. package/dist/core/web/public/next/assets/StatTile-C4KgjltA.js +2 -0
  470. package/dist/core/web/public/next/assets/StatTile-C4KgjltA.js.map +1 -0
  471. package/dist/core/web/public/next/assets/StatTile-CNCqDoPO.css +1 -0
  472. package/dist/core/web/public/next/assets/{StatusBadge-DHKRtttH.js → StatusBadge-CXsYqmdU.js} +2 -2
  473. package/dist/core/web/public/next/assets/{StatusBadge-DHKRtttH.js.map → StatusBadge-CXsYqmdU.js.map} +1 -1
  474. package/dist/core/web/public/next/assets/StepBand-BMtVOFpK.js +2 -0
  475. package/dist/core/web/public/next/assets/StepBand-BMtVOFpK.js.map +1 -0
  476. package/dist/core/web/public/next/assets/{Surface-D--LXgQm.js → Surface-BfDmQcKe.js} +2 -2
  477. package/dist/core/web/public/next/assets/{Surface-D--LXgQm.js.map → Surface-BfDmQcKe.js.map} +1 -1
  478. package/dist/core/web/public/next/assets/Swimlane-B9Exxekk.js +2 -0
  479. package/dist/core/web/public/next/assets/Swimlane-B9Exxekk.js.map +1 -0
  480. package/dist/core/web/public/next/assets/Swimlane-Bf4Rjoy9.css +1 -0
  481. package/dist/core/web/public/next/assets/{Switch-PMixU6b0.js → Switch-9NtO_6Lj.js} +2 -2
  482. package/dist/core/web/public/next/assets/{Switch-PMixU6b0.js.map → Switch-9NtO_6Lj.js.map} +1 -1
  483. package/dist/core/web/public/next/assets/{Tag-fordBsrJ.js → Tag-DscCRFcN.js} +2 -2
  484. package/dist/core/web/public/next/assets/{Tag-fordBsrJ.js.map → Tag-DscCRFcN.js.map} +1 -1
  485. package/dist/core/web/public/next/assets/{TerminalPane-BSnGdUuF.js → TerminalPane-B668-DJW.js} +5 -5
  486. package/dist/core/web/public/next/assets/{TerminalPane-BSnGdUuF.js.map → TerminalPane-B668-DJW.js.map} +1 -1
  487. package/dist/core/web/public/next/assets/UniverseConsoleApp-BUV_brY7.js +2 -0
  488. package/dist/core/web/public/next/assets/{UniverseConsoleApp-DtXFhAhw.js.map → UniverseConsoleApp-BUV_brY7.js.map} +1 -1
  489. package/dist/core/web/public/next/assets/{UniverseView-sWm3pnTW.js → UniverseView-DG70zH0W.js} +4 -4
  490. package/dist/core/web/public/next/assets/{UniverseView-sWm3pnTW.js.map → UniverseView-DG70zH0W.js.map} +1 -1
  491. package/dist/core/web/public/next/assets/UsageSection-DY7uOTm1.js +3 -0
  492. package/dist/core/web/public/next/assets/UsageSection-DY7uOTm1.js.map +1 -0
  493. package/dist/core/web/public/next/assets/VerseConsoleApp-CWU6R3By.js +3 -0
  494. package/dist/core/web/public/next/assets/VerseConsoleApp-CWU6R3By.js.map +1 -0
  495. package/dist/core/web/public/next/assets/Workspace-D1nP9BhD.js +10 -0
  496. package/dist/core/web/public/next/assets/{Workspace-BQSZFSeO.js.map → Workspace-D1nP9BhD.js.map} +1 -1
  497. package/dist/core/web/public/next/assets/actions-CY-PjpGc.js +2 -0
  498. package/dist/core/web/public/next/assets/{actions-Ci6I4C0l.js.map → actions-CY-PjpGc.js.map} +1 -1
  499. package/dist/core/web/public/next/assets/actions-DkWhhWIg.css +1 -0
  500. package/dist/core/web/public/next/assets/{apps-model-DlwnfqwJ.js → apps-model-Du02KhAf.js} +2 -2
  501. package/dist/core/web/public/next/assets/{apps-model-DlwnfqwJ.js.map → apps-model-Du02KhAf.js.map} +1 -1
  502. package/dist/core/web/public/next/assets/{authority-model-BFuPezSo.js → authority-model-79SeuKlJ.js} +2 -2
  503. package/dist/core/web/public/next/assets/{authority-model-BFuPezSo.js.map → authority-model-79SeuKlJ.js.map} +1 -1
  504. package/dist/core/web/public/next/assets/autonomy-ladder-BGWmZzP7.css +1 -0
  505. package/dist/core/web/public/next/assets/autonomy-ladder.module-ArDv4bkr.js +2 -0
  506. package/dist/core/web/public/next/assets/autonomy-ladder.module-ArDv4bkr.js.map +1 -0
  507. package/dist/core/web/public/next/assets/budget-queries-D8QV5XtH.js +2 -0
  508. package/dist/core/web/public/next/assets/{budget-queries-DsAjH8ac.js.map → budget-queries-D8QV5XtH.js.map} +1 -1
  509. package/dist/core/web/public/next/assets/{capacity-strip-model-Dn1cNOhz.js → capacity-strip-model-BwZ1ZbkU.js} +2 -2
  510. package/dist/core/web/public/next/assets/{capacity-strip-model-Dn1cNOhz.js.map → capacity-strip-model-BwZ1ZbkU.js.map} +1 -1
  511. package/dist/core/web/public/next/assets/charts-BZ50mZD_.js +2 -0
  512. package/dist/core/web/public/next/assets/charts-BZ50mZD_.js.map +1 -0
  513. package/dist/core/web/public/next/assets/charts-ClCB18la.css +1 -0
  514. package/dist/core/web/public/next/assets/cloud-model-BDivRMqv.js +2 -0
  515. package/dist/core/web/public/next/assets/{cloud-model-CX407gPY.js.map → cloud-model-BDivRMqv.js.map} +1 -1
  516. package/dist/core/web/public/next/assets/{cloud-queries-QAhpExlz.js → cloud-queries-BPQQ5_pJ.js} +2 -2
  517. package/dist/core/web/public/next/assets/{cloud-queries-QAhpExlz.js.map → cloud-queries-BPQQ5_pJ.js.map} +1 -1
  518. package/dist/core/web/public/next/assets/{colors-BZ3a9wFf.js → colors-DvK0wMHH.js} +2 -2
  519. package/dist/core/web/public/next/assets/{colors-BZ3a9wFf.js.map → colors-DvK0wMHH.js.map} +1 -1
  520. package/dist/core/web/public/next/assets/{command-catalog-CF0cQQac.js → command-catalog-BIntSa9l.js} +2 -2
  521. package/dist/core/web/public/next/assets/command-catalog-BIntSa9l.js.map +1 -0
  522. package/dist/core/web/public/next/assets/{context-model-Co4wh3SM.js → context-model-Br8t9jgG.js} +2 -2
  523. package/dist/core/web/public/next/assets/{context-model-Co4wh3SM.js.map → context-model-Br8t9jgG.js.map} +1 -1
  524. package/dist/core/web/public/next/assets/{context-model-DV1zCfAm.js → context-model-CokrgEUq.js} +3 -3
  525. package/dist/core/web/public/next/assets/{context-model-DV1zCfAm.js.map → context-model-CokrgEUq.js.map} +1 -1
  526. package/dist/core/web/public/next/assets/context-queries-eL3caKVG.js +2 -0
  527. package/dist/core/web/public/next/assets/{context-queries-CktFQqSS.js.map → context-queries-eL3caKVG.js.map} +1 -1
  528. package/dist/core/web/public/next/assets/{control-queries-DAvlh_YM.js → control-queries-B9K-wmcB.js} +2 -2
  529. package/dist/core/web/public/next/assets/{control-queries-DAvlh_YM.js.map → control-queries-B9K-wmcB.js.map} +1 -1
  530. package/dist/core/web/public/next/assets/copy-setup-XMgCC5f8.js +2 -0
  531. package/dist/core/web/public/next/assets/copy-setup-XMgCC5f8.js.map +1 -0
  532. package/dist/core/web/public/next/assets/{dock-icons-BFuBbqJl.js → dock-icons-BJ6ZqB2t.js} +2 -2
  533. package/dist/core/web/public/next/assets/{dock-icons-BFuBbqJl.js.map → dock-icons-BJ6ZqB2t.js.map} +1 -1
  534. package/dist/core/web/public/next/assets/{fleet-model-Dfd5JyLR.js → fleet-model-BvDR3gjp.js} +2 -2
  535. package/dist/core/web/public/next/assets/{fleet-model-Dfd5JyLR.js.map → fleet-model-BvDR3gjp.js.map} +1 -1
  536. package/dist/core/web/public/next/assets/{fleet-queries-RtMTd5rR.js → fleet-queries-W2UFVMZJ.js} +2 -2
  537. package/dist/core/web/public/next/assets/{fleet-queries-RtMTd5rR.js.map → fleet-queries-W2UFVMZJ.js.map} +1 -1
  538. package/dist/core/web/public/next/assets/{focus-trap-BdrbWfC4.js → focus-trap-CtI1SlMX.js} +2 -2
  539. package/dist/core/web/public/next/assets/{focus-trap-BdrbWfC4.js.map → focus-trap-CtI1SlMX.js.map} +1 -1
  540. package/dist/core/web/public/next/assets/format-CH4g_sl1.js +2 -0
  541. package/dist/core/web/public/next/assets/format-CH4g_sl1.js.map +1 -0
  542. package/dist/core/web/public/next/assets/{format-DKrNjdwD.js → format-D7nBg2bn.js} +2 -2
  543. package/dist/core/web/public/next/assets/{format-DKrNjdwD.js.map → format-D7nBg2bn.js.map} +1 -1
  544. package/dist/core/web/public/next/assets/{git-model-_BnI_Ogh.js → git-model-Dnkd1TnK.js} +2 -2
  545. package/dist/core/web/public/next/assets/{git-model-_BnI_Ogh.js.map → git-model-Dnkd1TnK.js.map} +1 -1
  546. package/dist/core/web/public/next/assets/global-CMNW_dqn.js +2 -0
  547. package/dist/core/web/public/next/assets/{global-CNNGMril.js.map → global-CMNW_dqn.js.map} +1 -1
  548. package/dist/core/web/public/next/assets/guarded-runners-YeAc9wLQ.js +2 -0
  549. package/dist/core/web/public/next/assets/{guarded-runners-DPh2d32e.js.map → guarded-runners-YeAc9wLQ.js.map} +1 -1
  550. package/dist/core/web/public/next/assets/{icons-0haWy6nh.js → icons-D1sYbCTQ.js} +2 -2
  551. package/dist/core/web/public/next/assets/{icons-0haWy6nh.js.map → icons-D1sYbCTQ.js.map} +1 -1
  552. package/dist/core/web/public/next/assets/{index-QesfXBsb.js → index-DZ-UQ7v8.js} +3 -3
  553. package/dist/core/web/public/next/assets/{index-QesfXBsb.js.map → index-DZ-UQ7v8.js.map} +1 -1
  554. package/dist/core/web/public/next/assets/leader-focus-BjeJv7CW.js +2 -0
  555. package/dist/core/web/public/next/assets/leader-focus-BjeJv7CW.js.map +1 -0
  556. package/dist/core/web/public/next/assets/leader-thread-types-CDb-VPPO.js +2 -0
  557. package/dist/core/web/public/next/assets/leader-thread-types-CDb-VPPO.js.map +1 -0
  558. package/dist/core/web/public/next/assets/{live-model-De-q0ZFK.js → live-model-D_32RAOR.js} +2 -2
  559. package/dist/core/web/public/next/assets/live-model-D_32RAOR.js.map +1 -0
  560. package/dist/core/web/public/next/assets/{mind.module-BrK2nFOL.js → mind.module-7hA92hRg.js} +2 -2
  561. package/dist/core/web/public/next/assets/{mind.module-BrK2nFOL.js.map → mind.module-7hA92hRg.js.map} +1 -1
  562. package/dist/core/web/public/next/assets/mutations-DQPbFdRJ.js +2 -0
  563. package/dist/core/web/public/next/assets/{mutations-DTCtKCn_.js.map → mutations-DQPbFdRJ.js.map} +1 -1
  564. package/dist/core/web/public/next/assets/{nav-KmGX0CVz.js → nav-0dOYe2rJ.js} +2 -2
  565. package/dist/core/web/public/next/assets/{nav-KmGX0CVz.js.map → nav-0dOYe2rJ.js.map} +1 -1
  566. package/dist/core/web/public/next/assets/{overnight-queries-mlO0xzsr.js → overnight-queries-C4wOnFtE.js} +2 -2
  567. package/dist/core/web/public/next/assets/{overnight-queries-mlO0xzsr.js.map → overnight-queries-C4wOnFtE.js.map} +1 -1
  568. package/dist/core/web/public/next/assets/primitives-2A5Eq8FQ.js +1 -0
  569. package/dist/core/web/public/next/assets/{queries-CyBE8nsW.js → queries-BTXWdZzU.js} +2 -2
  570. package/dist/core/web/public/next/assets/{queries-CyBE8nsW.js.map → queries-BTXWdZzU.js.map} +1 -1
  571. package/dist/core/web/public/next/assets/{reasoning-pref-CaoA4_Vl.js → reasoning-pref-Ca6lN6x_.js} +2 -2
  572. package/dist/core/web/public/next/assets/{reasoning-pref-CaoA4_Vl.js.map → reasoning-pref-Ca6lN6x_.js.map} +1 -1
  573. package/dist/core/web/public/next/assets/{reveal-anchor-BP1VqnPU.js → reveal-anchor-DfNLgK_I.js} +2 -2
  574. package/dist/core/web/public/next/assets/{reveal-anchor-BP1VqnPU.js.map → reveal-anchor-DfNLgK_I.js.map} +1 -1
  575. package/dist/core/web/public/next/assets/seat-subscription-C5uPHBsN.js +2 -0
  576. package/dist/core/web/public/next/assets/{seat-subscription-C5Tvr0WQ.js.map → seat-subscription-C5uPHBsN.js.map} +1 -1
  577. package/dist/core/web/public/next/assets/{sidebar-model-B5Qk95k_.js → sidebar-model-CLCdqwkR.js} +2 -2
  578. package/dist/core/web/public/next/assets/{sidebar-model-B5Qk95k_.js.map → sidebar-model-CLCdqwkR.js.map} +1 -1
  579. package/dist/core/web/public/next/assets/{slots-DHKQDoE6.js → slots-C-qBeu-8.js} +3 -3
  580. package/dist/core/web/public/next/assets/{slots-DHKQDoE6.js.map → slots-C-qBeu-8.js.map} +1 -1
  581. package/dist/core/web/public/next/assets/{surface-data-CchClvHo.js → surface-data-Dj71tdD-.js} +2 -2
  582. package/dist/core/web/public/next/assets/{surface-data-CchClvHo.js.map → surface-data-Dj71tdD-.js.map} +1 -1
  583. package/dist/core/web/public/next/assets/surface-prefetch-B0WdJOJG.js +2 -0
  584. package/dist/core/web/public/next/assets/surface-prefetch-B0WdJOJG.js.map +1 -0
  585. package/dist/core/web/public/next/assets/{tasks-model-D6WFVULI.js → tasks-model-O8yR5YXp.js} +2 -2
  586. package/dist/core/web/public/next/assets/{tasks-model-D6WFVULI.js.map → tasks-model-O8yR5YXp.js.map} +1 -1
  587. package/dist/core/web/public/next/assets/{terminal-icons-BvCvuXk2.js → terminal-icons-CoRZq9iO.js} +2 -2
  588. package/dist/core/web/public/next/assets/{terminal-icons-BvCvuXk2.js.map → terminal-icons-CoRZq9iO.js.map} +1 -1
  589. package/dist/core/web/public/next/assets/thread-data-DQB_g66d.js +2 -0
  590. package/dist/core/web/public/next/assets/thread-data-DQB_g66d.js.map +1 -0
  591. package/dist/core/web/public/next/assets/types-IYKrYLku.js +2 -0
  592. package/dist/core/web/public/next/assets/types-IYKrYLku.js.map +1 -0
  593. package/dist/core/web/public/next/assets/{usage-queries-D1SU1t7r.js → usage-queries-AdjEyEtn.js} +2 -2
  594. package/dist/core/web/public/next/assets/{usage-queries-D1SU1t7r.js.map → usage-queries-AdjEyEtn.js.map} +1 -1
  595. package/dist/core/web/public/next/assets/{use-guarded-action-BZmBv7CJ.js → use-guarded-action-CuuMHeDX.js} +2 -2
  596. package/dist/core/web/public/next/assets/{use-guarded-action-BZmBv7CJ.js.map → use-guarded-action-CuuMHeDX.js.map} +1 -1
  597. package/dist/core/web/public/next/assets/{use-ticker-CkJ4-0wU.js → use-ticker-BBcp02SZ.js} +2 -2
  598. package/dist/core/web/public/next/assets/{use-ticker-CkJ4-0wU.js.map → use-ticker-BBcp02SZ.js.map} +1 -1
  599. package/dist/core/web/public/next/assets/{use-token-gate-CYcfk_GS.js → use-token-gate-CbXVYQYI.js} +2 -2
  600. package/dist/core/web/public/next/assets/{use-token-gate-CYcfk_GS.js.map → use-token-gate-CbXVYQYI.js.map} +1 -1
  601. package/dist/core/web/public/next/assets/{useOnboarding-CujRS6PK.js → useOnboarding-C_Fpe_sH.js} +2 -2
  602. package/dist/core/web/public/next/assets/{useOnboarding-CujRS6PK.js.map → useOnboarding-C_Fpe_sH.js.map} +1 -1
  603. package/dist/core/web/public/next/assets/{useSeatsRefresh-BEaQdkZs.js → useSeatsRefresh-Co1CnxLc.js} +2 -2
  604. package/dist/core/web/public/next/assets/{useSeatsRefresh-BEaQdkZs.js.map → useSeatsRefresh-Co1CnxLc.js.map} +1 -1
  605. package/dist/core/web/public/next/assets/{useVerseTranscript-BQ0J6Xhx.js → useVerseTranscript-DgbigUlV.js} +2 -2
  606. package/dist/core/web/public/next/assets/{useVerseTranscript-BQ0J6Xhx.js.map → useVerseTranscript-DgbigUlV.js.map} +1 -1
  607. package/dist/core/web/public/next/assets/{verse-icons-DndgEgKS.js → verse-icons-S56hIiXS.js} +2 -2
  608. package/dist/core/web/public/next/assets/{verse-icons-DndgEgKS.js.map → verse-icons-S56hIiXS.js.map} +1 -1
  609. package/dist/core/web/public/next/assets/verse-model-DAVevkNe.js +2 -0
  610. package/dist/core/web/public/next/assets/{verse-model-MMySehjj.js.map → verse-model-DAVevkNe.js.map} +1 -1
  611. package/dist/core/web/public/next/assets/{warmup-CNEH_-be.js → warmup-B_RAtNZ_.js} +3 -3
  612. package/dist/core/web/public/next/assets/{warmup-CNEH_-be.js.map → warmup-B_RAtNZ_.js.map} +1 -1
  613. package/dist/core/web/public/next/assets/why-seat-model-M_r0wX3b.js +2 -0
  614. package/dist/core/web/public/next/assets/why-seat-model-M_r0wX3b.js.map +1 -0
  615. package/dist/core/web/public/next/assets/{workspace-model-Dukb2wwv.js → workspace-model-dji5-Al3.js} +2 -2
  616. package/dist/core/web/public/next/assets/{workspace-model-Dukb2wwv.js.map → workspace-model-dji5-Al3.js.map} +1 -1
  617. package/dist/core/web/public/next/index.html +1 -1
  618. package/dist/core/web/read-projection-worker.js +2 -1
  619. package/dist/core/web/read-projection-worker.js.map +1 -1
  620. package/dist/core/web/read-projections.d.ts +3 -0
  621. package/dist/core/web/read-projections.js +2 -2
  622. package/dist/core/web/read-projections.js.map +1 -1
  623. package/dist/core/web/visibility.js +3 -4
  624. package/dist/core/web/visibility.js.map +1 -1
  625. package/dist/release-dependency-inventory.json +1 -1
  626. package/docs/AUTONOMY-GAP.md +1 -1
  627. package/package.json +3 -2
  628. package/dist/core/web/public/next/assets/Advanced-B-LqYXvd.js +0 -2
  629. package/dist/core/web/public/next/assets/App-E2zCDRxm.js +0 -7
  630. package/dist/core/web/public/next/assets/AppsSection-8wXPPhZb.js +0 -2
  631. package/dist/core/web/public/next/assets/AreaTrend-BFimExYn.js +0 -2
  632. package/dist/core/web/public/next/assets/AreaTrend-BFimExYn.js.map +0 -1
  633. package/dist/core/web/public/next/assets/AutonomyOffState-B5eEkmiz.js +0 -2
  634. package/dist/core/web/public/next/assets/AutonomyOffState-B5eEkmiz.js.map +0 -1
  635. package/dist/core/web/public/next/assets/AutonomyOffState-DmbE71vI.css +0 -1
  636. package/dist/core/web/public/next/assets/AutonomySection-B46igJKR.js +0 -2
  637. package/dist/core/web/public/next/assets/BudgetControl-T_RjPrw9.js +0 -2
  638. package/dist/core/web/public/next/assets/BudgetControl-T_RjPrw9.js.map +0 -1
  639. package/dist/core/web/public/next/assets/ChartFrame-BVuBe6RP.css +0 -1
  640. package/dist/core/web/public/next/assets/ChartFrame-SygZ7B3x.js +0 -2
  641. package/dist/core/web/public/next/assets/ChartFrame-SygZ7B3x.js.map +0 -1
  642. package/dist/core/web/public/next/assets/ChatSection-D6WybBpB.js +0 -3
  643. package/dist/core/web/public/next/assets/ChatSection-D6WybBpB.js.map +0 -1
  644. package/dist/core/web/public/next/assets/CommandPalette-B6SgDJH-.js +0 -2
  645. package/dist/core/web/public/next/assets/CommandPalette-B6SgDJH-.js.map +0 -1
  646. package/dist/core/web/public/next/assets/CommandSection-CvAVd1w4.css +0 -1
  647. package/dist/core/web/public/next/assets/CommandSection-DgMGoepd.js +0 -2
  648. package/dist/core/web/public/next/assets/CommandSection-DgMGoepd.js.map +0 -1
  649. package/dist/core/web/public/next/assets/DockHost-DW9q0NdR.js +0 -2
  650. package/dist/core/web/public/next/assets/FleetSection-BdZN6rGS.js +0 -3
  651. package/dist/core/web/public/next/assets/FleetSection-BdZN6rGS.js.map +0 -1
  652. package/dist/core/web/public/next/assets/Funnel-BeNQZWv2.js +0 -2
  653. package/dist/core/web/public/next/assets/Funnel-BeNQZWv2.js.map +0 -1
  654. package/dist/core/web/public/next/assets/GrowthSection-iiQg6wvK.js +0 -2
  655. package/dist/core/web/public/next/assets/LeaderCard-BRr3_yE-.js +0 -2
  656. package/dist/core/web/public/next/assets/LeaderCard-BRr3_yE-.js.map +0 -1
  657. package/dist/core/web/public/next/assets/MatrixHeatmap-DZvZeWXL.js +0 -2
  658. package/dist/core/web/public/next/assets/MatrixHeatmap-DZvZeWXL.js.map +0 -1
  659. package/dist/core/web/public/next/assets/McpSection-BRuCcTjT.js +0 -2
  660. package/dist/core/web/public/next/assets/MindSection-BTIiQS8P.js +0 -2
  661. package/dist/core/web/public/next/assets/MindSection-BTIiQS8P.js.map +0 -1
  662. package/dist/core/web/public/next/assets/NeedsYouDrawer-lYN4G_aM.js +0 -2
  663. package/dist/core/web/public/next/assets/NeedsYouDrawer-lYN4G_aM.js.map +0 -1
  664. package/dist/core/web/public/next/assets/NeedsYouList-BgH8ezqf.js +0 -2
  665. package/dist/core/web/public/next/assets/NeedsYouList-CruOt4JT.css +0 -1
  666. package/dist/core/web/public/next/assets/NewChatDialog-Db5Xjrk8.js +0 -3
  667. package/dist/core/web/public/next/assets/OnboardingFlow-LoY-zuSe.js +0 -2
  668. package/dist/core/web/public/next/assets/OnboardingFlow-LoY-zuSe.js.map +0 -1
  669. package/dist/core/web/public/next/assets/OnboardingGate-C4VXn7BJ.js +0 -3
  670. package/dist/core/web/public/next/assets/PreviewPane-BPBbcROb.js +0 -2
  671. package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-BX2nkdmZ.js +0 -7
  672. package/dist/core/web/public/next/assets/ResourcesChrome-B2U2lO1H.js +0 -3
  673. package/dist/core/web/public/next/assets/ResourcesChrome-B2U2lO1H.js.map +0 -1
  674. package/dist/core/web/public/next/assets/ResourcesDrawer-BCFJ2Uq8.css +0 -1
  675. package/dist/core/web/public/next/assets/ResourcesDrawer-DlUKOjl9.js +0 -2
  676. package/dist/core/web/public/next/assets/ResourcesDrawer-DlUKOjl9.js.map +0 -1
  677. package/dist/core/web/public/next/assets/SettingsSection-mI9wQYZg.js.map +0 -1
  678. package/dist/core/web/public/next/assets/Sidebar-DT7ykaqS.js +0 -3
  679. package/dist/core/web/public/next/assets/Sidebar-DT7ykaqS.js.map +0 -1
  680. package/dist/core/web/public/next/assets/StatTile-BuLMsJMx.css +0 -1
  681. package/dist/core/web/public/next/assets/StatTile-DPZ5yyaU.js +0 -2
  682. package/dist/core/web/public/next/assets/StatTile-DPZ5yyaU.js.map +0 -1
  683. package/dist/core/web/public/next/assets/StepBand-DQykLkk_.js +0 -2
  684. package/dist/core/web/public/next/assets/StepBand-DQykLkk_.js.map +0 -1
  685. package/dist/core/web/public/next/assets/Swimlane-BzH6OCee.js +0 -2
  686. package/dist/core/web/public/next/assets/Swimlane-BzH6OCee.js.map +0 -1
  687. package/dist/core/web/public/next/assets/Swimlane-o6_Zsrnr.css +0 -1
  688. package/dist/core/web/public/next/assets/UniverseConsoleApp-DtXFhAhw.js +0 -2
  689. package/dist/core/web/public/next/assets/UsageSection-CiD1DbuF.js +0 -3
  690. package/dist/core/web/public/next/assets/UsageSection-CiD1DbuF.js.map +0 -1
  691. package/dist/core/web/public/next/assets/VerseConsoleApp-BCY5uSok.js +0 -3
  692. package/dist/core/web/public/next/assets/VerseConsoleApp-BCY5uSok.js.map +0 -1
  693. package/dist/core/web/public/next/assets/Workspace-BQSZFSeO.js +0 -10
  694. package/dist/core/web/public/next/assets/actions-BmIf9avl.css +0 -1
  695. package/dist/core/web/public/next/assets/actions-Ci6I4C0l.js +0 -2
  696. package/dist/core/web/public/next/assets/budget-queries-DsAjH8ac.js +0 -2
  697. package/dist/core/web/public/next/assets/charts-C_xJbJiw.js +0 -2
  698. package/dist/core/web/public/next/assets/charts-C_xJbJiw.js.map +0 -1
  699. package/dist/core/web/public/next/assets/charts-DhKTrQLw.css +0 -1
  700. package/dist/core/web/public/next/assets/cloud-model-CX407gPY.js +0 -2
  701. package/dist/core/web/public/next/assets/command-catalog-CF0cQQac.js.map +0 -1
  702. package/dist/core/web/public/next/assets/context-queries-CktFQqSS.js +0 -2
  703. package/dist/core/web/public/next/assets/copy-setup-CqRSfELB.js +0 -2
  704. package/dist/core/web/public/next/assets/copy-setup-CqRSfELB.js.map +0 -1
  705. package/dist/core/web/public/next/assets/format-Dk4Fmxax.js +0 -2
  706. package/dist/core/web/public/next/assets/format-Dk4Fmxax.js.map +0 -1
  707. package/dist/core/web/public/next/assets/global-CNNGMril.js +0 -2
  708. package/dist/core/web/public/next/assets/guarded-runners-DPh2d32e.js +0 -2
  709. package/dist/core/web/public/next/assets/live-model-De-q0ZFK.js.map +0 -1
  710. package/dist/core/web/public/next/assets/mutations-DTCtKCn_.js +0 -2
  711. package/dist/core/web/public/next/assets/primitives-D0Fb3TtS.js +0 -1
  712. package/dist/core/web/public/next/assets/seat-subscription-C5Tvr0WQ.js +0 -2
  713. package/dist/core/web/public/next/assets/surface-prefetch-BWr0LBQn.js +0 -2
  714. package/dist/core/web/public/next/assets/surface-prefetch-BWr0LBQn.js.map +0 -1
  715. package/dist/core/web/public/next/assets/types-D5XOdyw8.js +0 -2
  716. package/dist/core/web/public/next/assets/types-D5XOdyw8.js.map +0 -1
  717. package/dist/core/web/public/next/assets/verse-model-MMySehjj.js +0 -2
  718. package/dist/core/web/public/next/assets/why-seat-model-jlDTwYSc.js +0 -2
  719. package/dist/core/web/public/next/assets/why-seat-model-jlDTwYSc.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"NeedsYouList-BgH8ezqf.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/approvals/approvals-model.ts","../../../../../../src/web-ui/routes/verse/shell/needs-you-model.ts","../../../../../../src/web-ui/routes/verse/shell/NeedsYouDrawer.module.css","../../../../../../src/web-ui/routes/verse/shell/NeedsYouList.tsx"],"sourcesContent":["/**\n * routes/verse/approvals/approvals-model.ts — the pure decisions behind the\n * approvals queue: what order rows come in, and exactly what a human is\n * agreeing to when they press Approve.\n *\n * Kept framework-free and unit-tested because both are easy to get subtly\n * wrong: \"pending first\" must survive a status filter that also returns\n * decided rows, and the approve consequence sentence is the last thing\n * standing between a click and a real pull request against a real remote.\n */\nimport type { Proposal, ProposalKind } from '../../../data/api-types.js';\nimport { ENGINE_LABEL } from '../verse-model.js';\n\n/** Pending first, then newest first within each group. Stable and total. */\nexport function orderProposals(rows: readonly Proposal[]): Proposal[] {\n return [...rows].sort((a, b) => {\n const pendingA = a.status === 'pending' ? 0 : 1;\n const pendingB = b.status === 'pending' ? 0 : 1;\n if (pendingA !== pendingB) return pendingA - pendingB;\n const tsA = Date.parse(a.createdAt);\n const tsB = Date.parse(b.createdAt);\n const safeA = Number.isNaN(tsA) ? 0 : tsA;\n const safeB = Number.isNaN(tsB) ? 0 : tsB;\n if (safeA !== safeB) return safeB - safeA;\n return a.id.localeCompare(b.id);\n });\n}\n\nexport type RiskClass = NonNullable<Proposal['riskClass']>;\n\n/** high → medium → low → unstated. Used for the risk column's sort affordance. */\nexport function riskRank(risk: Proposal['riskClass']): number {\n switch (risk) {\n case 'high':\n return 0;\n case 'medium':\n return 1;\n case 'low':\n return 2;\n default:\n return 3;\n }\n}\n\n/** Client-side narrowing over whatever page the server returned. */\nexport function filterProposals(rows: readonly Proposal[], search: string, repo: string): Proposal[] {\n const s = search.trim().toLowerCase();\n const r = repo.trim().toLowerCase();\n if (!s && !r) return [...rows];\n return rows.filter((p) => {\n if (s && !p.title.toLowerCase().includes(s) && !(p.summary ?? '').toLowerCase().includes(s)) return false;\n if (r && !(p.repo ?? '').toLowerCase().includes(r)) return false;\n return true;\n });\n}\n\n/**\n * What approving this proposal actually does, in one sentence, naming the\n * repo. `pr` is the dangerous one: it pushes a branch to the remote and opens\n * a real pull request, which is visible to other people and cannot be undone\n * from the dialog. The confirm step MUST show this before the click.\n */\nexport function describeApproveConsequence(kind: ProposalKind | string, repo: string | null): string {\n // The project's NAME, not its absolute path: a sandbox checkout under\n // /private/tmp/claude-501/… is unreadable in a sentence. The confirm dialog\n // still prints the full path once, as the exact place the write lands.\n const where = repoName(repo) ?? 'the target repository';\n switch (kind) {\n case 'pr':\n return `Pushes a branch to ${where}'s remote and opens a real pull request. Other people can see it immediately, and this dialog cannot undo it.`;\n case 'patch':\n return `Writes the diff to ${where} on disk now. Nothing is pushed, but the working tree changes.`;\n default:\n return `Applies this ${String(kind)} proposal to ${where} now.`;\n }\n}\n\n/** True when approving reaches a remote — the loudest confirm wording. */\nexport function reachesRemote(kind: ProposalKind | string): boolean {\n return kind === 'pr';\n}\n\n/** The engine that produced the diff, as a short display string. */\nexport function engineOf(proposal: Pick<Proposal, 'engineModel' | 'engineTier'>): string | null {\n if (proposal.engineModel) return proposal.engineModel;\n if (proposal.engineTier) return proposal.engineTier;\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Readable detail\n// ---------------------------------------------------------------------------\n\n/** \"/Users/m/repos/binshield/\" → \"binshield\"; null for no repo. */\nexport function repoName(repo: string | null | undefined): string | null {\n if (typeof repo !== 'string') return null;\n const trimmed = repo.trim().replace(/\\/+$/, '');\n if (trimmed.length === 0) return null;\n const last = trimmed.slice(trimmed.lastIndexOf('/') + 1);\n return last.length > 0 ? last : trimmed;\n}\n\nconst KIND_LABEL: Record<string, string> = {\n patch: 'Patch',\n pr: 'Pull request',\n deploy: 'Deploy',\n note: 'Note',\n 'desktop-action': 'Desktop action',\n 'browser-action': 'Browser action',\n};\n\n/** \"patch\" → \"Patch\", \"pr\" → \"Pull request\"; an unknown kind is shown as sent. */\nexport function kindLabel(kind: ProposalKind | string): string {\n return KIND_LABEL[kind] ?? String(kind);\n}\n\n/**\n * The server builds a run proposal's title as `${engine} run: ${goal.slice(0, 80)}`\n * — cut at 80 characters, mid-word, sometimes mid-quote. This is the one\n * place that cut is made readable.\n */\nexport const RUN_TITLE_GOAL_CAP = 80;\n\nexport interface ReadableTitle {\n /** \"Claude run\" when the title carried an `engine run:` prefix; null otherwise. */\n eyebrow: string | null;\n /** The title to print: never ends mid-word; a cut one ends in \"…\". */\n text: string;\n /** True when the server's title was cut short (the full text we have rides in a tooltip). */\n truncated: boolean;\n}\n\nfunction capitalize(word: string): string {\n return word.length === 0 ? word : word.charAt(0).toUpperCase() + word.slice(1);\n}\n\n/** The app's own display name for an engine (\"Claude\", \"Codex\"); any other engine capitalized (\"Ollama\"). */\nfunction engineDisplayName(engine: string): string {\n const key = engine.toLowerCase();\n return Object.prototype.hasOwnProperty.call(ENGINE_LABEL, key)\n ? ENGINE_LABEL[key as keyof typeof ENGINE_LABEL]\n : capitalize(key);\n}\n\n/** Close a quote the cut left open, so the title does not read as a stray mark. */\nfunction closeQuotes(text: string): string {\n let out = text;\n if ((out.match(/\"/g) ?? []).length % 2 === 1) out += '\"';\n if ((out.match(/\\u201c/g) ?? []).length > (out.match(/\\u201d/g) ?? []).length) out += '\\u201d';\n return out;\n}\n\n/** Drop a trailing partial word and end on \"…\". */\nfunction cutAtWord(text: string): string {\n const body = text.replace(/(?:\\u2026|\\.\\.\\.)$/, '');\n const space = body.lastIndexOf(' ');\n const whole = space > 0 ? body.slice(0, space) : body;\n return `${whole.replace(/[\\s,;:\\-\\u2013\\u2014]+$/, '')}\\u2026`;\n}\n\nexport function readableTitle(title: string): ReadableTitle {\n const raw = typeof title === 'string' ? title.trim() : '';\n // Only the engines the sandboxed runner names — \"Dry run: …\" is a title, not an engine.\n const run = /^(\\[partial\\]\\s*)?(claude|codex|grok|local|ollama|gemini|api[\\w-]*) run:\\s*(.*)$/is.exec(raw);\n // \"Partial Claude run\", never \"Partial claude run\": the engine is a name either way.\n const eyebrow = run ? `${run[1] ? 'Partial ' : ''}${engineDisplayName(run[2]!)} run` : null;\n let text = run ? run[3]! : raw;\n // A title that already ends in an ellipsis right after a letter was cut mid-word upstream.\n const cutMidWord = /[\\p{L}\\p{N}](?:\\u2026|\\.\\.\\.)$/u.test(text);\n // A run goal at exactly the server's cap that does not end on a sentence boundary was sliced.\n const sliced = run !== null && text.length >= RUN_TITLE_GOAL_CAP && !/[.!?)\"'\\u201d\\u2026]$/.test(text);\n const truncated = cutMidWord || sliced;\n if (truncated) text = cutAtWord(text);\n text = closeQuotes(text);\n return { eyebrow, text: text.length > 0 ? text : raw, truncated };\n}\n\n/**\n * What a sandboxed run's summary line says, taken apart. The server writes\n * `[Partial ]<source> <engine:model> run produced N file(s) (+A/-D). <rest>`\n * (core/run/sandboxed-engine.ts); anything else parses to null and is shown\n * verbatim.\n */\nexport interface RunFacts {\n partial: boolean;\n /** The server's source label, verbatim (\"TITRR\", \"Best-of-N winner\"). */\n source: string;\n /** The source in plain words (\"Test-and-repair loop\"). */\n sourceLabel: string;\n /** What the source means, for a tooltip; null when the label says it already. */\n sourceHint: string | null;\n /** \"claude:claude-fable-5\". */\n model: string;\n files: number;\n insertions: number;\n deletions: number;\n /** Whatever the summary says after the run facts (\"Review before applying.\"), or null. */\n rest: string | null;\n}\n\nconst RUN_SUMMARY = /^(Partial )?(.+?) (\\S+) run produced (\\d+) file\\(s\\) \\(\\+(\\d+)\\/-(\\d+)\\)\\.?\\s*([\\s\\S]*)$/;\n\n/**\n * TITRR is internal shorthand (core/run/orchestrator.ts M78: Test → Iterate →\n * Test → Refine → Repeat). The operator sees the plain name; the acronym and\n * what it did ride in the tooltip.\n */\nconst TITRR_HINT =\n 'TITRR — Test, Iterate, Test, Refine, Repeat: after its change the run re-ran the repository\\u2019s tests and repaired the change until they passed or it ran out of attempts.';\n\nfunction describeSource(source: string): { label: string; hint: string | null } {\n if (/\\bTITRR\\b/.test(source)) {\n const rest = source.replace(/\\bTITRR\\b\\s*/, '').trim();\n const qualifier = rest === 'api-model' ? ' (API model)'\n : rest === 'api-model required-diff' ? ' (API model, retried for a missing diff)'\n : rest === 'api-model failed producer' ? ' (API model, producer failed)'\n : rest.length > 0 ? ` (${rest})` : '';\n return { label: `Test-and-repair loop${qualifier}`, hint: TITRR_HINT };\n }\n if (/^best-of-n/i.test(source)) {\n return { label: source, hint: 'Several models attempted this change in parallel; a judge compared them.' };\n }\n if (source === 'api-model') return { label: 'API model run', hint: null };\n if (source === 'Sandboxed') return { label: 'Sandboxed run', hint: 'Produced in an isolated sandbox checkout; nothing touched your working tree.' };\n return { label: source, hint: null };\n}\n\nexport function parseRunSummary(summary: string | null | undefined): RunFacts | null {\n if (typeof summary !== 'string') return null;\n const m = RUN_SUMMARY.exec(summary.trim());\n if (!m) return null;\n const { label, hint } = describeSource(m[2]!);\n const rest = m[7]!.trim();\n return {\n partial: m[1] !== undefined,\n source: m[2]!,\n sourceLabel: label,\n sourceHint: hint,\n model: m[3]!,\n files: Number(m[4]),\n insertions: Number(m[5]),\n deletions: Number(m[6]),\n rest: rest.length > 0 ? rest : null,\n };\n}\n\n/** \"2 files · +384 −0\" (a real minus sign, grouped thousands). */\nexport function formatDiffStats(facts: Pick<RunFacts, 'files' | 'insertions' | 'deletions'>): string {\n const n = (v: number) => v.toLocaleString('en-US');\n return `${n(facts.files)} ${facts.files === 1 ? 'file' : 'files'} \\u00b7 +${n(facts.insertions)} \\u2212${n(facts.deletions)}`;\n}\n\n/** The same stats as a sentence for assistive tech: \"2 files changed, 384 lines added, 0 removed\". */\nexport function describeDiffStats(facts: Pick<RunFacts, 'files' | 'insertions' | 'deletions'>): string {\n const n = (v: number) => v.toLocaleString('en-US');\n return `${n(facts.files)} ${facts.files === 1 ? 'file' : 'files'} changed, ${n(facts.insertions)} ${facts.insertions === 1 ? 'line' : 'lines'} added, ${n(facts.deletions)} removed`;\n}\n\n/**\n * \"just now\", \"5 minutes ago\", \"yesterday\", \"38 days ago\", then \"on Aug 17\"\n * past two months. Written out in full: the detail view has the room, and\n * \"38d\" is a sidebar abbreviation.\n */\nexport function longAgo(iso: string | null | undefined, now: number = Date.now()): string {\n if (typeof iso !== 'string') return 'at an unknown time';\n const then = Date.parse(iso);\n if (!Number.isFinite(then)) return 'at an unknown time';\n const seconds = Math.max(0, Math.round((now - then) / 1000));\n if (seconds < 45) return 'just now';\n const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });\n const minutes = Math.round(seconds / 60);\n if (minutes < 60) return rtf.format(-minutes, 'minute');\n const hours = Math.round(minutes / 60);\n if (hours < 24) return rtf.format(-hours, 'hour');\n const days = Math.round(hours / 24);\n if (days <= 60) return rtf.format(-days, 'day');\n return `on ${new Date(then).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })}`;\n}\n\n/** A local date and time for a tooltip: \"Mon, Aug 17, 3:12 PM\". */\nexport function localStamp(iso: string | null | undefined): string | undefined {\n if (typeof iso !== 'string') return undefined;\n const t = Date.parse(iso);\n if (!Number.isFinite(t)) return undefined;\n return new Date(t).toLocaleString([], { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit' });\n}\n","/**\n * routes/verse/shell/needs-you-model.ts — the Needs-you drawer as data (unit\n * C1): which items a split shows, how many each split has, whether the drawer\n * may say \"All clear\", and what a key press does to an item.\n *\n * Pure. The items come from GET /api/verse/activity (C1's own producers plus\n * Track B's, R1); each carries its own actions, so nothing here knows what a\n * grant or an owner-lane PR is.\n *\n * How a row READS (needsYouRowView) borrows the approvals detail view's text\n * helpers rather than growing a second copy: an approval item's title and\n * detail are the same proposal title and run summary that view already\n * untangles.\n */\nimport {\n NEEDS_YOU_KIND_CATEGORY,\n type NeedsYouAction,\n type NeedsYouActionKind,\n type NeedsYouItem,\n type NeedsYouSource,\n type VerseActivitySources,\n} from '../../../../core/verse/workbench-types.js';\nimport {\n describeDiffStats,\n formatDiffStats,\n kindLabel,\n localStamp,\n longAgo,\n parseRunSummary,\n readableTitle,\n repoName,\n} from '../approvals/approvals-model.js';\nimport type { VerseSeat } from '../../../data/api-types.js';\nimport { isVerseEngine, modelOptionFor, seatById } from '../verse-model.js';\nimport type { NeedsYouSplit } from '../verse-ui-store.js';\n\nexport const SPLIT_LABEL: Readonly<Record<NeedsYouSplit, string>> = {\n all: 'All',\n approvals: 'Approvals',\n fleet: 'Fleet',\n chats: 'Chats',\n accounts: 'Accounts',\n};\n\n/**\n * Which producers can put an item in each split. \"All clear\" is only\n * claimed for a split whose every producer answered: an owner-lane PR is in\n * Approvals but comes from the FLEET producer, so Approvals is only vouched\n * for when the fleet source answered too.\n */\nexport const SPLIT_SOURCES: Readonly<Record<NeedsYouSplit, readonly NeedsYouSource[]>> = {\n all: ['approvals', 'authority', 'fleet', 'leader', 'chats', 'accounts'],\n approvals: ['approvals', 'fleet', 'leader'],\n fleet: ['authority', 'fleet', 'leader'],\n chats: ['chats'],\n accounts: ['accounts'],\n};\n\nconst SOURCE_NAME: Readonly<Record<NeedsYouSource, string>> = {\n approvals: 'the approvals inbox',\n authority: 'the autonomy grant',\n fleet: 'the fleet',\n leader: 'the Leader',\n chats: 'chats',\n accounts: 'account health',\n};\n\nexport function itemsForSplit(items: readonly NeedsYouItem[], split: NeedsYouSplit): NeedsYouItem[] {\n if (split === 'all') return [...items];\n return items.filter((item) => NEEDS_YOU_KIND_CATEGORY[item.kind] === split);\n}\n\nexport function splitCounts(items: readonly NeedsYouItem[]): Record<NeedsYouSplit, number> {\n const counts: Record<NeedsYouSplit, number> = { all: items.length, approvals: 0, fleet: 0, chats: 0, accounts: 0 };\n for (const item of items) counts[NEEDS_YOU_KIND_CATEGORY[item.kind]] += 1;\n return counts;\n}\n\nexport interface SplitCoverage {\n /** Every producer feeding this split answered. */\n vouched: boolean;\n /** Operator-language names of the ones that did not, with why. */\n silent: Array<{ source: NeedsYouSource; name: string; state: 'unavailable' | 'error' }>;\n}\n\n/** Null sources (activity itself unavailable) vouch for nothing. */\nexport function splitCoverage(sources: VerseActivitySources | null, split: NeedsYouSplit): SplitCoverage {\n const silent: SplitCoverage['silent'] = [];\n for (const source of SPLIT_SOURCES[split]) {\n const state = sources?.[source] ?? 'unavailable';\n if (state !== 'ok') silent.push({ source, name: SOURCE_NAME[source], state });\n }\n return { vouched: silent.length === 0, silent };\n}\n\n/** \"the fleet isn't reporting yet and the Leader failed to answer\" — for the empty state. */\nexport function describeSilence(coverage: SplitCoverage): string {\n const phrases = coverage.silent.map((s) => (s.state === 'error' ? `${s.name} failed to answer` : `${s.name} isn't reporting in this build`));\n if (phrases.length === 0) return '';\n if (phrases.length === 1) return capitalise(phrases[0]!);\n return capitalise(`${phrases.slice(0, -1).join(', ')} and ${phrases[phrases.length - 1]}`);\n}\n\nfunction capitalise(text: string): string {\n return text.charAt(0).toUpperCase() + text.slice(1);\n}\n\n/** Approve / reject / veto ALWAYS confirm (SPEC-310C §1); other kinds only when the item says so. */\nexport const ALWAYS_CONFIRM: ReadonlySet<NeedsYouActionKind> = new Set(['approve', 'reject', 'veto']);\n\nexport function actionOf(item: NeedsYouItem, kind: NeedsYouActionKind): NeedsYouAction | null {\n return item.actions.find((a) => a.kind === kind) ?? null;\n}\n\nconst GENERIC_CONFIRM: Readonly<Record<'approve' | 'reject' | 'veto', { title: string; confirmLabel: string }>> = {\n approve: { title: 'Approve this?', confirmLabel: 'Approve' },\n reject: { title: 'Reject this?', confirmLabel: 'Reject' },\n veto: { title: 'Veto this action?', confirmLabel: 'Veto' },\n};\n\nexport interface ConfirmCopy {\n title: string;\n body: string;\n confirmLabel: string;\n}\n\n/** The dialog for `action` on `item`; null when the action runs without one. */\nexport function confirmCopy(item: NeedsYouItem, action: NeedsYouAction): ConfirmCopy | null {\n if (action.confirm) return action.confirm;\n if (action.kind === 'approve' || action.kind === 'reject' || action.kind === 'veto') {\n const generic = GENERIC_CONFIRM[action.kind];\n return { title: generic.title, body: readableItemTitle(item).text, confirmLabel: generic.confirmLabel };\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// How a row reads\n// ---------------------------------------------------------------------------\n\n/**\n * The approvals producer titles an item `${kind === 'pr' ? 'PR' : kind}: ${proposal.title}`\n * (core/verse/activity.ts approvalItem). Only an `approval` item is taken\n * apart this way — \"Failed: Migrate the store\" is a chat title, not a kind.\n */\nconst APPROVAL_KIND_PREFIX = /^(PR|[a-z][a-z-]*):\\s+([\\s\\S]+)$/;\n\nexport interface ReadableItemTitle {\n /** \"Patch · Claude run\": the proposal kind and the engine the title led with; null when neither. */\n kindLabel: string | null;\n /** The title to print. Never ends mid-word — a cut one ends in \"…\". */\n text: string;\n}\n\nexport function readableItemTitle(item: Pick<NeedsYouItem, 'kind' | 'title'>): ReadableItemTitle {\n let proposalKind: string | null = null;\n let rest = item.title;\n if (item.kind === 'approval') {\n const m = APPROVAL_KIND_PREFIX.exec(item.title.trim());\n if (m) {\n proposalKind = m[1] === 'PR' ? 'pr' : m[1]!;\n rest = m[2]!;\n }\n }\n const title = readableTitle(rest);\n const parts = [proposalKind === null ? null : kindLabel(proposalKind), title.eyebrow].filter((p): p is string => p !== null);\n return { kindLabel: parts.length > 0 ? parts.join(' · ') : null, text: title.text };\n}\n\n/** A sandboxed run's facts, lifted out of the item's detail line. */\nexport interface NeedsYouRunView {\n /** \"2 files · +384 −0\". */\n stats: string;\n /** \"2 files changed, 384 lines added, 0 removed\" — what a screen reader says instead. */\n statsSpoken: string;\n /** \"Test-and-repair loop\", never \"TITRR\". */\n source: string;\n /** What the source means, for a tooltip. */\n sourceHint: string | null;\n partial: boolean;\n /** \"claude:claude-fable-5\". */\n model: string;\n}\n\n/** Everything a Needs-you row prints, in operator language. The raw server text survives only in tooltips. */\nexport interface NeedsYouRowView {\n kindLabel: string | null;\n title: string;\n /** The title exactly as the server sent it — the row's tooltip. */\n fullTitle: string;\n run: NeedsYouRunView | null;\n /** What the detail says beyond the run facts (\"Review before applying.\"), or the detail verbatim; null when nothing. */\n detail: string | null;\n /** \"binshield\", never a path. */\n repo: string | null;\n /** The repo as sent, as a tooltip, when it was more than the name. */\n repoFull: string | undefined;\n /** \"38 days ago\". */\n age: string;\n /** The exact local time, for a tooltip. */\n ageStamp: string | undefined;\n}\n\nexport function needsYouRowView(item: NeedsYouItem, now: number = Date.now()): NeedsYouRowView {\n const title = readableItemTitle(item);\n const facts = parseRunSummary(item.detail);\n const repo = repoName(item.subject.repo);\n return {\n kindLabel: title.kindLabel,\n title: title.text,\n fullTitle: item.title,\n run: facts\n ? {\n stats: formatDiffStats(facts),\n statsSpoken: describeDiffStats(facts),\n source: facts.sourceLabel,\n sourceHint: facts.sourceHint,\n partial: facts.partial,\n model: facts.model,\n }\n : null,\n detail: facts ? facts.rest : item.detail,\n repo,\n repoFull: repo !== null && item.subject.repo !== null && item.subject.repo !== repo ? item.subject.repo : undefined,\n age: longAgo(item.since, now),\n ageStamp: localStamp(item.since),\n };\n}\n\n/** \"closes in 24m\" / \"expired\" — for veto windows and grants. */\nexport function until(iso: string, now: number = Date.now()): string {\n const t = Date.parse(iso);\n if (!Number.isFinite(t)) return '—';\n const s = Math.round((t - now) / 1000);\n if (s <= 0) return 'expired';\n if (s < 90) return `in ${s}s`;\n const m = Math.round(s / 60);\n if (m < 90) return `in ${m}m`;\n const h = Math.round(m / 60);\n if (h < 48) return `in ${h}h`;\n return `in ${Math.round(h / 24)}d`;\n}\n\n// ---------------------------------------------------------------------------\n// Seats and models, by name\n// ---------------------------------------------------------------------------\n\n/** A seat or model as the operator knows it; `raw` is the id as sent, for a tooltip, when the text differs. */\nexport interface DisplayName {\n text: string;\n raw: string | undefined;\n}\n\n/**\n * \"Claude Max\" for `claude-a`: the roster's label (bootstrap seats — the name\n * the seat picker and Apps & Accounts use). An id the roster does not know is\n * shown as sent: it is all there is.\n */\nexport function seatDisplayName(seats: readonly VerseSeat[], seatId: string): DisplayName {\n const label = seatById(seats, seatId)?.label;\n return label && label !== seatId ? { text: label, raw: seatId } : { text: seatId, raw: undefined };\n}\n\n/**\n * \"Fable 5.1\" for a run's `claude:claude-fable-5-1`: the catalog label (the\n * model picker's) on the item's own seat first, then on any seat of the run's\n * engine — exact id, then canonical (verse-model `modelOptionFor`, so a\n * pre-alias `claude-opus-5.5` still finds `claude-opus-5-5`). A model no\n * catalog lists is shown as sent.\n */\nexport function runModelDisplayName(seats: readonly VerseSeat[], model: string, seatId: string | null): DisplayName {\n const colon = model.indexOf(':');\n const prefix = colon > 0 ? model.slice(0, colon) : '';\n const engine = isVerseEngine(prefix) ? prefix : null;\n // `local:qwen3.8:27b` keeps its tag: only a known engine prefix is split off.\n const id = engine ? model.slice(colon + 1) : model;\n const order = [\n ...(seatId ? [seatId] : []),\n ...seats.filter((seat) => seat.id !== seatId && (engine === null || seat.engine === engine)).map((seat) => seat.id),\n ];\n for (const candidate of order) {\n const label = modelOptionFor(seats, { seatId: candidate, model: id })?.label;\n if (label && label !== model) return { text: label, raw: model };\n }\n return { text: model, raw: undefined };\n}\n","/* ⌘J — a right-hand sheet over the workbench; full screen on a phone.\n Hairlines, no cards. Severity is a word plus a 2px rule, never colour alone. */\n\n.backdrop {\n position: fixed;\n inset: 0;\n z-index: var(--z-dialog);\n display: flex;\n justify-content: flex-end;\n background: var(--bg-overlay);\n animation: fade var(--duration-fast) var(--ease-standard);\n}\n\n.panel {\n display: flex;\n flex-direction: column;\n width: min(480px, calc(100vw - var(--space-8)));\n height: 100%;\n background: var(--bg-surface);\n border-left: 1px solid var(--border-default);\n box-shadow: var(--shadow-dialog);\n outline: none;\n animation: slide var(--duration-base) var(--ease-decelerate);\n}\n\n/* Phone: the whole screen, sliding up. */\n.panel[data-presentation='full'] {\n width: 100%;\n border-left: 0;\n animation-name: rise;\n}\n\n.head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-3);\n min-height: var(--strip-height);\n padding: var(--space-2) var(--space-3) var(--space-2) var(--space-4);\n border-bottom: 1px solid var(--border-subtle);\n}\n\n.title {\n display: flex;\n align-items: baseline;\n gap: var(--space-2);\n font-family: var(--font-display);\n font-size: var(--text-md-size);\n line-height: var(--text-md-line);\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-display);\n}\n\n.titleCount {\n font-family: var(--font-ui);\n font-size: var(--text-sm-size);\n font-weight: var(--font-weight-regular);\n font-variant-numeric: tabular-nums;\n color: var(--text-tertiary);\n}\n\n.splits {\n display: flex;\n gap: var(--space-1);\n padding: var(--space-2) var(--space-3);\n border-bottom: 1px solid var(--border-subtle);\n overflow-x: auto;\n scrollbar-width: none;\n}\n\n.split {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n flex: none;\n min-height: var(--control-h-sm);\n padding: 0 var(--space-2);\n border-radius: var(--radius-sm);\n color: var(--text-secondary);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n.split:hover { background: var(--bg-hover); color: var(--text-primary); }\n.split[aria-selected='true'] { background: var(--bg-selected); color: var(--text-primary); font-weight: var(--font-weight-medium); }\n\n.splitCount {\n min-width: 18px;\n padding: 0 4px;\n border-radius: var(--radius-full);\n background: var(--bg-hover);\n font-size: var(--text-2xs-size);\n line-height: 18px;\n text-align: center;\n font-variant-numeric: tabular-nums;\n color: var(--text-secondary);\n}\n\n.body {\n position: relative;\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n}\n\n.rows { outline: none; }\n.rows:focus-visible { box-shadow: none; }\n/* The list holds focus (aria-activedescendant), so the focus ring is drawn on\n the ROW it points at — a ring around the whole list says nothing about\n which item A / R / V will act on. */\n.rows:focus-visible .row[aria-selected='true'] { box-shadow: inset 0 0 0 2px var(--border-focus); }\n\n.row {\n display: grid;\n grid-template-columns: 2px minmax(0, 1fr) auto;\n column-gap: var(--space-3);\n align-items: center;\n padding: var(--space-3) var(--space-4);\n border-bottom: 1px solid var(--border-subtle);\n cursor: pointer;\n}\n.row:hover { background: var(--bg-hover); }\n.row[aria-selected='true'] { background: var(--bg-selected); }\n\n.rule {\n align-self: stretch;\n border-radius: var(--radius-full);\n background: var(--border-strong);\n}\n.row[data-severity='high'] .rule { background: var(--status-danger-solid); }\n.row[data-severity='warn'] .rule { background: var(--status-warning-solid); }\n\n.rowMain { display: flex; flex-direction: column; min-width: 0; gap: 2px; }\n\n/* \"Patch · Claude run\" — the kind, above the title it no longer clutters.\n Secondary, not tertiary: tertiary falls under 4.5:1 on --bg-selected\n (approvals.module.css has the measurements). */\n.rowKind {\n margin: 0;\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n letter-spacing: var(--tracking-label);\n text-transform: uppercase;\n color: var(--text-secondary);\n}\n\n/* Two lines at most, wrapped at word boundaries. The text itself already\n ends on a whole word (approvals-model readableTitle); the full server\n title rides in `title`. */\n.rowTitle {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n line-clamp: 2;\n overflow: hidden;\n overflow-wrap: break-word;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-primary);\n}\n\n/* \"2 files · +384 −0 · Test-and-repair loop\". */\n.runFacts {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: 0 var(--space-2);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n}\n.diffStats { font-family: var(--font-display); font-variant-numeric: tabular-nums; color: var(--text-primary); }\n.runSource[title] { text-decoration: underline dotted; text-underline-offset: 3px; cursor: help; }\n\n.repo { font-weight: var(--font-weight-medium); }\n\n.rowMeta {\n display: flex;\n flex-wrap: wrap;\n gap: 0 var(--space-2);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n}\n\n.severity {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n letter-spacing: var(--tracking-label);\n text-transform: uppercase;\n}\n.severity[data-severity='high'] { color: var(--status-danger-fg); }\n.severity[data-severity='warn'] { color: var(--status-warning-fg); }\n\n.mono { font-family: var(--font-mono); font-size: var(--text-xs-size); }\n.deadline { color: var(--status-warning-fg); font-variant-numeric: tabular-nums; }\n\n.rowKeys { display: flex; gap: 2px; }\n\n.key,\n.inlineKey {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 4px;\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-xs);\n background: var(--bg-surface);\n font-family: var(--font-mono);\n font-size: var(--text-2xs-size);\n color: var(--text-secondary);\n}\n.inlineKey { margin-left: var(--space-2); background: transparent; }\n\n.loading { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-4); }\n\n.empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--space-2);\n padding: var(--space-16) var(--space-6);\n text-align: center;\n}\n.emptyTitle {\n font-family: var(--font-display);\n font-size: var(--text-md-size);\n line-height: var(--text-md-line);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n}\n.emptyBody {\n max-width: 44ch;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-secondary);\n}\n\n/* The reward for an empty inbox: a quiet check, not a confetti cannon. */\n.clearMark {\n position: relative;\n width: 40px;\n height: 40px;\n margin-bottom: var(--space-2);\n border-radius: var(--radius-full);\n background: var(--status-success-bg);\n}\n.clearMark::after {\n content: '';\n position: absolute;\n left: 14px;\n top: 10px;\n width: 10px;\n height: 16px;\n border: solid var(--status-success-solid);\n border-width: 0 2px 2px 0;\n transform: rotate(45deg);\n}\n\n.focusSink { position: absolute; width: 1px; height: 1px; overflow: hidden; outline: none; }\n\n.detail { outline: none; }\n\n.back {\n display: inline-flex;\n align-items: center;\n margin: var(--space-2) var(--space-3) 0;\n padding: var(--space-1) var(--space-2);\n border-radius: var(--radius-sm);\n font-size: var(--text-xs-size);\n color: var(--text-secondary);\n}\n.back:hover { background: var(--bg-hover); color: var(--text-primary); }\n\n/* ApprovalDetail was drawn for a wide pane: tighten its gutters in the sheet. */\n.approval > div { padding: var(--space-3) var(--space-4) var(--space-12); }\n\n.item { display: flex; flex-direction: column; gap: var(--space-4); padding: var(--space-3) var(--space-4) var(--space-8); }\n.itemHead { display: flex; flex-direction: column; gap: var(--space-1); }\n\n.itemTitle {\n font-family: var(--font-display);\n font-size: var(--text-lg-size);\n line-height: var(--text-lg-line);\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-display);\n}\n\n.itemDetail {\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line-relaxed);\n color: var(--text-secondary);\n overflow-wrap: anywhere;\n}\n\n.defs {\n display: grid;\n grid-template-columns: max-content minmax(0, 1fr);\n gap: var(--space-2) var(--space-4);\n margin: 0;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n.defs dt { color: var(--text-tertiary); }\n.defs dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }\n\n.itemActions { display: flex; flex-wrap: wrap; gap: var(--space-2); }\n\n.foot {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-1) var(--space-4);\n padding: var(--space-2) var(--space-4);\n border-top: 1px solid var(--border-subtle);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n color: var(--text-tertiary);\n}\n.foot span { display: inline-flex; align-items: center; gap: 2px; }\n\n.caveat {\n margin: 0;\n padding: var(--space-2) var(--space-4);\n border-top: 1px solid var(--border-subtle);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--status-warning-fg);\n background: var(--status-warning-bg);\n}\n\n@keyframes fade { from { opacity: 0; } }\n@keyframes slide { from { opacity: 0; transform: translateX(4px); } }\n@keyframes rise { from { opacity: 0; transform: translateY(4px); } }\n\n@media (prefers-reduced-motion: reduce) {\n :root:not([data-motion='full']) .backdrop,\n :root:not([data-motion='full']) .panel { animation: none; }\n}\n:root[data-motion='reduce'] .backdrop,\n:root[data-motion='reduce'] .panel { animation: none; }\n","/**\n * routes/verse/shell/NeedsYouList.tsx — the rows of the Needs-you drawer\n * (unit C1). A listbox with ONE tab stop and aria-activedescendant, so J / K\n * move the selection without moving focus (and without the page scrolling\n * under the drawer). Presentational: selection and keys belong to the drawer.\n *\n * Each row says what, where, and how urgent — severity is a word AND a colour\n * (never colour alone), and an item with a deadline shows it counting down.\n *\n * Rows print needsYouRowView, not the wire text: \"patch: claude run: Advance\n * goal \"… so a deg\" becomes a \"Patch · Claude run\" label over a title that\n * ends on a whole word (two lines at most; the server's text is the tooltip),\n * a run summary becomes \"2 files · +384 −0 · Test-and-repair loop\", and an age\n * is \"38 days ago\" with the exact local time on hover.\n */\nimport { forwardRef, useEffect, useRef } from 'react';\nimport type { NeedsYouItem } from '../../../../core/verse/workbench-types.js';\nimport { NEEDS_YOU_ACTION_KEYS } from '../../../../core/verse/workbench-types.js';\nimport { needsYouRowView, until, type NeedsYouRunView } from './needs-you-model.js';\nimport styles from './NeedsYouDrawer.module.css';\n\n/**\n * \"2 files · +384 −0 · Test-and-repair loop\". The stats are drawn for the eye\n * and spoken as a sentence; the source's meaning (what TITRR did) is its\n * tooltip. Shared with the drawer's item detail.\n */\nexport function NeedsYouRunFacts({ run }: { run: NeedsYouRunView }) {\n return (\n <span className={styles.runFacts}>\n <span className={styles.diffStats} aria-hidden=\"true\">{run.stats}</span>\n <span className=\"visually-hidden\">{run.statsSpoken}</span>\n <span aria-hidden=\"true\">·</span>\n <span className={styles.runSource} title={run.sourceHint ?? undefined}>\n {run.partial ? 'Partial · ' : ''}{run.source}\n </span>\n </span>\n );\n}\n\nconst SEVERITY_WORD: Readonly<Record<NeedsYouItem['severity'], string>> = { high: 'Urgent', warn: 'Soon', info: 'When you can' };\n\nconst SOURCE_WORD: Readonly<Record<NeedsYouItem['source'], string>> = {\n approvals: 'Approval',\n authority: 'Autonomy',\n fleet: 'Fleet',\n leader: 'Leader',\n chats: 'Chat',\n accounts: 'Account',\n};\n\nexport interface NeedsYouListProps {\n items: readonly NeedsYouItem[];\n selectedId: string | null;\n onSelect: (id: string) => void;\n onOpen: (id: string) => void;\n now: number;\n label: string;\n}\n\nexport const NeedsYouList = forwardRef<HTMLDivElement, NeedsYouListProps>(function NeedsYouList(\n { items, selectedId, onSelect, onOpen, now, label },\n ref,\n) {\n const listId = 'verse-needs-you-list';\n const rowsRef = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n if (!selectedId) return;\n // Matched by dataset, not a selector: ids come from other units' producers.\n const rows = rowsRef.current?.querySelectorAll<HTMLElement>('[data-item-id]') ?? [];\n const row = [...rows].find((el) => el.dataset['itemId'] === selectedId);\n row?.scrollIntoView?.({ block: 'nearest' });\n }, [selectedId]);\n\n return (\n <div\n ref={(node) => {\n rowsRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n }}\n id={listId}\n role=\"listbox\"\n aria-label={label}\n tabIndex={0}\n aria-activedescendant={selectedId ? `${listId}-${items.findIndex((i) => i.id === selectedId)}` : undefined}\n className={styles.rows}\n >\n {items.map((item, index) => {\n const keyed = item.actions\n .map((a) => NEEDS_YOU_ACTION_KEYS[a.kind])\n .filter((k): k is 'A' | 'R' | 'V' | 'E' => k !== undefined);\n const view = needsYouRowView(item, now);\n return (\n <div\n key={item.id}\n id={`${listId}-${index}`}\n data-item-id={item.id}\n role=\"option\"\n aria-selected={item.id === selectedId}\n className={styles.row}\n data-severity={item.severity}\n onClick={() => onOpen(item.id)}\n onMouseMove={() => item.id !== selectedId && onSelect(item.id)}\n >\n <span className={styles.rule} aria-hidden=\"true\" />\n <span className={styles.rowMain}>\n {view.kindLabel ? <span className={styles.rowKind}>{view.kindLabel}</span> : null}\n {/* Two lines at most, ending on a whole word; the server's title is the tooltip. */}\n <span className={styles.rowTitle} title={view.fullTitle}>{view.title}</span>\n {view.run ? <NeedsYouRunFacts run={view.run} /> : null}\n <span className={styles.rowMeta}>\n <span className={styles.severity} data-severity={item.severity}>{SEVERITY_WORD[item.severity]}</span>\n <span>{SOURCE_WORD[item.source]}</span>\n {view.repo ? <span className={styles.repo} title={view.repoFull}>{view.repo}</span> : null}\n {item.subject.pr ? <span>#{item.subject.pr}</span> : null}\n <span title={view.ageStamp}>{view.age}</span>\n {item.expiresAt ? <span className={styles.deadline}>closes {until(item.expiresAt, now)}</span> : null}\n </span>\n </span>\n {item.id === selectedId && keyed.length > 0 ? (\n <span className={styles.rowKeys} aria-hidden=\"true\">\n {keyed.map((k) => (\n <kbd key={k} className={styles.key}>{k}</kbd>\n ))}\n </span>\n ) : null}\n </div>\n );\n })}\n </div>\n );\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"NeedsYouList-CCsijdWt.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/approvals/approvals-model.ts","../../../../../../src/web-ui/routes/verse/shell/needs-you-model.ts","../../../../../../src/web-ui/routes/verse/shell/NeedsYouDrawer.module.css","../../../../../../src/web-ui/routes/verse/shell/NeedsYouList.tsx"],"sourcesContent":["/**\n * routes/verse/approvals/approvals-model.ts — the pure decisions behind the\n * approvals queue: what order rows come in, and exactly what a human is\n * agreeing to when they press Approve.\n *\n * Kept framework-free and unit-tested because both are easy to get subtly\n * wrong: \"pending first\" must survive a status filter that also returns\n * decided rows, and the approve consequence sentence is the last thing\n * standing between a click and a real pull request against a real remote.\n */\nimport type { Proposal, ProposalKind } from '../../../data/api-types.js';\nimport { ENGINE_LABEL } from '../verse-model.js';\n\n/** Pending first, then newest first within each group. Stable and total. */\nexport function orderProposals(rows: readonly Proposal[]): Proposal[] {\n return [...rows].sort((a, b) => {\n const pendingA = a.status === 'pending' ? 0 : 1;\n const pendingB = b.status === 'pending' ? 0 : 1;\n if (pendingA !== pendingB) return pendingA - pendingB;\n const tsA = Date.parse(a.createdAt);\n const tsB = Date.parse(b.createdAt);\n const safeA = Number.isNaN(tsA) ? 0 : tsA;\n const safeB = Number.isNaN(tsB) ? 0 : tsB;\n if (safeA !== safeB) return safeB - safeA;\n return a.id.localeCompare(b.id);\n });\n}\n\nexport type RiskClass = NonNullable<Proposal['riskClass']>;\n\n/** high → medium → low → unstated. Used for the risk column's sort affordance. */\nexport function riskRank(risk: Proposal['riskClass']): number {\n switch (risk) {\n case 'high':\n return 0;\n case 'medium':\n return 1;\n case 'low':\n return 2;\n default:\n return 3;\n }\n}\n\n/** Client-side narrowing over whatever page the server returned. */\nexport function filterProposals(rows: readonly Proposal[], search: string, repo: string): Proposal[] {\n const s = search.trim().toLowerCase();\n const r = repo.trim().toLowerCase();\n if (!s && !r) return [...rows];\n return rows.filter((p) => {\n if (s && !p.title.toLowerCase().includes(s) && !(p.summary ?? '').toLowerCase().includes(s)) return false;\n if (r && !(p.repo ?? '').toLowerCase().includes(r)) return false;\n return true;\n });\n}\n\n/**\n * What approving this proposal actually does, in one sentence, naming the\n * repo. `pr` is the dangerous one: it pushes a branch to the remote and opens\n * a real pull request, which is visible to other people and cannot be undone\n * from the dialog. The confirm step MUST show this before the click.\n */\nexport function describeApproveConsequence(kind: ProposalKind | string, repo: string | null): string {\n // The project's NAME, not its absolute path: a sandbox checkout under\n // /private/tmp/claude-501/… is unreadable in a sentence. The confirm dialog\n // still prints the full path once, as the exact place the write lands.\n const where = repoName(repo) ?? 'the target repository';\n switch (kind) {\n case 'pr':\n return `Pushes a branch to ${where}'s remote and opens a real pull request. Other people can see it immediately, and this dialog cannot undo it.`;\n case 'patch':\n return `Writes the diff to ${where} on disk now. Nothing is pushed, but the working tree changes.`;\n default:\n return `Applies this ${String(kind)} proposal to ${where} now.`;\n }\n}\n\n/** True when approving reaches a remote — the loudest confirm wording. */\nexport function reachesRemote(kind: ProposalKind | string): boolean {\n return kind === 'pr';\n}\n\n/** The engine that produced the diff, as a short display string. */\nexport function engineOf(proposal: Pick<Proposal, 'engineModel' | 'engineTier'>): string | null {\n if (proposal.engineModel) return proposal.engineModel;\n if (proposal.engineTier) return proposal.engineTier;\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Readable detail\n// ---------------------------------------------------------------------------\n\n/** \"/Users/m/repos/binshield/\" → \"binshield\"; null for no repo. */\nexport function repoName(repo: string | null | undefined): string | null {\n if (typeof repo !== 'string') return null;\n const trimmed = repo.trim().replace(/\\/+$/, '');\n if (trimmed.length === 0) return null;\n const last = trimmed.slice(trimmed.lastIndexOf('/') + 1);\n return last.length > 0 ? last : trimmed;\n}\n\nconst KIND_LABEL: Record<string, string> = {\n patch: 'Patch',\n pr: 'Pull request',\n deploy: 'Deploy',\n note: 'Note',\n 'desktop-action': 'Desktop action',\n 'browser-action': 'Browser action',\n};\n\n/** \"patch\" → \"Patch\", \"pr\" → \"Pull request\"; an unknown kind is shown as sent. */\nexport function kindLabel(kind: ProposalKind | string): string {\n return KIND_LABEL[kind] ?? String(kind);\n}\n\n/**\n * The server builds a run proposal's title as `${engine} run: ${goal.slice(0, 80)}`\n * — cut at 80 characters, mid-word, sometimes mid-quote. This is the one\n * place that cut is made readable.\n */\nexport const RUN_TITLE_GOAL_CAP = 80;\n\nexport interface ReadableTitle {\n /** \"Claude run\" when the title carried an `engine run:` prefix; null otherwise. */\n eyebrow: string | null;\n /** The title to print: never ends mid-word; a cut one ends in \"…\". */\n text: string;\n /** True when the server's title was cut short (the full text we have rides in a tooltip). */\n truncated: boolean;\n}\n\nfunction capitalize(word: string): string {\n return word.length === 0 ? word : word.charAt(0).toUpperCase() + word.slice(1);\n}\n\n/** The app's own display name for an engine (\"Claude\", \"Codex\"); any other engine capitalized (\"Ollama\"). */\nfunction engineDisplayName(engine: string): string {\n const key = engine.toLowerCase();\n return Object.prototype.hasOwnProperty.call(ENGINE_LABEL, key)\n ? ENGINE_LABEL[key as keyof typeof ENGINE_LABEL]\n : capitalize(key);\n}\n\n/** Close a quote the cut left open, so the title does not read as a stray mark. */\nfunction closeQuotes(text: string): string {\n let out = text;\n if ((out.match(/\"/g) ?? []).length % 2 === 1) out += '\"';\n if ((out.match(/\\u201c/g) ?? []).length > (out.match(/\\u201d/g) ?? []).length) out += '\\u201d';\n return out;\n}\n\n/** Drop a trailing partial word and end on \"…\". */\nfunction cutAtWord(text: string): string {\n const body = text.replace(/(?:\\u2026|\\.\\.\\.)$/, '');\n const space = body.lastIndexOf(' ');\n const whole = space > 0 ? body.slice(0, space) : body;\n return `${whole.replace(/[\\s,;:\\-\\u2013\\u2014]+$/, '')}\\u2026`;\n}\n\nexport function readableTitle(title: string): ReadableTitle {\n const raw = typeof title === 'string' ? title.trim() : '';\n // Only the engines the sandboxed runner names — \"Dry run: …\" is a title, not an engine.\n const run = /^(\\[partial\\]\\s*)?(claude|codex|grok|local|ollama|gemini|api[\\w-]*) run:\\s*(.*)$/is.exec(raw);\n // \"Partial Claude run\", never \"Partial claude run\": the engine is a name either way.\n const eyebrow = run ? `${run[1] ? 'Partial ' : ''}${engineDisplayName(run[2]!)} run` : null;\n let text = run ? run[3]! : raw;\n // A title that already ends in an ellipsis right after a letter was cut mid-word upstream.\n const cutMidWord = /[\\p{L}\\p{N}](?:\\u2026|\\.\\.\\.)$/u.test(text);\n // A run goal at exactly the server's cap that does not end on a sentence boundary was sliced.\n const sliced = run !== null && text.length >= RUN_TITLE_GOAL_CAP && !/[.!?)\"'\\u201d\\u2026]$/.test(text);\n const truncated = cutMidWord || sliced;\n if (truncated) text = cutAtWord(text);\n text = closeQuotes(text);\n return { eyebrow, text: text.length > 0 ? text : raw, truncated };\n}\n\n/**\n * What a sandboxed run's summary line says, taken apart. The server writes\n * `[Partial ]<source> <engine:model> run produced N file(s) (+A/-D). <rest>`\n * (core/run/sandboxed-engine.ts); anything else parses to null and is shown\n * verbatim.\n */\nexport interface RunFacts {\n partial: boolean;\n /** The server's source label, verbatim (\"TITRR\", \"Best-of-N winner\"). */\n source: string;\n /** The source in plain words (\"Test-and-repair loop\"). */\n sourceLabel: string;\n /** What the source means, for a tooltip; null when the label says it already. */\n sourceHint: string | null;\n /** \"claude:claude-fable-5\". */\n model: string;\n files: number;\n insertions: number;\n deletions: number;\n /** Whatever the summary says after the run facts (\"Review before applying.\"), or null. */\n rest: string | null;\n}\n\nconst RUN_SUMMARY = /^(Partial )?(.+?) (\\S+) run produced (\\d+) file\\(s\\) \\(\\+(\\d+)\\/-(\\d+)\\)\\.?\\s*([\\s\\S]*)$/;\n\n/**\n * TITRR is internal shorthand (core/run/orchestrator.ts M78: Test → Iterate →\n * Test → Refine → Repeat). The operator sees the plain name; the acronym and\n * what it did ride in the tooltip.\n */\nconst TITRR_HINT =\n 'TITRR — Test, Iterate, Test, Refine, Repeat: after its change the run re-ran the repository\\u2019s tests and repaired the change until they passed or it ran out of attempts.';\n\nfunction describeSource(source: string): { label: string; hint: string | null } {\n if (/\\bTITRR\\b/.test(source)) {\n const rest = source.replace(/\\bTITRR\\b\\s*/, '').trim();\n const qualifier = rest === 'api-model' ? ' (API model)'\n : rest === 'api-model required-diff' ? ' (API model, retried for a missing diff)'\n : rest === 'api-model failed producer' ? ' (API model, producer failed)'\n : rest.length > 0 ? ` (${rest})` : '';\n return { label: `Test-and-repair loop${qualifier}`, hint: TITRR_HINT };\n }\n if (/^best-of-n/i.test(source)) {\n return { label: source, hint: 'Several models attempted this change in parallel; a judge compared them.' };\n }\n if (source === 'api-model') return { label: 'API model run', hint: null };\n if (source === 'Sandboxed') return { label: 'Sandboxed run', hint: 'Produced in an isolated sandbox checkout; nothing touched your working tree.' };\n return { label: source, hint: null };\n}\n\nexport function parseRunSummary(summary: string | null | undefined): RunFacts | null {\n if (typeof summary !== 'string') return null;\n const m = RUN_SUMMARY.exec(summary.trim());\n if (!m) return null;\n const { label, hint } = describeSource(m[2]!);\n const rest = m[7]!.trim();\n return {\n partial: m[1] !== undefined,\n source: m[2]!,\n sourceLabel: label,\n sourceHint: hint,\n model: m[3]!,\n files: Number(m[4]),\n insertions: Number(m[5]),\n deletions: Number(m[6]),\n rest: rest.length > 0 ? rest : null,\n };\n}\n\n/** \"2 files · +384 −0\" (a real minus sign, grouped thousands). */\nexport function formatDiffStats(facts: Pick<RunFacts, 'files' | 'insertions' | 'deletions'>): string {\n const n = (v: number) => v.toLocaleString('en-US');\n return `${n(facts.files)} ${facts.files === 1 ? 'file' : 'files'} \\u00b7 +${n(facts.insertions)} \\u2212${n(facts.deletions)}`;\n}\n\n/** The same stats as a sentence for assistive tech: \"2 files changed, 384 lines added, 0 removed\". */\nexport function describeDiffStats(facts: Pick<RunFacts, 'files' | 'insertions' | 'deletions'>): string {\n const n = (v: number) => v.toLocaleString('en-US');\n return `${n(facts.files)} ${facts.files === 1 ? 'file' : 'files'} changed, ${n(facts.insertions)} ${facts.insertions === 1 ? 'line' : 'lines'} added, ${n(facts.deletions)} removed`;\n}\n\n/**\n * \"just now\", \"5 minutes ago\", \"yesterday\", \"38 days ago\", then \"on Aug 17\"\n * past two months. Written out in full: the detail view has the room, and\n * \"38d\" is a sidebar abbreviation.\n */\nexport function longAgo(iso: string | null | undefined, now: number = Date.now()): string {\n if (typeof iso !== 'string') return 'at an unknown time';\n const then = Date.parse(iso);\n if (!Number.isFinite(then)) return 'at an unknown time';\n const seconds = Math.max(0, Math.round((now - then) / 1000));\n if (seconds < 45) return 'just now';\n const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });\n const minutes = Math.round(seconds / 60);\n if (minutes < 60) return rtf.format(-minutes, 'minute');\n const hours = Math.round(minutes / 60);\n if (hours < 24) return rtf.format(-hours, 'hour');\n const days = Math.round(hours / 24);\n if (days <= 60) return rtf.format(-days, 'day');\n return `on ${new Date(then).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })}`;\n}\n\n/** A local date and time for a tooltip: \"Mon, Aug 17, 3:12 PM\". */\nexport function localStamp(iso: string | null | undefined): string | undefined {\n if (typeof iso !== 'string') return undefined;\n const t = Date.parse(iso);\n if (!Number.isFinite(t)) return undefined;\n return new Date(t).toLocaleString([], { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit' });\n}\n","/**\n * routes/verse/shell/needs-you-model.ts — the Needs-you drawer as data (unit\n * C1): which items a split shows, how many each split has, whether the drawer\n * may say \"All clear\", and what a key press does to an item.\n *\n * Pure. The items come from GET /api/verse/activity (C1's own producers plus\n * Track B's, R1); each carries its own actions, so nothing here knows what a\n * grant or an owner-lane PR is.\n *\n * How a row READS (needsYouRowView) borrows the approvals detail view's text\n * helpers rather than growing a second copy: an approval item's title and\n * detail are the same proposal title and run summary that view already\n * untangles.\n */\nimport {\n NEEDS_YOU_KIND_CATEGORY,\n type NeedsYouAction,\n type NeedsYouActionKind,\n type NeedsYouItem,\n type NeedsYouSource,\n type VerseActivitySources,\n} from '../../../../core/verse/workbench-types.js';\nimport {\n describeDiffStats,\n formatDiffStats,\n kindLabel,\n localStamp,\n longAgo,\n parseRunSummary,\n readableTitle,\n repoName,\n} from '../approvals/approvals-model.js';\nimport type { VerseSeat } from '../../../data/api-types.js';\nimport { isVerseEngine, modelOptionFor, seatById } from '../verse-model.js';\nimport type { NeedsYouSplit } from '../verse-ui-store.js';\n\nexport const SPLIT_LABEL: Readonly<Record<NeedsYouSplit, string>> = {\n all: 'All',\n approvals: 'Approvals',\n fleet: 'Fleet',\n chats: 'Chats',\n accounts: 'Accounts',\n};\n\n/**\n * Which producers can put an item in each split. \"All clear\" is only\n * claimed for a split whose every producer answered: an owner-lane PR is in\n * Approvals but comes from the FLEET producer, so Approvals is only vouched\n * for when the fleet source answered too.\n */\nexport const SPLIT_SOURCES: Readonly<Record<NeedsYouSplit, readonly NeedsYouSource[]>> = {\n all: ['approvals', 'authority', 'fleet', 'leader', 'chats', 'accounts'],\n approvals: ['approvals', 'fleet', 'leader'],\n fleet: ['authority', 'fleet', 'leader'],\n chats: ['chats'],\n accounts: ['accounts'],\n};\n\nconst SOURCE_NAME: Readonly<Record<NeedsYouSource, string>> = {\n approvals: 'the approvals inbox',\n authority: 'the autonomy grant',\n fleet: 'the fleet',\n leader: 'the Leader',\n chats: 'chats',\n accounts: 'account health',\n};\n\nexport function itemsForSplit(items: readonly NeedsYouItem[], split: NeedsYouSplit): NeedsYouItem[] {\n if (split === 'all') return [...items];\n return items.filter((item) => NEEDS_YOU_KIND_CATEGORY[item.kind] === split);\n}\n\nexport function splitCounts(items: readonly NeedsYouItem[]): Record<NeedsYouSplit, number> {\n const counts: Record<NeedsYouSplit, number> = { all: items.length, approvals: 0, fleet: 0, chats: 0, accounts: 0 };\n for (const item of items) counts[NEEDS_YOU_KIND_CATEGORY[item.kind]] += 1;\n return counts;\n}\n\nexport interface SplitCoverage {\n /** Every producer feeding this split answered. */\n vouched: boolean;\n /** Operator-language names of the ones that did not, with why. */\n silent: Array<{ source: NeedsYouSource; name: string; state: 'unavailable' | 'error' }>;\n}\n\n/** Null sources (activity itself unavailable) vouch for nothing. */\nexport function splitCoverage(sources: VerseActivitySources | null, split: NeedsYouSplit): SplitCoverage {\n const silent: SplitCoverage['silent'] = [];\n for (const source of SPLIT_SOURCES[split]) {\n const state = sources?.[source] ?? 'unavailable';\n if (state !== 'ok') silent.push({ source, name: SOURCE_NAME[source], state });\n }\n return { vouched: silent.length === 0, silent };\n}\n\n/** \"the fleet isn't reporting yet and the Leader failed to answer\" — for the empty state. */\nexport function describeSilence(coverage: SplitCoverage): string {\n const phrases = coverage.silent.map((s) => (s.state === 'error' ? `${s.name} failed to answer` : `${s.name} isn't reporting in this build`));\n if (phrases.length === 0) return '';\n if (phrases.length === 1) return capitalise(phrases[0]!);\n return capitalise(`${phrases.slice(0, -1).join(', ')} and ${phrases[phrases.length - 1]}`);\n}\n\nfunction capitalise(text: string): string {\n return text.charAt(0).toUpperCase() + text.slice(1);\n}\n\n/** Approve / reject / veto ALWAYS confirm (SPEC-310C §1); other kinds only when the item says so. */\nexport const ALWAYS_CONFIRM: ReadonlySet<NeedsYouActionKind> = new Set(['approve', 'reject', 'veto']);\n\nexport function actionOf(item: NeedsYouItem, kind: NeedsYouActionKind): NeedsYouAction | null {\n return item.actions.find((a) => a.kind === kind) ?? null;\n}\n\nconst GENERIC_CONFIRM: Readonly<Record<'approve' | 'reject' | 'veto', { title: string; confirmLabel: string }>> = {\n approve: { title: 'Approve this?', confirmLabel: 'Approve' },\n reject: { title: 'Reject this?', confirmLabel: 'Reject' },\n veto: { title: 'Veto this action?', confirmLabel: 'Veto' },\n};\n\nexport interface ConfirmCopy {\n title: string;\n body: string;\n confirmLabel: string;\n}\n\n/** The dialog for `action` on `item`; null when the action runs without one. */\nexport function confirmCopy(item: NeedsYouItem, action: NeedsYouAction): ConfirmCopy | null {\n if (action.confirm) return action.confirm;\n if (action.kind === 'approve' || action.kind === 'reject' || action.kind === 'veto') {\n const generic = GENERIC_CONFIRM[action.kind];\n return { title: generic.title, body: readableItemTitle(item).text, confirmLabel: generic.confirmLabel };\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// How a row reads\n// ---------------------------------------------------------------------------\n\n/**\n * The approvals producer titles an item `${kind === 'pr' ? 'PR' : kind}: ${proposal.title}`\n * (core/verse/activity.ts approvalItem). Only an `approval` item is taken\n * apart this way — \"Failed: Migrate the store\" is a chat title, not a kind.\n */\nconst APPROVAL_KIND_PREFIX = /^(PR|[a-z][a-z-]*):\\s+([\\s\\S]+)$/;\n\nexport interface ReadableItemTitle {\n /** \"Patch · Claude run\": the proposal kind and the engine the title led with; null when neither. */\n kindLabel: string | null;\n /** The title to print. Never ends mid-word — a cut one ends in \"…\". */\n text: string;\n}\n\nexport function readableItemTitle(item: Pick<NeedsYouItem, 'kind' | 'title'>): ReadableItemTitle {\n let proposalKind: string | null = null;\n let rest = item.title;\n if (item.kind === 'approval') {\n const m = APPROVAL_KIND_PREFIX.exec(item.title.trim());\n if (m) {\n proposalKind = m[1] === 'PR' ? 'pr' : m[1]!;\n rest = m[2]!;\n }\n }\n const title = readableTitle(rest);\n const parts = [proposalKind === null ? null : kindLabel(proposalKind), title.eyebrow].filter((p): p is string => p !== null);\n return { kindLabel: parts.length > 0 ? parts.join(' · ') : null, text: title.text };\n}\n\n/** A sandboxed run's facts, lifted out of the item's detail line. */\nexport interface NeedsYouRunView {\n /** \"2 files · +384 −0\". */\n stats: string;\n /** \"2 files changed, 384 lines added, 0 removed\" — what a screen reader says instead. */\n statsSpoken: string;\n /** \"Test-and-repair loop\", never \"TITRR\". */\n source: string;\n /** What the source means, for a tooltip. */\n sourceHint: string | null;\n partial: boolean;\n /** \"claude:claude-fable-5\". */\n model: string;\n}\n\n/** Everything a Needs-you row prints, in operator language. The raw server text survives only in tooltips. */\nexport interface NeedsYouRowView {\n kindLabel: string | null;\n title: string;\n /** The title exactly as the server sent it — the row's tooltip. */\n fullTitle: string;\n run: NeedsYouRunView | null;\n /** What the detail says beyond the run facts (\"Review before applying.\"), or the detail verbatim; null when nothing. */\n detail: string | null;\n /** \"binshield\", never a path. */\n repo: string | null;\n /** The repo as sent, as a tooltip, when it was more than the name. */\n repoFull: string | undefined;\n /** \"38 days ago\". */\n age: string;\n /** The exact local time, for a tooltip. */\n ageStamp: string | undefined;\n}\n\nexport function needsYouRowView(item: NeedsYouItem, now: number = Date.now()): NeedsYouRowView {\n const title = readableItemTitle(item);\n const facts = parseRunSummary(item.detail);\n const repo = repoName(item.subject.repo);\n return {\n kindLabel: title.kindLabel,\n title: title.text,\n fullTitle: item.title,\n run: facts\n ? {\n stats: formatDiffStats(facts),\n statsSpoken: describeDiffStats(facts),\n source: facts.sourceLabel,\n sourceHint: facts.sourceHint,\n partial: facts.partial,\n model: facts.model,\n }\n : null,\n detail: facts ? facts.rest : item.detail,\n repo,\n repoFull: repo !== null && item.subject.repo !== null && item.subject.repo !== repo ? item.subject.repo : undefined,\n age: longAgo(item.since, now),\n ageStamp: localStamp(item.since),\n };\n}\n\n/** \"closes in 24m\" / \"expired\" — for veto windows and grants. */\nexport function until(iso: string, now: number = Date.now()): string {\n const t = Date.parse(iso);\n if (!Number.isFinite(t)) return '—';\n const s = Math.round((t - now) / 1000);\n if (s <= 0) return 'expired';\n if (s < 90) return `in ${s}s`;\n const m = Math.round(s / 60);\n if (m < 90) return `in ${m}m`;\n const h = Math.round(m / 60);\n if (h < 48) return `in ${h}h`;\n return `in ${Math.round(h / 24)}d`;\n}\n\n// ---------------------------------------------------------------------------\n// Seats and models, by name\n// ---------------------------------------------------------------------------\n\n/** A seat or model as the operator knows it; `raw` is the id as sent, for a tooltip, when the text differs. */\nexport interface DisplayName {\n text: string;\n raw: string | undefined;\n}\n\n/**\n * \"Claude Max\" for `claude-a`: the roster's label (bootstrap seats — the name\n * the seat picker and Apps & Accounts use). An id the roster does not know is\n * shown as sent: it is all there is.\n */\nexport function seatDisplayName(seats: readonly VerseSeat[], seatId: string): DisplayName {\n const label = seatById(seats, seatId)?.label;\n return label && label !== seatId ? { text: label, raw: seatId } : { text: seatId, raw: undefined };\n}\n\n/**\n * \"Fable 5.1\" for a run's `claude:claude-fable-5-1`: the catalog label (the\n * model picker's) on the item's own seat first, then on any seat of the run's\n * engine — exact id, then canonical (verse-model `modelOptionFor`, so a\n * pre-alias `claude-opus-5.5` still finds `claude-opus-5-5`). A model no\n * catalog lists is shown as sent.\n */\nexport function runModelDisplayName(seats: readonly VerseSeat[], model: string, seatId: string | null): DisplayName {\n const colon = model.indexOf(':');\n const prefix = colon > 0 ? model.slice(0, colon) : '';\n const engine = isVerseEngine(prefix) ? prefix : null;\n // `local:qwen3.8:27b` keeps its tag: only a known engine prefix is split off.\n const id = engine ? model.slice(colon + 1) : model;\n const order = [\n ...(seatId ? [seatId] : []),\n ...seats.filter((seat) => seat.id !== seatId && (engine === null || seat.engine === engine)).map((seat) => seat.id),\n ];\n for (const candidate of order) {\n const label = modelOptionFor(seats, { seatId: candidate, model: id })?.label;\n if (label && label !== model) return { text: label, raw: model };\n }\n return { text: model, raw: undefined };\n}\n","/* ⌘J — a right-hand sheet over the workbench; full screen on a phone.\n Hairlines, no cards. Severity is a word plus a 2px rule, never colour alone. */\n\n.backdrop {\n position: fixed;\n inset: 0;\n z-index: var(--z-dialog);\n display: flex;\n justify-content: flex-end;\n background: var(--bg-overlay);\n animation: fade var(--duration-fast) var(--ease-standard);\n}\n\n.panel {\n display: flex;\n flex-direction: column;\n width: min(480px, calc(100vw - var(--space-8)));\n height: 100%;\n background: var(--bg-surface);\n border-left: 1px solid var(--border-default);\n box-shadow: var(--shadow-dialog);\n outline: none;\n animation: slide var(--duration-base) var(--ease-decelerate);\n}\n\n/* Phone: the whole screen, sliding up. */\n.panel[data-presentation='full'] {\n width: 100%;\n border-left: 0;\n animation-name: rise;\n}\n\n.head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-3);\n min-height: var(--strip-height);\n padding: var(--space-2) var(--space-3) var(--space-2) var(--space-4);\n border-bottom: 1px solid var(--border-subtle);\n}\n\n.title {\n display: flex;\n align-items: baseline;\n gap: var(--space-2);\n font-family: var(--font-display);\n font-size: var(--text-md-size);\n line-height: var(--text-md-line);\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-display);\n}\n\n.titleCount {\n font-family: var(--font-ui);\n font-size: var(--text-sm-size);\n font-weight: var(--font-weight-regular);\n font-variant-numeric: tabular-nums;\n color: var(--text-tertiary);\n}\n\n.splits {\n display: flex;\n gap: var(--space-1);\n padding: var(--space-2) var(--space-3);\n border-bottom: 1px solid var(--border-subtle);\n overflow-x: auto;\n scrollbar-width: none;\n}\n\n.split {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n flex: none;\n min-height: var(--control-h-sm);\n padding: 0 var(--space-2);\n border-radius: var(--radius-sm);\n color: var(--text-secondary);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n.split:hover { background: var(--bg-hover); color: var(--text-primary); }\n.split[aria-selected='true'] { background: var(--bg-selected); color: var(--text-primary); font-weight: var(--font-weight-medium); }\n\n.splitCount {\n min-width: 18px;\n padding: 0 4px;\n border-radius: var(--radius-full);\n background: var(--bg-hover);\n font-size: var(--text-2xs-size);\n line-height: 18px;\n text-align: center;\n font-variant-numeric: tabular-nums;\n color: var(--text-secondary);\n}\n\n.body {\n position: relative;\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n}\n\n.rows { outline: none; }\n.rows:focus-visible { box-shadow: none; }\n/* The list holds focus (aria-activedescendant), so the focus ring is drawn on\n the ROW it points at — a ring around the whole list says nothing about\n which item A / R / V will act on. */\n.rows:focus-visible .row[aria-selected='true'] { box-shadow: inset 0 0 0 2px var(--border-focus); }\n\n.row {\n display: grid;\n grid-template-columns: 2px minmax(0, 1fr) auto;\n column-gap: var(--space-3);\n align-items: center;\n padding: var(--space-3) var(--space-4);\n border-bottom: 1px solid var(--border-subtle);\n cursor: pointer;\n}\n.row:hover { background: var(--bg-hover); }\n.row[aria-selected='true'] { background: var(--bg-selected); }\n\n.rule {\n align-self: stretch;\n border-radius: var(--radius-full);\n background: var(--border-strong);\n}\n.row[data-severity='high'] .rule { background: var(--status-danger-solid); }\n.row[data-severity='warn'] .rule { background: var(--status-warning-solid); }\n\n.rowMain { display: flex; flex-direction: column; min-width: 0; gap: 2px; }\n\n/* \"Patch · Claude run\" — the kind, above the title it no longer clutters.\n Secondary, not tertiary: tertiary falls under 4.5:1 on --bg-selected\n (approvals.module.css has the measurements). */\n.rowKind {\n margin: 0;\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n letter-spacing: var(--tracking-label);\n text-transform: uppercase;\n color: var(--text-secondary);\n}\n\n/* Two lines at most, wrapped at word boundaries. The text itself already\n ends on a whole word (approvals-model readableTitle); the full server\n title rides in `title`. */\n.rowTitle {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n line-clamp: 2;\n overflow: hidden;\n overflow-wrap: break-word;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-primary);\n}\n\n/* \"2 files · +384 −0 · Test-and-repair loop\". */\n.runFacts {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: 0 var(--space-2);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n}\n.diffStats { font-family: var(--font-display); font-variant-numeric: tabular-nums; color: var(--text-primary); }\n.runSource[title] { text-decoration: underline dotted; text-underline-offset: 3px; cursor: help; }\n\n.repo { font-weight: var(--font-weight-medium); }\n\n.rowMeta {\n display: flex;\n flex-wrap: wrap;\n gap: 0 var(--space-2);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n}\n\n.severity {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n letter-spacing: var(--tracking-label);\n text-transform: uppercase;\n}\n.severity[data-severity='high'] { color: var(--status-danger-fg); }\n.severity[data-severity='warn'] { color: var(--status-warning-fg); }\n\n.mono { font-family: var(--font-mono); font-size: var(--text-xs-size); }\n.deadline { color: var(--status-warning-fg); font-variant-numeric: tabular-nums; }\n\n.rowKeys { display: flex; gap: 2px; }\n\n.key,\n.inlineKey {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 4px;\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-xs);\n background: var(--bg-surface);\n font-family: var(--font-mono);\n font-size: var(--text-2xs-size);\n color: var(--text-secondary);\n}\n.inlineKey { margin-left: var(--space-2); background: transparent; }\n\n.loading { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-4); }\n\n.empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--space-2);\n padding: var(--space-16) var(--space-6);\n text-align: center;\n}\n.emptyTitle {\n font-family: var(--font-display);\n font-size: var(--text-md-size);\n line-height: var(--text-md-line);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n}\n.emptyBody {\n max-width: 44ch;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-secondary);\n}\n\n/* The reward for an empty inbox: a quiet check, not a confetti cannon. */\n.clearMark {\n position: relative;\n width: 40px;\n height: 40px;\n margin-bottom: var(--space-2);\n border-radius: var(--radius-full);\n background: var(--status-success-bg);\n}\n.clearMark::after {\n content: '';\n position: absolute;\n left: 14px;\n top: 10px;\n width: 10px;\n height: 16px;\n border: solid var(--status-success-solid);\n border-width: 0 2px 2px 0;\n transform: rotate(45deg);\n}\n\n.focusSink { position: absolute; width: 1px; height: 1px; overflow: hidden; outline: none; }\n\n.detail { outline: none; }\n\n.back {\n display: inline-flex;\n align-items: center;\n margin: var(--space-2) var(--space-3) 0;\n padding: var(--space-1) var(--space-2);\n border-radius: var(--radius-sm);\n font-size: var(--text-xs-size);\n color: var(--text-secondary);\n}\n.back:hover { background: var(--bg-hover); color: var(--text-primary); }\n\n/* ApprovalDetail was drawn for a wide pane: tighten its gutters in the sheet. */\n.approval > div { padding: var(--space-3) var(--space-4) var(--space-12); }\n\n.item { display: flex; flex-direction: column; gap: var(--space-4); padding: var(--space-3) var(--space-4) var(--space-8); }\n.itemHead { display: flex; flex-direction: column; gap: var(--space-1); }\n\n.itemTitle {\n font-family: var(--font-display);\n font-size: var(--text-lg-size);\n line-height: var(--text-lg-line);\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-display);\n}\n\n.itemDetail {\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line-relaxed);\n color: var(--text-secondary);\n overflow-wrap: anywhere;\n}\n\n.defs {\n display: grid;\n grid-template-columns: max-content minmax(0, 1fr);\n gap: var(--space-2) var(--space-4);\n margin: 0;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n.defs dt { color: var(--text-tertiary); }\n.defs dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }\n\n.itemActions { display: flex; flex-wrap: wrap; gap: var(--space-2); }\n\n.foot {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-1) var(--space-4);\n padding: var(--space-2) var(--space-4);\n border-top: 1px solid var(--border-subtle);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n color: var(--text-tertiary);\n}\n.foot span { display: inline-flex; align-items: center; gap: 2px; }\n\n.caveat {\n margin: 0;\n padding: var(--space-2) var(--space-4);\n border-top: 1px solid var(--border-subtle);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--status-warning-fg);\n background: var(--status-warning-bg);\n}\n\n@keyframes fade { from { opacity: 0; } }\n@keyframes slide { from { opacity: 0; transform: translateX(4px); } }\n@keyframes rise { from { opacity: 0; transform: translateY(4px); } }\n\n@media (prefers-reduced-motion: reduce) {\n :root:not([data-motion='full']) .backdrop,\n :root:not([data-motion='full']) .panel { animation: none; }\n}\n:root[data-motion='reduce'] .backdrop,\n:root[data-motion='reduce'] .panel { animation: none; }\n\n/* ---- Cloud PR triage (3.13) ------------------------------------------------\n A verdict chip on the row (word + colour, never colour alone), picks for a\n batch, and the strip that acts on them. */\n.chip {\n display: inline-flex;\n align-items: baseline;\n max-width: 100%;\n padding: 0 var(--space-1);\n border-radius: var(--radius-xs);\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n line-height: var(--text-xs-line);\n letter-spacing: var(--tracking-label);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.chip[data-tone='clean'] { background: var(--status-success-bg); color: var(--status-success-fg); }\n.chip[data-tone='held'] { background: var(--status-warning-bg); color: var(--status-warning-fg); }\n.chipWhy { font-family: var(--font-ui); letter-spacing: normal; }\n\n.row[data-picked='true'] { background: var(--bg-selected); }\n.row[data-picked='true'] .rule { background: var(--border-focus); }\n.pickMark {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n border-radius: var(--radius-xs);\n background: var(--border-focus);\n color: var(--accent-contrast);\n font-size: var(--text-2xs-size);\n}\n\n.batch {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-2);\n padding: var(--space-2) var(--space-4);\n border-bottom: 1px solid var(--border-subtle);\n background: var(--bg-surface);\n}\n.batchCount {\n margin-right: auto;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n font-variant-numeric: tabular-nums;\n}\n\n.verdict {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n padding: var(--space-3);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-sm);\n}\n.verdictHead { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); margin: 0; }\n.checks {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));\n gap: var(--space-1) var(--space-3);\n margin: 0;\n padding: 0;\n list-style: none;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n}\n.checks li { display: flex; gap: var(--space-1); min-width: 0; overflow-wrap: anywhere; }\n.checks li[data-ok='false'] { color: var(--text-primary); }\n.checkMark { flex: none; width: 1em; text-align: center; }\n.checks li[data-ok='true'] .checkMark { color: var(--status-success-fg); }\n.checks li[data-ok='false'] .checkMark { color: var(--status-warning-fg); }\n","/**\n * routes/verse/shell/NeedsYouList.tsx — the rows of the Needs-you drawer\n * (unit C1). A listbox with ONE tab stop and aria-activedescendant, so J / K\n * move the selection without moving focus (and without the page scrolling\n * under the drawer). Presentational: selection and keys belong to the drawer.\n *\n * Each row says what, where, and how urgent — severity is a word AND a colour\n * (never colour alone), and an item with a deadline shows it counting down.\n *\n * Rows print needsYouRowView, not the wire text: \"patch: claude run: Advance\n * goal \"… so a deg\" becomes a \"Patch · Claude run\" label over a title that\n * ends on a whole word (two lines at most; the server's text is the tooltip),\n * a run summary becomes \"2 files · +384 −0 · Test-and-repair loop\", and an age\n * is \"38 days ago\" with the exact local time on hover.\n *\n * Triage (3.13): a cloud PR's row carries its gate verdict as a chip (\"Clean\",\n * or \"Held · 2 commits behind\"), and rows can be picked for a batch — X on\n * the selected row or Shift-click — which the drawer then acts on with\n * A / R / E. Picking never moves the cursor and never opens the item.\n */\nimport { forwardRef, useEffect, useRef } from 'react';\nimport type { NeedsYouItem } from '../../../../core/verse/workbench-types.js';\nimport { NEEDS_YOU_ACTION_KEYS } from '../../../../core/verse/workbench-types.js';\nimport type { TriageChip } from './cloud-triage.js';\nimport { needsYouRowView, until, type NeedsYouRunView } from './needs-you-model.js';\nimport styles from './NeedsYouDrawer.module.css';\n\n/**\n * \"2 files · +384 −0 · Test-and-repair loop\". The stats are drawn for the eye\n * and spoken as a sentence; the source's meaning (what TITRR did) is its\n * tooltip. Shared with the drawer's item detail.\n */\nexport function NeedsYouRunFacts({ run }: { run: NeedsYouRunView }) {\n return (\n <span className={styles.runFacts}>\n <span className={styles.diffStats} aria-hidden=\"true\">{run.stats}</span>\n <span className=\"visually-hidden\">{run.statsSpoken}</span>\n <span aria-hidden=\"true\">·</span>\n <span className={styles.runSource} title={run.sourceHint ?? undefined}>\n {run.partial ? 'Partial · ' : ''}{run.source}\n </span>\n </span>\n );\n}\n\nconst SEVERITY_WORD: Readonly<Record<NeedsYouItem['severity'], string>> = { high: 'Urgent', warn: 'Soon', info: 'When you can' };\n\nconst SOURCE_WORD: Readonly<Record<NeedsYouItem['source'], string>> = {\n approvals: 'Approval',\n authority: 'Autonomy',\n fleet: 'Fleet',\n leader: 'Leader',\n chats: 'Chat',\n accounts: 'Account',\n};\n\nexport interface NeedsYouListProps {\n items: readonly NeedsYouItem[];\n selectedId: string | null;\n onSelect: (id: string) => void;\n onOpen: (id: string) => void;\n now: number;\n label: string;\n /** Rows picked for a batch action. */\n picked?: ReadonlySet<string>;\n /** Shift-click: pick or unpick a row. */\n onTogglePick?: (id: string) => void;\n /** Cloud PR verdicts by item id. */\n chips?: ReadonlyMap<string, TriageChip>;\n}\n\nconst NO_PICKS: ReadonlySet<string> = new Set();\nconst NO_CHIPS: ReadonlyMap<string, TriageChip> = new Map();\n\n/** \"Clean\" / \"Held · 2 commits behind\" — tone is a word as well as a colour. */\nexport function TriageChipView({ chip }: { chip: TriageChip }) {\n return (\n <span className={styles.chip} data-tone={chip.tone} title={chip.title}>\n {chip.label}\n {chip.why ? <span className={styles.chipWhy}> · {chip.why}</span> : null}\n </span>\n );\n}\n\nexport const NeedsYouList = forwardRef<HTMLDivElement, NeedsYouListProps>(function NeedsYouList(\n { items, selectedId, onSelect, onOpen, now, label, picked = NO_PICKS, onTogglePick, chips = NO_CHIPS },\n ref,\n) {\n const listId = 'verse-needs-you-list';\n const rowsRef = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n if (!selectedId) return;\n // Matched by dataset, not a selector: ids come from other units' producers.\n const rows = rowsRef.current?.querySelectorAll<HTMLElement>('[data-item-id]') ?? [];\n const row = [...rows].find((el) => el.dataset['itemId'] === selectedId);\n row?.scrollIntoView?.({ block: 'nearest' });\n }, [selectedId]);\n\n return (\n <div\n ref={(node) => {\n rowsRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n }}\n id={listId}\n role=\"listbox\"\n aria-label={picked.size > 0 ? `${label}, ${picked.size} picked` : label}\n tabIndex={0}\n aria-activedescendant={selectedId ? `${listId}-${items.findIndex((i) => i.id === selectedId)}` : undefined}\n className={styles.rows}\n >\n {items.map((item, index) => {\n const keyed = item.actions\n .map((a) => NEEDS_YOU_ACTION_KEYS[a.kind])\n .filter((k): k is 'A' | 'R' | 'V' | 'E' => k !== undefined);\n const view = needsYouRowView(item, now);\n const isPicked = picked.has(item.id);\n const chip = chips.get(item.id);\n return (\n <div\n key={item.id}\n id={`${listId}-${index}`}\n data-item-id={item.id}\n role=\"option\"\n aria-selected={item.id === selectedId}\n data-picked={isPicked ? 'true' : undefined}\n className={styles.row}\n data-severity={item.severity}\n onClick={(event) => {\n if (event.shiftKey && onTogglePick) {\n event.preventDefault();\n onTogglePick(item.id);\n return;\n }\n onOpen(item.id);\n }}\n onMouseMove={() => item.id !== selectedId && onSelect(item.id)}\n >\n <span className={styles.rule} aria-hidden=\"true\" />\n <span className={styles.rowMain}>\n {view.kindLabel ? <span className={styles.rowKind}>{view.kindLabel}</span> : null}\n {/* Two lines at most, ending on a whole word; the server's title is the tooltip. */}\n <span className={styles.rowTitle} title={view.fullTitle}>{view.title}</span>\n {view.run ? <NeedsYouRunFacts run={view.run} /> : null}\n <span className={styles.rowMeta}>\n {isPicked ? <span className=\"visually-hidden\">Picked. </span> : null}\n {chip ? <TriageChipView chip={chip} /> : null}\n <span className={styles.severity} data-severity={item.severity}>{SEVERITY_WORD[item.severity]}</span>\n <span>{SOURCE_WORD[item.source]}</span>\n {view.repo ? <span className={styles.repo} title={view.repoFull}>{view.repo}</span> : null}\n {item.subject.pr ? <span>#{item.subject.pr}</span> : null}\n <span title={view.ageStamp}>{view.age}</span>\n {item.expiresAt ? <span className={styles.deadline}>closes {until(item.expiresAt, now)}</span> : null}\n </span>\n </span>\n {isPicked ? <span className={styles.pickMark} aria-hidden=\"true\">✓</span> : item.id === selectedId && keyed.length > 0 ? (\n <span className={styles.rowKeys} aria-hidden=\"true\">\n {keyed.map((k) => (\n <kbd key={k} className={styles.key}>{k}</kbd>\n ))}\n </span>\n ) : null}\n </div>\n );\n })}\n </div>\n );\n});\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ ._backdrop_1d2dw_4{z-index:var(--z-dialog);background:var(--bg-overlay);animation:_fade_1d2dw_1 var(--duration-fast) var(--ease-standard);justify-content:flex-end;display:flex;position:fixed;inset:0}._panel_1d2dw_14{width:min(480px, calc(100vw - var(--space-8)));background:var(--bg-surface);border-left:1px solid var(--border-default);height:100%;box-shadow:var(--shadow-dialog);animation:_slide_1d2dw_1 var(--duration-base) var(--ease-decelerate);outline:none;flex-direction:column;display:flex}._panel_1d2dw_14[data-presentation=full]{border-left:0;width:100%;animation-name:_rise_1d2dw_1}._head_1d2dw_33{justify-content:space-between;align-items:center;gap:var(--space-3);min-height:var(--strip-height);padding:var(--space-2) var(--space-3) var(--space-2) var(--space-4);border-bottom:1px solid var(--border-subtle);display:flex}._title_1d2dw_43{align-items:baseline;gap:var(--space-2);font-family:var(--font-display);font-size:var(--text-md-size);line-height:var(--text-md-line);font-weight:var(--font-weight-semibold);letter-spacing:var(--tracking-display);display:flex}._titleCount_1d2dw_54{font-family:var(--font-ui);font-size:var(--text-sm-size);font-weight:var(--font-weight-regular);font-variant-numeric:tabular-nums;color:var(--text-tertiary)}._splits_1d2dw_62{gap:var(--space-1);padding:var(--space-2) var(--space-3);border-bottom:1px solid var(--border-subtle);scrollbar-width:none;display:flex;overflow-x:auto}._split_1d2dw_62{align-items:center;gap:var(--space-1);min-height:var(--control-h-sm);padding:0 var(--space-2);border-radius:var(--radius-sm);color:var(--text-secondary);font-size:var(--text-sm-size);line-height:var(--text-sm-line);flex:none;display:inline-flex}._split_1d2dw_62:hover{background:var(--bg-hover);color:var(--text-primary)}._split_1d2dw_62[aria-selected=true]{background:var(--bg-selected);color:var(--text-primary);font-weight:var(--font-weight-medium)}._splitCount_1d2dw_86{border-radius:var(--radius-full);background:var(--bg-hover);min-width:18px;font-size:var(--text-2xs-size);text-align:center;font-variant-numeric:tabular-nums;color:var(--text-secondary);padding:0 4px;line-height:18px}._body_1d2dw_98{overscroll-behavior:contain;flex:1;min-height:0;position:relative;overflow-y:auto}._rows_1d2dw_106{outline:none}._rows_1d2dw_106:focus-visible{box-shadow:none}._rows_1d2dw_106:focus-visible ._row_1d2dw_106[aria-selected=true]{box-shadow:inset 0 0 0 2px var(--border-focus)}._row_1d2dw_106{column-gap:var(--space-3);padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--border-subtle);cursor:pointer;grid-template-columns:2px minmax(0,1fr) auto;align-items:center;display:grid}._row_1d2dw_106:hover{background:var(--bg-hover)}._row_1d2dw_106[aria-selected=true]{background:var(--bg-selected)}._rule_1d2dw_125{border-radius:var(--radius-full);background:var(--border-strong);align-self:stretch}._row_1d2dw_106[data-severity=high] ._rule_1d2dw_125{background:var(--status-danger-solid)}._row_1d2dw_106[data-severity=warn] ._rule_1d2dw_125{background:var(--status-warning-solid)}._rowMain_1d2dw_133{flex-direction:column;gap:2px;min-width:0;display:flex}._rowKind_1d2dw_138{font-family:var(--font-display);font-size:var(--text-2xs-size);line-height:var(--text-2xs-line);letter-spacing:var(--tracking-label);text-transform:uppercase;color:var(--text-secondary);margin:0}._rowTitle_1d2dw_151{-webkit-line-clamp:2;line-clamp:2;overflow-wrap:break-word;font-size:var(--text-sm-size);line-height:var(--text-sm-line);color:var(--text-primary);-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}._runFacts_1d2dw_164{align-items:baseline;gap:0 var(--space-2);font-size:var(--text-xs-size);line-height:var(--text-xs-line);color:var(--text-secondary);flex-wrap:wrap;display:flex}._diffStats_1d2dw_173{font-family:var(--font-display);font-variant-numeric:tabular-nums;color:var(--text-primary)}._runSource_1d2dw_174[title]{text-underline-offset:3px;cursor:help;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}._repo_1d2dw_176{font-weight:var(--font-weight-medium)}._rowMeta_1d2dw_178{gap:0 var(--space-2);font-size:var(--text-xs-size);line-height:var(--text-xs-line);color:var(--text-secondary);flex-wrap:wrap;display:flex}._severity_1d2dw_187{font-family:var(--font-display);font-size:var(--text-2xs-size);letter-spacing:var(--tracking-label);text-transform:uppercase}._severity_1d2dw_187[data-severity=high]{color:var(--status-danger-fg)}._severity_1d2dw_187[data-severity=warn]{color:var(--status-warning-fg)}._mono_1d2dw_196{font-family:var(--font-mono);font-size:var(--text-xs-size)}._deadline_1d2dw_197{color:var(--status-warning-fg);font-variant-numeric:tabular-nums}._rowKeys_1d2dw_199{gap:2px;display:flex}._key_1d2dw_201,._inlineKey_1d2dw_202{border:1px solid var(--border-subtle);border-radius:var(--radius-xs);background:var(--bg-surface);min-width:18px;height:18px;font-family:var(--font-mono);font-size:var(--text-2xs-size);color:var(--text-secondary);justify-content:center;align-items:center;padding:0 4px;display:inline-flex}._inlineKey_1d2dw_202{margin-left:var(--space-2);background:0 0}._loading_1d2dw_218{gap:var(--space-2);padding:var(--space-4);flex-direction:column;display:flex}._empty_1d2dw_220{align-items:center;gap:var(--space-2);padding:var(--space-16) var(--space-6);text-align:center;flex-direction:column;display:flex}._emptyTitle_1d2dw_228{font-family:var(--font-display);font-size:var(--text-md-size);line-height:var(--text-md-line);font-weight:var(--font-weight-semibold);color:var(--text-primary)}._emptyBody_1d2dw_235{max-width:44ch;font-size:var(--text-sm-size);line-height:var(--text-sm-line);color:var(--text-secondary)}._clearMark_1d2dw_243{width:40px;height:40px;margin-bottom:var(--space-2);border-radius:var(--radius-full);background:var(--status-success-bg);position:relative}._clearMark_1d2dw_243:after{content:"";border:solid var(--status-success-solid);border-width:0 2px 2px 0;width:10px;height:16px;position:absolute;top:10px;left:14px;transform:rotate(45deg)}._focusSink_1d2dw_263{outline:none;width:1px;height:1px;position:absolute;overflow:hidden}._detail_1d2dw_265{outline:none}._back_1d2dw_4{margin:var(--space-2) var(--space-3) 0;padding:var(--space-1) var(--space-2);border-radius:var(--radius-sm);font-size:var(--text-xs-size);color:var(--text-secondary);align-items:center;display:inline-flex}._back_1d2dw_4:hover{background:var(--bg-hover);color:var(--text-primary)}._approval_1d2dw_279>div{padding:var(--space-3) var(--space-4) var(--space-12)}._item_1d2dw_281{gap:var(--space-4);padding:var(--space-3) var(--space-4) var(--space-8);flex-direction:column;display:flex}._itemHead_1d2dw_282{gap:var(--space-1);flex-direction:column;display:flex}._itemTitle_1d2dw_284{font-family:var(--font-display);font-size:var(--text-lg-size);line-height:var(--text-lg-line);font-weight:var(--font-weight-semibold);letter-spacing:var(--tracking-display)}._itemDetail_1d2dw_292{font-size:var(--text-sm-size);line-height:var(--text-sm-line-relaxed);color:var(--text-secondary);overflow-wrap:anywhere}._defs_1d2dw_299{gap:var(--space-2) var(--space-4);font-size:var(--text-sm-size);line-height:var(--text-sm-line);grid-template-columns:max-content minmax(0,1fr);margin:0;display:grid}._defs_1d2dw_299 dt{color:var(--text-tertiary)}._defs_1d2dw_299 dd{overflow-wrap:anywhere;min-width:0;margin:0}._itemActions_1d2dw_310{gap:var(--space-2);flex-wrap:wrap;display:flex}._foot_1d2dw_312{gap:var(--space-1) var(--space-4);padding:var(--space-2) var(--space-4);border-top:1px solid var(--border-subtle);font-size:var(--text-2xs-size);line-height:var(--text-2xs-line);color:var(--text-tertiary);flex-wrap:wrap;display:flex}._foot_1d2dw_312 span{align-items:center;gap:2px;display:inline-flex}._caveat_1d2dw_324{padding:var(--space-2) var(--space-4);border-top:1px solid var(--border-subtle);font-size:var(--text-xs-size);line-height:var(--text-xs-line);color:var(--status-warning-fg);background:var(--status-warning-bg);margin:0}@keyframes _fade_1d2dw_1{0%{opacity:0}}@keyframes _slide_1d2dw_1{0%{opacity:0;transform:translate(4px)}}@keyframes _rise_1d2dw_1{0%{opacity:0;transform:translateY(4px)}}@media (prefers-reduced-motion:reduce){:root:not([data-motion=full]) ._backdrop_1d2dw_4,:root:not([data-motion=full]) ._panel_1d2dw_14{animation:none}}:root[data-motion=reduce] ._backdrop_1d2dw_4,:root[data-motion=reduce] ._panel_1d2dw_14{animation:none}._chip_1d2dw_348{max-width:100%;padding:0 var(--space-1);border-radius:var(--radius-xs);font-family:var(--font-display);font-size:var(--text-2xs-size);line-height:var(--text-xs-line);letter-spacing:var(--tracking-label);white-space:nowrap;text-overflow:ellipsis;align-items:baseline;display:inline-flex;overflow:hidden}._chip_1d2dw_348[data-tone=clean]{background:var(--status-success-bg);color:var(--status-success-fg)}._chip_1d2dw_348[data-tone=held]{background:var(--status-warning-bg);color:var(--status-warning-fg)}._chipWhy_1d2dw_364{font-family:var(--font-ui);letter-spacing:normal}._row_1d2dw_106[data-picked=true]{background:var(--bg-selected)}._row_1d2dw_106[data-picked=true] ._rule_1d2dw_125{background:var(--border-focus)}._pickMark_1d2dw_368{border-radius:var(--radius-xs);background:var(--border-focus);width:18px;height:18px;color:var(--accent-contrast);font-size:var(--text-2xs-size);justify-content:center;align-items:center;display:inline-flex}._batch_1d2dw_380{align-items:center;gap:var(--space-2);padding:var(--space-2) var(--space-4);border-bottom:1px solid var(--border-subtle);background:var(--bg-surface);flex-wrap:wrap;display:flex}._batchCount_1d2dw_389{font-size:var(--text-xs-size);line-height:var(--text-xs-line);color:var(--text-secondary);font-variant-numeric:tabular-nums;margin-right:auto}._verdict_1d2dw_397{gap:var(--space-2);padding:var(--space-3);border:1px solid var(--border-subtle);border-radius:var(--radius-sm);flex-direction:column;display:flex}._verdictHead_1d2dw_405{justify-content:space-between;align-items:center;gap:var(--space-2);margin:0;display:flex}._checks_1d2dw_406{gap:var(--space-1) var(--space-3);font-size:var(--text-xs-size);line-height:var(--text-xs-line);color:var(--text-secondary);grid-template-columns:repeat(auto-fill,minmax(180px,1fr));margin:0;padding:0;list-style:none;display:grid}._checks_1d2dw_406 li{gap:var(--space-1);overflow-wrap:anywhere;min-width:0;display:flex}._checks_1d2dw_406 li[data-ok=false]{color:var(--text-primary)}._checkMark_1d2dw_419{text-align:center;flex:none;width:1em}._checks_1d2dw_406 li[data-ok=true] ._checkMark_1d2dw_419{color:var(--status-success-fg)}._checks_1d2dw_406 li[data-ok=false] ._checkMark_1d2dw_419{color:var(--status-warning-fg)}
@@ -0,0 +1,3 @@
1
+ import{a as e,c as t,n}from"./index-DZ-UQ7v8.js";import{g as r,o as i}from"./global-CMNW_dqn.js";import{t as a}from"./Dialog-D3msQlCj.js";import{S as o,i as s,s as ee}from"./VerseConsoleApp-CWU6R3By.js";import{N as c,O as l,V as u,i as d}from"./verse-model-DAVevkNe.js";import{t as te}from"./Segmented-CGh_-tBb.js";import{c as f,i as ne,n as p}from"./context-queries-eL3caKVG.js";import{a as m,v as h}from"./git-model-Dnkd1TnK.js";import{C as g,_ as re,a as ie,b as ae,c as oe,g as _,h as v,i as se,l as y,n as b,t as x,u as S,x as ce,y as C}from"./context-model-Br8t9jgG.js";import{n as le,t as ue}from"./SeatSelector-J5R3zDkB.js";import{r as de}from"./CapacityStrip-qKDBC65C.js";import{a as fe,m as pe,o as me,s as he,v as ge}from"./workspace-model-dji5-Al3.js";import{n as _e,t as ve}from"./folder-picker-C8zo3A56.js";var w=t(e(),1),T={option:`_option_qkog4_1`,toggle:`_toggle_qkog4_12`,details:`_details_qkog4_24`,nameLabel:`_nameLabel_qkog4_30`,name:`_name_qkog4_30`,hint:`_hint_qkog4_46`},E=n(),D=/^[a-z0-9][a-z0-9._-]{0,62}$/i;function O(e){return D.test(e)&&!e.endsWith(`.lock`)&&!e.includes(`..`)}function ye(e=new Date){let t=e=>String(e).padStart(2,`0`);return`chat-${t(e.getMonth()+1)}${t(e.getDate())}-${t(e.getHours())}${t(e.getMinutes())}`}function k(e){return e.toLowerCase().replace(/[^a-z0-9._-]+/g,`-`).replace(/^[^a-z0-9]+/,``).replace(/-{2,}/g,`-`).slice(0,63)}function be({repoName:e,value:t,onChange:n,disabled:r=!1}){let i=(0,w.useId)(),a=(0,w.useId)(),o=O(t.name);return(0,E.jsxs)(`fieldset`,{className:T.option,disabled:r,children:[(0,E.jsxs)(`label`,{className:T.toggle,children:[(0,E.jsx)(`input`,{type:`checkbox`,checked:t.enabled,onChange:e=>n({enabled:e.target.checked,name:t.name||ye()}),"aria-describedby":a}),`Isolate in a worktree`]}),t.enabled?(0,E.jsxs)(`div`,{className:T.details,children:[(0,E.jsx)(`label`,{className:T.nameLabel,htmlFor:i,children:`Name`}),(0,E.jsx)(`input`,{id:i,className:T.name,value:t.name,onChange:e=>n({...t,name:k(e.target.value)}),spellCheck:!1,autoCapitalize:`off`,autoCorrect:`off`,"aria-invalid":!o||void 0,"aria-describedby":a,maxLength:63})]}):null,(0,E.jsx)(`p`,{id:a,className:T.hint,children:t.enabled?o?(0,E.jsxs)(E.Fragment,{children:[`Creates `,(0,E.jsxs)(`code`,{children:[`~/.ashlr-worktrees/`,e,`/`,t.name]}),` on a new branch `,(0,E.jsxs)(`code`,{children:[`verse/`,t.name]}),`, from the current commit. Uncommitted changes stay in `,e,`.`]}):`Use letters, digits, dots, dashes or underscores.`:`The chat works on its own branch in its own folder, so your checkout is untouched.`})]})}async function xe(e,t){return t.enabled?(await h(e,t.name)).path:e}var A={width:`_width_stwix_1`,form:`_form_stwix_3`,field:`_field_stwix_4`,label:`_label_stwix_5`,optional:`_optional_stwix_13`,select:`_select_stwix_15`,input:`_input_stwix_16`,hint:`_hint_stwix_40`,error:`_error_stwix_41`,actions:`_actions_stwix_49`,cancel:`_cancel_stwix_50`,create:`_create_stwix_51`,capacity:`_capacity_stwix_72`,rootRow:`_rootRow_stwix_78`,removeRoot:`_removeRoot_stwix_87`,addRoot:`_addRoot_stwix_88`,context:`_context_stwix_108`,contextHead:`_contextHead_stwix_115`,contextBudget:`_contextBudget_stwix_122`,warn:`_warn_stwix_130`,fit:`_fit_stwix_137`,fitLine:`_fitLine_stwix_138`,fitBadge:`_fitBadge_stwix_147`,seatFacts:`_seatFacts_stwix_165`},Se=`\0workspace:`,j=`\0other`,Ce=(e,t)=>t();function we(e,t){return e?.seats[t]?.contextMode??`standard`}function Te(e,t,n){return e?u(e)?C(e,t):n!==`standard`&&c(e,`standard`)!==null?`standard`:null:null}function M(e){return e instanceof s?`Unlock actions with the mutation token to save a default.`:e instanceof i?e.detail??e.message:e instanceof Error?e.message:String(e)}function N({open:e,onClose:t,projects:n,seats:i,workspaces:s=[],initialProjectPath:c,initialSeat:l,busy:d=!1,error:te,onCreate:h,runMutation:re=Ce}){let ie=(0,w.useId)(),ae=(0,w.useId)(),oe=(0,w.useId)(),v=(0,w.useId)(),se=(0,w.useId)(),y=(0,w.useRef)(null),[b,S]=(0,w.useState)(``),[ce,T]=(0,w.useState)(``),[D,k]=(0,w.useState)(null),[N,ke]=(0,w.useState)(``),[Ae,P]=(0,w.useState)(null),[F,I]=(0,w.useState)([]),[je,Me]=(0,w.useState)([]),[Ne,L]=(0,w.useState)(!1),[Pe,R]=(0,w.useState)(null),[z,Fe]=(0,w.useState)(null),[Ie,Le]=(0,w.useState)(null),[Re,B]=(0,w.useState)(null),[ze,Be]=(0,w.useState)(!1),[Ve,V]=(0,w.useState)(null),[He,H]=(0,w.useState)({status:`idle`}),[U,Ue]=(0,w.useState)({enabled:!1,name:``}),[We,Ge]=(0,w.useState)(!1),Ke=(0,w.useRef)(new Map),qe=(0,w.useMemo)(()=>[...n].sort((e,t)=>Number(t.enrolled)-Number(e.enrolled)||e.name.localeCompare(t.name)),[n]),Je=(0,w.useRef)({initialProjectPath:c,initialSeat:l,projects:n,seats:i,sortedProjects:qe});Je.current={initialProjectPath:c,initialSeat:l,projects:n,seats:i,sortedProjects:qe},(0,w.useEffect)(()=>{if(!e)return;let{initialProjectPath:t,initialSeat:n,projects:r,seats:i,sortedProjects:a}=Je.current,o=t&&r.some(e=>e.path===t)?t:null;S(o??(t?j:a[0]?.path??j)),T(o?``:t??``),k(De(n??null,i)??le(i)),ke(``),P(null),I([]),R(null),L(!1),Me([]),B(null),V(null),Be(!1),Ue({enabled:!1,name:ye()}),Ge(!1),Ke.current=new Map},[e]),(0,w.useEffect)(()=>{if(!e)return;let t=!1;return Le(null),ne().then(e=>{t||Fe(e)}).catch(e=>{t||(Fe(null),Le(M(e)))}),()=>{t=!0}},[e]),(0,w.useEffect)(()=>{e&&D===null&&i.length!==0&&k(De(l??null,i)??le(i))},[e,D,i,l]);let Ye=r(o);(0,w.useEffect)(()=>{e&&Ye()},[e,Ye]);let Xe=(0,w.useMemo)(()=>{let e=new Map;for(let t of s)e.set(t.id,t);for(let t of je)e.has(t.id)||e.set(t.id,t);return[...e.values()]},[s,je]),W=b.startsWith(Se),G=W?b.slice(11):null,K=W?``:b===j?ce.trim():b,q=D===null?null:i.find(e=>e.id===D.seatId)??null,J=q===null||D===null?null:g(q,D.model),Ze=q?.health.state===`unavailable`,Y=q!==null&&J!==null?_(q,J):null,Qe=!W&&K.length>0,$e=Qe&&U.enabled,et=!d&&!We&&(W||K.length>0)&&D!==null&&!Ze&&J!==null&&Y===null&&(!$e||O(U.name)),tt=G===null?null:Xe.find(e=>e.id===G)??null,X=D===null?`standard`:we(z,D.seatId),Z=C(J,Re??X),nt=u(J),rt=C(J,X),it=(0,w.useCallback)((e,t)=>D!==null&&e.id===D.seatId&&t.id===D.model?Z:C(t,we(z,e.id)),[D,Z,z]);function at(e){k(e),B(null),V(null)}async function ot(){if(D===null||q===null)return;let e=Z;Be(!0),V(null);try{let t=await re(`Saving ${x[e]} as the default context mode for ${q.label}.`,()=>f({seatId:D.seatId,contextMode:e}).then(e=>({ok:!0,prefs:e}),e=>({ok:!1,error:e})));if(t===null)return;if(!t.ok){V({ok:!1,text:M(t.error)});return}Fe(t.prefs),B(null),V({ok:!0,text:`New chats on ${q.label} now start in ${x[e]}.`})}catch(e){V({ok:!1,text:M(e)})}finally{Be(!1)}}let st=(0,w.useMemo)(()=>{if(G!==null)return{key:`w:${G}`,query:{workspaceId:G}};if(W)return null;let e=pe(K,F);if(!e.ok)return null;let[t,...n]=e.roots;return{key:`p:${e.roots.join(`
2
+ `)}`,query:n.length>0?{projectPath:t,extraRoots:n}:{projectPath:t}}},[G,W,K,F]),ct=(0,w.useRef)(st);ct.current=st;let Q=st?.key??null;(0,w.useEffect)(()=>{let t=ct.current;if(!e||Q===null||t===null){H({status:`idle`});return}let n=Ke.current.get(Q);if(n){H({status:`ready`,key:Q,fit:n});return}let r=!1;H({status:`loading`,key:Q});let i=setTimeout(()=>{p(t.query).then(e=>{Ke.current.set(Q,e),r||H({status:`ready`,key:Q,fit:e})}).catch(e=>{r||H({status:`error`,key:Q,message:M(e)})})},350);return()=>{r=!0,clearTimeout(i)}},[e,Q]);let $=Q===null?{status:`idle`}:He.status!==`idle`&&He.key===Q?He:{status:`loading`,key:Q},lt=$.status===`ready`?$.fit:null,ut=he(q?.engine??null,1+F.length),dt=me(q?.engine??null,tt?.roots.length??0),ft=ve();async function pt(){let e=await _e();e!==null&&e.length>0&&(S(j),T(e))}async function mt(e){let t=await _e();t!==null&&t.length>0&&I(F.map((n,r)=>r===e?t:n))}async function ht(){let e=pe(K,F);if(!e.ok){P(e.error);return}L(!0),P(null),R(null);try{let t=fe(e.roots[0]),n=await ee({name:t,roots:e.roots});Me(e=>[...e,n]),S(`${Se}${n.id}`),R(`Saved. “${n.name}” is in this list from now on.`)}catch(e){P(e instanceof Error?e.message:String(e))}finally{L(!1)}}function gt(e){if(e.preventDefault(),!D){P(`Pick a seat first.`);return}if(J===null){P(`Pick a model this seat offers.`);return}if(Y!==null){P(`${J.label} cannot run on this seat: ${Y}.`);return}if(G!==null){P(null);let e={workspaceId:G,seatId:D.seatId,model:D.model};delete e.projectPath;let t=N.trim();t&&(e.title=t);let n=Te(J,Z,X);n!==null&&(e.contextMode=n),h(e);return}let t=pe(K,F);if(!t.ok){P(t.error);return}if($e&&!O(U.name)){P(`Name the worktree with letters, digits, dots, dashes or underscores.`);return}P(null);let[n,...r]=t.roots,i={projectPath:n,seatId:D.seatId,model:D.model};r.length>0&&(i.extraRoots=r);let a=N.trim();a&&(i.title=a);let o=Te(J,Z,X);if(o!==null&&(i.contextMode=o),!$e){h(i);return}_t(n,i)}async function _t(e,t){Ge(!0);try{let n=await re(`Creating the worktree ${U.name} (a new branch verse/${U.name}) for this chat.`,()=>xe(e,U).then(e=>({ok:!0,folder:e}),e=>({ok:!1,error:e})));if(n===null)return;if(!n.ok){P(`The worktree could not be created: ${m(n.error)}`);return}await h({...t,projectPath:n.folder})}catch(e){P(m(e))}finally{Ge(!1)}}let vt=Ae??te??null;return(0,E.jsx)(a,{open:e,onClose:t,titleId:ie,title:`New chat`,initialFocusRef:y,widthClassName:A.width,children:(0,E.jsxs)(`form`,{className:A.form,onSubmit:gt,noValidate:!0,children:[(0,E.jsxs)(`label`,{className:A.field,htmlFor:ae,children:[(0,E.jsx)(`span`,{className:A.label,children:`Project`}),(0,E.jsxs)(`select`,{id:ae,ref:y,value:b,onChange:e=>S(e.target.value),className:A.select,children:[Xe.length>0?(0,E.jsx)(`optgroup`,{label:`Saved projects`,children:Xe.map(e=>(0,E.jsxs)(`option`,{value:`${Se}${e.id}`,children:[e.name,` — `,ge(e)]},e.id))}):null,qe.map(e=>(0,E.jsxs)(`option`,{value:e.path,children:[e.name,e.enrolled?``:` (recent)`,` — `,e.path]},e.path)),(0,E.jsx)(`option`,{value:j,children:`Other folder…`})]})]}),b===j&&!W?(0,E.jsxs)(`label`,{className:A.field,htmlFor:oe,children:[(0,E.jsx)(`span`,{className:A.label,children:`Folder path`}),(0,E.jsxs)(`div`,{className:A.rootRow,children:[(0,E.jsx)(`input`,{id:oe,className:A.input,value:ce,onChange:e=>T(e.target.value),placeholder:`/absolute/path/to/project`,autoComplete:`off`,spellCheck:!1}),ft?(0,E.jsx)(`button`,{type:`button`,className:A.addRoot,onClick:()=>void pt(),children:`Choose folder…`}):null]})]}):null,dt?(0,E.jsx)(`p`,{className:A.hint,children:dt}):null,W?null:(0,E.jsxs)(`div`,{className:A.field,children:[(0,E.jsxs)(`span`,{className:A.label,children:[`Also include `,(0,E.jsx)(`span`,{className:A.optional,children:`optional`})]}),F.map((e,t)=>(0,E.jsxs)(`div`,{className:A.rootRow,children:[(0,E.jsx)(`input`,{className:A.input,value:e,onChange:e=>I(F.map((n,r)=>r===t?e.target.value:n)),placeholder:`/absolute/path/to/another/folder`,"aria-label":`Additional folder ${t+1}`,autoComplete:`off`,spellCheck:!1}),ft?(0,E.jsx)(`button`,{type:`button`,className:A.removeRoot,onClick:()=>void mt(t),"aria-label":`Choose additional folder ${t+1}`,children:`Choose folder…`}):null,(0,E.jsx)(`button`,{type:`button`,className:A.removeRoot,onClick:()=>I(F.filter((e,n)=>n!==t)),"aria-label":`Remove additional folder ${t+1}`,children:`Remove`})]},t)),F.length+1<8?(0,E.jsx)(`button`,{type:`button`,className:A.addRoot,onClick:()=>I([...F,``]),children:`Add a folder`}):null,ut?(0,E.jsx)(`p`,{className:A.hint,children:ut}):null,(0,E.jsxs)(`div`,{className:A.rootRow,children:[(0,E.jsx)(`button`,{type:`button`,className:A.addRoot,onClick:()=>void ht(),disabled:Ne||K.length===0,children:Ne?`Saving…`:`Save as a project`}),(0,E.jsx)(`span`,{className:A.hint,children:`Keeps these folders in the list above. No chat needed first.`})]})]}),Pe?(0,E.jsx)(`p`,{role:`status`,className:A.hint,children:Pe}):null,Qe?(0,E.jsx)(be,{repoName:Ee(K),value:U,onChange:Ue,disabled:We||d}):null,(0,E.jsx)(ue,{id:se,seats:i,value:D,onChange:at,workingSetTokens:lt?.totalEstTokens??null,modeFor:it}),q===null?null:(0,E.jsx)(`div`,{className:A.capacity,children:(0,E.jsx)(de,{seats:i,seatIds:[q.id],local:`each`,headline:!1,title:`${q.label} capacity`})}),q===null||J===null?null:(0,E.jsx)(Oe,{seat:q,option:J,unavailableReason:Y,mode:Z,offersModes:nt,savedDefault:rt,prefsLoaded:z!==null,prefsError:Ie,onMode:e=>{B(e),V(null)},savingDefault:ze,defaultNote:Ve,onMakeDefault:()=>void ot(),fitState:$}),i.length===0?(0,E.jsx)(`p`,{className:A.hint,children:`No seats yet — connect an account or start Ollama, then reload.`}):null,(0,E.jsxs)(`label`,{className:A.field,htmlFor:v,children:[(0,E.jsxs)(`span`,{className:A.label,children:[`Title `,(0,E.jsx)(`span`,{className:A.optional,children:`optional`})]}),(0,E.jsx)(`input`,{id:v,className:A.input,value:N,onChange:e=>ke(e.target.value),placeholder:`Defaults to your first message`,maxLength:120})]}),vt?(0,E.jsx)(`p`,{role:`alert`,className:A.error,children:vt}):null,(0,E.jsxs)(`div`,{className:A.actions,children:[(0,E.jsx)(`button`,{type:`button`,className:A.cancel,onClick:t,children:`Cancel`}),(0,E.jsx)(`button`,{type:`submit`,className:A.create,disabled:!et,children:We?`Creating worktree…`:d?`Creating…`:`Start chat`})]})]})})}function Ee(e){let t=e.replace(/[\\/]+$/,``).split(/[\\/]/);return t[t.length-1]||e}function De(e,t){if(e===null)return null;let n=t.find(t=>t.id===e.seatId),r=g(n,e.model);return r===null?e:{seatId:e.seatId,model:r.id}}function Oe({seat:e,option:t,unavailableReason:n,mode:r,offersModes:i,savedDefault:a,prefsLoaded:o,prefsError:s,onMode:ee,savingDefault:u,defaultNote:f,onMakeDefault:ne,fitState:p}){let m=(0,w.useId)(),h=ie(t,r),g=ae(e),_=ce(e),C=p.status===`ready`?v(p.fit.totalEstTokens,t,r,e.engine):null;return(0,E.jsxs)(`div`,{className:A.context,role:`group`,"aria-labelledby":m,children:[(0,E.jsxs)(`div`,{className:A.contextHead,children:[(0,E.jsx)(`span`,{id:m,className:A.label,children:`Context`}),(0,E.jsx)(`span`,{className:A.contextBudget,children:h===null?`Window unknown`:`${l(h.contextWindow)} window${h.autoCompactAt===null?``:` · compacts ≈${l(h.autoCompactAt)}`}`})]}),h!==null&&t.windowSource?(0,E.jsxs)(`p`,{className:A.hint,children:[`Window `,d[t.windowSource],`.`]}):null,n===null?null:(0,E.jsxs)(`p`,{className:A.warn,children:[t.label,` cannot run on this seat: `,n,`. Pick another model.`]}),i?(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(te,{"aria-label":`Context mode`,size:`sm`,value:r,onChange:ee,options:[`standard`,`expansive`].map(e=>{let n=c(t,e);return{value:e,label:n===null?x[e]:`${x[e]} · ≈${l(n.autoCompactAt??n.contextWindow)}`,ariaLabel:x[e]}})}),(0,E.jsx)(`p`,{className:A.hint,children:se(e.engine,t,r)}),o&&r!==a?(0,E.jsx)(`div`,{className:A.rootRow,children:(0,E.jsx)(`button`,{type:`button`,className:A.addRoot,onClick:ne,disabled:u,children:u?`Saving…`:`Make ${x[r]} the default for ${e.label}`})}):null,f===null?null:(0,E.jsx)(`p`,{role:f.ok?`status`:`alert`,className:f.ok?A.hint:A.error,children:f.text}),s===null?null:(0,E.jsxs)(`p`,{className:A.hint,children:[`Saved defaults could not be read (`,s,`); this chat starts in `,x[r],` unless you pick otherwise.`]})]}):(0,E.jsx)(`p`,{className:A.hint,children:re(e.engine,t)}),(0,E.jsx)(`div`,{className:A.fit,"aria-live":`polite`,children:p.status===`idle`?null:p.status===`loading`?(0,E.jsx)(`p`,{className:A.hint,children:`Sizing the chosen folders…`}):p.status===`error`?(0,E.jsxs)(`p`,{className:A.hint,children:[`Could not size the chosen folders: `,p.message]}):C===null?(0,E.jsxs)(`p`,{className:A.hint,children:[`~`,l(p.fit.totalEstTokens),` tokens of tracked code; this model’s budget is unknown, so no fit is claimed.`]}):(0,E.jsxs)(E.Fragment,{children:[(0,E.jsxs)(`p`,{className:A.fitLine,children:[(0,E.jsx)(`span`,{className:A.fitBadge,"data-fit":C,children:b[C]}),(0,E.jsx)(`span`,{children:oe({verdict:C,tokens:p.fit.totalEstTokens,option:t,mode:r,floor:y(p.fit)})})]}),(0,E.jsx)(`p`,{className:A.hint,children:S(e.engine)})]})}),g===null&&_.length===0?null:(0,E.jsxs)(`ul`,{className:A.seatFacts,"aria-label":`${e.label} facts`,children:[g===null?null:(0,E.jsxs)(`li`,{children:[`Runs `,g,`.`]}),_.map(e=>(0,E.jsx)(`li`,{children:e},e))]})]})}export{N as NewChatDialog};
3
+ //# sourceMappingURL=NewChatDialog-BlCHtOIr.js.map