@iowarp/clio-coder 0.4.4 → 0.4.5

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 (555) hide show
  1. package/CHANGELOG.md +92 -2
  2. package/CONTRIBUTING.md +25 -15
  3. package/README.md +340 -27
  4. package/dist/{acp-WNAYYF4F.js → acp-H3CU2HBQ.js} +25 -24
  5. package/dist/{agents-3OKXHLOI.js → agents-IXQQZ7BD.js} +77 -77
  6. package/dist/assets/codewiki.json +1 -1
  7. package/dist/{auth-VKNNMGPU.js → auth-R7KYF7N3.js} +38 -38
  8. package/dist/builtins-CRFDQUVP.js +22 -0
  9. package/dist/{chunk-TQAHXW6Y.js → chunk-22PQ4TX4.js} +4 -4
  10. package/dist/{chunk-NEDJ26B5.js → chunk-2GPGAE5W.js} +6 -51
  11. package/dist/{chunk-IKCO5N3L.js → chunk-2QPI3TR3.js} +3 -3
  12. package/dist/{chunk-HRQMFLJP.js → chunk-32KJPXAM.js} +6 -6
  13. package/dist/{chunk-65DEGPJ6.js → chunk-3A3CUMKA.js} +6 -4
  14. package/dist/{chunk-JCI2ROMZ.js → chunk-3T4DXWP6.js} +7 -7
  15. package/dist/{chunk-DR52UMZW.js → chunk-3UW3KU4A.js} +2 -2
  16. package/dist/{chunk-6Q3CYFD3.js → chunk-4SVIVOMC.js} +184 -33
  17. package/dist/{chunk-W54I7H25.js → chunk-5A6XR3RJ.js} +44 -19
  18. package/dist/{chunk-YPC6ZR5L.js → chunk-5CMARGPF.js} +119 -5
  19. package/dist/{chunk-KXDSS5WJ.js → chunk-5CY4Q6QI.js} +4 -4
  20. package/dist/{chunk-I2DWJ4GM.js → chunk-5DDOTTG4.js} +54 -42
  21. package/dist/{chunk-D4CJV46V.js → chunk-5GZICIYO.js} +3 -3
  22. package/dist/{chunk-4IUZQIJ3.js → chunk-5PHVPU4G.js} +2 -2
  23. package/dist/{chunk-3ODX73FK.js → chunk-5VTJP36Q.js} +4 -4
  24. package/dist/{chunk-54X7T7DK.js → chunk-5ZMXGW7P.js} +79 -7
  25. package/dist/chunk-5ZSZEYJK.js +119 -0
  26. package/dist/{chunk-IXIY2H4R.js → chunk-633EXGZA.js} +5 -5
  27. package/dist/{chunk-CUSRQKPU.js → chunk-6CDNRHWH.js} +299 -89
  28. package/dist/{chunk-EBY63B7G.js → chunk-6EXUUOSN.js} +2 -2
  29. package/dist/{chunk-SVNXH4L2.js → chunk-6ICZKDUC.js} +2 -2
  30. package/dist/{chunk-JEIYHLOR.js → chunk-6SYEGZI3.js} +12 -12
  31. package/dist/{chunk-DQOVN6KV.js → chunk-6YA46L5A.js} +4 -4
  32. package/dist/{chunk-NZMNUPZZ.js → chunk-77CZRFTE.js} +3 -3
  33. package/dist/{chunk-6PAZTBPA.js → chunk-7HBHHVCK.js} +15 -6
  34. package/dist/{chunk-25QBEXRS.js → chunk-7TKWWPD7.js} +5 -4
  35. package/dist/{chunk-2VTFPG5O.js → chunk-7WLRF2U5.js} +2 -2
  36. package/dist/chunk-7WUZEB2M.js +165 -0
  37. package/dist/{chunk-3UUXNFEX.js → chunk-7YJWEF2L.js} +61 -34
  38. package/dist/{chunk-3EBYEESD.js → chunk-A46ILRS2.js} +5 -5
  39. package/dist/{chunk-UOIZ7DA4.js → chunk-AP7HDJOP.js} +2 -2
  40. package/dist/{chunk-APJ265NV.js → chunk-B5GGDIHT.js} +146 -146
  41. package/dist/{chunk-PMZVFWSR.js → chunk-B5ZTR6KZ.js} +2 -2
  42. package/dist/{chunk-I5FWO7L5.js → chunk-B6UM3OZC.js} +2 -2
  43. package/dist/{chunk-2CU2H6KE.js → chunk-BBV5TKE6.js} +5 -5
  44. package/dist/{chunk-4O6MANBS.js → chunk-BS4GAMUB.js} +14 -10
  45. package/dist/{chunk-S66XZJOF.js → chunk-C27U2TYG.js} +2 -2
  46. package/dist/{chunk-QZWQA4DE.js → chunk-CBSKDFWL.js} +3 -3
  47. package/dist/{chunk-2LEAKD4C.js → chunk-CKK25WN3.js} +3 -3
  48. package/dist/{chunk-BYP5D4HI.js → chunk-CTTI7G3T.js} +2 -2
  49. package/dist/{chunk-XAKHZX5N.js → chunk-CVDAFGPW.js} +4 -4
  50. package/dist/{chunk-RKKLTLYB.js → chunk-CXQ37WJH.js} +3 -3
  51. package/dist/{chunk-GTUD2WMY.js → chunk-DBREN25X.js} +44 -9
  52. package/dist/{chunk-YNFKXPEC.js → chunk-DIMRLNIC.js} +35 -66
  53. package/dist/{chunk-NDDGJUXD.js → chunk-DNCE23JJ.js} +2 -2
  54. package/dist/{chunk-HVDIIIQW.js → chunk-DNHVRBH4.js} +3 -3
  55. package/dist/{chunk-XULDXHTN.js → chunk-DRD2A54W.js} +102 -50
  56. package/dist/{chunk-D7E7WCDF.js → chunk-DVNAPPXU.js} +2 -2
  57. package/dist/{chunk-YXLYO42X.js → chunk-DXVMLM3Z.js} +3 -2
  58. package/dist/{chunk-5MEZN6CB.js → chunk-DZK63TZJ.js} +6 -6
  59. package/dist/{chunk-IGLP3ODT.js → chunk-E3BQTQUP.js} +15 -15
  60. package/dist/{chunk-IWHMRKLL.js → chunk-E3LEPLQ2.js} +2 -2
  61. package/dist/{chunk-3R73A4XB.js → chunk-ECBHH7LU.js} +3 -3
  62. package/dist/chunk-ECOMVOHP.js +139 -0
  63. package/dist/chunk-EFSEIZE6.js +56 -0
  64. package/dist/{chunk-FEAXX7B6.js → chunk-EHCPSZJF.js} +4 -4
  65. package/dist/{chunk-4NSRCOYP.js → chunk-EHOSNVVM.js} +3 -2
  66. package/dist/{chunk-7UGL4MB5.js → chunk-EQEJJ53P.js} +10 -10
  67. package/dist/{chunk-GWZNEVM2.js → chunk-EWD5P3GK.js} +9 -9
  68. package/dist/{chunk-6UINWWS6.js → chunk-F34AR6O3.js} +14 -14
  69. package/dist/{chunk-GHS5EBTQ.js → chunk-FKIOX6DS.js} +29 -20
  70. package/dist/{chunk-HAXOFFRH.js → chunk-FQOOGXBH.js} +7 -7
  71. package/dist/{chunk-Y55JBDO5.js → chunk-FSTIBAGM.js} +38 -23
  72. package/dist/{chunk-ZTJUVLTU.js → chunk-FXFVDPWY.js} +2 -2
  73. package/dist/{chunk-XPLRXC72.js → chunk-GD55RTIW.js} +3 -3
  74. package/dist/{chunk-5B2AEOW5.js → chunk-GH5ZR6JP.js} +472 -472
  75. package/dist/{chunk-TOIVGRUX.js → chunk-GJ24ODAX.js} +5 -5
  76. package/dist/{chunk-QUFRYSWI.js → chunk-GNQRWTMY.js} +129 -48
  77. package/dist/{chunk-5ICU3EUH.js → chunk-GVYWZNRK.js} +5 -5
  78. package/dist/{chunk-GX5WYQO4.js → chunk-GXCCHKN6.js} +6 -6
  79. package/dist/{chunk-K6T2ZAMZ.js → chunk-HGSLRG33.js} +6 -6
  80. package/dist/{chunk-26QSH3EJ.js → chunk-HHVJNVUJ.js} +5 -5
  81. package/dist/{chunk-F4EKGO4N.js → chunk-HL26ADLH.js} +4 -2
  82. package/dist/{chunk-JT2RFCC5.js → chunk-HR3HPQ76.js} +5 -5
  83. package/dist/{chunk-ID64D7PE.js → chunk-HXHFDHB6.js} +24 -24
  84. package/dist/{chunk-ELWDPP3Y.js → chunk-I7VLWRK2.js} +8 -8
  85. package/dist/{chunk-6OSVSQL5.js → chunk-ICO4TQ2F.js} +7 -5
  86. package/dist/{chunk-SZAA6XDG.js → chunk-IFDRAD6F.js} +2 -2
  87. package/dist/{chunk-72YIHOZQ.js → chunk-ILJ7DWGE.js} +9 -9
  88. package/dist/{chunk-2JH2WHGE.js → chunk-J2FYEQ5L.js} +4 -4
  89. package/dist/{chunk-BMS5RKQY.js → chunk-JABWPKFY.js} +3 -3
  90. package/dist/{chunk-QDC3K2U3.js → chunk-K2BLQC5E.js} +3 -3
  91. package/dist/{chunk-AUPNRN7C.js → chunk-K2HL3GBL.js} +4 -4
  92. package/dist/{chunk-2ASED4PZ.js → chunk-K6RDB7IA.js} +26 -26
  93. package/dist/{chunk-FFUPXJC4.js → chunk-KDWLXVMN.js} +23 -24
  94. package/dist/{chunk-OZNBF4L3.js → chunk-KECNXMDE.js} +2 -2
  95. package/dist/{chunk-6QOTUPRG.js → chunk-KF6GFW6O.js} +66 -18
  96. package/dist/{chunk-BTK3SSSK.js → chunk-KMF54VH3.js} +2 -2
  97. package/dist/chunk-KPRLAMP4.js +32 -0
  98. package/dist/{chunk-ECH6PKUQ.js → chunk-KQ6IDQIB.js} +2 -2
  99. package/dist/{chunk-3UNOLWNZ.js → chunk-KTFSFCVN.js} +20 -9
  100. package/dist/{chunk-57XXR6DR.js → chunk-KYKNBD4Y.js} +24 -23
  101. package/dist/{chunk-IRXAATOX.js → chunk-L4N3DWNW.js} +3 -3
  102. package/dist/{chunk-LCGCVYZ4.js → chunk-LQTKDAUO.js} +2 -2
  103. package/dist/{chunk-U6TMQNSI.js → chunk-LTR5QCLS.js} +4 -4
  104. package/dist/chunk-LUL5Z66S.js +221 -0
  105. package/dist/{chunk-ELZVTCGV.js → chunk-LVFANMOH.js} +151 -327
  106. package/dist/{chunk-H7IXIC72.js → chunk-LY4N4TTL.js} +17 -3
  107. package/dist/{chunk-VKPAQYEB.js → chunk-LZBMXNLP.js} +5 -5
  108. package/dist/{chunk-UL3WSD3F.js → chunk-M4KFUXS7.js} +2 -2
  109. package/dist/{chunk-NXYCB2VD.js → chunk-M6TAYK66.js} +6 -6
  110. package/dist/{chunk-NEKRRTYW.js → chunk-MC3JSVR6.js} +2 -2
  111. package/dist/{chunk-CFGTUFWB.js → chunk-MCJKEGHO.js} +2 -2
  112. package/dist/{chunk-DXKJURES.js → chunk-MDU3C27C.js} +10 -7
  113. package/dist/{chunk-6XLNIQDB.js → chunk-MYI32N4R.js} +2 -2
  114. package/dist/{chunk-3GY4F45V.js → chunk-NC4KV7EL.js} +6 -6
  115. package/dist/{chunk-LLXSDWXS.js → chunk-NF3BK5WR.js} +5 -5
  116. package/dist/chunk-NTK3WTHM.js +141 -0
  117. package/dist/{chunk-GYV6VZOC.js → chunk-NTTS3O53.js} +2 -2
  118. package/dist/{chunk-RZDWV63N.js → chunk-NY6IWDVU.js} +6 -6
  119. package/dist/{chunk-XXYSBZIQ.js → chunk-O2RQ7LCK.js} +4 -4
  120. package/dist/{chunk-4BJ5BYCE.js → chunk-O3VV6IVK.js} +2 -2
  121. package/dist/{chunk-W6GROXXM.js → chunk-O5F25NIE.js} +2 -2
  122. package/dist/{chunk-NXIMQY5W.js → chunk-ODUTYZIU.js} +5 -5
  123. package/dist/{chunk-LTIKRKFL.js → chunk-ONRTXOZY.js} +4 -4
  124. package/dist/{chunk-KFV5L5SK.js → chunk-OQM5IVJY.js} +118 -232
  125. package/dist/{chunk-XRZT5WY5.js → chunk-P5SC4DLJ.js} +4 -4
  126. package/dist/{chunk-R6Q67RJH.js → chunk-PECBKCDK.js} +34 -6
  127. package/dist/{chunk-33YXPOE3.js → chunk-PPEZJWUG.js} +2 -2
  128. package/dist/{chunk-RXTN6AKH.js → chunk-PWWSIB2A.js} +5 -5
  129. package/dist/{chunk-2STGEDFV.js → chunk-QEQISF75.js} +2 -2
  130. package/dist/{chunk-3DPEIQKN.js → chunk-QH3ZTUOA.js} +2 -2
  131. package/dist/{chunk-YAKGTXEV.js → chunk-QRFXEO6Y.js} +2 -2
  132. package/dist/{chunk-35MSIRKH.js → chunk-QUIJZSDW.js} +2 -2
  133. package/dist/{chunk-HHV2GANA.js → chunk-R2P2U3ZS.js} +2 -2
  134. package/dist/{chunk-2DSOYNFC.js → chunk-R6MAYTMS.js} +7 -7
  135. package/dist/{chunk-JQLNNIKT.js → chunk-R6MICQYU.js} +6 -6
  136. package/dist/{chunk-NAI6ZFCY.js → chunk-RLTT5GVY.js} +122 -11
  137. package/dist/{chunk-DT3LWJOB.js → chunk-RXIOCVBZ.js} +24 -6
  138. package/dist/{chunk-N56KALIC.js → chunk-S32UQ5GL.js} +61 -34
  139. package/dist/{chunk-UEPWCCTY.js → chunk-SBZX6ARC.js} +12 -12
  140. package/dist/chunk-SD7SHNDW.js +15 -0
  141. package/dist/{chunk-NRO2BJRH.js → chunk-SDWNDICN.js} +10235 -4015
  142. package/dist/{chunk-UXCU4E3T.js → chunk-SE4ZKILO.js} +6 -6
  143. package/dist/chunk-SL2RDHKO.js +19 -0
  144. package/dist/{chunk-NUGM5KR6.js → chunk-SRCEQKQS.js} +2 -2
  145. package/dist/{chunk-OMQNJVKW.js → chunk-SRZOW5L2.js} +43 -13
  146. package/dist/{chunk-3M6DQK6S.js → chunk-T334FW2H.js} +7 -7
  147. package/dist/{chunk-V76WTFTW.js → chunk-T52TPHYC.js} +6 -6
  148. package/dist/{chunk-I7XBWTYH.js → chunk-T53XI6I7.js} +5 -5
  149. package/dist/{chunk-2ZSONWVL.js → chunk-T7FDXNRU.js} +13 -13
  150. package/dist/{chunk-JSD46VO2.js → chunk-TEG3RYVZ.js} +43 -36
  151. package/dist/{chunk-3I7MS7N2.js → chunk-TK2BMCBZ.js} +2 -2
  152. package/dist/{chunk-5OIVVPHF.js → chunk-TN5FW4XY.js} +13 -6
  153. package/dist/{chunk-75W7L2E2.js → chunk-TZ7MFRG4.js} +1041 -162
  154. package/dist/{chunk-36CT5VVL.js → chunk-U2JOLB7O.js} +126 -77
  155. package/dist/{chunk-LL4KHSZI.js → chunk-U2MSJ57E.js} +2 -2
  156. package/dist/{chunk-FTMGRKEF.js → chunk-U44YYLVV.js} +4 -4
  157. package/dist/{chunk-YECAMM3D.js → chunk-U7H5WRG5.js} +5 -5
  158. package/dist/{chunk-RQCKCSRL.js → chunk-U7VQ4NI4.js} +22 -22
  159. package/dist/{chunk-5TUB6SLS.js → chunk-UFYNOQK4.js} +7 -7
  160. package/dist/{chunk-R346GLFC.js → chunk-UHW5V7HC.js} +2 -2
  161. package/dist/{chunk-USR47QNF.js → chunk-UL36QJX6.js} +14 -14
  162. package/dist/{chunk-VIA6RFQZ.js → chunk-UQIVHSE4.js} +4 -4
  163. package/dist/{chunk-RAY4OVGZ.js → chunk-URBGEOH3.js} +5 -5
  164. package/dist/chunk-USZA7GWL.js +341 -0
  165. package/dist/{chunk-YD5GIKET.js → chunk-UTUNT5QL.js} +48 -579
  166. package/dist/{chunk-ZA4VCIGV.js → chunk-UUQ5G6EZ.js} +60 -41
  167. package/dist/{chunk-23L32XTI.js → chunk-UXAC2FX4.js} +68 -39
  168. package/dist/{chunk-VG7TBQIY.js → chunk-V552WL53.js} +68 -4
  169. package/dist/{chunk-BWH6N36D.js → chunk-VHKTOLEW.js} +272 -42
  170. package/dist/{chunk-EXLD33WO.js → chunk-VLPTKCKT.js} +24 -9
  171. package/dist/{chunk-336NSSKI.js → chunk-VNBICSS2.js} +2 -2
  172. package/dist/{chunk-VAVR4IJY.js → chunk-VQD7NH7Z.js} +3 -3
  173. package/dist/{chunk-LBMZMYH2.js → chunk-W2RJEH6Q.js} +3 -3
  174. package/dist/{chunk-7CR24IG7.js → chunk-WDV62RKY.js} +2 -2
  175. package/dist/{chunk-S6PYF2XF.js → chunk-WFKDPU7U.js} +4 -4
  176. package/dist/{chunk-BJVFZO5U.js → chunk-WJIMKGD6.js} +7 -7
  177. package/dist/{chunk-5636DCO5.js → chunk-WLMSOT73.js} +59 -12
  178. package/dist/{chunk-MXHC5QYU.js → chunk-WTQGRBHV.js} +5 -144
  179. package/dist/chunk-WXA2CFJO.js +23 -0
  180. package/dist/{chunk-QSNYB6ZV.js → chunk-XCUDZQLX.js} +3 -3
  181. package/dist/{chunk-4M6Z5QVF.js → chunk-XXBQKW32.js} +11 -11
  182. package/dist/{chunk-OEJSLEPW.js → chunk-YEJIG7LN.js} +332 -332
  183. package/dist/chunk-YGDMBK7O.js +567 -0
  184. package/dist/{chunk-4WR7VSYB.js → chunk-YYB3MC65.js} +23 -9
  185. package/dist/{chunk-2IR2NMPA.js → chunk-ZIDFQJRB.js} +2 -2
  186. package/dist/{chunk-Q4WO54TA.js → chunk-ZMZQEBKI.js} +14 -14
  187. package/dist/{chunk-6EJMN2Y3.js → chunk-ZTNFYMIO.js} +2 -2
  188. package/dist/{chunk-WEPFGWHJ.js → chunk-ZZFWWYLX.js} +2 -2
  189. package/dist/cli/index.js +44 -44
  190. package/dist/clio-5I2IBFYL.js +26 -0
  191. package/dist/{code-nav-IJR2DBPR.js → code-nav-YXIAEZVS.js} +48 -32
  192. package/dist/codewiki/build-worker.js +76 -29
  193. package/dist/{compile-cache-OQAVB7Y5.js → compile-cache-WJEPUZEJ.js} +4 -4
  194. package/dist/{components-2TGAI2RC.js → components-TNIKXCBH.js} +13 -13
  195. package/dist/{config-IUA6OYNS.js → config-Y2JDJ3JJ.js} +210 -124
  196. package/dist/configure-SML6UBZ5.js +55 -0
  197. package/dist/{context-4MPR7WKB.js → context-P5YSEO55.js} +125 -121
  198. package/dist/{context-2DKHWH2T.js → context-QQ53HSGJ.js} +91 -62
  199. package/dist/{context-BOYF5EJM.js → context-S2EEC3EJ.js} +62 -31
  200. package/dist/context-clear-TMEQCOTH.js +183 -0
  201. package/dist/{context-index-HNG3MOME.js → context-index-HP2JFUWA.js} +13 -11
  202. package/dist/{context-map-COB37XXN.js → context-map-INTXD54D.js} +71 -21
  203. package/dist/{context-working-set-3I3FYX6Y.js → context-working-set-CNLSQN5K.js} +31 -31
  204. package/dist/detail-5572VLBO.js +114 -0
  205. package/dist/{dispatch-runner-RJ5I2F2O.js → dispatch-runner-FRHD6P2O.js} +191 -116
  206. package/dist/{docs-SPOV3BAN.js → docs-BL7ROUFN.js} +4 -4
  207. package/dist/{doctor-DKICC2SN.js → doctor-N3LCM2LG.js} +58 -58
  208. package/dist/{eval-OQOQUDHK.js → eval-BUU3ZOUZ.js} +473 -168
  209. package/dist/{eval-inventory-Y6QRFOH5.js → eval-inventory-QOYZERXJ.js} +7 -7
  210. package/dist/evidence-DTGEN456.js +224 -0
  211. package/dist/{evidence-4DQ25GUQ.js → evidence-SQ5DNFEN.js} +110 -94
  212. package/dist/{evolve-GSS52E5J.js → evolve-IJNUFZDS.js} +107 -91
  213. package/dist/{extensions-G7MFLYHT.js → extensions-YVRHX6ZI.js} +16 -16
  214. package/dist/{fleet-Q37YHHAQ.js → fleet-ZNNVSYFO.js} +147 -147
  215. package/dist/{fleet-commands-G7E4N7SM.js → fleet-commands-5YE7NPJL.js} +27 -26
  216. package/dist/{fleet-decisions-O7M6QBA2.js → fleet-decisions-3SBSCTCW.js} +16 -15
  217. package/dist/{fleet-graph-TOUBW6OW.js → fleet-graph-6HHPWF5T.js} +39 -38
  218. package/dist/{fleet-inspect-SW33JJNI.js → fleet-inspect-JEYMGCGC.js} +107 -91
  219. package/dist/{fleet-new-RDVJLHHH.js → fleet-new-RCKGSRDV.js} +3 -3
  220. package/dist/{fleet-preflight-CV2655TW.js → fleet-preflight-QRSHIIDE.js} +10 -9
  221. package/dist/{fleet-validate-KESZX2YH.js → fleet-validate-4PM4GDDL.js} +46 -42
  222. package/dist/{fleet-verify-UQPMTVE3.js → fleet-verify-NJDTHTO3.js} +105 -89
  223. package/dist/fleet-view-UP2BWQQY.js +117 -0
  224. package/dist/{init-PXEXQSBF.js → init-S3GZQ5ZF.js} +123 -123
  225. package/dist/{install-NKNG7KD4.js → install-3RZDDP23.js} +5 -5
  226. package/dist/{interop-ZG5T62U3.js → interop-YOTGXFJM.js} +25 -25
  227. package/dist/inventory-K2OZ36YJ.js +117 -0
  228. package/dist/{library-B2W4N74O.js → library-GJI6W6OK.js} +45 -44
  229. package/dist/{memory-YCANYS5A.js → memory-OQOXQGYD.js} +107 -93
  230. package/dist/{models-GERTU3YI.js → models-3IK2Y5WE.js} +63 -62
  231. package/dist/{monitor-CPNIUULB.js → monitor-FTJLTKCQ.js} +136 -107
  232. package/dist/{orchestrator-J4BSH4WQ.js → orchestrator-N47O7SFD.js} +1159 -697
  233. package/dist/{panes-BOHAEGYC.js → panes-7BTYH3XQ.js} +8 -8
  234. package/dist/{panes-NXSLDQZ2.js → panes-WPOMEMRH.js} +22 -22
  235. package/dist/{paths-VSUWNC22.js → paths-J3KN7UAO.js} +12 -12
  236. package/dist/preload-65U34NG6.js +115 -0
  237. package/dist/{registry-LG64LTF4.js → registry-DESGAXWK.js} +3 -3
  238. package/dist/{reset-TNWTB5LU.js → reset-MUVQDLNL.js} +20 -20
  239. package/dist/{resources-4PXNMD5G.js → resources-LM76COAO.js} +41 -40
  240. package/dist/{run-D6XJ34CN.js → run-3VFZQ33N.js} +162 -156
  241. package/dist/{share-2NWMJJEE.js → share-4JUB4BL7.js} +43 -42
  242. package/dist/{skills-KR7WON5G.js → skills-S36AAJHU.js} +47 -46
  243. package/dist/{skills-eval-O2ZNOLDS.js → skills-eval-G6T57L7M.js} +127 -107
  244. package/dist/{skills-inventory-ZZOUBK7O.js → skills-inventory-WLM46PJH.js} +41 -40
  245. package/dist/slash-commands-GBARG3Y7.js +91 -0
  246. package/dist/{steer-XA25PSCS.js → steer-S7D7IKPU.js} +7 -7
  247. package/dist/{support-7EMVWYG2.js → support-5VAEC32W.js} +14 -14
  248. package/dist/{targets-OMH2XCSN.js → targets-N5REUETU.js} +145 -94
  249. package/dist/tasks-6BVY5YZF.js +36 -0
  250. package/dist/{terminal-lease-C2J3JYRE.js → terminal-lease-57UEOJKS.js} +12 -11
  251. package/dist/tools-6OCQ6SVB.js +28 -0
  252. package/dist/{trace-FXMXUZUF.js → trace-JHLXWUMN.js} +18 -17
  253. package/dist/{tree-sitter-HGKH6LG4.js → tree-sitter-AQUUOSYM.js} +6 -6
  254. package/dist/{tui-primitives-K5PASC3O.js → tui-primitives-RCY2HN7G.js} +3 -3
  255. package/dist/{uninstall-HALS6BLF.js → uninstall-FXYMFFRT.js} +17 -17
  256. package/dist/{upgrade-MS72RJEP.js → upgrade-4HD5HAIV.js} +40 -39
  257. package/dist/{usage-NHG6MCJM.js → usage-4GWM2WWP.js} +136 -105
  258. package/dist/{verifiers-7AUNVXDY.js → verifiers-GSKWKWVG.js} +28 -27
  259. package/dist/verify-3AS3ULCY.js +30 -0
  260. package/dist/{version-KGEG7EPO.js → version-RFPKO6T7.js} +4 -4
  261. package/dist/{web-fetch-V4FKSDAV.js → web-fetch-MQN4FH3X.js} +169 -18
  262. package/dist/wiki-generate-7BV7XWIY.js +614 -0
  263. package/dist/{with-panes-BDQEWBRT.js → with-panes-OFTNAR4Y.js} +34 -20
  264. package/dist/worker/entry.js +99 -88
  265. package/dist/{workspace-ZJ6BFM3Q.js → workspace-DZ7JADBG.js} +6 -6
  266. package/docs/README.md +7 -6
  267. package/docs/architecture/acp.md +10 -0
  268. package/docs/architecture/architecture.md +5 -5
  269. package/docs/architecture/context-engine.md +44 -59
  270. package/docs/architecture/context-working-set.md +7 -9
  271. package/docs/architecture/dispatch-architecture-rationale.md +1 -1
  272. package/docs/architecture/evidence-and-memory.md +10 -0
  273. package/docs/architecture/pi-boundary.md +37 -7
  274. package/docs/architecture/prompt-envelope-and-tools.md +7 -7
  275. package/docs/architecture/session-lifecycle.md +4 -4
  276. package/docs/architecture/worker-dispatch-mechanics.md +4 -0
  277. package/docs/guide/commands-and-modes.md +49 -36
  278. package/docs/guide/configuration-and-targets.md +7 -2
  279. package/docs/guide/configuration-reference.md +13 -3
  280. package/docs/guide/environment-variables.md +6 -2
  281. package/docs/guide/fleet-dispatch.md +12 -0
  282. package/docs/guide/installation-and-lifecycle.md +35 -9
  283. package/docs/guide/proactive-memory.md +1 -1
  284. package/docs/guide/skills-marketplace.md +11 -3
  285. package/docs/guide/tool-usage.md +9 -2
  286. package/docs/process/development-pipeline.md +10 -10
  287. package/docs/process/documentation-guide.md +2 -2
  288. package/docs/process/eval-runner.md +15 -0
  289. package/docs/process/evals-internal.md +1 -1
  290. package/docs/process/release-cut-checklist.md +6 -6
  291. package/evals/README.md +4 -0
  292. package/evals/behavioral-corpus-grader.mjs +147 -14
  293. package/evals/behavioral-model-negative-control.yaml +1 -0
  294. package/evals/behavioral-model.yaml +266 -1
  295. package/evals/fixtures/docs-retrieval.json +102 -0
  296. package/evals/fixtures/scalar-decision.json +17 -0
  297. package/evals/fixtures/scout-citation-pipeline.json +55 -0
  298. package/evals/fixtures/source-explanation.json +74 -0
  299. package/evals/fixtures/tool-arguments.json +18 -0
  300. package/evals/fixtures/tool-surface/read.txt +4 -0
  301. package/evals/fixtures/tool-surface/subdir/keep.txt +1 -0
  302. package/evals/no-edit-memory-grader.mjs +149 -0
  303. package/evals/scalar-decision-grader.py +41 -0
  304. package/evals/scalar-decision-machinery.ts +145 -0
  305. package/evals/source-explanation-grader.mjs +118 -0
  306. package/evals/tool-surface-grader.mjs +53 -0
  307. package/evals/tool-surface-model.yaml +274 -0
  308. package/package.json +14 -14
  309. package/skills/README.md +6 -6
  310. package/skills/registry.yaml +1 -1
  311. package/skills/skill-marketplace.json +1 -1
  312. package/src/cli/bootstrap-generate.ts +6 -0
  313. package/src/cli/config-inspect.ts +24 -7
  314. package/src/cli/config-trust.ts +62 -0
  315. package/src/cli/config.ts +8 -0
  316. package/src/cli/context-map.ts +75 -14
  317. package/src/cli/context.ts +46 -17
  318. package/src/cli/eval.ts +17 -3
  319. package/src/cli/modes/print.ts +32 -4
  320. package/src/cli/run.ts +16 -14
  321. package/src/cli/skills-eval.ts +10 -8
  322. package/src/cli/steer-channel.ts +31 -18
  323. package/src/cli/targets.ts +83 -31
  324. package/src/cli/tasks.ts +10 -1
  325. package/src/cli/upgrade.ts +9 -6
  326. package/src/cli/usage.ts +24 -0
  327. package/src/cli/wiki-generate.ts +239 -96
  328. package/src/core/bash-exec.ts +43 -15
  329. package/src/core/bus-events.ts +15 -0
  330. package/src/core/config.ts +33 -14
  331. package/src/core/defaults.ts +5 -4
  332. package/src/core/file-references.ts +11 -1
  333. package/src/core/incomplete-installation.ts +3 -1
  334. package/src/core/settings-layers.ts +21 -5
  335. package/src/core/termination.ts +26 -9
  336. package/src/core/untrusted-content.ts +16 -0
  337. package/src/core/workspace-trust.ts +179 -0
  338. package/src/domains/agents/builtins/coder.md +4 -2
  339. package/src/domains/agents/builtins/context-bootstrap.md +3 -1
  340. package/src/domains/agents/builtins/documenter.md +7 -4
  341. package/src/domains/agents/builtins/researcher.md +1 -0
  342. package/src/domains/agents/builtins/scout.md +7 -1
  343. package/src/domains/agents/result-contract.ts +199 -26
  344. package/src/domains/context/bootstrap-prompt.ts +11 -9
  345. package/src/domains/context/bootstrap.ts +74 -39
  346. package/src/domains/context/clio-md.ts +88 -26
  347. package/src/domains/context/codewiki/build-operation.ts +121 -0
  348. package/src/domains/context/codewiki/build-worker-protocol.ts +37 -3
  349. package/src/domains/context/codewiki/build-worker.ts +3 -35
  350. package/src/domains/context/codewiki/coordinator.ts +36 -6
  351. package/src/domains/context/codewiki/indexer.ts +59 -19
  352. package/src/domains/context/contract.ts +6 -2
  353. package/src/domains/context/extension.ts +72 -10
  354. package/src/domains/context/fingerprint.ts +39 -34
  355. package/src/domains/context/index.ts +7 -1
  356. package/src/domains/context/prompt-context.ts +55 -14
  357. package/src/domains/context/refresh.ts +9 -57
  358. package/src/domains/context/wiki/assemble.ts +14 -10
  359. package/src/domains/context/wiki/evidence.ts +209 -0
  360. package/src/domains/context/wiki/generate.ts +201 -67
  361. package/src/domains/context/wiki/meta.ts +10 -2
  362. package/src/domains/context/wiki/plan-store.ts +70 -14
  363. package/src/domains/context/wiki/plan.ts +71 -14
  364. package/src/domains/context/wiki/prompts.ts +42 -1
  365. package/src/domains/context/wiki/source-content.ts +106 -0
  366. package/src/domains/context/wiki/staleness.ts +33 -22
  367. package/src/domains/context/working-set/contract.ts +8 -2
  368. package/src/domains/context/working-set/engine.ts +17 -4
  369. package/src/domains/context/working-set/fold.ts +15 -2
  370. package/src/domains/context/working-set/marker.ts +2 -1
  371. package/src/domains/context/working-set/project.ts +18 -7
  372. package/src/domains/context/working-set/recall.ts +82 -56
  373. package/src/domains/dispatch/active-route-planner.ts +6 -3
  374. package/src/domains/dispatch/admission-queue.ts +19 -7
  375. package/src/domains/dispatch/admission.ts +3 -3
  376. package/src/domains/dispatch/budget-envelope.ts +47 -82
  377. package/src/domains/dispatch/capacity-lease.ts +57 -19
  378. package/src/domains/dispatch/contract.ts +10 -2
  379. package/src/domains/dispatch/event-pump.ts +28 -7
  380. package/src/domains/dispatch/execution-role.ts +49 -2
  381. package/src/domains/dispatch/execution-scheduler.ts +2 -0
  382. package/src/domains/dispatch/extension.ts +190 -105
  383. package/src/domains/dispatch/fleet-run.ts +20 -0
  384. package/src/domains/dispatch/gate-role-prompts.ts +4 -2
  385. package/src/domains/dispatch/parallel-writers.ts +34 -0
  386. package/src/domains/dispatch/reservation-store.ts +8 -34
  387. package/src/domains/dispatch/route-approval.ts +3 -3
  388. package/src/domains/dispatch/route-observer.ts +4 -2
  389. package/src/domains/dispatch/route-quality.ts +6 -1
  390. package/src/domains/dispatch/types.ts +4 -3
  391. package/src/domains/dispatch/worker-spawn.ts +58 -21
  392. package/src/domains/dispatch/workspace-checkpoint.ts +57 -0
  393. package/src/domains/eval/compare/behavioral.ts +81 -14
  394. package/src/domains/eval/compare/compare.ts +15 -5
  395. package/src/domains/eval/compare/envelope.ts +12 -5
  396. package/src/domains/eval/metrics/context.ts +24 -1
  397. package/src/domains/eval/metrics/tracked.ts +4 -28
  398. package/src/domains/eval/reports/comparison.ts +9 -9
  399. package/src/domains/eval/runners/clio-run.ts +5 -1
  400. package/src/domains/eval/schema/suite.ts +2 -0
  401. package/src/domains/eval/schema/validate.ts +1 -0
  402. package/src/domains/eval/suites/run.ts +189 -13
  403. package/src/domains/eval/verifiers/integrity.ts +39 -0
  404. package/src/domains/eval/verifiers/patch.ts +58 -2
  405. package/src/domains/eval/workspaces/temp-copy.ts +3 -0
  406. package/src/domains/evidence/build.ts +4 -2
  407. package/src/domains/interop/registry.ts +2 -2
  408. package/src/domains/middleware/hooks-io.ts +45 -26
  409. package/src/domains/middleware/hooks.ts +6 -0
  410. package/src/domains/middleware/injection-screen.ts +23 -0
  411. package/src/domains/middleware/rules.ts +5 -1
  412. package/src/domains/middleware/stalled-turn.ts +18 -3
  413. package/src/domains/middleware/task-board-reminder.ts +4 -2
  414. package/src/domains/middleware/task-nudge.ts +4 -1
  415. package/src/domains/mux/contract.ts +34 -1
  416. package/src/domains/mux/dock-controller.ts +8 -1
  417. package/src/domains/mux/index.ts +1 -0
  418. package/src/domains/mux/socket-client.ts +13 -3
  419. package/src/domains/observability/contract.ts +2 -2
  420. package/src/domains/observability/projection.ts +30 -9
  421. package/src/domains/prompts/compiler.ts +10 -2
  422. package/src/domains/prompts/contract.ts +7 -4
  423. package/src/domains/prompts/extension.ts +28 -64
  424. package/src/domains/prompts/fragments/identity/clio.md +23 -0
  425. package/src/domains/prompts/fragments/operating/contract.md +10 -0
  426. package/src/domains/prompts/fragments/operating/delegation.md +5 -0
  427. package/src/domains/prompts/fragments/wiki/page.md +28 -15
  428. package/src/domains/prompts/fragments/wiki/plan.md +4 -4
  429. package/src/domains/prompts/preload-prefix.ts +31 -0
  430. package/src/domains/prompts/preload.ts +135 -61
  431. package/src/domains/providers/auth/backend-file.ts +15 -11
  432. package/src/domains/providers/auth/storage.ts +3 -5
  433. package/src/domains/providers/catalog.ts +18 -3
  434. package/src/domains/providers/runtime-resolution.ts +11 -9
  435. package/src/domains/providers/runtimes/cloud/openrouter.ts +2 -0
  436. package/src/domains/resources/skills/promotion.ts +8 -1
  437. package/src/domains/safety/action-classifier.ts +9 -0
  438. package/src/domains/safety/autonomy.ts +10 -1
  439. package/src/domains/safety/contract.ts +5 -1
  440. package/src/domains/safety/default-path-policy.ts +11 -0
  441. package/src/domains/safety/extension.ts +11 -2
  442. package/src/domains/safety/policy-engine.ts +189 -32
  443. package/src/domains/safety/project-policy.ts +7 -2
  444. package/src/domains/safety/workspace-trust.ts +43 -0
  445. package/src/domains/session/compaction/compact.ts +384 -21
  446. package/src/domains/session/compaction/cut-point.ts +42 -5
  447. package/src/domains/session/compaction/tokens.ts +9 -1
  448. package/src/domains/session/decision-board.ts +43 -33
  449. package/src/domains/session/entries.ts +169 -4
  450. package/src/domains/session/prompt-manifest.ts +47 -8
  451. package/src/domains/session/task-board.ts +21 -3
  452. package/src/domains/user-tasks/handoff.ts +16 -0
  453. package/src/engine/acp/adapter.ts +44 -12
  454. package/src/engine/acp/server.ts +1 -0
  455. package/src/engine/acp/transport.ts +2 -1
  456. package/src/engine/acp/types.ts +6 -1
  457. package/src/engine/antigravity/subprocess-runtime.ts +20 -4
  458. package/src/engine/api-registry.ts +19 -2
  459. package/src/engine/apis/openai-completions.ts +13 -6
  460. package/src/engine/apis/output-budget.ts +26 -10
  461. package/src/engine/claude/sdk-runtime.ts +4 -3
  462. package/src/engine/env-api-keys.ts +2 -1
  463. package/src/engine/external-subprocess.ts +14 -3
  464. package/src/engine/loop-guard.ts +19 -2
  465. package/src/engine/provider-diagnostics.ts +129 -0
  466. package/src/engine/provider-payload.ts +3 -1
  467. package/src/engine/worker-runtime.ts +13 -2
  468. package/src/engine/worker-tools.ts +5 -1
  469. package/src/entry/extension-reload.ts +1 -0
  470. package/src/entry/orchestrator.ts +53 -15
  471. package/src/interactive/chat-loop-messages.ts +12 -4
  472. package/src/interactive/chat-loop.ts +115 -45
  473. package/src/interactive/chat-renderer.ts +60 -0
  474. package/src/interactive/context-recall-command.ts +2 -1
  475. package/src/interactive/dispatch-board.ts +17 -2
  476. package/src/interactive/editor-submit.ts +13 -0
  477. package/src/interactive/interactive-application.ts +8 -2
  478. package/src/interactive/interactive-event-projection.ts +7 -1
  479. package/src/interactive/interactive-presentation.ts +15 -7
  480. package/src/interactive/interactive-slash-runtime.ts +2 -0
  481. package/src/interactive/layout.ts +2 -1
  482. package/src/interactive/model-session-replay.ts +2 -2
  483. package/src/interactive/overlay-frame.ts +1 -0
  484. package/src/interactive/overlay-general-openers.ts +3 -1
  485. package/src/interactive/overlay-session-lifecycle.ts +6 -0
  486. package/src/interactive/overlays/ask-user.ts +1 -0
  487. package/src/interactive/overlays/message-picker.ts +1 -1
  488. package/src/interactive/renderers/tool-execution.ts +17 -1
  489. package/src/interactive/renderers/worker-entry.ts +25 -10
  490. package/src/interactive/slash-commands.ts +9 -7
  491. package/src/interactive/turn-context.ts +221 -53
  492. package/src/interactive/turn-middleware.ts +3 -1
  493. package/src/interactive/turn-persistence.ts +3 -0
  494. package/src/interactive/turn-runtime.ts +11 -2
  495. package/src/interactive/turn-state.ts +10 -9
  496. package/src/interactive/watch-pane.ts +18 -4
  497. package/src/interactive/worker-stream.ts +7 -7
  498. package/src/tools/agent-tools.ts +6 -3
  499. package/src/tools/bash.ts +1 -1
  500. package/src/tools/builtin-tool-catalog.ts +9 -2
  501. package/src/tools/codewiki/code-nav.ts +4 -10
  502. package/src/tools/compete-judge-task.ts +71 -0
  503. package/src/tools/compete-worktrees.ts +34 -0
  504. package/src/tools/context/index.ts +32 -7
  505. package/src/tools/context/surface.ts +15 -4
  506. package/src/tools/decide.ts +1 -1
  507. package/src/tools/dispatch-admission.ts +12 -1
  508. package/src/tools/dispatch-arguments.ts +38 -1
  509. package/src/tools/dispatch-plan.ts +7 -7
  510. package/src/tools/dispatch-runner.ts +48 -32
  511. package/src/tools/dispatch-schema.ts +30 -23
  512. package/src/tools/dispatch-scout-admission.ts +10 -44
  513. package/src/tools/dispatch-scout.ts +2 -3
  514. package/src/tools/find.ts +13 -4
  515. package/src/tools/grep.ts +13 -1
  516. package/src/tools/ls.ts +7 -1
  517. package/src/tools/monitor.ts +26 -11
  518. package/src/tools/network-policy.ts +11 -24
  519. package/src/tools/observation.ts +39 -2
  520. package/src/tools/read.ts +112 -15
  521. package/src/tools/registry.ts +54 -17
  522. package/src/tools/result-shaping.ts +110 -2
  523. package/src/tools/tasks.ts +33 -7
  524. package/src/tools/verify/frontend.ts +67 -30
  525. package/src/tools/verify/numeric.ts +6 -1
  526. package/src/tools/web-fetch-network.ts +179 -0
  527. package/src/tools/web-fetch-surface.ts +2 -1
  528. package/src/tools/web-fetch.ts +15 -13
  529. package/src/tools/worker-evidence.ts +27 -0
  530. package/src/worker/spec-contract.ts +12 -8
  531. package/dist/builtins-WGALA46I.js +0 -22
  532. package/dist/chunk-2WZ546HR.js +0 -792
  533. package/dist/chunk-5PSMVOLM.js +0 -56
  534. package/dist/chunk-EL24TAU4.js +0 -1560
  535. package/dist/chunk-IZXGRF7P.js +0 -4048
  536. package/dist/chunk-JVCV3ICN.js +0 -47
  537. package/dist/chunk-MNJGS2IN.js +0 -33
  538. package/dist/chunk-O5CVSAG5.js +0 -122
  539. package/dist/chunk-ODGTEFFI.js +0 -50
  540. package/dist/chunk-OQE5J4C6.js +0 -73
  541. package/dist/chunk-UUVG37B4.js +0 -244
  542. package/dist/chunk-V6HJFQZE.js +0 -228
  543. package/dist/clio-QLICPCF5.js +0 -25
  544. package/dist/configure-VEPX4NMX.js +0 -55
  545. package/dist/context-clear-S4ZJCQUX.js +0 -182
  546. package/dist/detail-A7JAVSIG.js +0 -98
  547. package/dist/evidence-4F5USFKH.js +0 -208
  548. package/dist/fleet-view-MN2VG4MR.js +0 -101
  549. package/dist/inventory-C26CFDRR.js +0 -101
  550. package/dist/preload-P6DGH2PZ.js +0 -13
  551. package/dist/slash-commands-ZXPJD64J.js +0 -92
  552. package/dist/tasks-IPAGMEIX.js +0 -36
  553. package/dist/tools-EFFEAIDP.js +0 -28
  554. package/dist/verify-FWYGPKMR.js +0 -29
  555. package/dist/wiki-generate-743CIGJW.js +0 -476
