0sec-cli 0.23.0 → 0.24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/0.js +66 -67
  2. package/README.md +37 -11
  3. package/chunks/{adapt-loop-V3JFWOKC.js → adapt-loop-L77BWMNE.js} +4 -4
  4. package/chunks/{artifact-scraper-NYKUF2M5.js → artifact-scraper-BV67RAP5.js} +2 -2
  5. package/chunks/{assumption-mining-ZX3YVWEH.js → assumption-mining-RPVR77A3.js} +18 -18
  6. package/chunks/{backend-connections-H52NIVH2.js → backend-connections-ACIXNYZN.js} +3 -3
  7. package/chunks/{chunk-MQJVU2GZ.js → chunk-2NBZZFRG.js} +79 -9
  8. package/chunks/{chunk-A2ADXAC5.js → chunk-2XGBEH53.js} +1288 -2313
  9. package/chunks/{chunk-3E54JYS4.js → chunk-3LPBJMHB.js} +1 -1
  10. package/chunks/{chunk-XORZUR2H.js → chunk-3WUPCZGF.js} +1 -1
  11. package/chunks/{chunk-65H3MRBF.js → chunk-4ROZFLSR.js} +1 -1
  12. package/chunks/chunk-56UTQKXO.js +56 -0
  13. package/chunks/{chunk-YYS2H33A.js → chunk-5ETI27Q3.js} +2 -2
  14. package/chunks/{chunk-3ZNI7F42.js → chunk-5NFIY2SJ.js} +3 -3
  15. package/chunks/{chunk-A5QO7N3S.js → chunk-5PFRE522.js} +1 -1
  16. package/chunks/{chunk-EH2WTNY7.js → chunk-5WAHHZBF.js} +1424 -859
  17. package/chunks/{chunk-WIYNYNL2.js → chunk-6XMFCVJS.js} +1 -1
  18. package/chunks/chunk-7UHAXEOV.js +289 -0
  19. package/chunks/{chunk-CP6HANBE.js → chunk-BD7WULFS.js} +4 -3
  20. package/chunks/{chunk-T7ZEVY5G.js → chunk-BMDG6T7D.js} +815 -41
  21. package/chunks/{chunk-QMICC5O2.js → chunk-BOBIAHKA.js} +2 -2
  22. package/chunks/{chunk-VDOWARMJ.js → chunk-BPU6M42R.js} +15 -1
  23. package/chunks/{chunk-UELXHK2Y.js → chunk-CGBDEST2.js} +16 -5
  24. package/chunks/{remote-workflow-runtime-RGQ5ECMN.js → chunk-CJRZSWII.js} +39 -8
  25. package/chunks/chunk-F2P25DJY.js +5421 -0
  26. package/chunks/{chunk-TO35Y326.js → chunk-GTED3FSZ.js} +5 -2
  27. package/chunks/{chunk-LT7BFGXA.js → chunk-GV5WXDHY.js} +10 -10
  28. package/chunks/{chunk-LTEE2JWK.js → chunk-GXXX7AGH.js} +251 -8
  29. package/chunks/chunk-GZA7RGK7.js +5198 -0
  30. package/chunks/{chunk-KHPOSLCF.js → chunk-H5QURBBK.js} +174 -710
  31. package/chunks/chunk-I43YYHDU.js +566 -0
  32. package/chunks/{chunk-62ENS6XO.js → chunk-IIBNQTOK.js} +3 -2
  33. package/chunks/{chunk-BF5FIK7H.js → chunk-IJ6UPW3H.js} +108 -24
  34. package/chunks/{chunk-TPUJZ74W.js → chunk-ILRMLA6J.js} +2 -2
  35. package/chunks/{chunk-I3OCJ2OA.js → chunk-JWSOUKFF.js} +5 -3
  36. package/chunks/{chunk-UZUELPFW.js → chunk-K74DRDC5.js} +1 -1
  37. package/chunks/chunk-LMP2T4G2.js +700 -0
  38. package/chunks/{chunk-K55B4OH4.js → chunk-NBV4I237.js} +1 -1
  39. package/chunks/chunk-OOMBOLAF.js +295 -0
  40. package/chunks/{chunk-YAEJAZYW.js → chunk-PJU24AKR.js} +2 -2
  41. package/chunks/{chunk-NI6QYQSK.js → chunk-PVJUPIQG.js} +6 -6
  42. package/chunks/{chunk-WYNZFNMF.js → chunk-Q7JKIKKF.js} +289 -10
  43. package/chunks/{chunk-ITES7BCY.js → chunk-QNRYOJEB.js} +3 -111
  44. package/chunks/{chunk-PIR6BNE7.js → chunk-R2XBH476.js} +2 -2
  45. package/chunks/{chunk-O6Z4XPOM.js → chunk-RURJYCWY.js} +1 -1
  46. package/chunks/chunk-RVJVM5L4.js +164 -0
  47. package/chunks/{chunk-NX4H6L4M.js → chunk-S2GITRD5.js} +2 -2
  48. package/chunks/{chunk-W5VNCB57.js → chunk-SU4IHQQI.js} +1 -1
  49. package/chunks/{chunk-V2BWXPZP.js → chunk-SZDD77KX.js} +6 -6
  50. package/chunks/{chunk-EJH2TNVH.js → chunk-TVS6WVSK.js} +3 -3
  51. package/chunks/{chunk-LVGZGG63.js → chunk-UJE4WOQS.js} +1 -1
  52. package/chunks/chunk-VU7V2SDW.js +284 -0
  53. package/chunks/chunk-W624J7NF.js +117 -0
  54. package/chunks/{chunk-OLSKXTQZ.js → chunk-WUPN3D37.js} +22 -248
  55. package/chunks/{chunk-HFDSIHTE.js → chunk-X2IPO5JO.js} +202 -30
  56. package/chunks/{chunk-JEYIWMGL.js → chunk-X2ZMSRTP.js} +1 -1
  57. package/chunks/{chunk-F344NYUN.js → chunk-XA2IBHPB.js} +1 -1
  58. package/chunks/{chunk-Y4HJRUFE.js → chunk-YERUDEXT.js} +876 -817
  59. package/chunks/{chunk-AAA4PRWK.js → chunk-YKWARO3T.js} +2 -2
  60. package/chunks/{chunk-P7KDN5PK.js → chunk-YSQWZ67M.js} +14 -14
  61. package/chunks/{chunk-4HGGNBKK.js → chunk-ZM6ANQZJ.js} +2593 -1563
  62. package/chunks/{codex-models-Y457ND6Q.js → codex-models-6XVNFRXZ.js} +7 -7
  63. package/chunks/{commands-PBDAOZKA.js → commands-FRPOFIO4.js} +1603 -6945
  64. package/chunks/dashboard-5HDSNBAU.js +76 -0
  65. package/chunks/{db-TPSI552V.js → db-BXJNWUYJ.js} +3 -3
  66. package/chunks/{deep-review-DKED6EN5.js → deep-review-GSJEBLCG.js} +34 -33
  67. package/chunks/{disclose-LDNKAVRH.js → disclose-OU6Z6GVT.js} +4 -2
  68. package/chunks/{dist-RLPNLRZD.js → dist-7KSYDDSG.js} +33 -1
  69. package/chunks/{dist-7Q5A6TQM.js → dist-RKLQIXDT.js} +18 -2
  70. package/chunks/{dist-4LGRIBOC.js → dist-TQMHMSBZ.js} +99 -64
  71. package/chunks/eval-runner-A2DIGVP7.js +31 -0
  72. package/chunks/{exploit-agent-RMFYNG7H.js → exploit-agent-Y2P4GFIY.js} +1 -1
  73. package/chunks/{exploit-autoclimb-2A2PQI4E.js → exploit-autoclimb-YRZ3TMS2.js} +1 -1
  74. package/chunks/{exploit-climb-DEJ232QN.js → exploit-climb-4LEY4SDW.js} +2 -2
  75. package/chunks/{fix-JGBW7XUN.js → fix-RQSIG75B.js} +7 -7
  76. package/chunks/{harness-CBOLMUHB.js → harness-3NVC3DDY.js} +3 -3
  77. package/chunks/{hunt-scan-MIRMABY4.js → hunt-scan-W246VWJC.js} +16 -16
  78. package/chunks/{kernel-primitive-NAPDMJC7.js → kernel-primitive-T47V3RD3.js} +2 -2
  79. package/chunks/{kernel-vm-runner-PR5OSDQ2.js → kernel-vm-runner-AEL5E3SV.js} +2 -2
  80. package/chunks/local-engine-ZCW4YC6E.js +21 -0
  81. package/chunks/managed-operation-6R2QPPW5.js +60 -0
  82. package/chunks/{memsafety-scan-RPS446CD.js → memsafety-scan-L2Z7E7TE.js} +2 -2
  83. package/chunks/{native-loop-CGOJMNHV.js → native-loop-26X2CHBV.js} +14 -13
  84. package/chunks/orchestrate-OBS37FWQ.js +63 -0
  85. package/chunks/{prepare-YVNENPNL.js → prepare-C3KGMBXT.js} +5 -5
  86. package/chunks/provider-model-discovery-QGUGL3XW.js +277 -0
  87. package/chunks/remote-workflow-runtime-DB52SINR.js +12 -0
  88. package/chunks/{run-VH4OIDKF.js → run-MU3MFL2Z.js} +902 -322
  89. package/chunks/{runtime-4TAJFVF7.js → runtime-AUBLQUOH.js} +2 -2
  90. package/chunks/{runtime-HWL6HG7A.js → runtime-U66JNSAY.js} +7 -7
  91. package/chunks/{scan-stream-HJAZJONE.js → scan-stream-34F3LTPV.js} +3 -2
  92. package/chunks/{scope-Q5PIX2IS.js → scope-HSTG63TQ.js} +2 -2
  93. package/chunks/service-plugins-5B23PWXC.js +64 -0
  94. package/chunks/{session-store-2FEIZGSV.js → session-store-MKAAP3WL.js} +2 -2
  95. package/chunks/{variant-candidates-TX5V6XOT.js → variant-candidates-LG767HWH.js} +7 -7
  96. package/chunks/{web-recon-prepass-6HOUGF7Q.js → web-recon-prepass-NJP6J3E4.js} +5 -5
  97. package/chunks/workflow-runtime-AR627I26.js +178 -0
  98. package/dashboard/assets/{abnfDiagram-VCTEODGH-BuvumFYR.js → abnfDiagram-VCTEODGH-Cq149Jpk.js} +1 -1
  99. package/dashboard/assets/{arc-DZzWDuCG.js → arc-CpP-3TRW.js} +1 -1
  100. package/dashboard/assets/architecture-7GRP2DOG-z5EHYkyH.js +1 -0
  101. package/dashboard/assets/{architectureDiagram-5GKGNRK7-Bw5el_EL.js → architectureDiagram-5GKGNRK7-ewtXpjR_.js} +1 -1
  102. package/dashboard/assets/{blockDiagram-I7D4REHJ-BjVLEApp.js → blockDiagram-I7D4REHJ-CZYkRRDi.js} +1 -1
  103. package/dashboard/assets/{c4Diagram-7LVT6UL2-B9nNzx2J.js → c4Diagram-7LVT6UL2-CV7Iu3_Z.js} +1 -1
  104. package/dashboard/assets/channel-CuYjfiC5.js +1 -0
  105. package/dashboard/assets/{chunk-4HAMMTFA-y72Q95nW.js → chunk-4HAMMTFA-PKCyW4m-.js} +1 -1
  106. package/dashboard/assets/{chunk-75Z2AOVW-BOhrOGMO.js → chunk-75Z2AOVW-C5MlFTc_.js} +1 -1
  107. package/dashboard/assets/{chunk-DU6HZSFF-B0EhAaNb.js → chunk-DU6HZSFF-3M37ulcO.js} +2 -2
  108. package/dashboard/assets/{chunk-F27PBJKO-BR-hiDvM.js → chunk-F27PBJKO-DTAok0qM.js} +1 -1
  109. package/dashboard/assets/{chunk-GMAD6QVW-H15vJYXg.js → chunk-GMAD6QVW-CPsr2F33.js} +1 -1
  110. package/dashboard/assets/{chunk-GVQU2GXP-BRndps0o.js → chunk-GVQU2GXP-C2AXGf9A.js} +1 -1
  111. package/dashboard/assets/{chunk-IMKFNOWR-CIzC_OWx.js → chunk-IMKFNOWR-DMG6yD_O.js} +1 -1
  112. package/dashboard/assets/{chunk-L3NEJ4N5-NR4P1Vko.js → chunk-L3NEJ4N5-BSvwdbXx.js} +1 -1
  113. package/dashboard/assets/{chunk-OSK3NFVY-DtjTDf8S.js → chunk-OSK3NFVY-CfB8V7FU.js} +1 -1
  114. package/dashboard/assets/{chunk-P2QGCYS3-CYT11Qjx.js → chunk-P2QGCYS3-CvmZvq6n.js} +1 -1
  115. package/dashboard/assets/{chunk-POPQ4Y6H-Duj2Ygwu.js → chunk-POPQ4Y6H-D_TvwDxL.js} +1 -1
  116. package/dashboard/assets/{chunk-PWAF6VOD-z4p5Tf_y.js → chunk-PWAF6VOD-Da5GnuOY.js} +1 -1
  117. package/dashboard/assets/{chunk-SHT3W25Y-DYeLYLS3.js → chunk-SHT3W25Y-CcsMJpR-.js} +1 -1
  118. package/dashboard/assets/{chunk-SVP7TREG-BKowxCVI.js → chunk-SVP7TREG-COojjieJ.js} +1 -1
  119. package/dashboard/assets/{chunk-TICWLB2K-GDAwEFlH.js → chunk-TICWLB2K-nBAmJwx6.js} +1 -1
  120. package/dashboard/assets/{chunk-XXDRQBXY-DRD79Mjx.js → chunk-XXDRQBXY-r5HyhWDv.js} +1 -1
  121. package/dashboard/assets/classDiagram-ZZMXUADV-DCuOrWUV.js +1 -0
  122. package/dashboard/assets/classDiagram-v2-VYDZK3BY-DCuOrWUV.js +1 -0
  123. package/dashboard/assets/{common-vnzd7UOF.js → common-C6snVPsk.js} +1 -1
  124. package/dashboard/assets/{cose-bilkent-JH36ORCC-GqCLsRyf.js → cose-bilkent-JH36ORCC-BLGcaZHk.js} +1 -1
  125. package/dashboard/assets/{cynefin-OW5HDTMX-CJN9YwWN.js → cynefin-OW5HDTMX-DbZMK00I.js} +1 -1
  126. package/dashboard/assets/{cynefinDiagram-5FMLGOSQ-DVJHCYQY.js → cynefinDiagram-5FMLGOSQ-xodkuQtW.js} +1 -1
  127. package/dashboard/assets/{dagre-GXQ25YYZ-BMCrrJJR.js → dagre-GXQ25YYZ-CRk9qfSG.js} +1 -1
  128. package/dashboard/assets/{diagram-S7CK7UJ4-CLYDdOEm.js → diagram-S7CK7UJ4-DNoTMlCO.js} +1 -1
  129. package/dashboard/assets/{diagram-UQ7AKVKN-CnPuAZK7.js → diagram-UQ7AKVKN-COccuyew.js} +1 -1
  130. package/dashboard/assets/{diagram-VSXAHHWV-Cr2I2DnG.js → diagram-VSXAHHWV-g6D1tWRb.js} +1 -1
  131. package/dashboard/assets/{diagram-VX7I27RA-_mGW1wpp.js → diagram-VX7I27RA-DhO4eVIC.js} +1 -1
  132. package/dashboard/assets/{diagram-Z3DM3KII-igybB0l9.js → diagram-Z3DM3KII-DeOQFexd.js} +1 -1
  133. package/dashboard/assets/{dist-Bb7_-x5y.js → dist-BQYeOQg3.js} +1 -1
  134. package/dashboard/assets/{ebnfDiagram-PWID7BFC-CVCICf2R.js → ebnfDiagram-PWID7BFC-MtkX2feM.js} +1 -1
  135. package/dashboard/assets/{erDiagram-RLTQ6QDP-CRjnfgxj.js → erDiagram-RLTQ6QDP-DIWSsoYZ.js} +1 -1
  136. package/dashboard/assets/eventmodeling-NTZA5JFV-D_3ez4Gv.js +1 -0
  137. package/dashboard/assets/flowDiagram-HODETNUW-D2boyYEd.js +1 -0
  138. package/dashboard/assets/{ganttDiagram-EL5Y4UJY-DppD7sD7.js → ganttDiagram-EL5Y4UJY-DKggkJe0.js} +1 -1
  139. package/dashboard/assets/{gitGraph-4MIJSDKK-Tw0vNnQc.js → gitGraph-4MIJSDKK-DFOQYwXc.js} +1 -1
  140. package/dashboard/assets/{gitGraphDiagram-WWUBYQGX-Cpf96-z3.js → gitGraphDiagram-WWUBYQGX-r_iR8Qzo.js} +1 -1
  141. package/dashboard/assets/{info-A6RAGUB7-DLyt9arx.js → info-A6RAGUB7-DeednLoB.js} +1 -1
  142. package/dashboard/assets/{infoDiagram-27XIBGKW-B6_piSNS.js → infoDiagram-27XIBGKW-ClQk7UyQ.js} +1 -1
  143. package/dashboard/assets/{ishikawaDiagram-5VMMS53U-DvMO0B0X.js → ishikawaDiagram-5VMMS53U-tR7Vziog.js} +1 -1
  144. package/dashboard/assets/{journeyDiagram-3NMN7TZE-f7ZK98b6.js → journeyDiagram-3NMN7TZE-Cpb9IqKL.js} +1 -1
  145. package/dashboard/assets/{kanban-definition-UXKFOSKX-Dso0nAxL.js → kanban-definition-UXKFOSKX-BzUuKbA9.js} +1 -1
  146. package/dashboard/assets/katex-BdBmVSus.js +257 -0
  147. package/dashboard/assets/{line-VcKaFG0G.js → line-BHY_tSHu.js} +1 -1
  148. package/dashboard/assets/{linear-D7YnpiWh.js → linear-naZZ1pHk.js} +1 -1
  149. package/dashboard/assets/{mermaid-parser.core-DriL2hrV.js → mermaid-parser.core-CPvd4cEx.js} +3 -3
  150. package/dashboard/assets/{mermaid.core-DJWYDh_P.js → mermaid.core-D_QsUPU8.js} +4 -4
  151. package/dashboard/assets/{mindmap-definition-YA3MSWOX-DZsoIeac.js → mindmap-definition-YA3MSWOX-CtfLTPPJ.js} +1 -1
  152. package/dashboard/assets/operations-BwCzhVnT.js +130 -0
  153. package/dashboard/assets/operations-QjKT0Hwi.css +1 -0
  154. package/dashboard/assets/{packet-AYTQ26CC-BQBIXKxk.js → packet-AYTQ26CC-DDQbkT9I.js} +1 -1
  155. package/dashboard/assets/{pegDiagram-XKGWAZYB-B0-lslgW.js → pegDiagram-XKGWAZYB-C1Dclbzj.js} +1 -1
  156. package/dashboard/assets/{pie-WAS4IAKB-DoY6dwQs.js → pie-WAS4IAKB-LpU4ULAs.js} +1 -1
  157. package/dashboard/assets/{pieDiagram-E7YTZNPT-ElmdRjp5.js → pieDiagram-E7YTZNPT-Cd7XwYo5.js} +1 -1
  158. package/dashboard/assets/{quadrantDiagram-AXDQQJYC-Ci1h98Q2.js → quadrantDiagram-AXDQQJYC-CaS-GQ4X.js} +1 -1
  159. package/dashboard/assets/{radar-RG4KPBEZ-DHod2WgB.js → radar-RG4KPBEZ-CcxW3NJm.js} +1 -1
  160. package/dashboard/assets/{railroad-74A4TZTK-90JxB4xV.js → railroad-74A4TZTK-9P5Rl8fP.js} +1 -1
  161. package/dashboard/assets/railroad-abnf-HS5TGJTU-CSfpwjna.js +1 -0
  162. package/dashboard/assets/railroad-ebnf-LZEXJU2U-D6R5qzr-.js +1 -0
  163. package/dashboard/assets/railroad-peg-WCYAUIDC-DKEX7ITG.js +1 -0
  164. package/dashboard/assets/{railroadDiagram-O6MQD6OU-k3190A6L.js → railroadDiagram-O6MQD6OU-BeesTrqn.js} +1 -1
  165. package/dashboard/assets/{requirementDiagram-BXWQKSXE-C3-eR7I5.js → requirementDiagram-BXWQKSXE-IjyK0DhW.js} +1 -1
  166. package/dashboard/assets/{sankeyDiagram-P5KCCOFB-Bc86pi8w.js → sankeyDiagram-P5KCCOFB-DmIluQqo.js} +1 -1
  167. package/dashboard/assets/{sequenceDiagram-WJ2MYXX4-Bv_MvEmz.js → sequenceDiagram-WJ2MYXX4-CUp8ZjTc.js} +1 -1
  168. package/dashboard/assets/{src-D7Dqq5yP.js → src-r61wDjcA.js} +1 -1
  169. package/dashboard/assets/{stateDiagram-D77RDMKH-Bq_GVmeW.js → stateDiagram-D77RDMKH-Dy9TQb8P.js} +1 -1
  170. package/dashboard/assets/stateDiagram-v2-MP3YSRHH-CQb0ZtPr.js +1 -0
  171. package/dashboard/assets/{swimlanes-42K2YHIH-q0iK-e0P.js → swimlanes-42K2YHIH-CZuDV7V5.js} +1 -1
  172. package/dashboard/assets/swimlanesDiagram-VR7AAH4N-BxgWMq8X.js +8 -0
  173. package/dashboard/assets/{timeline-definition-24CTP7MA-CNfF07hM.js → timeline-definition-24CTP7MA-BGdXW-iY.js} +1 -1
  174. package/dashboard/assets/{treeView-Q6P3EWNA-m629ePnS.js → treeView-Q6P3EWNA-DlRrayjM.js} +1 -1
  175. package/dashboard/assets/{treemap-WGGIJYW6-D9Cb2ETv.js → treemap-WGGIJYW6-C6UqLKfI.js} +1 -1
  176. package/dashboard/assets/{vennDiagram-4TSXK5OY-v4dKF-FE.js → vennDiagram-4TSXK5OY-DzKWHJsl.js} +1 -1
  177. package/dashboard/assets/{wardley-WFR3VGLG-DkwH_nRe.js → wardley-WFR3VGLG-thmyHKb0.js} +1 -1
  178. package/dashboard/assets/{wardleyDiagram-VM6X3IG4-3ImohVu4.js → wardleyDiagram-VM6X3IG4-DGsjYmNJ.js} +1 -1
  179. package/dashboard/assets/{xychartDiagram-S5SC5T6Z-QJu3dm7K.js → xychartDiagram-S5SC5T6Z-C7_T_tWt.js} +1 -1
  180. package/dashboard/index.html +3 -3
  181. package/package.json +3 -2
  182. package/worker-assets/demo-target/README.md +15 -0
  183. package/worker-assets/demo-target/include/decoder.h +27 -0
  184. package/worker-assets/demo-target/patched-decoder.c +40 -0
  185. package/worker-assets/demo-target/src/decoder.c +50 -0
  186. package/worker-assets/demo-target/witness-65537x1.bin +0 -0
  187. package/chunks/chunk-3P3XXSIJ.js +0 -463
  188. package/chunks/chunk-EWXOG6D3.js +0 -1695
  189. package/chunks/chunk-FXR3BT2G.js +0 -226
  190. package/chunks/chunk-R35KKJA4.js +0 -90
  191. package/chunks/eval-runner-RZKDOQ2G.js +0 -30
  192. package/chunks/managed-operation-YNQQEA5V.js +0 -59
  193. package/chunks/orchestrate-5NK34H3W.js +0 -62
  194. package/chunks/service-plugins-QYFITODK.js +0 -63
  195. package/chunks/workflow-runtime-ZEEBJFQG.js +0 -64
  196. package/dashboard/assets/architecture-7GRP2DOG-DK9bv1Md.js +0 -1
  197. package/dashboard/assets/channel-Ck17eKdX.js +0 -1
  198. package/dashboard/assets/classDiagram-ZZMXUADV-BaeZA6LE.js +0 -1
  199. package/dashboard/assets/classDiagram-v2-VYDZK3BY-BaeZA6LE.js +0 -1
  200. package/dashboard/assets/eventmodeling-NTZA5JFV-po5oDydv.js +0 -1
  201. package/dashboard/assets/flowDiagram-HODETNUW-TSV9s7q4.js +0 -1
  202. package/dashboard/assets/katex-CXMH3UgJ.js +0 -257
  203. package/dashboard/assets/operations-BIaUSnYv.js +0 -121
  204. package/dashboard/assets/operations-BeCdkT4S.css +0 -1
  205. package/dashboard/assets/railroad-abnf-HS5TGJTU-BkXGl114.js +0 -1
  206. package/dashboard/assets/railroad-ebnf-LZEXJU2U-QVAERn2C.js +0 -1
  207. package/dashboard/assets/railroad-peg-WCYAUIDC-B1-PM01z.js +0 -1
  208. package/dashboard/assets/stateDiagram-v2-MP3YSRHH-z1XRaftz.js +0 -1
  209. package/dashboard/assets/swimlanesDiagram-VR7AAH4N-C9L6XBQj.js +0 -8
  210. package/dashboard/assets/zero-connect-BGDY0PMZ.webp +0 -0
  211. package/dashboard/assets/zero-curious-DovTLOs8.webp +0 -0
  212. package/dashboard/assets/zero-peek-Dzm3MT3X.png +0 -0
  213. package/dashboard/assets/zero-planning-CBeHDrG_.webp +0 -0