@@ -12,10 +12,21 @@
12
12
 
13
13
  import { streamSimple } from "../../../engine/ai.js";
14
14
  import type { EngineModel, Usage } from "../../../engine/types.js";
15
+ import type { WorkingSetView } from "../../context/working-set/contract.js";
15
16
  import { foldWorkingSet } from "../../context/working-set/fold.js";
17
+ import { projectWorkingSet } from "../../context/working-set/project.js";
16
18
  import { recallableRefListing } from "../../context/working-set/recall.js";
17
- import { extractReasoningTokens } from "../context-accounting.js";
18
- import type { CompactionUsage, SessionEntry } from "../entries.js";
19
+ import { estimateAgentContextTokens, extractReasoningTokens } from "../context-accounting.js";
20
+ import {
21
+ type CompactionUsage,
22
+ latestSkillContextState,
23
+ type PreservedUserContext,
24
+ type SessionEntry,
25
+ type SkillContextCheckpoint,
26
+ type SkillContextState,
27
+ skillContextContentHash,
28
+ verifiedSkillContextCheckpoint,
29
+ } from "../entries.js";
19
30
  import { serializeConversation } from "./branch-summary.js";
20
31
  import { findCutPoint } from "./cut-point.js";
21
32
  import { DEFAULT_KEEP_RECENT_TOKENS, DEFAULT_RESERVE_TOKENS } from "./defaults.js";