@@ -1,54 +1,56 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire as __0CreateRequire } from "node:module";
3
3
  const require = __0CreateRequire(import.meta.url);
4
+ import {
5
+ runLensSynthesisInput,
6
+ watchLensSynthCommand
7
+ } from "./chunk-VU7V2SDW.js";
8
+ import {
9
+ compareFindingRowsByBusinessPriority,
10
+ cycleChoice,
11
+ describeEventPayload,
12
+ describeFindingsFilters,
13
+ findingFromRow,
14
+ findingRowPriority,
15
+ formatDuration,
16
+ isNativeRuntime,
17
+ parseSummary
18
+ } from "./chunk-W624J7NF.js";
4
19
  import {
5
20
  DIALOG_HOST_FOOTER_ROWS,
6
21
  FIX_USAGE,
7
22
  PROVIDER_DEVICE_AUTH,
8
23
  SETTINGS_DIALOG_HOST_ROWS,
9
24
  actionForRow,
10
- activateModelConnectAction,
11
- agentRosterLines,
12
- buildContextWindowIndex,
13
25
  buildDialogRows,
26
+ buildFindingChatPrompt,
14
27
  buildFullModelCatalog,
15
28
  buildMarketItems,
16
29
  buildMarketRows,
17
- buildModelRows,
30
+ buildModelCatalog,
18
31
  buildSettingsRows,
19
- catalogContextKey,
20
32
  clampDialogSelection,
21
33
  clampSelection,
22
34
  clipMarketDetailLines,
23
- clipModelDetailLines,
24
35
  computeDialogPanel,
25
36
  computeDialogScreenLayout,
26
37
  computeKvSplit,
27
38
  computeListWindow,
28
39
  computeMarketLayout,
29
- computeModelDialogLayout,
30
40
  computeSettingsLayout,
31
- configuredProviderLabels,
32
41
  confirmPrompt,
33
- contextWindowFor,
34
42
  createLocalConsoleSession,
35
43
  createPluginService,
36
44
  createPreferredConsoleRuntime,
37
45
  createSessionPluginHostManager,
38
- credentialEnvPatch,
39
- credentialSummary,
40
- cycleChoice,
41
46
  cycleSetting,
42
- describeEventPayload,
43
- describeFindingsFilters,
44
47
  describeFixStatus,
45
- dialogContentWidth,
46
48
  dialogDisplayIndex,
47
49
  dialogRowColumns,
48
50
  dialogWindow,
51
+ discoverConnectionModels,
49
52
  exportChatConversation,
50
53
  filterDialogItems,
51
- findingFromRow,
52
54
  findingSourcePath,
53
55
  firstEnabled,
54
56
  fitHint,
@@ -59,50 +61,29 @@ import {
59
61
  fixInputEligibility,
60
62
  fixPublicationLines,
61
63
  fixResultLines,
62
- formatDuration,
63
- getSymbols,
64
- groupFindings,
65
64
  isFilterKey,
66
65
  isFilterKey2,
67
- isFilterKey3,
68
- isModelConnectAction,
69
- isNativeRuntime,
70
66
  isSettingModified,
71
67
  keyGlyph,
72
- loadAccountStore,
73
68
  loadCatalogModels,
74
- loadCredentials,
69
+ loadFindingFocus,
75
70
  marketDetailLines,
76
71
  marketDialogItems,
77
72
  marketDialogMeta,
78
73
  marketEmptyLines,
79
74
  marketFooterHint,
80
- modelConnectActionItem,
81
- modelConnectDetailLines,
82
- modelDetailLines,
83
- modelDialogCount,
84
- modelDialogHint,
85
- modelDialogTitle,
86
- modelFooterHint,
87
- modelResultCount,
88
- modelTargetLine,
89
75
  moveDialogSelection,
90
76
  moveSelection,
91
77
  paneTitleColumns,
92
- parseSummary,
93
78
  rankDialogItem,
94
- reachableModelCatalog,
95
- redactSecret,
96
79
  reduceWorkerTelemetry,
97
80
  resetAllSettings,
98
81
  resetSetting,
99
82
  resolveContextLimit,
100
- runLensSynthesisInput,
101
83
  runUnified,
102
84
  sanitizeComposerText,
103
85
  sanitizeTuiText,
104
86
  saveAppliedModelPreference,
105
- saveCredentials,
106
87
  scopeModelCatalog,
107
88
  selectConversationContext,
108
89
  settingValue,
@@ -115,22 +96,13 @@ import {
115
96
  stateTag,
116
97
  syncModelCatalog,
117
98
  titleColumns,
118
- watchLensSynthCommand,
119
99
  wrapCells,
120
100
  wrapText
121
- } from "./chunk-A2ADXAC5.js";
101
+ } from "./chunk-2XGBEH53.js";
122
102
  import {
123
103
  buildShareUrl,
124
104
  getRuntimeAvailability
125
- } from "./chunk-KHPOSLCF.js";
126
- import {
127
- buildFindingChatPrompt,
128
- loadFindingFocus
129
- } from "./chunk-FXR3BT2G.js";
130
- import {
131
- consoleExecutionProfile,
132
- loadServicePluginConnections
133
- } from "./chunk-MQJVU2GZ.js";
105
+ } from "./chunk-I43YYHDU.js";
134
106
  import {
135
107
  deleteSession,
136
108
  listSessions,
@@ -138,7 +110,11 @@ import {
138
110
  pruneSessions,
139
111
  relativeAge,
140
112
  saveSession
141
- } from "./chunk-I3OCJ2OA.js";
113
+ } from "./chunk-JWSOUKFF.js";
114
+ import {
115
+ consoleExecutionProfile,
116
+ loadServicePluginConnections
117
+ } from "./chunk-2NBZZFRG.js";
142
118
  import {
143
119
  reportHerdrActivity,
144
120
  reportHerdrCompaction,
@@ -148,25 +124,36 @@ import {
148
124
  reportHerdrSession,
149
125
  reportHerdrSessionClose,
150
126
  reportHerdrTarget,
151
- reportOperatorGate
152
- } from "./chunk-VDOWARMJ.js";
127
+ reportOperatorGate,
128
+ savedConnectionEnvPatch
129
+ } from "./chunk-BPU6M42R.js";
130
+ import {
131
+ SHIMMER_TEXT_INTERVAL_MS,
132
+ UI_ANIMATION_INTERVAL_MS,
133
+ resumeProcessPresentationStreamBridge,
134
+ shimmerText,
135
+ spinnerGlyph,
136
+ suspendProcessPresentationStreamBridge
137
+ } from "./chunk-OOMBOLAF.js";
153
138
  import {
154
139
  createPresentationEmitter,
140
+ presentationEventBus
141
+ } from "./chunk-56UTQKXO.js";
142
+ import {
155
143
  getAnalyticsSetupDraft,
156
144
  getSettings,
157
- presentationEventBus,
145
+ loadAccountStore,
146
+ loadCredentials,
158
147
  previewSetting,
148
+ redactSecret,
159
149
  reloadSettings,
160
150
  resetSettings,
161
- resumeProcessPresentationStreamBridge,
151
+ resolveEngagement,
152
+ saveCredentials,
162
153
  subscribeSettings,
163
- suspendProcessPresentationStreamBridge,
164
154
  updateSetting,
165
155
  useSettings
166
- } from "./chunk-3P3XXSIJ.js";
167
- import {
168
- resolveEngagement
169
- } from "./chunk-R35KKJA4.js";
156
+ } from "./chunk-LMP2T4G2.js";
170
157
  import "./chunk-HLFS6WV2.js";
171
158
  import {
172
159
  KEYBINDINGS,
@@ -197,7 +184,7 @@ import {
197
184
  severityToneFor,
198
185
  submissionBlockedReason,
199
186
  submitFeedback
200
- } from "./chunk-HFDSIHTE.js";
187
+ } from "./chunk-X2IPO5JO.js";
201
188
  import {
202
189
  DEFAULT_REGISTRY_URL,
203
190
  appendStageAction,
@@ -208,41 +195,45 @@ import {
208
195
  markProcessed,
209
196
  normalizeStageAction,
210
197
  normalizeStageEndDetail,
211
- parseImpactAssessment,
212
198
  parseMcpConfig,
213
199
  releaseClaim,
214
200
  releaseStaleClaims
215
- } from "./chunk-4HGGNBKK.js";
216
- import "./chunk-QMICC5O2.js";
201
+ } from "./chunk-ZM6ANQZJ.js";
202
+ import "./chunk-H5QURBBK.js";
203
+ import "./chunk-5NFIY2SJ.js";
204
+ import "./chunk-BOBIAHKA.js";
217
205
  import {
218
206
  getRuntimeMetadata
219
- } from "./chunk-TPUJZ74W.js";
207
+ } from "./chunk-ILRMLA6J.js";
208
+ import "./chunk-GVD6SJGH.js";
220
209
  import "./chunk-QCUFBVIZ.js";
221
- import "./chunk-NX4H6L4M.js";
222
- import "./chunk-62ENS6XO.js";
210
+ import "./chunk-S2GITRD5.js";
211
+ import "./chunk-IIBNQTOK.js";
223
212
  import "./chunk-2WNCI664.js";
224
213
  import "./chunk-23DG5YKS.js";
225
214
  import "./chunk-DQTNI3KY.js";
226
- import "./chunk-XORZUR2H.js";
227
- import "./chunk-LVGZGG63.js";
228
- import "./chunk-3ZNI7F42.js";
229
- import "./chunk-WIYNYNL2.js";
215
+ import "./chunk-3WUPCZGF.js";
216
+ import "./chunk-UJE4WOQS.js";
217
+ import "./chunk-PJU24AKR.js";
218
+ import "./chunk-6XMFCVJS.js";
230
219
  import "./chunk-AZ7L3HFD.js";