@@ -87,6 +98,43 @@ In addition to that carried-forward context, summarize ONLY the active-turn deta
87
98
 
88
99
  Do NOT answer the user. Do NOT summarize unrelated older history.`;
89
100
 
101
+ /** Validate the history checkpoint, never the intentionally different split-turn prompt. */
102
+ function validateHistorySummary(text: string): void {
103
+ const required = [
104
+ "## Goal",
105
+ "## Constraints & Preferences",
106
+ "## Progress",
107
+ "### Done",
108
+ "### In Progress",
109
+ "### Blocked",
110
+ "## Key Decisions",
111
+ "## Next Steps",
112
+ "## Critical Context",
113
+ ];
114
+ const headings: string[] = [];
115
+ let fence: { character: string; length: number } | undefined;
116
+ for (const line of text.split(/\r?\n/)) {
117
+ const fenceMatch = /^ {0,3}(`{3,}|~{3,})(.*)$/.exec(line);
118
+ if (fenceMatch) {
119
+ const marker = fenceMatch[1] ?? "";
120
+ if (!fence) fence = { character: marker[0] ?? "", length: marker.length };
121
+ else if (marker[0] === fence.character && marker.length >= fence.length && !fenceMatch[2]?.trim()) fence = undefined;
122
+ continue;
123
+ }
124
+ if (fence) continue;
125
+ const heading = /^ {0,3}(#{2,3})[ \t]+(.+?)(?:[ \t]+#+)?[ \t]*$/.exec(line);
126
+ if (heading) {
127
+ const normalized = `${heading[1]} ${heading[2]}`;
128
+ if (required.includes(normalized)) headings.push(normalized);
129
+ }
130
+ }
131
+ if (fence || headings.length !== required.length || headings.some((heading, index) => heading !== required[index])) {
132
+ throw new Error(
133
+ "compaction returned an incomplete history checkpoint: required headings must appear in order outside code fences; checkpoint was not saved",
134
+ );
135
+ }
136
+ }
137
+
90
138
  /** One invoked summary stream, including failed calls that produce no checkpoint. */