231
- import "./chunk-EJH2TNVH.js";
232
- import "./chunk-P7KDN5PK.js";
220
+ import "./chunk-TVS6WVSK.js";
221
+ import "./chunk-YSQWZ67M.js";
233
222
  import {
234
223
  TOOL_DEFINITIONS,
235
224
  agentTaskLabel,
236
225
  getWorkspaceHarnessTrust,
237
226
  renderInboundMessage,
238
227
  sendOperatorMessage
239
- } from "./chunk-EH2WTNY7.js";
228
+ } from "./chunk-5WAHHZBF.js";
229
+ import "./chunk-3LPBJMHB.js";
240
230
  import "./chunk-K2PWUPUI.js";
241
- import "./chunk-JEYIWMGL.js";
242
- import "./chunk-Y4HJRUFE.js";
231
+ import "./chunk-X2ZMSRTP.js";
232
+ import "./chunk-YERUDEXT.js";
243
233
  import "./chunk-UEX7PFSE.js";
244
- import "./chunk-3E54JYS4.js";
245
- import "./chunk-F344NYUN.js";
234
+ import "./chunk-4ROZFLSR.js";
235
+ import "./chunk-BD7WULFS.js";
236
+ import "./chunk-XA2IBHPB.js";
246
237
  import {
247
238
  loadSourceFixProjectInputs,
248
239
  planSourceFixPublication,
@@ -250,58 +241,58 @@ import {
250
241
  resolveSourceFixRepository,
251
242
  runSourceFix,
252
243
  saveSourceFixProjectInputs
253
- } from "./chunk-YYS2H33A.js";
254
- import "./chunk-AAA4PRWK.js";
244
+ } from "./chunk-5ETI27Q3.js";
245
+ import "./chunk-YKWARO3T.js";
255
246
  import "./chunk-SQCBHFWN.js";
256
- import "./chunk-GVD6SJGH.js";
257
247
  import {
258
248
  createRuntime
259
- } from "./chunk-UZUELPFW.js";
249
+ } from "./chunk-K74DRDC5.js";
260
250
  import "./chunk-O6KPVYOI.js";
261
251
  import "./chunk-FHC2B7LN.js";
262
252
  import "./chunk-DKSCN2AB.js";
263
253
  import "./chunk-UFHN6RIU.js";
264
- import "./chunk-T7ZEVY5G.js";
265
- import "./chunk-TO35Y326.js";
254
+ import "./chunk-BMDG6T7D.js";
255
+ import "./chunk-GTED3FSZ.js";
266
256
  import "./chunk-IXT64DV5.js";
267
- import "./chunk-W5VNCB57.js";
268
- import "./chunk-YAEJAZYW.js";
269
- import "./chunk-65H3MRBF.js";
270
- import "./chunk-CP6HANBE.js";
257
+ import "./chunk-SU4IHQQI.js";
271
258
  import "./chunk-NJLKFC66.js";
272
259
  import {
273
260
  CodexCatalogRefreshError,
274
261
  loadCodexModelCatalog
275
- } from "./chunk-K55B4OH4.js";
262
+ } from "./chunk-NBV4I237.js";
276
263
  import {
277
264
  claimDiagnostics
278
- } from "./chunk-BF5FIK7H.js";
279
- import "./chunk-NI6QYQSK.js";
265
+ } from "./chunk-IJ6UPW3H.js";
266
+ import "./chunk-PVJUPIQG.js";
267
+ import {
268
+ eventBus
269
+ } from "./chunk-5PFRE522.js";
280
270
  import "./chunk-RS4MAN3Q.js";
281
271
  import {
282
272
  redactSensitiveHeaders,
283
273
  renderCvssSection,
284
274
  renderPlatformReport
285
- } from "./chunk-UELXHK2Y.js";
286
- import {
287
- eventBus
288
- } from "./chunk-A5QO7N3S.js";
275
+ } from "./chunk-CGBDEST2.js";
289
276
  import {
290
277
  ScopePolicy
291
- } from "./chunk-ITES7BCY.js";
278
+ } from "./chunk-QNRYOJEB.js";
292
279
  import "./chunk-5IBCBQEH.js";
293
280
  import {
294
281
  DEFAULT_AUTONOMY_MODE,
282
+ ImpactAssessmentSchema,
295
283
  MODEL_PRICING,
296
284
  SLASH_COMMANDS,
297
285
  VERSION,
286
+ compareFindingsByBusinessPriority,
298
287
  createPresentationEvent,
299
288
  createTranscriptDocument,
300
289
  filterCommands,
301
290
  findCommand,
291
+ getFindingPriority,
302
292
  homeStateDir,
293
+ isHeuristicImpactAssessment,
303
294
  modelProvider
304
- } from "./chunk-LTEE2JWK.js";
295
+ } from "./chunk-GXXX7AGH.js";
305
296
  import "./chunk-VIT5ALXF.js";
306
297
  import {
307
298
  __commonJS,
@@ -649,6 +640,272 @@ function useMouseSupport() {
649
640
  // packages/cli/src/tui/shell-frame.tsx
650
641
  import { createContext as createContext2, useContext as useContext2, useEffect as useEffect3, useState as useState5 } from "react";
651
642
 
643
+ // packages/cli/src/tui/symbols.ts
644
+ var UNICODE = {
645
+ check: "\u2713",
646
+ cross: "\u2717",
647
+ warning: "\u26A0",
648
+ info: "\u2139",
649
+ running: "\u25B8",
650
+ parked: "\u25CC",
651
+ stopped: "\u25A0",
652
+ queued: "\xB7",
653
+ bulletFilled: "\u25CF",
654
+ bulletHollow: "\u25CB",
655
+ bulletActive: "\u25C9",
656
+ radioOn: "(\u25CF)",
657
+ radioOff: "( )",
658
+ checkboxOn: "[\u2713]",
659
+ checkboxOff: "[ ]",
660
+ rowMarker: "\u203A",
661
+ caretOpen: "\u25BE",
662
+ caretClosed: "\u25B8",
663
+ foldMore: "\u25B8",
664
+ treeBranch: "\u21B3",
665
+ roleGlyph: "\u258C",
666
+ meterFilled: "\u25B0",
667
+ meterEmpty: "\u25B1",
668
+ iconNew: "+",
669
+ iconOps: "\u25A6",
670
+ iconDoctor: "\u271A",
671
+ iconHistory: "\u25F7",
672
+ iconFindings: "\u25C7",
673
+ iconReplay: "\u25B7",
674
+ iconSettings: "*",
675
+ iconHarness: "\u2318",
676
+ iconAgents: "\u2659",
677
+ iconAudits: "\u25A3",
678
+ iconMarket: "\u229E",
679
+ iconConnect: "\u2197",
680
+ iconOnboard: "\u2726",
681
+ iconModels: "\u25C8",
682
+ iconUsage: "\u25A5",
683
+ iconShortcuts: "=",
684
+ fieldFolderOpen: "\u25A6",
685
+ fieldFolder: "\u25A5",
686
+ fieldStatus: "\u25CF",
687
+ fieldTags: "\u25C8",
688
+ fieldInfo: "\u25D0",
689
+ fieldFile: "\u25A4",
690
+ fieldEye: "\u2726",
691
+ fieldGavel: "\u271A",
692
+ fieldDiamond: "\u25C7",
693
+ fieldLink: "\u2197",
694
+ fieldContext: "\u25EB",
695
+ fieldInput: "\u2193",
696
+ fieldOutput: "\u2191",
697
+ fieldReason: "\u2726",
698
+ fieldCost: "$",
699
+ fieldModel: "\u25C8",
700
+ fieldHost: "=",
701
+ fieldCwd: "\u2302",
702
+ fieldBranch: "\u2442",
703
+ fieldDirty: "\xB1",
704
+ fieldTokens: "\u2195",
705
+ fieldPlan: "\u25A3",
706
+ fieldSearch: "\u2315",
707
+ fieldProtected: "\u2298",
708
+ fieldEffort: "\u2726",
709
+ fieldMode: "\u25D0"
710
+ };
711
+ var NERD = {
712
+ check: "\uF00C",
713
+ // nf-fa-check
714
+ cross: "\uF00D",
715
+ // nf-fa-times
716
+ warning: "\uF071",
717
+ // nf-fa-warning
718
+ info: "\uF05A",
719
+ // nf-fa-info-circle
720
+ running: "\uF04B",
721
+ // nf-fa-play
722
+ parked: "\uF04C",
723
+ // nf-fa-pause
724
+ stopped: "\uF04D",
725
+ // nf-fa-stop
726
+ queued: "\uF111",
727
+ // nf-fa-circle
728
+ bulletFilled: "\uF111",
729
+ // nf-fa-circle
730
+ bulletHollow: "\uF10C",
731
+ // nf-fa-circle-o
732
+ bulletActive: "\uF192",
733
+ // nf-fa-dot-circle-o
734
+ radioOn: "(\uF192)",
735
+ radioOff: "( )",
736
+ checkboxOn: "[\uF14A]",
737
+ // nf-fa-check-square
738
+ checkboxOff: "[\uF0C8]",
739
+ // nf-fa-square
740
+ rowMarker: "\uF054",
741
+ // nf-fa-chevron-right
742
+ caretOpen: "\uF078",
743
+ // nf-fa-chevron-down
744
+ caretClosed: "\uF054",
745
+ // nf-fa-chevron-right
746
+ foldMore: "\uF142",
747
+ // nf-fa-ellipsis-v
748
+ treeBranch: "\uF148",
749
+ // nf-fa-level-up (corner)
750
+ roleGlyph: "\u258C",
751
+ meterFilled: "\u25B0",
752
+ meterEmpty: "\u25B1",
753
+ iconNew: "\uF067",
754
+ // nf-fa-plus
755
+ iconOps: "\uF0E4",
756
+ // nf-fa-dashboard
757
+ iconDoctor: "\uF0F0",
758
+ // nf-fa-user-md
759
+ iconHistory: "\uF017",
760
+ // nf-fa-clock-o
761
+ iconFindings: "\uF0EB",
762
+ // nf-fa-lightbulb-o
763
+ iconReplay: "\uF04B",
764
+ // nf-fa-play
765
+ iconSettings: "\uF013",
766
+ // nf-fa-cog
767
+ iconHarness: "\uF085",
768
+ // nf-fa-cogs
769
+ iconAgents: "\uF0C0",
770
+ // nf-fa-users
771
+ iconAudits: "\uF0CA",
772
+ // nf-fa-list-ul
773
+ iconMarket: "\uF07A",
774
+ // nf-fa-shopping-cart
775
+ iconConnect: "\uF0C1",
776
+ // nf-fa-link
777
+ iconOnboard: "\uF005",
778
+ // nf-fa-star
779
+ iconModels: "\uF0E7",
780
+ // nf-fa-bolt
781
+ iconUsage: "\uF080",
782
+ // nf-fa-bar-chart
783
+ iconShortcuts: "\uF11C",
784
+ // nf-fa-keyboard-o
785
+ fieldFolderOpen: "\uF07C",
786
+ // nf-fa-folder-open
787
+ fieldFolder: "\uF07B",
788
+ // nf-fa-folder
789
+ fieldStatus: "\uF111",
790
+ // nf-fa-circle
791
+ fieldTags: "\uF0AE",
792
+ // nf-fa-tasks (tags family)
793
+ fieldInfo: "\uF05A",
794
+ // nf-fa-info-circle
795
+ fieldFile: "\uF15C",
796
+ // nf-fa-file-text
797
+ fieldEye: "\uF06E",
798
+ // nf-fa-eye
799
+ fieldGavel: "\uF0E3",
800
+ // nf-fa-gavel
801
+ fieldDiamond: "\uF0C4",
802
+ // nf-fa-scissors (diamond family)
803
+ fieldLink: "\uF0C1",
804
+ // nf-fa-link
805
+ fieldContext: "\uF0DB",
806
+ // nf-fa-columns
807
+ fieldInput: "\uF063",
808
+ // nf-fa-arrow-down
809
+ fieldOutput: "\uF062",
810
+ // nf-fa-arrow-up
811
+ fieldReason: "\uF0EB",
812
+ // nf-fa-lightbulb-o
813
+ fieldCost: "\uF155",
814
+ // nf-fa-dollar
815
+ fieldModel: "\uF0E7",
816
+ // nf-fa-bolt
817
+ fieldHost: "\uF085",
818
+ // nf-fa-cogs
819
+ fieldCwd: "\uF015",
820
+ // nf-fa-home
821
+ fieldBranch: "\uF126",
822
+ // nf-fa-code-fork
823
+ fieldDirty: "\uF069",
824
+ // nf-fa-asterisk
825
+ fieldTokens: "\uF0EC",
826
+ // nf-fa-exchange
827
+ fieldPlan: "\uF0CA",
828
+ // nf-fa-list-ul
829
+ fieldSearch: "\uF002",
830
+ // nf-fa-search
831
+ fieldProtected: "\uF023",
832
+ // nf-fa-lock
833
+ fieldEffort: "\uF0E7",
834
+ // nf-fa-bolt
835
+ fieldMode: "\uF042"
836
+ // nf-fa-adjust
837
+ };
838
+ var ASCII = {
839
+ check: "+",
840
+ cross: "x",
841
+ warning: "!",
842
+ info: "i",
843
+ running: ">",
844
+ parked: "=",
845
+ stopped: "#",
846
+ queued: ".",
847
+ bulletFilled: "*",
848
+ bulletHollow: "o",
849
+ bulletActive: "@",
850
+ radioOn: "(*)",
851
+ radioOff: "( )",
852
+ checkboxOn: "[x]",
853
+ checkboxOff: "[ ]",
854
+ rowMarker: ">",
855
+ caretOpen: "v",
856
+ caretClosed: ">",
857
+ foldMore: "+",
858
+ treeBranch: "\\",
859
+ roleGlyph: "|",
860
+ meterFilled: "#",
861
+ meterEmpty: "-",
862
+ iconNew: "+",
863
+ iconOps: "#",
864
+ iconDoctor: "+",
865
+ iconHistory: "h",
866
+ iconFindings: "*",
867
+ iconReplay: ">",
868
+ iconSettings: "%",
869
+ iconHarness: "&",
870
+ iconAgents: "&",
871
+ iconAudits: "#",
872
+ iconMarket: "#",
873
+ iconConnect: ">",
874
+ iconOnboard: "*",
875
+ iconModels: "#",
876
+ iconUsage: "#",
877
+ iconShortcuts: "=",
878
+ fieldFolderOpen: "#",
879
+ fieldFolder: "#",
880
+ fieldStatus: "*",
881
+ fieldTags: "#",
882
+ fieldInfo: "i",
883
+ fieldFile: "=",
884
+ fieldEye: "*",
885
+ fieldGavel: "+",
886
+ fieldDiamond: "<",
887
+ fieldLink: ">",
888
+ fieldContext: "#",
889
+ fieldInput: "v",
890
+ fieldOutput: "^",
891
+ fieldReason: "*",
892
+ fieldCost: "$",
893
+ fieldModel: "#",
894
+ fieldHost: "=",
895
+ fieldCwd: "~",
896
+ fieldBranch: "Y",
897
+ fieldDirty: "*",
898
+ fieldTokens: "=",
899
+ fieldPlan: "#",
900
+ fieldSearch: "/",
901
+ fieldProtected: "!",
902
+ fieldEffort: "*",
903
+ fieldMode: "%"
904
+ };
905
+ function getSymbols(preset) {
906
+ return preset === "nerd" ? NERD : preset === "ascii" ? ASCII : UNICODE;
907
+ }
908
+
652
909
  // packages/cli/src/tui/symbol-context.ts
653
910
  var cache = /* @__PURE__ */ new Map();
654
911
  function tableFor(preset) {
@@ -801,16 +1058,16 @@ function allocateColumns({
801
1058
  };
802
1059
  }
803
1060
  function fitCells(value, width, { align = "left", fit, maxEncodedRun } = {}) {
804
- const cells8 = toCells(width);
805
- if (cells8 <= 0) return "";
806
- const text = fitTuiText(value ?? "", cells8, { mode: fit, maxEncodedRun });
807
- if (text.length >= cells8) return text.slice(0, cells8);
808
- if (align === "right") return text.padStart(cells8, " ");
1061
+ const cells9 = toCells(width);
1062
+ if (cells9 <= 0) return "";
1063
+ const text = fitTuiText(value ?? "", cells9, { mode: fit, maxEncodedRun });
1064
+ if (text.length >= cells9) return text.slice(0, cells9);
1065
+ if (align === "right") return text.padStart(cells9, " ");
809
1066
  if (align === "center") {
810
- const left = Math.floor((cells8 - text.length) / 2);
811
- return `${" ".repeat(left)}${text}`.padEnd(cells8, " ");
1067
+ const left = Math.floor((cells9 - text.length) / 2);
1068
+ return `${" ".repeat(left)}${text}`.padEnd(cells9, " ");
812
1069
  }
813
- return text.padEnd(cells8, " ");
1070
+ return text.padEnd(cells9, " ");
814
1071
  }
815
1072
  function Cells({
816
1073
  width,
@@ -823,12 +1080,12 @@ function Cells({
823
1080
  maxEncodedRun,
824
1081
  onMouseDown
825
1082
  }) {
826
- const cells8 = toCells(width);
827
- if (cells8 <= 0) return null;
1083
+ const cells9 = toCells(width);
1084
+ if (cells9 <= 0) return null;
828
1085
  return /* @__PURE__ */ jsx(
829
1086
  "text",
830
1087
  {
831
- width: cells8,
1088
+ width: cells9,
832
1089
  flexShrink: 0,
833
1090
  flexGrow: 0,
834
1091
  wrapMode: "none",
@@ -836,7 +1093,7 @@ function Cells({
836
1093
  bg,
837
1094
  attributes,
838
1095
  onMouseDown,
839
- children: fitCells(children, cells8, { align, fit, maxEncodedRun })
1096
+ children: fitCells(children, cells9, { align, fit, maxEncodedRun })
840
1097
  }
841
1098
  );
842
1099
  }
@@ -1089,7 +1346,7 @@ function dialogTotalRows(items) {
1089
1346
  return count;
1090
1347
  }
1091
1348
  function wrapDialogLines(value, width, fg) {
1092
- const cells8 = Math.max(1, Math.trunc(width));
1349
+ const cells9 = Math.max(1, Math.trunc(width));
1093
1350
  const words = String(value ?? "").split(/\s+/).filter(Boolean);
1094
1351
  const out = [];
1095
1352
  let line4 = "";
@@ -1101,14 +1358,14 @@ function wrapDialogLines(value, width, fg) {
1101
1358
  };
1102
1359
  for (const word of words) {
1103
1360
  let rest = word;
1104
- while (rest.length > cells8) {
1361
+ while (rest.length > cells9) {
1105
1362
  flush();
1106
- out.push({ text: rest.slice(0, cells8), fg });
1107
- rest = rest.slice(cells8);
1363
+ out.push({ text: rest.slice(0, cells9), fg });
1364
+ rest = rest.slice(cells9);
1108
1365
  }
1109
1366
  if (rest.length === 0) continue;
1110
1367
  if (line4.length === 0) line4 = rest;
1111
- else if (line4.length + 1 + rest.length <= cells8) line4 = `${line4} ${rest}`;
1368
+ else if (line4.length + 1 + rest.length <= cells9) line4 = `${line4} ${rest}`;
1112
1369
  else {
1113
1370
  flush();
1114
1371
  line4 = rest;
@@ -1960,76 +2217,6 @@ function frameAt(kind, elapsedMs, opts = {}) {
1960
2217
  return frame;
1961
2218
  }
1962
2219
 
1963
- // packages/cli/src/tui/animations.ts
1964
- var UI_ANIMATION_INTERVAL_MS = 70;
1965
- function clamp(x, lo, hi) {
1966
- if (!Number.isFinite(x)) return lo;
1967
- return x < lo ? lo : x > hi ? hi : x;
1968
- }
1969
- function clamp01(x) {
1970
- return clamp(x, 0, 1);
1971
- }
1972
- function smoothstep(t) {
1973
- const x = clamp01(t);
1974
- return x * x * (3 - 2 * x);
1975
- }
1976
- function safeFrame(frame) {
1977
- if (!Number.isFinite(frame)) return 0;
1978
- const t = Math.trunc(frame);
1979
- return t < 0 ? 0 : t;
1980
- }
1981
- var SPINNER_PERIOD = 8;
1982
- var TOAST_ENTER_FRAMES = 6;
1983
- var TOAST_HOLD_FRAMES = 28;
1984
- var TOAST_EXIT_FRAMES = 6;
1985
- var TOAST_TOTAL_FRAMES = TOAST_ENTER_FRAMES + TOAST_HOLD_FRAMES + TOAST_EXIT_FRAMES;
1986
- var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827"];
1987
- function spinnerFrame(frame, opts = {}) {
1988
- if (opts.reduceMotion) return 0;
1989
- return safeFrame(frame) % SPINNER_PERIOD;
1990
- }
1991
- function spinnerGlyph(frame, opts = {}) {
1992
- return SPINNER_FRAMES[spinnerFrame(frame, opts)] ?? SPINNER_FRAMES[0];
1993
- }
1994
- var SHIMMER_TEXT_TAIL = 5;
1995
- var SHIMMER_TEXT_INTERVAL_MS = 80;
1996
- var SHIMMER_TEXT_REST_GAP = 6;
1997
- function shimmerTail(opts) {
1998
- const t = opts?.tail;
1999
- if (t === void 0 || !Number.isFinite(t)) return SHIMMER_TEXT_TAIL;
2000
- return Math.max(1, Math.trunc(t));
2001
- }
2002
- function shimmerRestGap(opts) {
2003
- const g = opts?.restGap;
2004
- if (g === void 0 || !Number.isFinite(g)) return SHIMMER_TEXT_REST_GAP;
2005
- return Math.max(0, Math.trunc(g));
2006
- }
2007
- function shimmerLength(length) {
2008
- if (!Number.isFinite(length)) return 0;
2009
- const n = Math.trunc(length);
2010
- return n < 0 ? 0 : n;
2011
- }
2012
- function shimmerText(length, frame, opts) {
2013
- const len = shimmerLength(length);
2014
- if (len <= 0) return [];
2015
- const out = new Array(len).fill(0);
2016
- if (opts?.reduceMotion) return out;
2017
- const tail = shimmerTail(opts);
2018
- const rest = shimmerRestGap(opts);
2019
- const period = len + 2 * tail + rest;
2020
- const sweep = len + 2 * tail;
2021
- const idx = (safeFrame(frame) % period + period) % period;
2022
- if (idx >= sweep) return out;
2023
- const head = idx - tail;
2024
- for (let offset = -tail; offset <= tail; offset += 1) {
2025
- const col = head + offset;
2026
- if (col < 0 || col >= len) continue;
2027
- const intensity = 1 - smoothstep(Math.abs(offset) / tail);
2028
- if (intensity > out[col]) out[col] = intensity;
2029
- }
2030
- return out;
2031
- }
2032
-
2033
2220
  // packages/cli/src/tui/chat/shimmer.tsx
2034
2221
  import { jsx as jsx7 } from "@opentui/react/jsx-runtime";
2035
2222
  var GRAPHEMES = new Intl.Segmenter(void 0, { granularity: "grapheme" });
@@ -3353,7 +3540,7 @@ function matchListItem(line4) {
3353
3540
  }
3354
3541
  function splitTableCells(line4) {
3355
3542
  const trimmed = line4.trim();
3356
- const cells8 = [];
3543
+ const cells9 = [];
3357
3544
  let current = "";
3358
3545
  for (let j = 0; j < trimmed.length; j += 1) {
3359
3546
  const ch = trimmed[j];
@@ -3363,24 +3550,24 @@ function splitTableCells(line4) {
3363
3550
  continue;
3364
3551
  }
3365
3552
  if (ch === "|") {
3366
- cells8.push(current);
3553
+ cells9.push(current);
3367
3554
  current = "";
3368
3555
  continue;
3369
3556
  }
3370
3557
  current += ch;
3371
3558
  }
3372
- cells8.push(current);
3373
- if (cells8.length > 1 && cells8[0].trim() === "") cells8.shift();
3374
- if (cells8.length > 1 && cells8[cells8.length - 1].trim() === "") cells8.pop();
3375
- return cells8.map((cell) => cell.trim());
3559
+ cells9.push(current);
3560
+ if (cells9.length > 1 && cells9[0].trim() === "") cells9.shift();
3561
+ if (cells9.length > 1 && cells9[cells9.length - 1].trim() === "") cells9.pop();
3562
+ return cells9.map((cell) => cell.trim());
3376
3563
  }
3377
3564
  function matchTableDelimiter(line4) {
3378
3565
  if (leadingSpaces(line4) > 3) return null;
3379
3566
  if (!line4.includes("-") || !line4.includes("|")) return null;
3380
- const cells8 = splitTableCells(line4);
3381
- if (cells8.length === 0) return null;
3567
+ const cells9 = splitTableCells(line4);
3568
+ if (cells9.length === 0) return null;
3382
3569
  const align = [];
3383
- for (const cell of cells8) {
3570
+ for (const cell of cells9) {
3384
3571
  if (!/^:?-+:?$/.test(cell)) return null;
3385
3572
  const left = cell.startsWith(":");
3386
3573
  const right = cell.endsWith(":");
@@ -3487,8 +3674,8 @@ function parseMarkdownBlocks(source) {
3487
3674
  i += 1;
3488
3675
  }
3489
3676
  const cols = Math.max(header.length, align.length);
3490
- const fit = (cells8) => {
3491
- const out = cells8.slice(0, cols);
3677
+ const fit = (cells9) => {
3678
+ const out = cells9.slice(0, cols);
3492
3679
  while (out.length < cols) out.push("");
3493
3680
  return out;
3494
3681
  };
@@ -3591,7 +3778,7 @@ function wrapBlock(block, width) {
3591
3778
  return { kind: "paragraph", lines: wrapSpans(joinLines(block.lines), width) };
3592
3779
  case "table": {
3593
3780
  const widths = tableColumnWidths(block.header, block.rows, width);
3594
- const clip2 = (cells8) => cells8.map((cell, c) => truncateSpans(cell, widths[c] ?? 1));
3781
+ const clip2 = (cells9) => cells9.map((cell, c) => truncateSpans(cell, widths[c] ?? 1));
3595
3782
  return {
3596
3783
  kind: "table",
3597
3784
  align: block.align,
@@ -4078,8 +4265,8 @@ function previewTranscriptText(source, maxChars = MAX_TRANSCRIPT_PREVIEW_CHARS)
4078
4265
  var MAX_REVIEW_CHARS = 32e3;
4079
4266
  var MAX_REVIEW_LINE_CHARS = 8e3;
4080
4267
  function reviewRule(width) {
4081
- const cells8 = Number.isFinite(width) ? Math.floor(width) : 0;
4082
- return "\u2500".repeat(Math.max(3, Math.min(cells8, 80)));
4268
+ const cells9 = Number.isFinite(width) ? Math.floor(width) : 0;
4269
+ return "\u2500".repeat(Math.max(3, Math.min(cells9, 80)));
4083
4270
  }
4084
4271
  var GUTTER = {
4085
4272
  speaker: "\u258C",
@@ -5082,7 +5269,7 @@ function SessionScreen({ state, onExit, shell, queueUserMessage }) {
5082
5269
  /* @__PURE__ */ jsx13("text", { fg: stage.status === "running" ? theme.PRIMARY : stage.status === "done" ? theme.SUCCESS : stage.status === "error" ? theme.ERROR : theme.MUTED, children: fitTuiText(`${stage.label} \xB7 ${stage.status}`, sidebarTextWidth) }),
5083
5270
  stage.detail ? /* @__PURE__ */ jsx13("text", { fg: theme.TEXT, wrapMode: "word", children: fitTuiText(stage.detail, sidebarTextWidth) }) : stage.status === "pending" ? /* @__PURE__ */ jsx13("text", { fg: theme.MUTED, children: fitTuiText("waiting", sidebarTextWidth) }) : null
5084
5271
  ] }, stage.id)) }) }),
5085
- /* @__PURE__ */ jsx13(PanelSection, { title: "Findings", contentWidth: sidebarTextWidth, tone: totalFindings > 0 ? theme.WARNING : theme.BORDER, children: /* @__PURE__ */ jsx13("box", { flexDirection: "column", minWidth: 0, children: state.stages.flatMap((stage) => stage.findings).length === 0 ? /* @__PURE__ */ jsx13("text", { fg: theme.TEXT, children: fitTuiText("No findings yet.", sidebarTextWidth) }) : state.stages.flatMap((stage) => stage.findings).slice(0, SESSION_MAX_SIDEBAR_FINDINGS).map((finding, index) => /* @__PURE__ */ jsx13("text", { fg: severityToneFor(theme, finding.severity), children: fitTuiText(`${finding.severity} \xB7 ${finding.title}`, sidebarTextWidth) }, `${finding.title}-${index}`)) }) }),
5272
+ /* @__PURE__ */ jsx13(PanelSection, { title: "Findings", contentWidth: sidebarTextWidth, tone: totalFindings > 0 ? theme.WARNING : theme.BORDER, children: /* @__PURE__ */ jsx13("box", { flexDirection: "column", minWidth: 0, children: state.stages.flatMap((stage) => stage.findings).length === 0 ? /* @__PURE__ */ jsx13("text", { fg: theme.TEXT, children: fitTuiText("No findings yet.", sidebarTextWidth) }) : state.stages.flatMap((stage) => stage.findings).sort(compareFindingsByBusinessPriority).slice(0, SESSION_MAX_SIDEBAR_FINDINGS).map((finding, index) => /* @__PURE__ */ jsx13("text", { fg: getFindingPriority(finding).assessed ? theme.TEXT : theme.MUTED, children: fitTuiText(`${getFindingPriority(finding).label} \xB7 ${finding.title} \xB7 technical ${finding.severity}`, sidebarTextWidth) }, `${finding.title}-${index}`)) }) }),
5086
5273
  summary ? /* @__PURE__ */ jsx13(PanelSection, { title: "Report", contentWidth: sidebarTextWidth, tone: summary.critical > 0 || summary.high > 0 ? theme.ERROR : theme.SUCCESS, children: /* @__PURE__ */ jsxs8("box", { flexDirection: "column", minWidth: 0, children: [
5087
5274
  /* @__PURE__ */ jsxs8("box", { flexDirection: "row", width: "100%", minWidth: 0, children: [
5088
5275
  /* @__PURE__ */ jsx13("text", { flexShrink: 0, fg: summary.critical > 0 ? theme.ERROR : theme.TEXT, children: "critical " }),
@@ -5751,7 +5938,7 @@ function OpsScreen({ dbPath, refreshMs, onExit, shell }) {
5751
5938
  let alive = true;
5752
5939
  const refresh = async () => {
5753
5940
  try {
5754
- const { osecDB } = await import("./dist-7Q5A6TQM.js");
5941
+ const { osecDB } = await import("./dist-RKLQIXDT.js");
5755
5942
  const db = new osecDB(dbPath);
5756
5943
  try {
5757
5944
  const scans = db.listScans(12);
@@ -6316,7 +6503,7 @@ function HistoryScreen({ dbPath, limit, onResolve, onExit, shell }) {
6316
6503
  let alive = true;
6317
6504
  const load = async () => {
6318
6505
  try {
6319
- const { osecDB } = await import("./dist-7Q5A6TQM.js");
6506
+ const { osecDB } = await import("./dist-RKLQIXDT.js");
6320
6507
  const db = new osecDB(dbPath);
6321
6508
  try {
6322
6509
  const rows = db.listScans(limit);
@@ -6683,7 +6870,7 @@ function cells(value, fallback = 0) {
6683
6870
  const truncated = Math.trunc(raw);
6684
6871
  return truncated > 0 ? truncated : 0;
6685
6872
  }
6686
- function clamp2(value, low, high) {
6873
+ function clamp(value, low, high) {
6687
6874
  if (high < low) return low;
6688
6875
  return Math.min(Math.max(value, low), high);
6689
6876
  }
@@ -6740,10 +6927,17 @@ function findingCvssLine(finding, injected) {
6740
6927
  return EM_DASH;
6741
6928
  }
6742
6929
  function findingImpactLines(finding) {
6743
- const assessment = finding.impactAssessment ? parseImpactAssessment(JSON.stringify(finding.impactAssessment)) : null;
6744
- if (!assessment) return ["Not assessed."];
6930
+ const parsed = ImpactAssessmentSchema.safeParse(finding.impactAssessment);
6931
+ const priority = getFindingPriority(finding);
6932
+ if (!priority.assessed) return [
6933
+ "Not assessed.",
6934
+ ...parsed.success && isHeuristicImpactAssessment(parsed.data) ? ["Heuristic baseline; business consequences have not been established."] : [],
6935
+ priority.rationale
6936
+ ];
6937
+ if (!parsed.success) return ["Not assessed.", priority.rationale];
6938
+ const assessment = parsed.data;
6745
6939
  return [
6746
- "Model's estimate \u2014 not reproduction proof.",
6940
+ assessment.assessment_source === "model" ? "Model's estimate \u2014 not reproduction proof." : assessment.assessment_source === "provided" ? "Provided assessment \u2014 not reproduction proof." : "Assessment source not recorded \u2014 not reproduction proof.",
6747
6941
  `Business impact: ${assessment.business_impact}`,
6748
6942
  `Reachability: ${assessment.reachability_tier}`,
6749
6943
  `Blast radius: ${assessment.blast_radius}`,
@@ -6785,6 +6979,13 @@ function buildFindingRows(finding, innerWidth, options = {}) {
6785
6979
  const icon = findingRowIcons(options.symbols ?? DEFAULT_SYMBOLS2);
6786
6980
  const rows = [];
6787
6981
  pushWrapped(rows, findingText(finding.title || EM_DASH), width, "title");
6982
+ const priority = getFindingPriority(finding);
6983
+ rows.push({
6984
+ kind: "kv",
6985
+ label: `${icon.status} Business priority`,
6986
+ value: priority.label,
6987
+ tone: priority.label === "Urgent" || priority.label === "High" ? "error" : priority.label === "Moderate" ? "warn" : "muted"
6988
+ });
6788
6989
  rows.push({
6789
6990
  kind: "kv",
6790
6991
  label: `${icon.status} Severity`,
@@ -6810,7 +7011,7 @@ function buildFindingRows(finding, innerWidth, options = {}) {
6810
7011
  rows.push({
6811
7012
  kind: "kv",
6812
7013
  label: `${icon.confid} Confidence`,
6813
- value: typeof finding.confidence === "number" && Number.isFinite(finding.confidence) ? `${Math.round(clamp2(finding.confidence, 0, 1) * 100)}%` : EM_DASH,
7014
+ value: typeof finding.confidence === "number" && Number.isFinite(finding.confidence) ? `${Math.round(clamp(finding.confidence, 0, 1) * 100)}%` : EM_DASH,
6814
7015
  tone: "text"
6815
7016
  });
6816
7017
  pushWrapped(rows, `${icon.location} Location: ${findingLocation(finding) ?? EM_DASH}`, width, "text");
@@ -6928,7 +7129,7 @@ function computeScrollWindow({ total, offset, visible }) {
6928
7129
  return { start: 0, end: 0, count: 0, total: rowCount, hasAbove: rowCount > 0, hasBelow: false };
6929
7130
  }
6930
7131
  const maxStart = Math.max(0, rowCount - capacity);
6931
- const start = clamp2(cells(offset), 0, maxStart);
7132
+ const start = clamp(cells(offset), 0, maxStart);
6932
7133
  const end = Math.min(rowCount, start + capacity);
6933
7134
  return {
6934
7135
  start,
@@ -7051,20 +7252,16 @@ function findingDetailFooterHint({
7051
7252
 
7052
7253
  // packages/cli/src/tui/findings-screen.tsx
7053
7254
  import { jsx as jsx19, jsxs as jsxs13 } from "@opentui/react/jsx-runtime";
7054
- var FINDING_SEVERITY_ORDER = ["critical", "high", "medium", "low", "info"];
7055
- function findingSeverityRank(severity) {
7056
- const index = FINDING_SEVERITY_ORDER.indexOf(String(severity).toLowerCase());
7057
- return index < 0 ? FINDING_SEVERITY_ORDER.length : index;
7058
- }
7059
- function findingSeverityHeading(severity) {
7060
- const value = String(severity).trim();
7061
- return value.length === 0 ? "unrated" : value.toUpperCase();
7062
- }
7063
7255
  function FindingsScreen({ options, onExit, shell, onSourceFix }) {
7064
7256
  const theme = useTheme();
7257
+ const priorityTone = (row) => {
7258
+ const priority = findingRowPriority(row);
7259
+ return priority.assessed ? severityToneFor(theme, { Urgent: "critical", High: "high", Moderate: "medium", Low: "low" }[priority.label]) : theme.MUTED;
7260
+ };
7065
7261
  const { mouseSupport } = useSettings();
7066
7262
  const contextMenu = useContextMenu();
7067
7263
  const [rows, setRows] = useState15([]);
7264
+ const [families, setFamilies] = useState15([]);
7068
7265
  const [error, setError] = useState15(null);
7069
7266
  const [index, setIndex] = useState15(0);
7070
7267
  const [reloadNonce, setReloadNonce] = useState15(0);
@@ -7093,19 +7290,28 @@ function FindingsScreen({ options, onExit, shell, onSourceFix }) {
7093
7290
  let alive = true;
7094
7291
  const load = async () => {
7095
7292
  try {
7096
- const { osecDB } = await import("./dist-7Q5A6TQM.js");
7293
+ const { osecDB } = await import("./dist-RKLQIXDT.js");
7097
7294
  const db = new osecDB(options.dbPath);
7098
7295
  try {
7099
- const findings = db.listFindings({
7296
+ const filters = {
7100
7297
  scanId: options.scan,
7101
7298
  severity: options.severity,
7102
7299
  category: options.category,
7103
7300
  status: options.status,
7104
7301
  triageStatus: options.triage,
7105
- limit: options.all ? options.limit : 1e3
7106
- });
7302
+ limit: Math.min(options.limit, 5e3)
7303
+ };
7304
+ const groups2 = options.all ? [] : db.listFindingFamiliesByBusinessPriority(filters);
7305
+ const findings = options.all ? db.listFindingsByBusinessPriority(filters) : groups2.map((group) => group.latest);
7107
7306
  if (!alive) return;
7108
7307
  setRows(findings);
7308
+ setFamilies(groups2.map((group) => ({
7309
+ fingerprint: group.key,
7310
+ latest: group.latest,
7311
+ count: group.count,
7312
+ scans: group.scanCount
7313
+ })));
7314
+ if (options.limit > 5e3) setNotice("Showing the top 5000 findings by business priority.");
7109
7315
  applyIndex(0);
7110
7316
  setError(null);
7111
7317
  } finally {
@@ -7121,7 +7327,7 @@ function FindingsScreen({ options, onExit, shell, onSourceFix }) {
7121
7327
  alive = false;
7122
7328
  };
7123
7329
  }, [options, reloadNonce]);
7124
- const groups = useMemo10(() => groupFindings(rows).slice(0, options.limit), [rows, options.limit]);
7330
+ const groups = families;
7125
7331
  const items = options.all ? rows.slice(0, options.limit) : groups;
7126
7332
  const itemCount = items.length;
7127
7333
  const findingsItems = useMemo10(() => {
@@ -7130,12 +7336,12 @@ function FindingsScreen({ options, onExit, shell, onSourceFix }) {
7130
7336
  if (visible.length === 0) {
7131
7337
  return [{ id: "finding:none", label: "No findings found.", category: "Findings", disabled: true }];
7132
7338
  }
7133
- return [...visible].sort((a, b) => findingSeverityRank(a.severity) - findingSeverityRank(b.severity)).map((row) => ({
7339
+ return [...visible].sort(compareFindingRowsByBusinessPriority).map((row) => ({
7134
7340
  id: `row:${row.id}`,
7135
7341
  label: row.title,
7136
- description: `${row.category} \xB7 ${row.status}${row.triageStatus && row.triageStatus !== "new" ? ` \xB7 ${row.triageStatus}` : ""}`,
7137
- category: findingSeverityHeading(row.severity),
7138
- tone: severityToneFor(theme, row.severity),
7342
+ description: `Technical severity: ${row.severity} \xB7 ${row.category} \xB7 ${row.status}${row.triageStatus && row.triageStatus !== "new" ? ` \xB7 ${row.triageStatus}` : ""}`,
7343
+ category: findingRowPriority(row).label,
7344
+ tone: priorityTone(row),
7139
7345
  // The gutter dot marks a family whose triage decision is in effect;
7140
7346
  // an untriaged row carries none.
7141
7347
  current: (row.triageStatus ?? "new") !== "new"
@@ -7144,13 +7350,13 @@ function FindingsScreen({ options, onExit, shell, onSourceFix }) {
7144
7350
  if (groups.length === 0) {
7145
7351
  return [{ id: "finding:none", label: "No findings found.", category: "Findings", disabled: true }];
7146
7352
  }
7147
- return [...groups].sort((a, b) => findingSeverityRank(a.latest.severity) - findingSeverityRank(b.latest.severity)).map((group) => ({
7353
+ return [...groups].sort((a, b) => compareFindingRowsByBusinessPriority(a.latest, b.latest)).map((group) => ({
7148
7354
  id: `group:${group.fingerprint}`,
7149
7355
  label: group.latest.title,
7150
- description: `${group.latest.category} \xB7 ${group.latest.status}${group.latest.triageStatus && group.latest.triageStatus !== "new" ? ` \xB7 ${group.latest.triageStatus}` : ""}`,
7356
+ description: `Technical severity: ${group.latest.severity} \xB7 ${group.latest.category} \xB7 ${group.latest.status}${group.latest.triageStatus && group.latest.triageStatus !== "new" ? ` \xB7 ${group.latest.triageStatus}` : ""}`,
7151
7357
  meta: group.count > 1 ? `${group.count}\xD7` : "",
7152
- category: findingSeverityHeading(group.latest.severity),
7153
- tone: severityToneFor(theme, group.latest.severity),
7358
+ category: findingRowPriority(group.latest).label,
7359
+ tone: priorityTone(group.latest),
7154
7360
  current: (group.latest.triageStatus ?? "new") !== "new"
7155
7361
  }));
7156
7362
  }, [options.all, options.limit, rows, groups, theme]);
@@ -7267,7 +7473,7 @@ function FindingsScreen({ options, onExit, shell, onSourceFix }) {
7267
7473
  setError(null);
7268
7474
  setNotice(`Marking ${triageStatus}\u2026`);
7269
7475
  try {
7270
- const { osecDB } = await import("./dist-7Q5A6TQM.js");
7476
+ const { osecDB } = await import("./dist-RKLQIXDT.js");
7271
7477
  const db = new osecDB(options.dbPath);
7272
7478
  try {
7273
7479
  db.updateFindingTriageByFingerprint(selectedRow2.fingerprint, triageStatus);
@@ -7304,7 +7510,8 @@ function FindingsScreen({ options, onExit, shell, onSourceFix }) {
7304
7510
  const copyFinding = (row) => {
7305
7511
  const text = [
7306
7512
  row.title,
7307
- `${row.severity} \xB7 ${row.status} \xB7 ${row.triageStatus ?? "new"}`,
7513
+ `Business priority: ${findingRowPriority(row).label}`,
7514
+ `Technical severity: ${row.severity} \xB7 ${row.status} \xB7 ${row.triageStatus ?? "new"}`,
7308
7515
  "",
7309
7516
  row.description,
7310
7517
  "",
@@ -7430,12 +7637,13 @@ function FindingsScreen({ options, onExit, shell, onSourceFix }) {
7430
7637
  const push2 = (value, fg) => {
7431
7638
  lines.push(...wrapDialogLines(sanitizeTuiText(value), inner, fg));
7432
7639
  };
7433
- lines.push({ text: options.all ? "FINDING" : "FAMILY", fg: row ? severityToneFor(theme, row.severity) : theme.PRIMARY });
7640
+ lines.push({ text: options.all ? "FINDING" : "FAMILY", fg: theme.PRIMARY });
7434
7641
  if (!row) {
7435
7642
  push2("No finding selected", theme.MUTED);
7436
7643
  } else {
7437
7644
  push2(row.title, theme.TEXT);
7438
- push2(`${row.severity} \xB7 ${row.status} \xB7 ${row.triageStatus ?? "new"}`, severityToneFor(theme, row.severity));
7645
+ push2(`Business priority: ${findingRowPriority(row).label}`, theme.PRIMARY);
7646
+ push2(`Technical severity: ${row.severity} \xB7 ${row.status} \xB7 ${row.triageStatus ?? "new"}`, theme.MUTED);
7439
7647
  if (group) push2(`seen ${group.count}\xD7 in ${group.scans} scan${group.scans === 1 ? "" : "s"}`, theme.MUTED);
7440
7648
  push2(`id ${row.id}`, theme.MUTED);
7441
7649
  if (row.triageNote) push2(row.triageNote, theme.ACCENT);
@@ -7566,7 +7774,7 @@ function ReplayScreen({ dbPath, scanId, onExit, shell }) {
7566
7774
  let alive = true;
7567
7775
  const load = async () => {
7568
7776
  try {
7569
- const { osecDB } = await import("./dist-7Q5A6TQM.js");
7777
+ const { osecDB } = await import("./dist-RKLQIXDT.js");
7570
7778
  const db = new osecDB(dbPath);
7571
7779
  try {
7572
7780
  let selected = scanId ? db.getScan(scanId) : void 0;
@@ -9651,6 +9859,9 @@ function connectionRecoveryForError(error) {
9651
9859
  detail
9652
9860
  };
9653
9861
  }
9862
+ if (/\bcline(?:pass)?\b|cline_api_key/i.test(detail)) {
9863
+ return { providerId: "cline", title: "Cline credentials need attention", detail };
9864
+ }
9654
9865
  if (/anthropic|claude/i.test(detail)) {
9655
9866
  return {
9656
9867
  providerId: "anthropic",
@@ -11000,10 +11211,10 @@ function progressOf(frame, count) {
11000
11211
  if (count <= 1) return 1;
11001
11212
  return frame / (count - 1);
11002
11213
  }
11003
- function clamp012(x) {
11214
+ function clamp01(x) {
11004
11215
  return x < 0 ? 0 : x > 1 ? 1 : x;
11005
11216
  }
11006
- function smoothstep2(t) {
11217
+ function smoothstep(t) {
11007
11218
  if (t <= 0) return 0;
11008
11219
  if (t >= 1) return 1;
11009
11220
  return t * t * (3 - 2 * t);
@@ -11031,7 +11242,7 @@ function rgbHex(r, g, b) {
11031
11242
  return `#${channelHex(r)}${channelHex(g)}${channelHex(b)}`;
11032
11243
  }
11033
11244
  function greyHex(l) {
11034
- const v = clamp012(l) * 255;
11245
+ const v = clamp01(l) * 255;
11035
11246
  return rgbHex(v, v, v);
11036
11247
  }
11037
11248
  function hslToHex(h, s, l) {
@@ -11118,7 +11329,7 @@ function fadeFrame(grid, frame, width) {
11118
11329
  const cy = (rows - 1) / 2;
11119
11330
  const maxDist = Math.hypot(Math.max(cx, width - 1 - cx), Math.max(cy, rows - 1 - cy)) || 1;
11120
11331
  const SPREAD = 0.6;
11121
- const progress = smoothstep2(progressOf(frame, FRAME_COUNTS.fade));
11332
+ const progress = smoothstep(progressOf(frame, FRAME_COUNTS.fade));
11122
11333
  for (let r = 0; r < rows; r += 1) {
11123
11334
  for (let c = 0; c < width; c += 1) {
11124
11335
  const ch = out[r][c].ch;
@@ -11127,10 +11338,10 @@ function fadeFrame(grid, frame, width) {
11127
11338
  const local = progress * (1 + SPREAD) - dist * SPREAD;
11128
11339
  let tone;
11129
11340
  if (local < 1 / 3 - EPS) {
11130
- const t = clamp012(local / (1 / 3));
11341
+ const t = clamp01(local / (1 / 3));
11131
11342
  tone = hslToHex(0, 0.72, 0.14 + t * 0.24);
11132
11343
  } else if (local < 2 / 3 - EPS) {
11133
- const t = clamp012((local - 1 / 3) / (1 / 3));
11344
+ const t = clamp01((local - 1 / 3) / (1 / 3));
11134
11345
  tone = hslToHex(4, 0.78, 0.42 + t * 0.2);
11135
11346
  } else {
11136
11347
  tone = finalTone(ch);
@@ -11150,7 +11361,7 @@ function typeinFrame(grid, frame, width) {
11150
11361
  }
11151
11362
  const total = order.length;
11152
11363
  if (total === 0) return out;
11153
- const progress = smoothstep2(progressOf(frame, FRAME_COUNTS.typein));
11364
+ const progress = smoothstep(progressOf(frame, FRAME_COUNTS.typein));
11154
11365
  const revealed = Math.round(progress * total);
11155
11366
  const GLOW = progress < 1 - EPS ? 3 : 0;
11156
11367
  for (let i = 0; i < revealed; i += 1) {
@@ -11164,7 +11375,7 @@ function typeinFrame(grid, frame, width) {
11164
11375
  function sweepFrame(grid, frame, width) {
11165
11376
  const out = blankFrame(grid, width);
11166
11377
  const BAR = 2;
11167
- const lead = smoothstep2(progressOf(frame, FRAME_COUNTS.sweep)) * (width + BAR);
11378
+ const lead = smoothstep(progressOf(frame, FRAME_COUNTS.sweep)) * (width + BAR);
11168
11379
  for (let r = 0; r < grid.length; r += 1) {
11169
11380
  for (let c = 0; c < width; c += 1) {
11170
11381
  const ch = out[r][c].ch;
@@ -11180,7 +11391,7 @@ function sweepFrame(grid, frame, width) {
11180
11391
  }
11181
11392
  function glitchFrame(grid, frame, width) {
11182
11393
  const out = blankFrame(grid, width);
11183
- const progress = smoothstep2(progressOf(frame, FRAME_COUNTS.glitch));
11394
+ const progress = smoothstep(progressOf(frame, FRAME_COUNTS.glitch));
11184
11395
  for (let r = 0; r < grid.length; r += 1) {
11185
11396
  for (let c = 0; c < width; c += 1) {
11186
11397
  const ch = out[r][c].ch;
@@ -11201,12 +11412,12 @@ function glitchFrame(grid, frame, width) {
11201
11412
  function matrixFrame(grid, frame, width) {
11202
11413
  const out = blankFrame(grid, width);
11203
11414
  const rows = grid.length;
11204
- const progress = smoothstep2(progressOf(frame, FRAME_COUNTS.matrix));
11415
+ const progress = smoothstep(progressOf(frame, FRAME_COUNTS.matrix));
11205
11416
  const TRAIL = MATRIX_REDS.length - 1;
11206
11417
  const DELAY = 0.55;
11207
11418
  for (let c = 0; c < width; c += 1) {
11208
11419
  const delay = hash3(c, 0, 7) % 1e3 / 1e3 * DELAY;
11209
- const cp = clamp012(progress * (1 + DELAY) - delay);
11420
+ const cp = clamp01(progress * (1 + DELAY) - delay);
11210
11421
  const front = cp * (rows + TRAIL);
11211
11422
  for (let r = 0; r < rows; r += 1) {
11212
11423
  const ch = out[r][c].ch;
@@ -11224,7 +11435,7 @@ function matrixFrame(grid, frame, width) {
11224
11435
  function waveFrame(grid, frame, width) {
11225
11436
  const out = blankFrame(grid, width);
11226
11437
  const rows = grid.length;
11227
- const progress = smoothstep2(progressOf(frame, FRAME_COUNTS.wave));
11438
+ const progress = smoothstep(progressOf(frame, FRAME_COUNTS.wave));
11228
11439
  const AMP = 2.2;
11229
11440
  const CREST = WAVE_REDS.length;
11230
11441
  const K = 2 * Math.PI / Math.max(1, rows);
@@ -11246,7 +11457,7 @@ function waveFrame(grid, frame, width) {
11246
11457
  }
11247
11458
  function neonFrame(grid, frame, width) {
11248
11459
  const out = blankFrame(grid, width);
11249
- const progress = smoothstep2(progressOf(frame, FRAME_COUNTS.neon));
11460
+ const progress = smoothstep(progressOf(frame, FRAME_COUNTS.neon));
11250
11461
  for (let r = 0; r < grid.length; r += 1) {
11251
11462
  for (let c = 0; c < width; c += 1) {
11252
11463
  const ch = out[r][c].ch;
@@ -11693,14 +11904,14 @@ var DEFAULT_TOAST_ENVELOPE = {
11693
11904
  holdMs: 1500,
11694
11905
  exitMs: 180
11695
11906
  };
11696
- function clamp013(t) {
11907
+ function clamp012(t) {
11697
11908
  if (!Number.isFinite(t)) return 0;
11698
11909
  if (t <= 0) return 0;
11699
11910
  if (t >= 1) return 1;
11700
11911
  return t;
11701
11912
  }
11702
11913
  var smoothstepRamp = (t) => {
11703
- const x = clamp013(t);
11914
+ const x = clamp012(t);
11704
11915
  return x * x * (3 - 2 * x);
11705
11916
  };
11706
11917
  var HIDDEN_FRAME = {
@@ -12083,11 +12294,11 @@ function formatMessageAge(ts, now) {
12083
12294
  function boundBodyLines(body, width, options = {}) {
12084
12295
  const cap = options.expanded ? options.expandedLines ?? BODY_LINES_EXPANDED : options.collapsedLines ?? BODY_LINES_COLLAPSED;
12085
12296
  const limit = Math.max(1, Math.trunc(cap));
12086
- const cells8 = Math.max(1, Math.trunc(Number.isFinite(width) ? width : 0));
12297
+ const cells9 = Math.max(1, Math.trunc(Number.isFinite(width) ? width : 0));
12087
12298
  const wrapped = [];
12088
12299
  for (const paragraph2 of body.split("\n")) {
12089
12300
  if (!paragraph2.trim()) continue;
12090
- for (const line4 of wrapText(paragraph2, cells8)) {
12301
+ for (const line4 of wrapText(paragraph2, cells9)) {
12091
12302
  if (line4.trim()) wrapped.push(line4);
12092
12303
  }
12093
12304
  }
@@ -12776,9 +12987,9 @@ function renderMarkdownBlocks(blocks, key, theme, tone) {
12776
12987
  if (block.kind === "table") {
12777
12988
  const { widths } = block;
12778
12989
  const rule = (lc, mc, rc) => lc + widths.map((w) => "\u2500".repeat(Math.max(1, w) + 2)).join(mc) + rc;
12779
- const renderRow = (cells8, rowKey, header) => /* @__PURE__ */ jsxs18("box", { flexDirection: "row", flexShrink: 0, minWidth: 0, children: [
12990
+ const renderRow = (cells9, rowKey, header) => /* @__PURE__ */ jsxs18("box", { flexDirection: "row", flexShrink: 0, minWidth: 0, children: [
12780
12991
  /* @__PURE__ */ jsx24("text", { flexShrink: 0, fg: BORDER, children: "\u2502 " }),
12781
- cells8.map((cell, c) => {
12992
+ cells9.map((cell, c) => {
12782
12993
  const w = widths[c] ?? 1;
12783
12994
  const disp = cell.reduce((n, s) => n + Array.from(s.text).length, 0);
12784
12995
  const pad = Math.max(0, w - disp);
@@ -13314,13 +13525,13 @@ var TODO_STRIKE_REVEAL_MS = 640;
13314
13525
  var TODO_STRIKE_TOTAL_MS = TODO_STRIKE_HOLD_MS + TODO_STRIKE_REVEAL_MS;
13315
13526
  var TODO_CLEAR_DELAY_MS = 6e3;
13316
13527
  var TODO_STRIKE_FRAME_MS = 60;
13317
- function clamp014(value) {
13528
+ function clamp013(value) {
13318
13529
  return value < 0 ? 0 : value > 1 ? 1 : value;
13319
13530
  }
13320
13531
  function strikeReveal(elapsed, holdMs, revealMs) {
13321
13532
  if (elapsed <= holdMs) return 0;
13322
13533
  if (revealMs <= 0) return 1;
13323
- return clamp014((elapsed - holdMs) / revealMs);
13534
+ return clamp013((elapsed - holdMs) / revealMs);
13324
13535
  }
13325
13536
  function selectEphemeralTodos(todos, options) {
13326
13537
  const { now, completedAt } = options;
@@ -14705,13 +14916,13 @@ function renderComposerRow(line4, textColor, chipColor) {
14705
14916
  if (last < line4.length) parts.push(/* @__PURE__ */ jsx29("span", { fg: textColor, children: line4.slice(last) }, key++));
14706
14917
  return parts;
14707
14918
  }
14708
- function truncateGhostText(text, cells8) {
14709
- if (cells8 <= 0 || text.length === 0) return "";
14919
+ function truncateGhostText(text, cells9) {
14920
+ if (cells9 <= 0 || text.length === 0) return "";
14710
14921
  let out = "";
14711
14922
  let used = 0;
14712
14923
  for (const { segment } of GRAPHEMES3.segment(text)) {
14713
14924
  const w = stringWidth(segment);
14714
- if (used + w > cells8) break;
14925
+ if (used + w > cells9) break;
14715
14926
  out += segment;
14716
14927
  used += w;
14717
14928
  }
@@ -14745,10 +14956,10 @@ function wrapComposerInput(text, width) {
14745
14956
  continue;
14746
14957
  }
14747
14958
  for (const { segment } of GRAPHEMES3.segment(tok)) {
14748
- const cells8 = stringWidth(segment);
14749
- if (rowW + cells8 > w && row) pushRow();
14959
+ const cells9 = stringWidth(segment);
14960
+ if (rowW + cells9 > w && row) pushRow();
14750
14961
  row += segment;
14751
- rowW += cells8;
14962
+ rowW += cells9;
14752
14963
  }
14753
14964
  }
14754
14965
  pushRow();
@@ -14919,13 +15130,13 @@ function wrapWorkText(value, width, maxLines) {
14919
15130
  }
14920
15131
  const lastLine = lines.length + 1 === maxLines;
14921
15132
  const limit = lastLine ? width - 1 : width;
14922
- let cells8 = 0;
15133
+ let cells9 = 0;
14923
15134
  let end = 0;
14924
15135
  let breakAt = 0;
14925
15136
  for (const { segment, index } of workTextSegments.segment(rest)) {
14926
15137
  const segmentWidth = stringWidth(segment);
14927
- if (cells8 + segmentWidth > limit) break;
14928
- cells8 += segmentWidth;
15138
+ if (cells9 + segmentWidth > limit) break;
15139
+ cells9 += segmentWidth;
14929
15140
  end = index + segment.length;
14930
15141
  if (segment === " ") breakAt = index;
14931
15142
  }
@@ -15288,7 +15499,7 @@ function cells3(value, fallback = 0) {
15288
15499
  const truncated = Math.trunc(raw);
15289
15500
  return truncated > 0 ? truncated : 0;
15290
15501
  }
15291
- function clamp3(value, low, high) {
15502
+ function clamp2(value, low, high) {
15292
15503
  if (high < low) return low;
15293
15504
  return Math.min(Math.max(value, low), high);
15294
15505
  }
@@ -15410,7 +15621,7 @@ function commsFleetStatLine(row, now) {
15410
15621
  function clampFleetSelection(count, current) {
15411
15622
  const total = cells3(count);
15412
15623
  if (total === 0) return -1;
15413
- return clamp3(Math.trunc(Number.isFinite(current) ? current : 0), 0, total - 1);
15624
+ return clamp2(Math.trunc(Number.isFinite(current) ? current : 0), 0, total - 1);
15414
15625
  }
15415
15626
  function moveFleetSelection(count, current, delta) {
15416
15627
  const total = cells3(count);
@@ -17055,7 +17266,7 @@ ${preview.warnings.join("\n")}` : "") + "\n\n/feedback send to submit \xB7 /feed
17055
17266
  const buildSession = useCallback4(async (opts = {}) => {
17056
17267
  if (closingRef.current || stoppingAuditRef.current) throw new Error("This audit is stopping.");
17057
17268
  const buildEpoch = ++sessionBuildEpoch.current;
17058
- const env = { ...process.env, ...credentialEnvPatch(loadCredentials(), process.env) };
17269
+ const env = { ...process.env, ...savedConnectionEnvPatch(process.env) };
17059
17270
  const { runtime, explicitChoice } = await createPreferredConsoleRuntime({
17060
17271
  model: (opts.providerId !== void 0 ? opts.model : opts.model ?? options?.model) || void 0,
17061
17272
  provider: opts.providerId ?? options?.providerId,
@@ -17251,7 +17462,7 @@ ${preview.warnings.join("\n")}` : "") + "\n\n/feedback send to submit \xB7 /feed
17251
17462
  const applyRuntimeSelection = useCallback4((sel) => {
17252
17463
  const runtime = runtimeRef.current;
17253
17464
  if (!runtime) return;
17254
- const env = { ...process.env, ...credentialEnvPatch(loadCredentials(), process.env) };
17465
+ const env = { ...process.env, ...savedConnectionEnvPatch(process.env) };
17255
17466
  const currentProvider = runtime.getConfigurationDiagnostics().provider;
17256
17467
  let targetProvider = sel.providerId;
17257
17468
  if (targetProvider === void 0 && sel.model !== void 0) {
@@ -18070,7 +18281,13 @@ ${preview.warnings.join("\n")}` : "") + "\n\n/feedback send to submit \xB7 /feed
18070
18281
  `test command ${testCommand}`,
18071
18282
  "Working on isolated copies; your checkout is untouched. /fix cancel stops it."
18072
18283
  ]);
18073
- const runtime = createRuntime({ type: "api", timeout: 6e5, model: modelId ?? void 0, provider: options?.providerId });
18284
+ const runtime = createRuntime({
18285
+ type: "api",
18286
+ timeout: 6e5,
18287
+ model: modelId ?? void 0,
18288
+ provider: options?.providerId,
18289
+ env: Object.fromEntries(Object.entries({ ...process.env, ...savedConnectionEnvPatch(process.env) }).filter((entry) => entry[1] !== void 0))
18290
+ });
18074
18291
  if (!isNativeRuntime(runtime) || !await runtime.isAvailable()) throw new Error("selected API runtime is unavailable; connect a provider first");
18075
18292
  const result = await runSourceFix({
18076
18293
  repoRoot,
@@ -21118,7 +21335,7 @@ function connectFooterHint(mode, hasFilter = false, canContinue = false) {
21118
21335
  hasFilter ? "Esc clear" : "Esc back"
21119
21336
  ].join(" \xB7 ");
21120
21337
  }
21121
- function isFilterKey4(sequence) {
21338
+ function isFilterKey3(sequence) {
21122
21339
  if (typeof sequence !== "string" || sequence.length !== 1) return false;
21123
21340
  const code = sequence.charCodeAt(0);
21124
21341
  return code >= 32 && code !== 127;
@@ -23093,6 +23310,348 @@ function HarnessLifecycle({ children, host, busy, workspaceRoot }) {
23093
23310
  import { useEffect as useEffect22, useMemo as useMemo18, useRef as useRef21, useState as useState25 } from "react";
23094
23311
  import { useKeyboard as useKeyboard18, usePaste as usePaste4 } from "@opentui/react";
23095
23312
  import { decodePasteBytes as decodePasteBytes4, TextAttributes as TextAttributes20 } from "@opentui/core";
23313
+
23314
+ // packages/cli/src/tui/model-layout.ts
23315
+ var DEFAULT_SYMBOLS4 = getSymbols("unicode");
23316
+ function cells6(value, fallback = 0) {
23317
+ const raw = typeof value === "number" && Number.isFinite(value) ? value : fallback;
23318
+ const truncated = Math.trunc(raw);
23319
+ return truncated > 0 ? truncated : 0;
23320
+ }
23321
+ function titleCase(id) {
23322
+ return sanitizeTuiText(id).split(/[-_\s]+/).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
23323
+ }
23324
+ function providerGroupFor(id, states) {
23325
+ const state = states.find((candidate) => candidate.id === id);
23326
+ if (!state) {
23327
+ return {
23328
+ id,
23329
+ label: titleCase(id) || id,
23330
+ credential: "unmapped",
23331
+ envVars: []
23332
+ };
23333
+ }
23334
+ return {
23335
+ id: state.id,
23336
+ label: state.label,
23337
+ credential: state.configured ? "ready" : "missing",
23338
+ via: state.via,
23339
+ hint: state.hint,
23340
+ fileSource: state.fileSource,
23341
+ envVars: state.envVars
23342
+ };
23343
+ }
23344
+ function configuredProviderLabels(states) {
23345
+ return states.filter((state) => state.configured).map((state) => state.label);
23346
+ }
23347
+ function credentialSummary(states) {
23348
+ const labels = configuredProviderLabels(states);
23349
+ if (labels.length === 0) {
23350
+ return "No provider connected \xB7 /connect to add one";
23351
+ }
23352
+ return `Connected: ${labels.join(", ")}`;
23353
+ }
23354
+ function compareStrings2(a, b) {
23355
+ if (a === b) return 0;
23356
+ return a < b ? -1 : 1;
23357
+ }
23358
+ var PROVIDER_ORDER = new Map(PROVIDERS.map((info, index) => [info.id, index]));
23359
+ function groupRank(group, activeProvider) {
23360
+ if (activeProvider !== void 0 && group.id === activeProvider) return 0;
23361
+ switch (group.credential) {
23362
+ case "ready":
23363
+ return 1;
23364
+ case "missing":
23365
+ return 2;
23366
+ default:
23367
+ return 3;
23368
+ }
23369
+ }
23370
+ function buildModelRows({
23371
+ catalog = buildModelCatalog(),
23372
+ states = providerStates({}),
23373
+ filter = "",
23374
+ activeModel,
23375
+ activeProvider: selectedProvider
23376
+ } = {}) {
23377
+ const terms = sanitizeTuiText(filter).toLowerCase().split(" ").filter(Boolean);
23378
+ const groups = /* @__PURE__ */ new Map();
23379
+ const byProvider = /* @__PURE__ */ new Map();
23380
+ for (const model of catalog) {
23381
+ if (!model || typeof model.id !== "string" || model.id.length === 0) continue;
23382
+ const providerId = typeof model.provider === "string" && model.provider.length > 0 ? model.provider : "unknown";
23383
+ let group = groups.get(providerId);
23384
+ if (!group) {
23385
+ group = providerGroupFor(providerId, states);
23386
+ groups.set(providerId, group);
23387
+ }
23388
+ const haystack2 = `${model.id} ${group.id} ${group.label} ${model.price}`.toLowerCase();
23389
+ if (terms.length > 0 && !terms.every((term) => haystack2.includes(term))) continue;
23390
+ const bucket = byProvider.get(providerId);
23391
+ if (bucket) bucket.push(model);
23392
+ else byProvider.set(providerId, [model]);
23393
+ }
23394
+ const activeProvider = selectedProvider ?? [...byProvider.entries()].find(
23395
+ ([, models]) => models.some((model) => model.id === activeModel)
23396
+ )?.[0];
23397
+ const order = [...byProvider.keys()].sort((a, b) => {
23398
+ const left = groups.get(a);
23399
+ const right = groups.get(b);
23400
+ if (!left || !right) return compareStrings2(a, b);
23401
+ return groupRank(left, activeProvider) - groupRank(right, activeProvider) || (PROVIDER_ORDER.get(a) ?? Number.MAX_SAFE_INTEGER) - (PROVIDER_ORDER.get(b) ?? Number.MAX_SAFE_INTEGER) || compareStrings2(a, b);
23402
+ });
23403
+ const rows = [];
23404
+ for (const providerId of order) {
23405
+ const group = groups.get(providerId);
23406
+ const models = byProvider.get(providerId);
23407
+ if (!group || !models || models.length === 0) continue;
23408
+ const sorted = [...models].sort((a, b) => {
23409
+ if (a.id === activeModel) return b.id === activeModel ? 0 : -1;
23410
+ if (b.id === activeModel) return 1;
23411
+ return compareStrings2(a.id, b.id);
23412
+ });
23413
+ rows.push({ kind: "heading", group, count: sorted.length });
23414
+ for (const model of sorted) {
23415
+ rows.push({ kind: "model", group, model, active: model.id === activeModel && providerId === activeProvider });
23416
+ }
23417
+ }
23418
+ return rows;
23419
+ }
23420
+ var MODEL_CONNECT_ACTION_ID = "\0model-connect";
23421
+ function modelConnectActionItem() {
23422
+ return {
23423
+ id: MODEL_CONNECT_ACTION_ID,
23424
+ label: "Connect another provider\u2026",
23425
+ description: "Open Connections",
23426
+ category: "Connections"
23427
+ };
23428
+ }
23429
+ function isModelConnectAction(item) {
23430
+ return item.id === MODEL_CONNECT_ACTION_ID;
23431
+ }
23432
+ function activateModelConnectAction(item, onConnect) {
23433
+ if (!isModelConnectAction(item)) return false;
23434
+ onConnect?.();
23435
+ return true;
23436
+ }
23437
+ function modelResultCount(items) {
23438
+ return items.reduce((count, item) => count + (isModelConnectAction(item) ? 0 : 1), 0);
23439
+ }
23440
+ function modelConnectDetailLines(width) {
23441
+ const limit = cells6(width);
23442
+ if (limit === 0) return [];
23443
+ return wrapCells("Add a provider in Connections.", limit).map((text) => ({ text, tone: "accent" }));
23444
+ }
23445
+ function catalogContextKey(provider, id) {
23446
+ return `${provider}\0${id}`;
23447
+ }
23448
+ function buildContextWindowIndex(models) {
23449
+ const index = /* @__PURE__ */ new Map();
23450
+ const conflicted = /* @__PURE__ */ new Set();
23451
+ for (const model of models) {
23452
+ if (typeof model?.id !== "string" || model.id.length === 0) continue;
23453
+ if (typeof model.provider !== "string" || model.provider.length === 0) continue;
23454
+ const tokens = model.contextTokens;
23455
+ if (typeof tokens !== "number" || !Number.isFinite(tokens) || tokens <= 0) continue;
23456
+ const key = catalogContextKey(model.provider, model.id);
23457
+ if (conflicted.has(key)) continue;
23458
+ const seen = index.get(key);
23459
+ if (seen !== void 0 && seen !== Math.trunc(tokens)) {
23460
+ index.delete(key);
23461
+ conflicted.add(key);
23462
+ continue;
23463
+ }
23464
+ index.set(key, Math.trunc(tokens));
23465
+ }
23466
+ return index;
23467
+ }
23468
+ function contextWindowFor(index, provider, id) {
23469
+ if (typeof provider !== "string" || provider.length === 0) return null;
23470
+ if (typeof id !== "string" || id.length === 0) return null;
23471
+ return index.get(catalogContextKey(provider, id)) ?? null;
23472
+ }
23473
+ function formatContextTokens(value) {
23474
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return "unknown";
23475
+ const tokens = Math.trunc(value);
23476
+ if (tokens >= 1e6 && tokens % 1e6 === 0) return `${tokens / 1e6}M tokens`;
23477
+ if (tokens >= 1e3 && tokens % 1e3 === 0) return `${tokens / 1e3}K tokens`;
23478
+ return `${tokens} tokens`;
23479
+ }
23480
+ function modelPriceText(price) {
23481
+ const text = sanitizeTuiText(price ?? "");
23482
+ if (text.length === 0 || text === "\u2014" || text === "-") return "not published";
23483
+ return text;
23484
+ }
23485
+ function modelDetailLines({ row, configured = [], compact = false, contextTokens }, width, symbols = DEFAULT_SYMBOLS4) {
23486
+ const limit = cells6(width);
23487
+ if (!row || limit <= 0) return [];
23488
+ const ICON_PROVIDER = symbols.fieldHost;
23489
+ const ICON_PRICE = symbols.fieldCost;
23490
+ const ICON_CONTEXT = symbols.fieldContext;
23491
+ const lines = [];
23492
+ const push2 = (value, tone) => {
23493
+ for (const text of wrapCells(value, limit)) lines.push({ text, tone });
23494
+ };
23495
+ const separate = () => {
23496
+ if (!compact) lines.push({ text: "", tone: "blank" });
23497
+ };
23498
+ const group = row.group;
23499
+ if (row.kind === "heading") {
23500
+ push2(group.label, "title");
23501
+ separate();
23502
+ push2(`${row.count} model${row.count === 1 ? "" : "s"}`, "text");
23503
+ } else {
23504
+ push2(row.model.id, "title");
23505
+ separate();
23506
+ push2(`${ICON_PROVIDER} Provider: ${group.label}`, "text");
23507
+ const priceText = modelPriceText(row.model.price);
23508
+ push2(`${ICON_PRICE} Price: ${priceText}`, priceText === "not published" ? "muted" : "text");
23509
+ const contextText = formatContextTokens(contextTokens);
23510
+ push2(`${ICON_CONTEXT} Context: ${contextText}`, contextText === "unknown" ? "muted" : "text");
23511
+ if (row.active) push2("In use", "accent");
23512
+ else push2("Enter to use", "accent");
23513
+ }
23514
+ separate();
23515
+ switch (group.credential) {
23516
+ case "ready":
23517
+ push2(`Connected via ${group.via ?? "the environment"}`, "ok");
23518
+ break;
23519
+ case "missing":
23520
+ push2("Not connected \xB7 /connect to set up", "warn");
23521
+ if (group.envVars.length > 0) push2(`Reads: ${group.envVars.join(", ")}`, "muted");
23522
+ if (group.hint) push2(`Setup: ${group.hint}`, "muted");
23523
+ if (group.fileSource) {
23524
+ push2(`Also reads ${group.fileSource} (not checked).`, "muted");
23525
+ }
23526
+ if (configured.length > 0) push2(`Connected: ${configured.join(", ")}`, "muted");
23527
+ break;
23528
+ default:
23529
+ push2("No direct access. Use a gateway like OpenRouter or OpenCode Zen.", "muted");
23530
+ break;
23531
+ }
23532
+ return lines;
23533
+ }
23534
+ function clipModelDetailLines(lines, rows, width = 0) {
23535
+ const limit = cells6(rows);
23536
+ if (limit <= 0) return [];
23537
+ if (lines.length <= limit) return [...lines];
23538
+ const kept = lines.slice(0, limit);
23539
+ const last = kept[limit - 1];
23540
+ const room = cells6(width);
23541
+ if (room >= 8 && last && last.text.length > 0) {
23542
+ const head = last.text.slice(0, Math.max(0, room - 4)).trimEnd();
23543
+ kept[limit - 1] = { text: `${head} ...`, tone: last.tone };
23544
+ } else {
23545
+ kept[limit - 1] = { text: "...", tone: "muted" };
23546
+ }
23547
+ return kept;
23548
+ }
23549
+ var MODEL_DIALOG_HOST_CHROME_ROWS = 2;
23550
+ function dialogContentWidth(width, inDialog = false) {
23551
+ return Math.max(0, cells6(width) - (inDialog ? 0 : 4));
23552
+ }
23553
+ var MAX_META_ROWS = 8;
23554
+ var META_BODY_FLOOR = 6;
23555
+ var STACKED_MIN_WIDTH = 24;
23556
+ var STACKED_MIN_LIST_ROWS = 6;
23557
+ var STACKED_MAX_ROWS = 8;
23558
+ function computeModelDialogLayout({
23559
+ width,
23560
+ height,
23561
+ totalRows,
23562
+ inDialog = false,
23563
+ compact = false,
23564
+ hostChromeRows,
23565
+ metaLineCount
23566
+ }) {
23567
+ const surfaceWidth = cells6(width);
23568
+ const surfaceHeight = cells6(height);
23569
+ const contentWidth = dialogContentWidth(surfaceWidth, inDialog);
23570
+ const chrome = inDialog ? cells6(hostChromeRows ?? MODEL_DIALOG_HOST_CHROME_ROWS) : shellChromeRows(surfaceWidth);
23571
+ const available = Math.max(0, surfaceHeight - chrome);
23572
+ const titleRows = available >= 5 ? 1 : 0;
23573
+ const statusRows = available >= 4 ? 1 : 0;
23574
+ const desiredMeta = cells6(metaLineCount ?? 2);
23575
+ const metaCeiling = available >= 10 ? MAX_META_ROWS : available >= 8 ? 1 : 0;
23576
+ const metaBudget = Math.max(0, available - titleRows - statusRows - META_BODY_FLOOR);
23577
+ const metaRows = Math.min(desiredMeta, metaCeiling, metaBudget);
23578
+ const bodyRows = Math.max(0, available - titleRows - statusRows - metaRows);
23579
+ const panelFor = (rows) => computeDialogPanel({
23580
+ width: contentWidth,
23581
+ height: surfaceHeight,
23582
+ size: "large",
23583
+ totalRows,
23584
+ withDetail: !compact,
23585
+ bodyRows: rows
23586
+ });
23587
+ let panel = panelFor(bodyRows);
23588
+ let stackedRows = 0;
23589
+ if (!compact && !panel.showDetail && contentWidth >= STACKED_MIN_WIDTH && bodyRows >= STACKED_MIN_LIST_ROWS + 3) {
23590
+ stackedRows = Math.min(STACKED_MAX_ROWS, bodyRows - STACKED_MIN_LIST_ROWS);
23591
+ panel = panelFor(bodyRows - stackedRows);
23592
+ }
23593
+ return { contentWidth, titleRows, metaRows, statusRows, bodyRows, stackedRows, panel };
23594
+ }
23595
+ function modelDialogTitle({ scope }) {
23596
+ return scope === "unknown" ? "Select model \xB7 not connected" : "Select model";
23597
+ }
23598
+ function modelDialogCount(matched, refreshing) {
23599
+ const count = cells6(matched);
23600
+ return `${count} model${count === 1 ? "" : "s"}${refreshing ? " \xB7 loading" : ""}`;
23601
+ }
23602
+ function modelDialogHint({ scope, role = null, hasFilter = false, canReload = false }) {
23603
+ void scope;
23604
+ void canReload;
23605
+ return [
23606
+ "[\u23CE] apply",
23607
+ "[\u2303\u2190\u2192] target",
23608
+ "[\u2303S] single model",
23609
+ role !== null ? "[\u2303\u232B] inherit" : void 0,
23610
+ hasFilter ? "[esc] clear" : "[esc] back"
23611
+ ].filter((part) => part !== void 0).join(" \xB7 ");
23612
+ }
23613
+ function modelTargetLine(role, activeModel, assigned, symbols = DEFAULT_SYMBOLS4, singleModel = false) {
23614
+ const target = role === null ? "parent" : sanitizeTuiText(role);
23615
+ const model = sanitizeTuiText(activeModel ?? "");
23616
+ const value = model.length > 0 ? model : "not selected";
23617
+ const inherits = role !== null && !assigned ? " (inherits parent)" : "";
23618
+ const inert = singleModel && role !== null ? " \xB7 ignored (single model on)" : "";
23619
+ return `${symbols.fieldModel} Target: ${target} \u2192 ${value}${inherits}${inert}`;
23620
+ }
23621
+ function agentRosterToken(role, parentModel, agentModels, focused) {
23622
+ let token;
23623
+ if (role === null) {
23624
+ const model = sanitizeTuiText(parentModel ?? "");
23625
+ token = `parent \u2192 ${model.length > 0 ? model : "not selected"}`;
23626
+ } else {
23627
+ const assigned = agentModels[role];
23628
+ token = assigned !== void 0 ? `${sanitizeTuiText(role)} \u2192 ${sanitizeTuiText(assigned)}` : `${sanitizeTuiText(role)} \u2192 inherits parent`;
23629
+ }
23630
+ return focused ? `[${token}]` : token;
23631
+ }
23632
+ function agentRosterLines({ roles, parentModel, agentModels = {}, activeRole, singleModel = false }, width, _symbols = DEFAULT_SYMBOLS4) {
23633
+ const limit = cells6(width);
23634
+ if (limit <= 0 || roles.length === 0) return [];
23635
+ const tokens = roles.map((role) => agentRosterToken(role, parentModel, agentModels, role === activeRole));
23636
+ const header = singleModel ? "Agents (ignored, single model on): " : "Agents: ";
23637
+ const lines = [];
23638
+ wrapCells(`${header}${tokens.join(" ")}`, limit).forEach((text, index) => {
23639
+ lines.push({ text, tone: index === 0 && singleModel ? "warn" : "muted" });
23640
+ });
23641
+ return lines;
23642
+ }
23643
+ function modelFooterHint(mode, hasFilter = false) {
23644
+ return [
23645
+ "[\u23CE] select",
23646
+ "[\u21E5] curated/all",
23647
+ mode === "filter" || hasFilter ? "[esc] clear" : "[esc] back"
23648
+ ].join(" \xB7 ");
23649
+ }
23650
+ function isFilterKey4(sequence) {
23651
+ return typeof sequence === "string" && sequence.length > 0 && !/[\x00-\x1f\x7f-\x9f]/.test(sequence);
23652
+ }
23653
+
23654
+ // packages/cli/src/tui/model-screen.tsx
23096
23655
  import { Fragment as Fragment16, jsx as jsx44, jsxs as jsxs36 } from "@opentui/react/jsx-runtime";
23097
23656
  var PAGE_STEP3 = 5;
23098
23657
  var MODEL_ROLES = ["discovery", "attack", "verify", "report", "audit", "review"];
@@ -23155,7 +23714,7 @@ function ModelScreen({
23155
23714
  const [reload, setReload] = useState25(0);
23156
23715
  const env = useMemo18(() => suppliedEnv ?? {
23157
23716
  ...process.env,
23158
- ...credentialEnvPatch(loadCredentials(), process.env)
23717
+ ...savedConnectionEnvPatch(process.env)
23159
23718
  }, [suppliedEnv, reload]);
23160
23719
  const scope = "byok";
23161
23720
  const rolesLive = onAgentModelsChange !== void 0;
@@ -23178,6 +23737,9 @@ function ModelScreen({
23178
23737
  const loadCodex = providerId === "chatgpt-codex" || credentialStates.some((state) => state.id === "chatgpt-codex" && state.configured);
23179
23738
  const source = useMemo18(() => ({ providerId, env, reload, codexCatalog }), [providerId, env, reload, codexCatalog]);
23180
23739
  const [codexState, setCodexState] = useState25(null);
23740
+ const [connectionState, setConnectionState] = useState25(null);
23741
+ const connectionModels = connectionState?.source === source ? connectionState.result.models : [];
23742
+ const connectionDiagnostics = connectionState?.source === source ? connectionState.result.diagnostics : [];
23181
23743
  const codexModels = codexState?.source === source ? codexState.models : null;
23182
23744
  const codexFailed = codexState?.source === source && codexState.failed;
23183
23745
  const states = useMemo18(() => credentialStates.map((state) => state.id === "chatgpt-codex" && codexModels !== null ? { ...state, configured: true } : state), [credentialStates, codexModels]);
@@ -23202,6 +23764,9 @@ function ModelScreen({
23202
23764
  }
23203
23765
  ));
23204
23766
  }
23767
+ tasks.push(discoverConnectionModels(env, credentialStates.filter((state) => state.configured && state.id !== "chatgpt-codex").map((state) => state.id), controller.signal).then((result) => {
23768
+ if (alive) setConnectionState({ source, result });
23769
+ }));
23205
23770
  tasks.push(
23206
23771
  syncModelCatalog({ force: reload > 0 }).then((updated) => {
23207
23772
  if (!alive) return;
@@ -23229,12 +23794,16 @@ function ModelScreen({
23229
23794
  );
23230
23795
  const scopeCatalog = (query, all) => {
23231
23796
  const scoped = scopeModelCatalog(catalog, { showAll: all, filter: query, currentModel: activeModel });
23232
- const catalogRows = [
23233
- ...scoped.filter((model) => model.provider !== "chatgpt-codex"),
23797
+ const metadata = new Map(catalog.map((model) => [`${model.provider}/${model.id}`, model]));
23798
+ const scopedIds = new Set(scoped.map((model) => `${model.provider}/${model.id}`));
23799
+ return [
23800
+ ...connectionModels.filter((model) => !metadata.has(`${model.provider}/${model.id}`) || scopedIds.has(`${model.provider}/${model.id}`)).map((model) => ({
23801
+ id: model.id,
23802
+ provider: model.provider,
23803
+ price: model.provider === "cline" && model.id.startsWith("cline-pass/") ? "Pass \xB7 access unverified" : metadata.get(`${model.provider}/${model.id}`)?.price ?? "\u2014"
23804
+ })),
23234
23805
  ...(codexModels ?? []).map((model) => ({ id: model.id, provider: "chatgpt-codex", price: "subscription" }))
23235
- ];
23236
- const codexModelIds = new Set((codexModels ?? []).map((model) => model.id));
23237
- return reachableModelCatalog(catalogRows, states, { env, providerId, codexModelIds }).filter((model) => role === null || model.provider === providerId);
23806
+ ].filter((model) => role === null || model.provider === providerId);
23238
23807
  };
23239
23808
  const scopedCatalog = scopeCatalog(filter, showAll);
23240
23809
  const modelRows = useMemo18(
@@ -23267,7 +23836,15 @@ function ModelScreen({
23267
23836
  () => providerId && activeModel ? catalogContextKey(providerId, activeModel) : items.find((item) => item.row?.active)?.id ?? items[0]?.id
23268
23837
  );
23269
23838
  const selectedIdRef = useRef21(selectedId);
23270
- const selectionIndex = (visible, selection = selectedIdRef.current) => clampDialogSelection(visible, visible.findIndex((item) => item.id === selection));
23839
+ const selectionTouchedRef = useRef21(false);
23840
+ const selectionIndex = (visible, selection = selectedIdRef.current) => {
23841
+ if (!selectionTouchedRef.current) {
23842
+ const initial = visible.findIndex((item) => item.row?.active);
23843
+ const firstModel = visible.findIndex((item) => item.row !== void 0);
23844
+ if (initial >= 0 || firstModel >= 0) return clampDialogSelection(visible, initial >= 0 ? initial : firstModel);
23845
+ }
23846
+ return clampDialogSelection(visible, visible.findIndex((item) => item.id === selection));
23847
+ };
23271
23848
  const cursor = selectionIndex(items, selectedId);
23272
23849
  const metaContentWidth = dialogContentWidth(width, inDialog);
23273
23850
  const metaLines = [];
@@ -23298,7 +23875,8 @@ function ModelScreen({
23298
23875
  const visibleMetaLines = metaLines.slice(0, layout.metaRows);
23299
23876
  const mode = filter ? "filter" : "browse";
23300
23877
  const baseStatusText = credentialSummary(states);
23301
- const catalogStatus = publicFailed ? "Catalog offline \xB7 showing cached models \xB7 Ctrl+R retry" : baseStatusText;
23878
+ const discoveryStatus = connectionDiagnostics.length ? `${connectionDiagnostics.map((item) => item.providerId).join(", ")} models unavailable \xB7 Ctrl+R retry` : baseStatusText;
23879
+ const catalogStatus = publicFailed ? `Pricing offline \xB7 ${discoveryStatus}` : discoveryStatus;
23302
23880
  const statusText = !loadCodex ? catalogStatus : `${codexFailed ? `Codex models unavailable${codexModels ? " \xB7 showing cached" : ""} \xB7 Ctrl+R retry` : codexModels === null ? "Loading Codex models\u2026" : `${codexModels.length} Codex models`} \xB7 ${catalogStatus}`;
23303
23881
  const currentItems = () => {
23304
23882
  const byok = filterRef.current === filter && showAllRef.current === showAll ? byokItems : modelDialogItems(buildModelRows({
@@ -23312,6 +23890,7 @@ function ModelScreen({
23312
23890
  };
23313
23891
  const highlight = (index, visible = currentItems()) => {
23314
23892
  const item = visible[clampDialogSelection(visible, index)];
23893
+ selectionTouchedRef.current = true;
23315
23894
  selectedIdRef.current = item?.id;
23316
23895
  setSelectedId(item?.id);
23317
23896
  };
@@ -23435,7 +24014,7 @@ function ModelScreen({
23435
24014
  setQuery((current) => Array.from(current).slice(0, -1).join(""));
23436
24015
  return;
23437
24016
  }
23438
- if (isFilterKey2(seq)) {
24017
+ if (isFilterKey4(seq)) {
23439
24018
  setQuery((current) => current === "" && seq === "/" ? "" : current + seq);
23440
24019
  }
23441
24020
  });
@@ -23502,7 +24081,7 @@ function ModelScreen({
23502
24081
  renderDetail,
23503
24082
  onActivateRow: (index) => highlight(index, items),
23504
24083
  onScroll: move2,
23505
- emptyText: showAll || filter.trim() ? "No matches. Ctrl+U clears search." : "No connected models. Tab shows all, or connect a provider."
24084
+ emptyText: filter.trim() ? "No matches. Ctrl+U clears search." : "No discovered models. Ctrl+R retries, or connect a provider."
23506
24085
  }
23507
24086
  ),
23508
24087
  stackedRows > 0 && items[cursor] ? /* @__PURE__ */ jsx44("box", { width: contentWidth, height: stackedRows, flexDirection: "column", flexShrink: 0, minWidth: 0, children: renderDetail(items[cursor], { width: contentWidth, height: stackedRows }) }) : null,
@@ -23525,8 +24104,8 @@ import { useKeyboard as useKeyboard19, usePaste as usePaste5 } from "@opentui/re
23525
24104
  import { decodePasteBytes as decodePasteBytes5, TextAttributes as TextAttributes21 } from "@opentui/core";
23526
24105
 
23527
24106
  // packages/cli/src/tui/resume-layout.ts
23528
- var DEFAULT_SYMBOLS4 = getSymbols("unicode");
23529
- function cells6(value, fallback = 0) {
24107
+ var DEFAULT_SYMBOLS5 = getSymbols("unicode");
24108
+ function cells7(value, fallback = 0) {
23530
24109
  const raw = typeof value === "number" && Number.isFinite(value) ? value : fallback;
23531
24110
  const truncated = Math.trunc(raw);
23532
24111
  return truncated > 0 ? truncated : 0;
@@ -23548,7 +24127,7 @@ function sessionMeta(session, now) {
23548
24127
  const parts = [];
23549
24128
  const age = relativeAge(session.savedAt, now);
23550
24129
  if (age.length > 0) parts.push(age);
23551
- const count = cells6(session.messageCount);
24130
+ const count = cells7(session.messageCount);
23552
24131
  parts.push(`${count} msg${count === 1 ? "" : "s"}`);
23553
24132
  const model = sanitizeTuiText(session.model ?? "");
23554
24133
  if (model.length > 0) parts.push(model);
@@ -23563,7 +24142,7 @@ function resumeItems({
23563
24142
  now,
23564
24143
  filter = "",
23565
24144
  protectedSessionIds,
23566
- symbols = DEFAULT_SYMBOLS4
24145
+ symbols = DEFAULT_SYMBOLS5
23567
24146
  }) {
23568
24147
  const terms = sanitizeTuiText(filter).toLowerCase().split(" ").filter(Boolean);
23569
24148
  const matches = (text) => {
@@ -23621,8 +24200,8 @@ function formatSavedAt(savedAt) {
23621
24200
  const time = `${pad2(date.getUTCHours())}:${pad2(date.getUTCMinutes())}`;
23622
24201
  return `${day} ${time} UTC`;
23623
24202
  }
23624
- function resumeDetailLines({ session, liveSession, now, compact = false, isProtected = false }, width, symbols = DEFAULT_SYMBOLS4) {
23625
- const limit = cells6(width);
24203
+ function resumeDetailLines({ session, liveSession, now, compact = false, isProtected = false }, width, symbols = DEFAULT_SYMBOLS5) {
24204
+ const limit = cells7(width);
23626
24205
  if (!session && !liveSession || limit <= 0) return [];
23627
24206
  const ICON_PROTECTED = symbols.fieldProtected;
23628
24207
  const lines = [];
@@ -23662,7 +24241,7 @@ function resumeDetailLines({ session, liveSession, now, compact = false, isProte
23662
24241
  );
23663
24242
  }
23664
24243
  separate();
23665
- const count = cells6(session.messageCount);
24244
+ const count = cells7(session.messageCount);
23666
24245
  push2(`Messages: ${count}`, "muted");
23667
24246
  const model = sanitizeTuiText(session.model ?? "");
23668
24247
  if (model.length > 0) push2(`Model: ${model}`, "muted");
@@ -23680,12 +24259,12 @@ function resumeDetailLines({ session, liveSession, now, compact = false, isProte
23680
24259
  return lines;
23681
24260
  }
23682
24261
  function clipResumeDetailLines(lines, rows, width = 0) {
23683
- const limit = cells6(rows);
24262
+ const limit = cells7(rows);
23684
24263
  if (limit <= 0) return [];
23685
24264
  if (lines.length <= limit) return [...lines];
23686
24265
  const kept = lines.slice(0, limit);
23687
24266
  const last = kept[limit - 1];
23688
- const room = cells6(width);
24267
+ const room = cells7(width);
23689
24268
  if (room >= 8 && last && last.text.length > 0) {
23690
24269
  const head = last.text.slice(0, Math.max(0, room - 4)).trimEnd();
23691
24270
  kept[limit - 1] = { text: `${head} ...`, tone: last.tone };
@@ -23694,9 +24273,9 @@ function clipResumeDetailLines(lines, rows, width = 0) {
23694
24273
  }
23695
24274
  return kept;
23696
24275
  }
23697
- var STACKED_MIN_WIDTH = 24;
23698
- var STACKED_MIN_LIST_ROWS = 6;
23699
- var STACKED_MAX_ROWS = 8;
24276
+ var STACKED_MIN_WIDTH2 = 24;
24277
+ var STACKED_MIN_LIST_ROWS2 = 6;
24278
+ var STACKED_MAX_ROWS2 = 8;
23700
24279
  function computeResumeDialogLayout({
23701
24280
  width,
23702
24281
  height,
@@ -23705,8 +24284,8 @@ function computeResumeDialogLayout({
23705
24284
  hasStatus = false,
23706
24285
  hasActions = false
23707
24286
  }) {
23708
- const surfaceWidth = cells6(width);
23709
- const surfaceHeight = cells6(height);
24287
+ const surfaceWidth = cells7(width);
24288
+ const surfaceHeight = cells7(height);
23710
24289
  const contentWidth = Math.max(0, surfaceWidth - (inDialog ? 0 : 4));
23711
24290
  const available = Math.max(0, surfaceHeight - (inDialog ? 0 : shellChromeRows(surfaceWidth)));
23712
24291
  const footerRows = available >= 3 ? 1 : 0;
@@ -23724,24 +24303,24 @@ function computeResumeDialogLayout({
23724
24303
  });
23725
24304
  let panel = panelFor(bodyRows);
23726
24305
  let stackedRows = 0;
23727
- if (!panel.showDetail && contentWidth >= STACKED_MIN_WIDTH && bodyRows >= STACKED_MIN_LIST_ROWS + 3) {
23728
- stackedRows = Math.min(STACKED_MAX_ROWS, bodyRows - STACKED_MIN_LIST_ROWS);
24306
+ if (!panel.showDetail && contentWidth >= STACKED_MIN_WIDTH2 && bodyRows >= STACKED_MIN_LIST_ROWS2 + 3) {
24307
+ stackedRows = Math.min(STACKED_MAX_ROWS2, bodyRows - STACKED_MIN_LIST_ROWS2);
23729
24308
  panel = panelFor(bodyRows - stackedRows);
23730
24309
  }
23731
24310
  return { contentWidth, titleRows, statusRows, footerRows, actionRows, bodyRows, stackedRows, panel };
23732
24311
  }
23733
- function resumeDialogTitle(scope, scoped, symbols = DEFAULT_SYMBOLS4) {
24312
+ function resumeDialogTitle(scope, scoped, symbols = DEFAULT_SYMBOLS5) {
23734
24313
  const head = `${operatorIcon("resume", symbols)} ${operatorTitle("resume")}`;
23735
24314
  if (!scoped) return head;
23736
24315
  return `${head} \xB7 ${scope === "project" ? "this project" : "all projects"}`;
23737
24316
  }
23738
- function resumeDialogCount(matched, protectedCount = 0, symbols = DEFAULT_SYMBOLS4) {
23739
- const count = cells6(matched);
23740
- const locked = cells6(protectedCount);
24317
+ function resumeDialogCount(matched, protectedCount = 0, symbols = DEFAULT_SYMBOLS5) {
24318
+ const count = cells7(matched);
24319
+ const locked = cells7(protectedCount);
23741
24320
  const head = `${count} session${count === 1 ? "" : "s"}`;
23742
24321
  return locked > 0 ? `${head} \xB7 ${symbols.fieldProtected} ${locked} live` : head;
23743
24322
  }
23744
- function resumeFooterHint(mode, hasFilter = false, hasSessions = true, scope = "project", sessionCount, highlightProtected = false, symbols = DEFAULT_SYMBOLS4) {
24323
+ function resumeFooterHint(mode, hasFilter = false, hasSessions = true, scope = "project", sessionCount, highlightProtected = false, symbols = DEFAULT_SYMBOLS5) {
23745
24324
  const ICON_PROTECTED = symbols.fieldProtected;
23746
24325
  void sessionCount;
23747
24326
  switch (mode) {
@@ -24415,7 +24994,7 @@ function MarketScreen({
24415
24994
  setQuery(filterRef.current.slice(0, -1));
24416
24995
  return;
24417
24996
  }
24418
- if (isFilterKey3(seq)) setQuery(filterRef.current + seq);
24997
+ if (isFilterKey2(seq)) setQuery(filterRef.current + seq);
24419
24998
  return;
24420
24999
  }
24421
25000
  if (key.name === "escape") {
@@ -24435,7 +25014,7 @@ function MarketScreen({
24435
25014
  setQuery("");
24436
25015
  return;
24437
25016
  }
24438
- if (isFilterKey3(seq)) {
25017
+ if (isFilterKey2(seq)) {
24439
25018
  applyMode("filter");
24440
25019
  setQuery(seq);
24441
25020
  }
@@ -24882,7 +25461,7 @@ function ConnectScreen({ frame, onBack, onSkip, onExit, recovery, onConnected, e
24882
25461
  setQuery(filterRef.current.slice(0, -1));
24883
25462
  return;
24884
25463
  }
24885
- if (isFilterKey4(seq)) setQuery(filterRef.current + seq);
25464
+ if (isFilterKey3(seq)) setQuery(filterRef.current + seq);
24886
25465
  return;
24887
25466
  }
24888
25467
  if (key.name === "backspace") {
@@ -24894,7 +25473,7 @@ function ConnectScreen({ frame, onBack, onSkip, onExit, recovery, onConnected, e
24894
25473
  setQuery("");
24895
25474
  return;
24896
25475
  }
24897
- if (isFilterKey4(seq)) {
25476
+ if (isFilterKey3(seq)) {
24898
25477
  setFilterMode(true);
24899
25478
  setQuery(seq);
24900
25479
  }
@@ -25118,8 +25697,8 @@ import { TextAttributes as TextAttributes24 } from "@opentui/core";
25118
25697
  import { useKeyboard as useKeyboard22 } from "@opentui/react";
25119
25698
 
25120
25699
  // packages/cli/src/tui/usage-layout.ts
25121
- var DEFAULT_SYMBOLS5 = getSymbols("unicode");
25122
- function cells7(value, fallback = 0) {
25700
+ var DEFAULT_SYMBOLS6 = getSymbols("unicode");
25701
+ function cells8(value, fallback = 0) {
25123
25702
  const raw = typeof value === "number" && Number.isFinite(value) ? value : fallback;
25124
25703
  const truncated = Math.trunc(raw);
25125
25704
  return truncated > 0 ? truncated : 0;
@@ -25227,7 +25806,7 @@ function usageIcons(symbols) {
25227
25806
  // warning
25228
25807
  };
25229
25808
  }
25230
- function buildUsageReport(snapshot = {}, symbols = DEFAULT_SYMBOLS5) {
25809
+ function buildUsageReport(snapshot = {}, symbols = DEFAULT_SYMBOLS6) {
25231
25810
  const icon = usageIcons(symbols);
25232
25811
  const rows = [];
25233
25812
  const heading = (label2) => rows.push({ kind: "heading", label: label2, tone: "title" });
@@ -25302,8 +25881,8 @@ function buildUsageReport(snapshot = {}, symbols = DEFAULT_SYMBOLS5) {
25302
25881
  }
25303
25882
  return rows;
25304
25883
  }
25305
- function usageMeterBar(fraction, cellCount2, symbols = DEFAULT_SYMBOLS5) {
25306
- const width = cells7(cellCount2);
25884
+ function usageMeterBar(fraction, cellCount2, symbols = DEFAULT_SYMBOLS6) {
25885
+ const width = cells8(cellCount2);
25307
25886
  if (width <= 0) return "";
25308
25887
  const clamped = Number.isFinite(fraction) ? Math.max(0, Math.min(1, fraction)) : 0;
25309
25888
  const filled = Math.max(0, Math.min(width, Math.round(clamped * width)));
@@ -25322,8 +25901,8 @@ function borderChrome3(bordered) {
25322
25901
  return bordered ? { horizontal: 4, vertical: 2 } : { horizontal: 0, vertical: 0 };
25323
25902
  }
25324
25903
  function makePane4(width, height, chromeH, chromeV) {
25325
- const outerWidth = cells7(width);
25326
- const outerHeight = cells7(height);
25904
+ const outerWidth = cells8(width);
25905
+ const outerHeight = cells8(height);
25327
25906
  if (outerWidth <= chromeH || outerHeight <= chromeV) {
25328
25907
  return { width: 0, innerWidth: 0, height: 0, bodyRows: 0 };
25329
25908
  }
@@ -25343,7 +25922,7 @@ function computeKvLayout(innerWidth) {
25343
25922
  });
25344
25923
  }
25345
25924
  function computeMeterLayout(innerWidth) {
25346
- const width = cells7(innerWidth);
25925
+ const width = cells8(innerWidth);
25347
25926
  if (width <= 0) return { width: 0, barCells: 0, gap: 0, captionWidth: 0 };
25348
25927
  const barCells = width >= METER_MIN_ROOM ? Math.min(METER_MAX_CELLS, Math.floor(width * METER_WIDTH_SHARE)) : 0;
25349
25928
  const gap = barCells > 0 && width > barCells ? 1 : 0;
@@ -25357,11 +25936,11 @@ function computeUsageLayout({
25357
25936
  hostRows,
25358
25937
  hostPaddingX
25359
25938
  }) {
25360
- const terminalWidth = cells7(width);
25361
- const padding = hostPaddingX === void 0 ? 2 : cells7(hostPaddingX);
25362
- const chromeRows = hostRows === void 0 ? shellChromeRows(terminalWidth) : cells7(hostRows);
25939
+ const terminalWidth = cells8(width);
25940
+ const padding = hostPaddingX === void 0 ? 2 : cells8(hostPaddingX);
25941
+ const chromeRows = hostRows === void 0 ? shellChromeRows(terminalWidth) : cells8(hostRows);
25363
25942
  const contentWidth = Math.max(0, terminalWidth - padding * 2);
25364
- const bodyRows = Math.max(0, cells7(height) - chromeRows - cells7(headerRows));
25943
+ const bodyRows = Math.max(0, cells8(height) - chromeRows - cells8(headerRows));
25365
25944
  const bordered = bodyRows >= BORDERED_MIN_ROWS4 && contentWidth >= BORDERED_MIN_WIDTH3;
25366
25945
  const chrome = borderChrome3(bordered);
25367
25946
  const pane = makePane4(contentWidth, bodyRows, chrome.horizontal, chrome.vertical);
@@ -25376,7 +25955,7 @@ function computeUsageLayout({
25376
25955
  };
25377
25956
  }
25378
25957
  function clipUsageRows(rows, visible) {
25379
- const limit = cells7(visible);
25958
+ const limit = cells8(visible);
25380
25959
  if (limit <= 0) return [];
25381
25960
  if (rows.length <= limit) return [...rows];
25382
25961
  const kept = rows.slice(0, limit);
@@ -25841,10 +26420,10 @@ function createSessionCloseGate() {
25841
26420
 
25842
26421
  // packages/cli/src/tui/session-state.ts
25843
26422
  function upsertFinding(findings, finding) {
25844
- const exists = findings.some(
25845
- (item) => item.severity.toLowerCase() === finding.severity.toLowerCase() && item.title === finding.title
25846
- );
25847
- return exists ? findings : [...findings, finding];
26423
+ const matches = (item) => item.severity.toLowerCase() === finding.severity.toLowerCase() && item.title === finding.title;
26424
+ if (!findings.some(matches)) return [...findings, finding];
26425
+ if (!finding.impactAssessment) return findings;
26426
+ return findings.map((item) => matches(item) ? { ...item, impactAssessment: finding.impactAssessment } : item);
25848
26427
  }
25849
26428
  function parseSavedFinding(action) {
25850
26429
  const match = /^save_finding:\s*\[([^\]]+)\]\s+(.+)$/i.exec(action.trim());
@@ -26101,11 +26680,12 @@ function applySessionEvent(state, event) {
26101
26680
  if (event.type === "finding") {
26102
26681
  const running = next.stages.find((stage) => stage.status === "running") ?? next.stages.find((stage) => stage.id === "attack");
26103
26682
  const severity = event.data?.severity ?? "info";
26683
+ const impact = ImpactAssessmentSchema.safeParse(event.data?.impactAssessment);
26104
26684
  const title = cleanDisplayText(msg.replace(/^\[[\w]+\]\s*/g, "").trim() || "Finding from AI analysis", 200);
26105
26685
  if (running) {
26106
26686
  next.stages = updateStage(next.stages, running.id, (stage) => ({
26107
26687
  ...stage,
26108
- findings: upsertFinding(stage.findings, { severity, title })
26688
+ findings: upsertFinding(stage.findings, { severity, title, ...impact.success ? { impactAssessment: impact.data } : {} })
26109
26689
  }));
26110
26690
  }
26111
26691
  next.transcript.push(transcriptItem("finding", `[${severity}] ${title}`, { stage: running?.id, tone: severity === "critical" || severity === "high" ? "error" : severity === "medium" ? "warning" : "info" }));