91
139
  export interface CompactionCallObservation {
92
140
  outcome: "success" | "error" | "aborted";
@@ -96,8 +144,17 @@ export interface CompactionCallObservation {
96
144
  }
97
145
 
98
146
  export interface CompactInput {
99
- /** Ordered session entries to compact. The caller reads these from the session domain. */
147
+ /** Ordered active-path session entries to compact; returned cut indexes address this same array. */
100
148
  entries: ReadonlyArray<SessionEntry>;
149
+ /** Authoritative main-agent selection; omitted for unknown legacy state. */
150
+ skillContextState?: SkillContextState | null;
151
+ /** Pure source-test seam. Production uses the existing summary stream. */
152
+ summarize?: (request: {
153
+ systemPrompt: string;
154
+ userText: string;
155
+ maxTokens: number;
156
+ }) => Promise<{ text: string; usage?: unknown }>;
157
+
101
158
  /** Resolved orchestrator or compaction-override model. */
102
159
  model: EngineModel;
103
160
  /** API key for the model. Optional because local engines accept a fallback handled upstream. */
@@ -114,11 +171,15 @@ export interface CompactInput {
114
171
  reserveTokens?: number;
115
172
  /** Override the built-in keep-recent default (DEFAULT_KEEP_RECENT_TOKENS). */
116
173
  keepRecentTokens?: number;
174
+ /** Carry this user message verbatim if removed; defaults to the latest operator turn for manual compaction. */
175
+ preserveUserTurnId?: string;
117
176
  /** Accounting observer; called once per invoked stream, including failures. */
118
177
  onCall?: (call: CompactionCallObservation) => void;
119
178
  }
120
179
 
121
180
  export interface CompactResult {
181
+ skillContext?: SkillContextCheckpoint;
182
+ userContext?: PreservedUserContext;
122
183
  /** Generated summary text. Empty when there was nothing to summarize. */
123
184
  summary: string;
124
185
  /**
@@ -191,6 +252,157 @@ function findTurnStartForProtection(
191
252
  return -1;
192
253
  }
193
254
 
255
+ /** Recover only complete, uniquely paired historical main-agent loads. Never consult current disk. */
256
+ export function captureSkillContext(
257
+ entries: ReadonlyArray<SessionEntry>,
258
+ selection: SkillContextState | undefined,
259
+ ): SkillContextCheckpoint | undefined {
260
+ if (!selection || selection.unknown) return undefined;
261
+ const newestSelected = Math.max(
262
+ -1,
263
+ ...selection.activationRefs.map((ref) => entries.findIndex((entry) => entry.turnId === ref)),
264
+ );
265
+ if (
266
+ selection.activationRefs.length > 0 &&
267
+ entries
268
+ .slice(newestSelected + 1)
269
+ .some((entry) => entry.kind === "skillActivation" && entry.activation.runId === undefined)
270
+ )
271
+ return undefined;
272
+ const skills: SkillContextCheckpoint["skills"] = [];
273
+ for (const ref of selection.activationRefs) {
274
+ const matches = entries.filter((entry) => entry.turnId === ref);
275
+ const entry = matches[0];
276
+ if (matches.length !== 1 || entry?.kind !== "skillActivation") return undefined;
277
+ const activation = entry.activation;
278
+ if (
279
+ activation.runId !== undefined ||
280
+ activation.triggeredBy !== "tool" ||
281
+ !activation.turnId ||
282
+ activation.drift === "mismatch"
283
+ )
284
+ return undefined;
285
+ // A later load with the same name supersedes this receipt, even if the later evidence is incomplete.
286
+ if (
287
+ entries
288
+ .slice(entries.indexOf(entry) + 1)
289
+ .some(
290
+ (later) =>
291
+ later.kind === "skillActivation" &&
292
+ later.activation.runId === undefined &&
293
+ later.activation.name === activation.name,
294
+ )
295
+ )
296
+ return undefined;
297
+ const request = entries.find((candidate) => candidate.turnId === activation.turnId);
298
+ if (request?.kind !== "message" || request.role !== "user") return undefined;
299
+ const start = entries.indexOf(request);
300
+ const next = entries.findIndex(
301
+ (candidate, index) => index > start && candidate.kind === "message" && candidate.role === "user",
302
+ );
303
+ const turn = entries.slice(start, next < 0 ? undefined : next);
304
+ if (!turn.includes(entry)) return undefined;
305
+ const calls = turn.filter((candidate) => {
306
+ if (candidate.kind !== "message" || candidate.role !== "tool_call") return false;
307
+ const payload = payloadObject(candidate.payload);
308
+ const args = payloadObject(payload?.args);
309
+ return payload?.name === "context" && args?.scope === "skills" && args.name === activation.name;
310
+ });
311
+ if (calls.length !== 1) return undefined;
312
+ const call = calls[0];
313
+ if (call?.kind !== "message") return undefined;
314
+ const callId = payloadObject(call.payload)?.toolCallId;
315
+ if (typeof callId !== "string" || !callId) return undefined;
316
+ const assistant = turn.find((candidate) => candidate.turnId === call.parentTurnId);
317
+ if (
318
+ assistant?.kind !== "message" ||
319
+ assistant.role !== "assistant" ||
320
+ !contentBlocks(assistant.payload).some(
321
+ (block) =>
322
+ block.type === "toolCall" &&
323
+ block.id === callId &&
324
+ block.name === "context" &&
325
+ JSON.stringify(block.arguments) === JSON.stringify(payloadObject(call.payload)?.args),
326
+ )
327
+ )
328
+ return undefined;
329
+ const results = entries.filter(
330
+ (candidate) =>
331
+ candidate.kind === "message" &&
332
+ candidate.role === "tool_result" &&
333
+ payloadObject(candidate.payload)?.toolCallId === callId,
334
+ );
335
+ const resultEntry = results[0];
336
+ if (
337
+ results.length !== 1 ||
338
+ resultEntry?.kind !== "message" ||
339
+ !turn.includes(resultEntry) ||
340
+ resultEntry.parentTurnId !== call.turnId ||
341
+ entry.parentTurnId !== request.turnId
342
+ )
343
+ return undefined;
344
+ const payload = payloadObject(resultEntry.payload);
345
+ const result = payloadObject(payload?.result);
346
+ const details = payloadObject(result?.details);
347
+ const observation = payloadObject(details?.observation);
348
+ const resultSummary = payloadObject(payload?.resultSummary);
349
+ const summaryObservation = payloadObject(resultSummary?.observation);
350
+ const sourceInfo = payloadObject(details?.sourceInfo);
351
+ if (
352
+ payload?.toolName !== "context" ||
353
+ payload.isError !== false ||
354
+ payload.outcome !== "ok" ||
355
+ details?.kind !== "ok" ||
356
+ observation?.truncated !== false ||
357
+ details.workingSet !== undefined ||
358
+ details.contextCompaction !== undefined ||
359
+ resultSummary?.truncated !== false ||
360
+ summaryObservation?.truncated === true ||
361
+ details.name !== activation.name ||
362
+ details.path !== activation.filePath ||
363
+ details.hash !== activation.hash ||
364
+ details.source !== activation.source ||
365
+ details.sourceOrigin !== activation.sourceOrigin ||
366
+ sourceInfo?.path !== activation.filePath ||
367
+ sourceInfo.scope !== details.scope ||
368
+ sourceInfo.source !== activation.sourceOrigin ||
369
+ (details.drift !== undefined && details.drift !== "match") ||
370
+ details.drift !== activation.drift ||
371
+ !Array.isArray(result?.content) ||
372
+ !result.content.every((block: unknown) => {
373
+ const obj = payloadObject(block);
374
+ return obj?.type === "text" && typeof obj.text === "string";
375
+ })
376
+ )
377
+ return undefined;
378
+ const content = result.content as Array<{ type: "text"; text: string }>;
379
+ const text = content.map((block) => block.text).join("\n");
380
+ if (
381
+ observation.shownBytes !== Buffer.byteLength(text, "utf8") ||
382
+ observation.totalBytes !== observation.shownBytes ||
383
+ resultSummary?.bytes !== observation.shownBytes
384
+ )
385
+ return undefined;
386
+ const requestPayload = payloadObject(request.payload);
387
+ const operatorText = requestPayload?.operatorText;
388
+ const requestText =
389
+ typeof operatorText === "string" && operatorText.trim().length > 0 ? operatorText : requestPayload?.text;
390
+ if (typeof requestText !== "string") return undefined;
391
+ skills.push({
392
+ activationRef: ref,
393
+ requestRef: request.turnId,
394
+ callRef: call.turnId,
395
+ resultRef: resultEntry.turnId,
396
+ activation: structuredClone(activation),
397
+ requestText,
398
+ content: structuredClone(content),
399
+ contentHash: skillContextContentHash(content),
400
+ });
401
+ }
402
+ const checkpoint = { version: 1 as const, skills };
403
+ return verifiedSkillContextCheckpoint(checkpoint) ? checkpoint : undefined;
404
+ }
405
+
194
406
  function buildPreviousContextPrefix(previousContextText: string): string {
195
407
  const trimmed = previousContextText.trim();
196
408
  return trimmed.length > 0 ? `<previous-context>\n${trimmed}\n</previous-context>\n\n` : "";
@@ -320,20 +532,30 @@ function formatFileOperations(fileOps: FileOperations): string {
320
532
  return sections.length > 0 ? `\n\n${sections.join("\n\n")}` : "";
321
533
  }
322
534
 
323
- function formatRecallableRefs(entries: ReadonlyArray<SessionEntry>, firstKeptEntryIndex: number): string {
535
+ function formatRecallableRefs(
536
+ entries: ReadonlyArray<SessionEntry>,
537
+ firstKeptEntryIndex: number,
538
+ view: WorkingSetView,
539
+ ): string {
324
540
  const entryIndexes = new Map<string, number>();
325
541
  for (let index = 0; index < entries.length; index += 1) {
326
542
  const entry = entries[index];
327
543
  if (entry) entryIndexes.set(entry.turnId, index);
328
544
  }
329
- const view = foldWorkingSet(entries);
330
545
  const evictedBeforeCut = new Map(
331
546
  [...view.evicted].filter(([ref]) => (entryIndexes.get(ref) ?? Number.POSITIVE_INFINITY) < firstKeptEntryIndex),
332
547
  );
333
548
  const listing = recallableRefListing(entries, { ...view, evicted: evictedBeforeCut });
334
- if (listing.refs.length === 0) return "";
549
+ if (
550
+ listing.refs.length === 0 &&
551
+ !entries.slice(0, firstKeptEntryIndex).some((entry) => entry.kind === "message" && entry.role === "tool_result")
552
+ )
553
+ return "";
335
554
  const rows = [...listing.refs];
336
555
  if (listing.remaining > 0) rows.push(`and ${listing.remaining} more`);
556
+ rows.push(
557
+ 'Preview only. Persisted original tool results removed by this summary are also recallable. Discover all active-path results with context(scope="recall", limit=8, offset=0), omitting ref; query filters path/tool/ref terms. Follow nextOffset, then recall the selected ref.',
558
+ );
337
559
  return `\n\n<recallable-refs>\n${rows.join("\n")}\n</recallable-refs>`;
338
560
  }
339
561
 
@@ -411,13 +633,36 @@ async function runSummaryStream(
411
633
  systemPrompt,
412
634
  messages: [buildUserMessage(userText)],
413
635
  };
636
+ // Price the complete serialized request, including templates, previous
637
+ // context, custom instructions and message overhead. This is the shared
638
+ // estimate, not provider-exact tokenization; never truncate constraints to
639
+ // make an oversized projected conversation fit.
640
+ const estimatedInput = estimateAgentContextTokens(context);
641
+ const contextWindow = input.model.contextWindow;
642
+ if (!Number.isFinite(contextWindow) || contextWindow <= 0) {
643
+ throw new Error("compaction requires a positive finite model context window");
644
+ }
645
+ if (estimatedInput + maxTokens > contextWindow) {
646
+ throw new Error(
647
+ `compaction estimated input ${estimatedInput} tokens plus output ${maxTokens} tokens exceeds model context window ${contextWindow}; use a larger compaction model or reduce the working set`,
648
+ );
649
+ }
414
650
 
651
+ input.signal?.throwIfAborted();
415
652
  const timestamp = new Date().toISOString();
416
653
  const started = performance.now();
417
654
  let usage: unknown;
418
655
  let reported: Record<string, unknown> = {};
419
656
  let outcome: CompactionCallObservation["outcome"] = "error";
420
657
  try {
658
+ if (input.summarize) {
659
+ const response = await input.summarize({ systemPrompt, userText, maxTokens });
660
+ usage = response.usage;
661
+ reported = retainReportedUsage(reported, usage);
662
+ input.signal?.throwIfAborted();
663
+ outcome = "success";
664
+ return { text: response.text.trim(), usage };
665
+ }
421
666
  // Summarization requests thinking off, as its resolver does. Bare stream
422
667
  // infers an active level from model.reasoning and would undo that choice.
423
668
  const events = streamSimple(
@@ -434,6 +679,11 @@ async function runSummaryStream(
434
679
  }
435
680
  if (event.type === "done") {
436
681
  usage = event.message.usage ?? usage;
682
+ reported = retainReportedUsage(reported, usage);
683
+ input.signal?.throwIfAborted();
684
+ if (event.reason === "length" || event.message.stopReason === "length") {
685
+ throw new Error("compaction summary reached the model output limit; incomplete checkpoint was not saved");
686
+ }
437
687
  outcome = "success";
438
688
  return { text: textFromAssistant(event.message).trim(), usage };
439
689
  }
@@ -465,6 +715,12 @@ async function runSummaryStream(
465
715
  export async function compact(input: CompactInput): Promise<CompactResult> {
466
716
  const reserveTokens = input.reserveTokens ?? DEFAULT_RESERVE_TOKENS;
467
717
  const keepRecentTokens = input.keepRecentTokens ?? DEFAULT_KEEP_RECENT_TOKENS;
718
+ // Apply the same ledger decisions as live replay before pricing or
719
+ // serializing any slice, including the prior checkpoint's retained suffix.
720
+ // Projection preserves positions and turn IDs; cuts still address the raw
721
+ // input, which remains untouched and available for exact recall.
722
+ const workingSet = foldWorkingSet(input.entries);
723
+ const entries = projectWorkingSet(input.entries, workingSet);
468
724
  // Iterative compaction: when a prior `compactionSummary` exists, the
469
725
  // summary is canonical history. Restrict the cut search and the new-history
470
726
  // slice to entries strictly after that boundary; the canonical summary and
@@ -472,29 +728,89 @@ export async function compact(input: CompactInput): Promise<CompactResult> {
472
728
  // than rediscovering already-compacted raw history. Mirrors pi-coding-agent's
473
729
  // `boundaryStart = prevCompactionIndex + 1` and `usageStart = prevCompactionIndex`
474
730
  // in compaction.ts:619-628.
475
- const prevCompactionIndex = findLatestCompactionIndex(input.entries);
731
+ const prevCompactionIndex = findLatestCompactionIndex(entries);
476
732
  const boundaryStart = prevCompactionIndex + 1;
477
- const protectedStart = findLatestSkillActivationProtectionStart(input.entries, boundaryStart);
733
+ const selection =
734
+ input.skillContextState === null ? undefined : (input.skillContextState ?? latestSkillContextState(input.entries));
735
+ let skillContext = captureSkillContext(input.entries, selection);
736
+ const priorCheckpoint = entries[prevCompactionIndex];
737
+ // An explicit-off checkpoint carries an empty skill list: nothing was
738
+ // retained, so nothing needs re-verification and later unknown state must
739
+ // not block compaction forever.
740
+ const priorSkillContext =
741
+ priorCheckpoint?.kind === "compactionSummary" &&
742
+ priorCheckpoint.skillContext !== undefined &&
743
+ priorCheckpoint.skillContext.skills.length > 0
744
+ ? priorCheckpoint.skillContext
745
+ : undefined;
746
+ // A typed checkpoint is not regenerated from summary prose. Failure to verify
747
+ // its original receipts prevents another destructive pass.
748
+ if (priorSkillContext !== undefined && !skillContext) {
749
+ throw new Error("cannot verify preserved skill context; retaining the existing checkpoint");
750
+ }
751
+ if (priorSkillContext !== undefined) {
752
+ if (!verifiedSkillContextCheckpoint(priorSkillContext)) throw new Error("invalid preserved skill checkpoint");
753
+ for (const previous of priorSkillContext.skills) {
754
+ const current = skillContext?.skills.find((skill) => skill.activationRef === previous.activationRef);
755
+ if (current && JSON.stringify(current) !== JSON.stringify(previous)) {
756
+ throw new Error("preserved skill context no longer matches its captured receipt");
757
+ }
758
+ }
759
+ }
760
+ if (skillContext && priorSkillContext !== undefined) {
761
+ skillContext = {
762
+ version: 1,
763
+ skills: skillContext.skills.map((skill) =>
764
+ structuredClone(
765
+ priorSkillContext.skills.find((previous) => previous.activationRef === skill.activationRef) ?? skill,
766
+ ),
767
+ ),
768
+ };
769
+ }
770
+ // A legacy checkpoint (no typed field) never adjudicated older activations,
771
+ // so the fallback clamp stays fail-closed across its boundary. A typed
772
+ // checkpoint already retained or explicitly dropped everything before it.
773
+ const legacyPriorCheckpoint =
774
+ priorCheckpoint?.kind === "compactionSummary" && priorCheckpoint.skillContext === undefined;
775
+ const protectedStart = skillContext
776
+ ? null
777
+ : findLatestSkillActivationProtectionStart(entries, legacyPriorCheckpoint ? 0 : boundaryStart);
478
778
  const usageStart = prevCompactionIndex >= 0 ? prevCompactionIndex : 0;
479
- const usageEntries = input.entries.slice(usageStart);
779
+ const usageEntries = entries.slice(usageStart);
480
780
  const lastUsage = getLastAssistantUsage(usageEntries);
481
781
  const tokensBefore = calculateContextTokens(usageEntries, lastUsage);
482
- const rawCut = findCutPoint(input.entries, keepRecentTokens, { startIndex: boundaryStart });
782
+ const rawCut = findCutPoint(entries, keepRecentTokens, { startIndex: boundaryStart });
483
783
  const cut =
484
784
  protectedStart !== null && rawCut.firstKeptEntryIndex > protectedStart
485
785
  ? { firstKeptEntryIndex: protectedStart, turnStartIndex: -1, isSplitTurn: false }
486
786
  : rawCut;
487
787
  const historyEnd = cut.isSplitTurn ? cut.turnStartIndex : cut.firstKeptEntryIndex;
488
- const pre = input.entries.slice(boundaryStart, Math.max(boundaryStart, historyEnd));
788
+ const pre = entries.slice(boundaryStart, Math.max(boundaryStart, historyEnd));
489
789
  const turnPrefix = cut.isSplitTurn
490
- ? input.entries.slice(Math.max(boundaryStart, cut.turnStartIndex), cut.firstKeptEntryIndex)
790
+ ? entries.slice(Math.max(boundaryStart, cut.turnStartIndex), cut.firstKeptEntryIndex)
491
791
  : [];
492
- const previousContextEntries = priorCompactionContextEntries(input.entries, prevCompactionIndex);
792
+ const previousContextEntries = priorCompactionContextEntries(entries, prevCompactionIndex);
493
793
  const previousContextText = serializeConversation(previousContextEntries);
494
- const fileOps = extractFileOps([...previousContextEntries, ...pre, ...turnPrefix]);
794
+ const fileOps = extractFileOps([
795
+ ...priorCompactionContextEntries(input.entries, prevCompactionIndex),
796
+ ...input.entries.slice(boundaryStart, cut.firstKeptEntryIndex),
797
+ ]);
495
798
  const firstKept = input.entries[cut.firstKeptEntryIndex] ?? null;
496
-
497
- if (pre.length === 0 && turnPrefix.length === 0) {
799
+ // The newest complete exchange can begin immediately after the checkpoint.
800
+ // Its earlier retained suffix is still live context, even though it sits
801
+ // before boundaryStart in the append-only ledger. Summarize that suffix
802
+ // with the canonical prior summary instead of declaring nothing to compact.
803
+ // Never use this path to cross a protected cut or to re-summarize a bare
804
+ // checkpoint with no retained work; the caller still enforces request fit.
805
+ const priorSuffix = previousContextEntries.slice(1);
806
+ const summarizePriorSuffix =
807
+ pre.length === 0 &&
808
+ turnPrefix.length === 0 &&
809
+ firstKept !== null &&
810
+ cut.firstKeptEntryIndex >= boundaryStart &&
811
+ priorSuffix.some((entry) => entry.kind === "message" || entry.kind === "bashExecution");
812
+
813
+ if (pre.length === 0 && turnPrefix.length === 0 && !summarizePriorSuffix) {
498
814
  return {
499
815
  summary: "",
500
816
  firstKeptEntryIndex: cut.firstKeptEntryIndex,
@@ -506,15 +822,25 @@ export async function compact(input: CompactInput): Promise<CompactResult> {
506
822
  }
507
823
 
508
824
  const systemPrompt = input.systemPrompt ?? COMPACTION_SYSTEM_PROMPT;
509
- const maxTokens = Math.max(1024, Math.floor(reserveTokens * 0.8));
825
+ if (!Number.isFinite(reserveTokens) || reserveTokens <= 0) {
826
+ throw new Error("compaction requires a positive finite reserve token budget");
827
+ }
828
+ if (!Number.isFinite(input.model.maxTokens) || input.model.maxTokens < 1) {
829
+ throw new Error("compaction requires a positive finite model output token limit");
830
+ }
831
+ const maxTokens = Math.min(Math.floor(input.model.maxTokens), Math.max(1024, Math.floor(reserveTokens * 0.8)));
510
832
  const summaryParts: string[] = [];
511
833
  let usage: CompactionUsage | undefined;
512
- if (pre.length > 0) {
513
- const conversationText = serializeConversation(pre);
514
- const userText = buildUserText(conversationText, input.instructions, previousContextText);
834
+ if (pre.length > 0 || summarizePriorSuffix) {
835
+ const conversationText = serializeConversation(summarizePriorSuffix ? priorSuffix : pre);
836
+ const previousText = summarizePriorSuffix
837
+ ? serializeConversation(previousContextEntries.slice(0, 1))
838
+ : previousContextText;
839
+ const userText = buildUserText(conversationText, input.instructions, previousText);
515
840
  const historySummary = await runSummaryStream(input, userText, systemPrompt, maxTokens);
516
841
  usage = addCompactionUsage(usage, historySummary.usage);
517
842
  if (historySummary.text.length === 0) throw new Error("compaction returned an empty history summary");
843
+ validateHistorySummary(historySummary.text);
518
844
  summaryParts.push(historySummary.text);
519
845
  }
520
846
  if (turnPrefix.length > 0) {
@@ -526,9 +852,44 @@ export async function compact(input: CompactInput): Promise<CompactResult> {
526
852
  summaryParts.push(`**Turn Context (split turn):**\n\n${prefixSummary.text}`);
527
853
  }
528
854
 
855
+ // A generated split summary is not a reliable copy of the active request.
856
+ // Keep it in the canonical checkpoint so live replay and resume agree.
857
+ let userContext: PreservedUserContext | undefined =
858
+ priorCheckpoint?.kind === "compactionSummary" ? priorCheckpoint.userContext : undefined;
859
+ // Manual compaction has no live active-turn hint after a turn settles.
860
+ // Preserve the latest operator request if the split removes it as well.
861
+ let activeUserIndex = -1;
862
+ for (let index = entries.length - 1; index >= 0; index--) {
863
+ const entry = entries[index];
864
+ if (
865
+ entry?.kind === "message" &&
866
+ entry.role === "user" &&
867
+ (input.preserveUserTurnId === undefined || entry.turnId === input.preserveUserTurnId)
868
+ ) {
869
+ activeUserIndex = index;
870
+ break;
871
+ }
872
+ }
873
+ const activeUser =
874
+ activeUserIndex >= 0 && activeUserIndex < cut.firstKeptEntryIndex ? entries[activeUserIndex] : undefined;
875
+ if (activeUser?.kind === "message" && activeUser.payload && typeof activeUser.payload === "object") {
876
+ const payload = activeUser.payload;
877
+ // Composed text can contain transient reminders. Reassert only the
878
+ // operator's canonical words when present, without normalizing them.
879
+ const operatorText = "operatorText" in payload ? payload.operatorText : undefined;
880
+ const text =
881
+ typeof operatorText === "string" && operatorText.trim().length > 0
882
+ ? operatorText
883
+ : "text" in payload && typeof payload.text === "string"
884
+ ? payload.text
885
+ : null;
886
+ if (text !== null) userContext = { turnId: activeUser.turnId, text };
887
+ }
888
+
529
889
  const summary = `${summaryParts.join("\n\n---\n\n").trim()}${formatFileOperations(fileOps)}${formatRecallableRefs(
530
890
  input.entries,
531
891
  cut.firstKeptEntryIndex,
892
+ workingSet,
532
893
  )}`.trim();
533
894
 
534
895
  return {
@@ -536,9 +897,11 @@ export async function compact(input: CompactInput): Promise<CompactResult> {
536
897
  firstKeptEntryIndex: cut.firstKeptEntryIndex,
537
898
  firstKeptTurnId: firstKept?.turnId ?? null,
538
899
  tokensBefore,
539
- messagesSummarized: pre.length + turnPrefix.length,
900
+ messagesSummarized: pre.length + turnPrefix.length + (summarizePriorSuffix ? priorSuffix.length : 0),
540
901
  isSplitTurn: cut.isSplitTurn,
541
902
  ...(usage !== undefined ? { usage } : {}),
903
+ ...(skillContext !== undefined ? { skillContext } : {}),
904
+ ...(userContext !== undefined ? { userContext } : {}),
542
905
  };
543
906
  }
544
907
 
@@ -52,11 +52,11 @@ function findTurnStartIndex(entries: ReadonlyArray<SessionEntry>, entryIndex: nu
52
52
  return -1;
53
53
  }
54
54
 
55
- /** Entries we can cut at. `tool_result` is the only role we must NOT cut at. */
55
+ /** Entries we can cut at. Tool rows must stay with their assistant declaration. */
56
56
  function isValidCutPoint(entry: SessionEntry): boolean {
57
57
  switch (entry.kind) {
58
58
  case "message":
59
- return entry.role !== "tool_result";
59
+ return entry.role !== "tool_result" && entry.role !== "tool_call";
60
60
  case "bashExecution":
61
61
  case "custom":
62
62
  case "skillActivation":
@@ -88,6 +88,36 @@ function findValidCutPoints(entries: ReadonlyArray<SessionEntry>, startIndex: nu
88
88
  return cuts;
89
89
  }
90
90
 
91
+ /** Retain the assistant declaration and its entire tool batch when the tail alone exceeds the budget. */
92
+ function findToolBatchStart(
93
+ entries: ReadonlyArray<SessionEntry>,
94
+ resultIndex: number,
95
+ startIndex: number,
96
+ endIndex: number,
97
+ ): number {
98
+ for (let index = resultIndex - 1; index >= startIndex; index--) {
99
+ const entry = entries[index];
100
+ if (entry?.kind !== "message") continue;
101
+ if (entry.role === "user") break;
102
+ if (entry.role !== "assistant") continue;
103
+ const payload = entry.payload as { content?: unknown } | null;
104
+ if (!Array.isArray(payload?.content)) break;
105
+ const callIds = new Set<string>();
106
+ for (const block of payload.content) {
107
+ if (block?.type === "toolCall" && typeof block.id === "string") callIds.add(block.id);
108
+ }
109
+ if (callIds.size === 0) break;
110
+ for (let tail = index + 1; tail < endIndex; tail++) {
111
+ const result = entries[tail];
112
+ if (result?.kind !== "message" || result.role !== "tool_result") continue;
113
+ const id = (result.payload as { toolCallId?: unknown } | null)?.toolCallId;
114
+ if (typeof id !== "string" || !callIds.has(id)) return -1;
115
+ }
116
+ return index;
117
+ }
118
+ return -1;
119
+ }
120
+
91
121
  /**
92
122
  * Find the cut point that keeps at least `keepRecentTokens` tokens in the
93
123
  * retained suffix. Never cuts at a `tool_result`. When walking forward from
@@ -131,14 +161,21 @@ export function findCutPoint(
131
161
  break;
132
162
  }
133
163
  }
164
+ // No newer cut exists inside a final tool-result batch. Snap back to
165
+ // its assistant, not the whole user turn or an individual call row.
166
+ // The suffix may exceed the target; the continuation guard still
167
+ // checks whether summarizing older work actually made the request fit.
168
+ if (cutIndex === -1 && entry.kind === "message" && (entry.role === "tool_result" || entry.role === "tool_call")) {
169
+ cutIndex = findToolBatchStart(entries, i, startIndex, endIndex);
170
+ }
134
171
  break;
135
172
  }
136
173
  }
137
174
 
138
175
  if (cutIndex === -1) {
139
- // Walker never crossed keepRecentTokens, or crossed but found no valid
140
- // cut at/after the stop index (all valid cuts precede the tool_result
141
- // tail). Prefer the newest turn start so older turns still feed the
176
+ // Walker never crossed keepRecentTokens, or found neither a newer cut
177
+ // nor a verifiable assistant declaration for the final result batch.
178
+ // Prefer the newest turn start so older turns still feed the
142
179
  // summary prompt. Absent any turn start, fall back to the oldest valid
143
180
  // cut. That matches the pre-fix behavior, so pre stays empty and the
144
181
  // orchestrator reports nothing to compact.
@@ -62,7 +62,15 @@ function estimateCustom(entry: CustomEntry): number {
62
62
  }
63
63
 
64
64
  function estimateSummary(entry: BranchSummaryEntry | CompactionSummaryEntry): number {
65
- return ceilChars(entry.summary.length);
65
+ let tokens = ceilChars(entry.summary.length);
66
+ if (entry.kind !== "compactionSummary") return tokens;
67
+ if (entry.userContext) tokens += ceilChars(entry.userContext.text.length + 40) + 4;
68
+ for (const skill of entry.skillContext?.skills ?? []) {
69
+ tokens += ceilChars(skill.requestText.length + 40) + 4;
70
+ tokens += ceilChars(JSON.stringify(skill.activation).length + 32) + 4;
71
+ for (const block of skill.content) tokens += ceilChars(block.text.length) + 4;
72
+ }
73
+ return tokens;
66
74
  }
67
75
 
68
76
  /**