token-goat 2.9.29 → 2.9.31

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 (197) hide show
  1. package/README.md +53 -42
  2. package/SECURITY.md +37 -11
  3. package/THIRD_PARTY_NOTICES.md +41 -4
  4. package/dist/native/linux-arm64/tg-hook +0 -0
  5. package/dist/native/linux-x64/tg-hook +0 -0
  6. package/dist/native/win32-arm64/tg-hook.exe +0 -0
  7. package/dist/native/win32-x64/tg-hook.exe +0 -0
  8. package/dist/ort-wasm-simd-threaded.mjs +59 -0
  9. package/dist/{token-goat-chunk-SE6E4BKJ.mjs → token-goat-chunk-25TRAWET.mjs} +23 -6
  10. package/dist/token-goat-chunk-2KXO6V2B.mjs +203 -0
  11. package/dist/{token-goat-chunk-UXSXQQIY.mjs → token-goat-chunk-2M7E4PF7.mjs} +43 -14
  12. package/dist/token-goat-chunk-2UPZGKKY.mjs +188 -0
  13. package/dist/token-goat-chunk-2WLPWKHV.mjs +135 -0
  14. package/dist/token-goat-chunk-2XBMMDBD.mjs +126 -0
  15. package/dist/token-goat-chunk-32ZOY4N5.mjs +23 -0
  16. package/dist/token-goat-chunk-3EZRNKTK.mjs +188 -0
  17. package/dist/token-goat-chunk-4ADZHI7J.mjs +63 -0
  18. package/dist/token-goat-chunk-4GBVPH3D.mjs +242 -0
  19. package/dist/{token-goat-chunk-2WOUYWLM.mjs → token-goat-chunk-4GILLLWY.mjs} +34 -7
  20. package/dist/token-goat-chunk-4NAPX7BA.mjs +90 -0
  21. package/dist/{token-goat-chunk-NMBWLRHW.mjs → token-goat-chunk-4SC7UJYV.mjs} +9981 -11563
  22. package/dist/token-goat-chunk-4SMRO4TO.mjs +366 -0
  23. package/dist/{token-goat-chunk-O6I2XU4P.mjs → token-goat-chunk-4ZBFWLXF.mjs} +310 -441
  24. package/dist/token-goat-chunk-57BIAXJL.mjs +286 -0
  25. package/dist/token-goat-chunk-5AC66HNP.mjs +115 -0
  26. package/dist/token-goat-chunk-5IMLKSOP.mjs +145 -0
  27. package/dist/token-goat-chunk-5RG5SBL6.mjs +221 -0
  28. package/dist/{token-goat-chunk-RRNZMM3A.mjs → token-goat-chunk-5Y6ZYL6U.mjs} +21 -2
  29. package/dist/token-goat-chunk-646E6U44.mjs +398 -0
  30. package/dist/token-goat-chunk-65N4RHP4.mjs +33 -0
  31. package/dist/{token-goat-chunk-6AK46ZT7.mjs → token-goat-chunk-6DG6HWP3.mjs} +13 -3
  32. package/dist/token-goat-chunk-6ENQSNRZ.mjs +573 -0
  33. package/dist/token-goat-chunk-6ZY4GNF2.mjs +91 -0
  34. package/dist/{token-goat-chunk-E5TK5DNO.mjs → token-goat-chunk-76FGDLRO.mjs} +574 -340
  35. package/dist/{token-goat-chunk-TGOXNAHW.mjs → token-goat-chunk-7EZTZOMC.mjs} +780 -767
  36. package/dist/token-goat-chunk-7MAOA6X4.mjs +3647 -0
  37. package/dist/token-goat-chunk-7R2ZVVAX.mjs +218 -0
  38. package/dist/{token-goat-chunk-TCQANXYC.mjs → token-goat-chunk-AM5V6GSX.mjs} +18 -2
  39. package/dist/token-goat-chunk-AUNGYYQX.mjs +184 -0
  40. package/dist/token-goat-chunk-AUQYRMMH.mjs +2985 -0
  41. package/dist/token-goat-chunk-B3PEKBYG.mjs +128 -0
  42. package/dist/{token-goat-chunk-KOPIR3KZ.mjs → token-goat-chunk-BA4HI6BW.mjs} +1910 -165
  43. package/dist/{token-goat-chunk-52NSDWYY.mjs → token-goat-chunk-BFCWY73P.mjs} +58 -20
  44. package/dist/token-goat-chunk-BPGCUMR7.mjs +30 -0
  45. package/dist/token-goat-chunk-BWGFUZZE.mjs +25 -0
  46. package/dist/token-goat-chunk-C75NA7PL.mjs +322 -0
  47. package/dist/token-goat-chunk-CBIQ7WTD.mjs +87 -0
  48. package/dist/token-goat-chunk-CETM74KC.mjs +307 -0
  49. package/dist/token-goat-chunk-CIMQ2BB3.mjs +233 -0
  50. package/dist/{token-goat-chunk-DNSPXQXQ.mjs → token-goat-chunk-CJLS3CDL.mjs} +70 -18
  51. package/dist/{token-goat-chunk-MELOKFDJ.mjs → token-goat-chunk-CO3UYX6G.mjs} +7 -1
  52. package/dist/token-goat-chunk-COPNXRJM.mjs +154 -0
  53. package/dist/token-goat-chunk-CSJ5L3NL.mjs +479 -0
  54. package/dist/token-goat-chunk-CVCEVUGK.mjs +315 -0
  55. package/dist/token-goat-chunk-CXHOFN7R.mjs +371 -0
  56. package/dist/token-goat-chunk-D735C4QM.mjs +603 -0
  57. package/dist/{token-goat-chunk-E4ZOJIZK.mjs → token-goat-chunk-DGS2LVNA.mjs} +70 -160
  58. package/dist/{token-goat-chunk-L7H3U27L.mjs → token-goat-chunk-DOWRSMWO.mjs} +1 -1
  59. package/dist/token-goat-chunk-E45INMY3.mjs +71 -0
  60. package/dist/token-goat-chunk-EC5F37F4.mjs +244 -0
  61. package/dist/{token-goat-chunk-XTQAOTSO.mjs → token-goat-chunk-EDBDRVH5.mjs} +4 -1
  62. package/dist/token-goat-chunk-EELTBKDM.mjs +613 -0
  63. package/dist/token-goat-chunk-EVMZJ27Z.mjs +147 -0
  64. package/dist/token-goat-chunk-EXKGNHEG.mjs +2096 -0
  65. package/dist/{token-goat-chunk-YOOVFPTP.mjs → token-goat-chunk-F4HYL64R.mjs} +12 -2
  66. package/dist/token-goat-chunk-F6PAUIEK.mjs +624 -0
  67. package/dist/token-goat-chunk-FDSREWLX.mjs +692 -0
  68. package/dist/{token-goat-chunk-NMTKNYGF.mjs → token-goat-chunk-FNFBKLRD.mjs} +74 -9
  69. package/dist/token-goat-chunk-G5PJ7AGM.mjs +36 -0
  70. package/dist/token-goat-chunk-GGGG7RWB.mjs +236 -0
  71. package/dist/{token-goat-chunk-TDUT2CL6.mjs → token-goat-chunk-GL3ETKSC.mjs} +276 -19
  72. package/dist/{token-goat-chunk-7CPMDFGB.mjs → token-goat-chunk-GVB2MUST.mjs} +265 -1567
  73. package/dist/token-goat-chunk-GWFLAUMQ.mjs +307 -0
  74. package/dist/token-goat-chunk-HAVAOB3S.mjs +87 -0
  75. package/dist/token-goat-chunk-HLPW63A7.mjs +48 -0
  76. package/dist/token-goat-chunk-HU4TORC5.mjs +1377 -0
  77. package/dist/token-goat-chunk-I7VKZZAW.mjs +35 -0
  78. package/dist/token-goat-chunk-IA6XSPE3.mjs +218 -0
  79. package/dist/token-goat-chunk-IAGXMHIK.mjs +863 -0
  80. package/dist/{token-goat-chunk-435UQTKD.mjs → token-goat-chunk-IK2DRMFX.mjs} +129 -74
  81. package/dist/{token-goat-chunk-ZER6EAXZ.mjs → token-goat-chunk-INNPTRUX.mjs} +2954 -2783
  82. package/dist/token-goat-chunk-JJ5BX4F4.mjs +129 -0
  83. package/dist/token-goat-chunk-JVFSHVFJ.mjs +129 -0
  84. package/dist/token-goat-chunk-KGEFFSHD.mjs +50 -0
  85. package/dist/token-goat-chunk-KKUFXAPD.mjs +25 -0
  86. package/dist/token-goat-chunk-KQBLRPBN.mjs +433 -0
  87. package/dist/token-goat-chunk-LCNQ2CNN.mjs +497 -0
  88. package/dist/token-goat-chunk-M3LFJDPU.mjs +58 -0
  89. package/dist/token-goat-chunk-M52KPT3C.mjs +87 -0
  90. package/dist/token-goat-chunk-MBEG42H7.mjs +150 -0
  91. package/dist/{token-goat-chunk-EVC4TOLE.mjs → token-goat-chunk-METECDOH.mjs} +3 -12
  92. package/dist/{token-goat-chunk-2AWQ2R5X.mjs → token-goat-chunk-MHX7XCC3.mjs} +3 -2
  93. package/dist/token-goat-chunk-MNWKPRAL.mjs +13 -0
  94. package/dist/token-goat-chunk-N5LSOVSU.mjs +137 -0
  95. package/dist/{token-goat-chunk-DPNLUJWB.mjs → token-goat-chunk-N5MMR2IW.mjs} +30 -8
  96. package/dist/token-goat-chunk-N7B3JQ2C.mjs +160 -0
  97. package/dist/{token-goat-chunk-VMFWNHGR.mjs → token-goat-chunk-NISNMD7T.mjs} +2545 -2953
  98. package/dist/token-goat-chunk-NMD42SFQ.mjs +434 -0
  99. package/dist/token-goat-chunk-NOSS5VWY.mjs +174 -0
  100. package/dist/token-goat-chunk-NSNSPPBG.mjs +69 -0
  101. package/dist/token-goat-chunk-OBOFIHKN.mjs +38 -0
  102. package/dist/token-goat-chunk-OBRFJ5O5.mjs +76 -0
  103. package/dist/token-goat-chunk-ODBT2USM.mjs +800 -0
  104. package/dist/token-goat-chunk-OS5EM5PP.mjs +107 -0
  105. package/dist/token-goat-chunk-OUKDTVNU.mjs +1178 -0
  106. package/dist/token-goat-chunk-OXFMP75N.mjs +566 -0
  107. package/dist/{token-goat-chunk-ASLWOQ3I.mjs → token-goat-chunk-OYIYKDDT.mjs} +2 -1
  108. package/dist/{token-goat-chunk-67BNIKKO.mjs → token-goat-chunk-P6HQSWQ3.mjs} +55 -47
  109. package/dist/token-goat-chunk-P6VGNTQT.mjs +71 -0
  110. package/dist/token-goat-chunk-PFWIMH2E.mjs +261 -0
  111. package/dist/token-goat-chunk-PJZXIS3G.mjs +39 -0
  112. package/dist/token-goat-chunk-PUO5INXP.mjs +606 -0
  113. package/dist/token-goat-chunk-PX5PQWTY.mjs +462 -0
  114. package/dist/token-goat-chunk-Q5QDBC6O.mjs +111 -0
  115. package/dist/token-goat-chunk-QFNQXSDT.mjs +40 -0
  116. package/dist/token-goat-chunk-QH7YVYOY.mjs +3957 -0
  117. package/dist/token-goat-chunk-QLMUHEPB.mjs +43 -0
  118. package/dist/{token-goat-chunk-PYSUADX4.mjs → token-goat-chunk-QQOJIHL3.mjs} +50 -14
  119. package/dist/token-goat-chunk-QQTWJY2O.mjs +85 -0
  120. package/dist/token-goat-chunk-QYHO5CPH.mjs +93 -0
  121. package/dist/token-goat-chunk-RELAVWAD.mjs +27 -0
  122. package/dist/token-goat-chunk-RSLPOBKQ.mjs +339 -0
  123. package/dist/token-goat-chunk-SAMFDIS2.mjs +712 -0
  124. package/dist/token-goat-chunk-SDELXLDM.mjs +48 -0
  125. package/dist/{token-goat-chunk-PGTH2U4C.mjs → token-goat-chunk-SOAFZNNZ.mjs} +164 -40
  126. package/dist/{token-goat-chunk-G23DWHV4.mjs → token-goat-chunk-SRTHT7KV.mjs} +33 -15
  127. package/dist/token-goat-chunk-T5P5ACNQ.mjs +212 -0
  128. package/dist/token-goat-chunk-T5YGG4V3.mjs +45 -0
  129. package/dist/token-goat-chunk-TAUZ4OFS.mjs +110 -0
  130. package/dist/token-goat-chunk-TM6MC754.mjs +40 -0
  131. package/dist/token-goat-chunk-TWUKBOMP.mjs +72 -0
  132. package/dist/token-goat-chunk-U2KSB4SG.mjs +56 -0
  133. package/dist/token-goat-chunk-U4WHMG6Y.mjs +898 -0
  134. package/dist/token-goat-chunk-UA5V6P3P.mjs +122 -0
  135. package/dist/token-goat-chunk-UGJHGR5A.mjs +52 -0
  136. package/dist/{token-goat-chunk-RQGGMPCR.mjs → token-goat-chunk-UOUDVA5U.mjs} +76 -16
  137. package/dist/{token-goat-chunk-HNFZZHFW.mjs → token-goat-chunk-URRJ33GR.mjs} +22 -4
  138. package/dist/token-goat-chunk-UZOROKIS.mjs +165 -0
  139. package/dist/token-goat-chunk-VIHGGGEI.mjs +4234 -0
  140. package/dist/token-goat-chunk-VTJLAA7P.mjs +21 -0
  141. package/dist/token-goat-chunk-VWDXLT4F.mjs +678 -0
  142. package/dist/token-goat-chunk-VWZA2H4P.mjs +368 -0
  143. package/dist/{token-goat-chunk-QO3LXVVR.mjs → token-goat-chunk-VXEXMJDL.mjs} +2964 -3153
  144. package/dist/token-goat-chunk-WBA5SKT4.mjs +547 -0
  145. package/dist/{token-goat-chunk-ONXH6NZ5.mjs → token-goat-chunk-WDH44VAU.mjs} +19 -22
  146. package/dist/token-goat-chunk-X2SUP3EI.mjs +107 -0
  147. package/dist/token-goat-chunk-X3BELZSJ.mjs +125 -0
  148. package/dist/{token-goat-chunk-RLP6J7WR.mjs → token-goat-chunk-XLRBNZCC.mjs} +40 -21
  149. package/dist/{token-goat-chunk-S4VSXURL.mjs → token-goat-chunk-XRKUX6CM.mjs} +4 -0
  150. package/dist/token-goat-chunk-XX6O25RN.mjs +82 -0
  151. package/dist/token-goat-chunk-XZSUHBVS.mjs +65 -0
  152. package/dist/token-goat-chunk-Y2ZTQOCL.mjs +35 -0
  153. package/dist/{token-goat-chunk-UA5BKWWQ.mjs → token-goat-chunk-YB4VMGK2.mjs} +15 -4
  154. package/dist/token-goat-chunk-YBIIY3HR.mjs +51 -0
  155. package/dist/{token-goat-chunk-PKRWMHVP.mjs → token-goat-chunk-YHVDKQBR.mjs} +389 -221
  156. package/dist/token-goat-chunk-YJB5XLWI.mjs +26 -0
  157. package/dist/{token-goat-chunk-PQ53BSCF.mjs → token-goat-chunk-YKB6AQG3.mjs} +53 -31
  158. package/dist/token-goat-chunk-YMTG2YA5.mjs +35 -0
  159. package/dist/token-goat-chunk-YPBZYQRV.mjs +40 -0
  160. package/dist/{token-goat-chunk-HUYUHODZ.mjs → token-goat-chunk-YY6AVUFL.mjs} +13246 -12247
  161. package/dist/token-goat-chunk-Z7N5OMMP.mjs +98 -0
  162. package/dist/{token-goat-chunk-BGHSSJUA.mjs → token-goat-chunk-ZFOBKUWH.mjs} +1 -1
  163. package/dist/token-goat-chunk-ZMBL6UVV.mjs +110 -0
  164. package/dist/token-goat-chunk-ZNMNUPAZ.mjs +938 -0
  165. package/dist/token-goat-hook-client.cjs +87 -23
  166. package/dist/token-goat-hook-client.mjs +3 -3
  167. package/dist/token-goat-hook.mjs +76 -31
  168. package/dist/token-goat.core.mjs +6 -6
  169. package/docs/C4_RUNTIME_ARCHITECTURE.md +2 -2
  170. package/docs/cli.md +113 -60
  171. package/docs/install.md +63 -20
  172. package/docs/security.md +10 -8
  173. package/package.json +18 -7
  174. package/scripts/verify-native-dist.mjs +386 -0
  175. package/dist/token-goat-chunk-2NNUA2LR.mjs +0 -143
  176. package/dist/token-goat-chunk-44BM7DDQ.mjs +0 -294
  177. package/dist/token-goat-chunk-BGYOZ6DO.mjs +0 -24
  178. package/dist/token-goat-chunk-C5YPNZKQ.mjs +0 -318
  179. package/dist/token-goat-chunk-CIQ2FTY3.mjs +0 -1990
  180. package/dist/token-goat-chunk-D4ETHJD6.mjs +0 -246
  181. package/dist/token-goat-chunk-DNRPXHYH.mjs +0 -1062
  182. package/dist/token-goat-chunk-EUSDXRXU.mjs +0 -1429
  183. package/dist/token-goat-chunk-FTP4U4QA.mjs +0 -64
  184. package/dist/token-goat-chunk-G7IWXCFF.mjs +0 -456
  185. package/dist/token-goat-chunk-GLXRTTLE.mjs +0 -36
  186. package/dist/token-goat-chunk-H5J3C56Q.mjs +0 -1511
  187. package/dist/token-goat-chunk-IVWI2OCK.mjs +0 -368
  188. package/dist/token-goat-chunk-JTKCQMQA.mjs +0 -418
  189. package/dist/token-goat-chunk-LZNBQTDK.mjs +0 -26
  190. package/dist/token-goat-chunk-ORNFMIER.mjs +0 -295
  191. package/dist/token-goat-chunk-RTMVLHWX.mjs +0 -7113
  192. package/dist/token-goat-chunk-VQ6F6T7X.mjs +0 -36
  193. package/dist/token-goat-chunk-VZQEWRVH.mjs +0 -312
  194. package/dist/token-goat-chunk-XYWPOSCN.mjs +0 -807
  195. package/dist/token-goat-chunk-YAGLESS3.mjs +0 -23
  196. package/dist/token-goat-chunk-YKSRAWUU.mjs +0 -33
  197. package/dist/token-goat-chunk-Z6KBMOBI.mjs +0 -53
@@ -2,19 +2,23 @@ import { createRequire as __cjsRequire } from 'node:module';
2
2
  const require = __cjsRequire(import.meta.url);
3
3
  import {
4
4
  redactSecrets
5
- } from "./token-goat-chunk-CIQ2FTY3.mjs";
5
+ } from "./token-goat-chunk-T5P5ACNQ.mjs";
6
6
  import {
7
7
  shortFingerprint
8
- } from "./token-goat-chunk-TGOXNAHW.mjs";
8
+ } from "./token-goat-chunk-4GBVPH3D.mjs";
9
9
  import {
10
10
  registerReset
11
11
  } from "./token-goat-chunk-YZAAZU2S.mjs";
12
+ import {
13
+ quotedArg
14
+ } from "./token-goat-chunk-GGGG7RWB.mjs";
12
15
  import {
13
16
  foldPath
14
- } from "./token-goat-chunk-TCQANXYC.mjs";
17
+ } from "./token-goat-chunk-AM5V6GSX.mjs";
15
18
  import {
19
+ hostPathOfIndexKey,
16
20
  normalizePath
17
- } from "./token-goat-chunk-NMTKNYGF.mjs";
21
+ } from "./token-goat-chunk-FNFBKLRD.mjs";
18
22
  import {
19
23
  init_define_import_meta_env
20
24
  } from "./token-goat-chunk-A37V4PBF.mjs";
@@ -23,6 +27,127 @@ import {
23
27
  init_define_import_meta_env();
24
28
  import { randomBytes, randomUUID } from "node:crypto";
25
29
  import * as fs from "node:fs";
30
+
31
+ // src/read_range_evasion.ts
32
+ init_define_import_meta_env();
33
+ var states = /* @__PURE__ */ new Map();
34
+ var clock = 0;
35
+ function stamp() {
36
+ clock = Math.max(Date.now(), clock + 1);
37
+ return clock;
38
+ }
39
+ function stateFor(key) {
40
+ const state = states.get(key) ?? { resetAt: 0, denied: [], recent: [] };
41
+ states.set(key, state);
42
+ return state;
43
+ }
44
+ function evaluateRangeEvasion(options) {
45
+ if (options.locked) return "locked";
46
+ const [start, end] = options.span;
47
+ const denied = options.denied ?? [];
48
+ const recent = [...options.served.slice(-3), ...denied].slice(-3);
49
+ const overlap = ([s, e]) => Math.max(0, Math.min(end, e) - Math.max(start, s) + 1);
50
+ const anchored = recent.filter(([s]) => s === start);
51
+ if (anchored.length >= 3 || anchored.some(([, e]) => Math.abs(end - e) <= 20)) return "same_anchor";
52
+ const microCandidates = [...options.served.slice(-2), ...denied.slice(-1)];
53
+ if (microCandidates.some(([s, e]) => {
54
+ const startDelta = Math.abs(start - s);
55
+ const endDelta = Math.abs(end - e);
56
+ return startDelta >= 1 && startDelta <= 15 && endDelta >= 1 && endDelta <= 15 && overlap([s, e]) > 0;
57
+ })) return "micro_shift";
58
+ if (recent.some(([s, e]) => {
59
+ if (s === start && end - e > 20) return false;
60
+ return overlap([s, e]) >= Math.min(end - start + 1, e - s + 1) / 2;
61
+ })) return "overlap";
62
+ return null;
63
+ }
64
+ function getReadRangeDenials(key) {
65
+ return states.get(key)?.denied.map((v) => v.span) ?? [];
66
+ }
67
+ function lockReadRange(key, span, identity) {
68
+ const state = stateFor(key);
69
+ state.denied.push({ span: [span[0], span[1]], at: stamp() });
70
+ state.denied = state.denied.slice(-3);
71
+ if (identity) state.identity = identity;
72
+ }
73
+ function recordRecentReadRange(key, span) {
74
+ const state = stateFor(key);
75
+ const last = state.recent.at(-1)?.span;
76
+ if (last?.[0] === span[0] && last[1] === span[1]) return;
77
+ const resync = state.resetAt > 0 && state.recent.length === 0 && state.denied.length === 0;
78
+ state.recent.push({ span: [span[0], span[1]], at: stamp(), ...resync ? { resync: true } : {} });
79
+ state.recent = state.recent.slice(-3);
80
+ }
81
+ function getRecentReadRanges(key) {
82
+ return states.get(key)?.recent.filter((v) => v.resync !== true).map((v) => v.span) ?? [];
83
+ }
84
+ function clearReadRangeIfChanged(key, identity) {
85
+ const prior = states.get(key)?.identity;
86
+ if (prior && identity && (prior.size !== identity.size || prior.mtimeMs !== identity.mtimeMs)) clearReadRangeEvasion(key);
87
+ }
88
+ function clearReadRangeEvasion(key) {
89
+ states.set(key, { resetAt: stamp(), denied: [], recent: [] });
90
+ }
91
+ function clearAllReadRangeEvasion() {
92
+ states.clear();
93
+ }
94
+ function exportReadRangeEvasion() {
95
+ return structuredClone(Array.from(states));
96
+ }
97
+ function importReadRangeEvasion(entries) {
98
+ states = new Map(structuredClone(entries));
99
+ for (const [, state] of states) {
100
+ clock = Math.max(clock, state.resetAt, ...state.recent.map((v) => v.at), ...state.denied.map((v) => v.at));
101
+ }
102
+ }
103
+ function coerceReadRangeEvasion(raw) {
104
+ if (!Array.isArray(raw)) return [];
105
+ const finite = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0;
106
+ const visits = (rawVisits) => {
107
+ if (!Array.isArray(rawVisits)) return [];
108
+ return rawVisits.flatMap((v) => {
109
+ if (typeof v !== "object" || v === null || !("span" in v) || !("at" in v)) return [];
110
+ const span = v.span;
111
+ if (!Array.isArray(span) || span.length !== 2 || !finite(span[0]) || !finite(span[1]) || !Number.isInteger(span[0]) || !Number.isInteger(span[1]) || span[0] < 1 || span[1] < span[0] || !finite(v.at)) return [];
112
+ return [{ span: [span[0], span[1]], at: v.at, ..."resync" in v && v.resync === true ? { resync: true } : {} }];
113
+ }).slice(-3);
114
+ };
115
+ return raw.flatMap((pair) => {
116
+ if (!Array.isArray(pair) || typeof pair[0] !== "string") return [];
117
+ const value = pair[1];
118
+ if (typeof value !== "object" || value === null || !("resetAt" in value) || !finite(value.resetAt)) return [];
119
+ const state = {
120
+ resetAt: value.resetAt,
121
+ denied: visits("denied" in value ? value.denied : void 0),
122
+ recent: visits("recent" in value ? value.recent : void 0)
123
+ };
124
+ if ("identity" in value && typeof value.identity === "object" && value.identity !== null && "size" in value.identity && "mtimeMs" in value.identity && finite(value.identity.size) && finite(value.identity.mtimeMs)) {
125
+ state.identity = { size: value.identity.size, mtimeMs: value.identity.mtimeMs };
126
+ }
127
+ return [[pair[0], state]];
128
+ });
129
+ }
130
+ function mergeReadRangeEvasion(disk, mem) {
131
+ const merged = new Map(structuredClone(disk));
132
+ const mergeVisits = (a, b) => Array.from(new Map([...a, ...b].map((v) => [JSON.stringify(v), v])).values()).sort((a2, b2) => a2.at - b2.at).slice(-3);
133
+ for (const [key, state] of mem) {
134
+ const prior = merged.get(key);
135
+ if (!prior || state.resetAt > prior.resetAt) {
136
+ merged.set(key, state);
137
+ } else if (state.resetAt === prior.resetAt) {
138
+ const denied = mergeVisits(prior.denied, state.denied);
139
+ const recent = mergeVisits(prior.recent, state.recent);
140
+ const newestIdentity = (state.denied.at(-1)?.at ?? 0) >= (prior.denied.at(-1)?.at ?? 0) ? state.identity : prior.identity;
141
+ merged.set(key, { resetAt: state.resetAt, denied, recent, ...newestIdentity ? { identity: newestIdentity } : {} });
142
+ }
143
+ }
144
+ return Array.from(merged);
145
+ }
146
+ function rangeLockMessage(shown, span) {
147
+ return "Line-range reads of this file are locked for this compaction epoch. Run `token-goat read " + quotedArg(shown + "@" + span[0] + "-" + span[1]) + "` for this window, or `token-goat skeleton " + quotedArg(shown) + "` for structure. Do not shrink, grow, or shift the Read range.";
148
+ }
149
+
150
+ // src/session.ts
26
151
  var _files = /* @__PURE__ */ new Map();
27
152
  var _filesAtLoad = /* @__PURE__ */ new Map();
28
153
  var _filesFullReadCountAtLoad = /* @__PURE__ */ new Map();
@@ -34,6 +159,7 @@ var _grepQueries = /* @__PURE__ */ new Map();
34
159
  var _globQueries = /* @__PURE__ */ new Map();
35
160
  var _lastTabContext = null;
36
161
  var _seenImageHashes = [];
162
+ var _verificationRuns = [];
37
163
  var _outstandingAgentSpawns = [];
38
164
  var _outstandingAgentSpawnsAtLoad = [];
39
165
  var _bashReruns = /* @__PURE__ */ new Set();
@@ -43,15 +169,19 @@ var _fileLineRanges = /* @__PURE__ */ new Map();
43
169
  var _fileServedOutputs = /* @__PURE__ */ new Map();
44
170
  var _fileLineRangesAtLoad = /* @__PURE__ */ new Map();
45
171
  var _fileServedOutputsAtLoad = /* @__PURE__ */ new Map();
172
+ var _fileLineRangesReset = /* @__PURE__ */ new Set();
173
+ var _fileLineRangeIdentities = /* @__PURE__ */ new Map();
46
174
  var _compactedAt = 0;
47
175
  var _cliReads = /* @__PURE__ */ new Set();
48
176
  var _pendingLargeFileHints = /* @__PURE__ */ new Map();
49
177
  var _pendingLargeFileHintsAtLoad = /* @__PURE__ */ new Map();
178
+ var _bashStartCwds = /* @__PURE__ */ new Map();
179
+ var _bashStartCwdsAtLoad = /* @__PURE__ */ new Map();
50
180
  var _sessionId = null;
51
181
  var _transcriptPath = null;
52
182
  function fileSize(absPath) {
53
183
  try {
54
- return fs.statSync(absPath).size;
184
+ return fs.statSync(hostPathOfIndexKey(absPath)).size;
55
185
  } catch {
56
186
  return 0;
57
187
  }
@@ -65,6 +195,9 @@ function resolveFilesKey(normalized) {
65
195
  }
66
196
  return normalized;
67
197
  }
198
+ function newEntryEpochBase() {
199
+ return _compactedAt > 0 ? { epochBase: { at: _compactedAt, readCount: 0, fullReadCount: 0 } } : {};
200
+ }
68
201
  function recordFileRead(filePath, isFullRead = true) {
69
202
  const normalized = normalizePath(filePath);
70
203
  const key = resolveFilesKey(normalized);
@@ -78,16 +211,35 @@ function recordFileRead(filePath, isFullRead = true) {
78
211
  lastReadAt: now,
79
212
  wasEdited: false,
80
213
  sizeBytes: size,
81
- ...isFullRead ? { lastFullReadAt: now, fullReadCount: 1 } : {}
214
+ ...isFullRead ? { lastFullReadAt: now, fullReadCount: 1 } : {},
215
+ ...newEntryEpochBase()
82
216
  });
83
217
  return;
84
218
  }
219
+ const opensEpoch = _compactedAt > 0 && prev.lastReadAt < _compactedAt && (prev.epochBase?.at ?? 0) < _compactedAt;
85
220
  _files.set(key, {
86
221
  ...prev,
87
222
  readCount: prev.readCount + 1,
88
223
  lastReadAt: now,
89
224
  sizeBytes: size,
90
- ...isFullRead ? { lastFullReadAt: now, fullReadCount: (prev.fullReadCount ?? 0) + 1 } : {}
225
+ ...isFullRead ? { lastFullReadAt: now, fullReadCount: (prev.fullReadCount ?? 0) + 1 } : {},
226
+ ...opensEpoch ? { epochBase: { at: _compactedAt, readCount: prev.readCount, fullReadCount: prev.fullReadCount ?? 0 } } : {}
227
+ });
228
+ }
229
+ function unrecordRefusedRead(filePath, before) {
230
+ const key = resolveFilesKey(normalizePath(filePath));
231
+ const current = _files.get(key);
232
+ if (current === void 0) return;
233
+ if (before === void 0) {
234
+ _files.delete(key);
235
+ return;
236
+ }
237
+ const { fullReadCount: _fullReadCount, lastFullReadAt: _lastFullReadAt, ...rest } = current;
238
+ _files.set(key, {
239
+ ...rest,
240
+ readCount: before.readCount,
241
+ ...before.fullReadCount !== void 0 ? { fullReadCount: before.fullReadCount } : {},
242
+ ...before.lastFullReadAt !== void 0 ? { lastFullReadAt: before.lastFullReadAt } : {}
91
243
  });
92
244
  }
93
245
  var MAX_SYMBOLS_PER_FILE = 25;
@@ -102,7 +254,8 @@ function recordSymbolRead(filePath, symbol) {
102
254
  lastReadAt: Date.now(),
103
255
  wasEdited: false,
104
256
  sizeBytes: fileSize(normalized),
105
- symbols_read: [symbol]
257
+ symbols_read: [symbol],
258
+ ...newEntryEpochBase()
106
259
  });
107
260
  return;
108
261
  }
@@ -120,19 +273,21 @@ function filesFullReadCountAtLoad() {
120
273
  function recordFileEdit(filePath) {
121
274
  const normalized = normalizePath(filePath);
122
275
  const key = resolveFilesKey(normalized);
123
- _fileLineRanges.delete(foldPath(normalized));
276
+ resetFileLineRanges(normalized);
124
277
  const prev = _files.get(key);
278
+ const now = Date.now();
125
279
  if (prev === void 0) {
126
280
  _files.set(key, {
127
281
  path: key,
128
282
  readCount: 0,
129
283
  lastReadAt: 0,
130
284
  wasEdited: true,
285
+ lastEditedAt: now,
131
286
  sizeBytes: fileSize(normalized)
132
287
  });
133
288
  return;
134
289
  }
135
- _files.set(key, { ...prev, wasEdited: true });
290
+ _files.set(key, { ...prev, wasEdited: true, lastEditedAt: now });
136
291
  }
137
292
  function getSessionFiles() {
138
293
  return _files;
@@ -145,6 +300,24 @@ function wasFileFullyReadThisSession(filePath) {
145
300
  const entry = _files.get(resolveFilesKey(normalizePath(filePath)));
146
301
  return entry !== void 0 && entry.lastFullReadAt !== void 0 && entry.lastFullReadAt >= _compactedAt;
147
302
  }
303
+ function epochReadCounts(entry, compactedAt = _compactedAt) {
304
+ if (entry.lastReadAt < compactedAt) return { reads: 0, fullReads: 0 };
305
+ const base = entry.epochBase !== void 0 && entry.epochBase.at === compactedAt ? entry.epochBase : void 0;
306
+ const fullInEpoch = entry.lastFullReadAt !== void 0 && entry.lastFullReadAt >= compactedAt;
307
+ if (base === void 0 && compactedAt > 0) return { reads: Math.min(entry.readCount, 1), fullReads: fullInEpoch ? 1 : 0 };
308
+ const reads = Math.max(0, entry.readCount - (base?.readCount ?? 0));
309
+ const fullReads = fullInEpoch ? Math.max(0, (entry.fullReadCount ?? 0) - (base?.fullReadCount ?? 0)) : 0;
310
+ return { reads, fullReads };
311
+ }
312
+ function wasEditedSinceCompaction(entry, compactedAt = _compactedAt) {
313
+ return entry.wasEdited && (entry.lastEditedAt === void 0 || entry.lastEditedAt >= compactedAt);
314
+ }
315
+ function mergeEpochBase(a, b) {
316
+ if (a === void 0) return b;
317
+ if (b === void 0 || a.at > b.at) return a;
318
+ if (b.at > a.at) return b;
319
+ return { at: a.at, readCount: Math.max(a.readCount, b.readCount), fullReadCount: Math.max(a.fullReadCount, b.fullReadCount) };
320
+ }
148
321
  function getCompactedAt() {
149
322
  return _compactedAt;
150
323
  }
@@ -152,7 +325,10 @@ function markCompacted(now = Date.now()) {
152
325
  if (now <= _compactedAt) return;
153
326
  _compactedAt = now;
154
327
  _fileLineRanges = /* @__PURE__ */ new Map();
328
+ _fileLineRangeIdentities = /* @__PURE__ */ new Map();
329
+ clearAllReadRangeEvasion();
155
330
  _fileServedOutputs = /* @__PURE__ */ new Map();
331
+ _cliReads = /* @__PURE__ */ new Set();
156
332
  }
157
333
  function getSessionFileEntry(filePath) {
158
334
  return _files.get(resolveFilesKey(normalizePath(filePath)));
@@ -194,6 +370,31 @@ function consumedPendingLargeFileHintKeys() {
194
370
  function pendingLargeFileHintsAtLoad() {
195
371
  return _pendingLargeFileHintsAtLoad;
196
372
  }
373
+ var MAX_BASH_START_CWDS = 32;
374
+ function recordBashStartCwd(toolUseId, cwd) {
375
+ _bashStartCwds.delete(toolUseId);
376
+ _bashStartCwds.set(toolUseId, cwd);
377
+ for (const oldest of _bashStartCwds.keys()) {
378
+ if (_bashStartCwds.size <= MAX_BASH_START_CWDS) break;
379
+ _bashStartCwds.delete(oldest);
380
+ }
381
+ }
382
+ function takeBashStartCwd(toolUseId) {
383
+ const cwd = _bashStartCwds.get(toolUseId);
384
+ if (cwd === void 0) return null;
385
+ _bashStartCwds.delete(toolUseId);
386
+ return cwd;
387
+ }
388
+ function bashStartCwdsAtLoad() {
389
+ return _bashStartCwdsAtLoad;
390
+ }
391
+ function consumedBashStartCwdKeys() {
392
+ const consumed = [];
393
+ for (const key of _bashStartCwdsAtLoad.keys()) {
394
+ if (!_bashStartCwds.has(key)) consumed.push(key);
395
+ }
396
+ return consumed;
397
+ }
197
398
  var WEB_FETCH_KEY_SEP = "\0";
198
399
  function webFetchKey(url, prompt) {
199
400
  const digest = shortFingerprint(`${url}${WEB_FETCH_KEY_SEP}${prompt}`);
@@ -247,6 +448,12 @@ function setLastTabContext(text) {
247
448
  function lastTabContextMatches(text) {
248
449
  return _lastTabContext !== null && _lastTabContext === shortFingerprint(text);
249
450
  }
451
+ var MAX_VERIFICATION_RUNS = 8;
452
+ function recordVerificationRun(command, exitCode, at = Date.now()) {
453
+ _verificationRuns = _verificationRuns.filter((r) => r.command !== command);
454
+ _verificationRuns.push({ command, exitCode, at });
455
+ if (_verificationRuns.length > MAX_VERIFICATION_RUNS) _verificationRuns = _verificationRuns.slice(-MAX_VERIFICATION_RUNS);
456
+ }
250
457
  var MAX_SEEN_IMAGE_HASHES = 16;
251
458
  function hasSeenImage(hash) {
252
459
  return _seenImageHashes.includes(hash);
@@ -311,11 +518,11 @@ function consumedCurlDownloadKeys() {
311
518
  return consumed;
312
519
  }
313
520
  function consumedFileLineRangeKeys() {
314
- const consumed = [];
521
+ const consumed = new Set(_fileLineRangesReset);
315
522
  for (const key of _fileLineRangesAtLoad.keys()) {
316
- if (!_fileLineRanges.has(key)) consumed.push(key);
523
+ if (!_fileLineRanges.has(key)) consumed.add(key);
317
524
  }
318
- return consumed;
525
+ return [...consumed];
319
526
  }
320
527
  function consumedFileServedOutputKeys() {
321
528
  const consumed = [];
@@ -327,7 +534,7 @@ function consumedFileServedOutputKeys() {
327
534
  var MAX_RANGES_PER_FILE = 64;
328
535
  function statIdentity(absPath) {
329
536
  try {
330
- const st = fs.statSync(absPath);
537
+ const st = fs.statSync(hostPathOfIndexKey(absPath));
331
538
  return { size: st.size, mtimeMs: st.mtimeMs };
332
539
  } catch {
333
540
  return void 0;
@@ -336,22 +543,34 @@ function statIdentity(absPath) {
336
543
  function recordFileLineRange(filePath, start, end) {
337
544
  const normalized = normalizePath(filePath);
338
545
  const key = foldPath(normalized);
546
+ const entryKey = resolveFilesKey(normalized);
547
+ const entry = _files.get(entryKey);
548
+ const identity = dropFileLineRangesIfChanged(normalized);
339
549
  const ranges = _fileLineRanges.get(key) ?? [];
340
550
  if (!ranges.some(([s, e]) => s === start && e === end)) {
341
551
  ranges.push([start, end]);
342
552
  if (ranges.length > MAX_RANGES_PER_FILE) ranges.splice(0, ranges.length - MAX_RANGES_PER_FILE);
343
553
  _fileLineRanges.set(key, ranges);
344
554
  }
345
- const entryKey = resolveFilesKey(normalized);
346
- const entry = _files.get(entryKey);
347
- const identity = statIdentity(normalized);
555
+ if (identity) _fileLineRangeIdentities.set(key, identity);
348
556
  if (entry && identity) _files.set(entryKey, { ...entry, rangeFileIdentity: identity });
349
557
  }
558
+ function dropFileLineRangesIfChanged(filePath) {
559
+ const normalized = normalizePath(filePath);
560
+ const identity = statIdentity(normalized);
561
+ const prior = _fileLineRangeIdentities.get(foldPath(normalized)) ?? _files.get(resolveFilesKey(normalized))?.rangeFileIdentity;
562
+ if (prior !== void 0 && identity !== void 0 && (prior.size !== identity.size || prior.mtimeMs !== identity.mtimeMs)) resetFileLineRanges(normalized);
563
+ return identity;
564
+ }
350
565
  function getFileLineRanges(filePath) {
351
566
  return _fileLineRanges.get(foldPath(normalizePath(filePath))) ?? [];
352
567
  }
353
568
  function resetFileLineRanges(filePath) {
354
- _fileLineRanges.delete(foldPath(normalizePath(filePath)));
569
+ const key = foldPath(normalizePath(filePath));
570
+ clearReadRangeEvasion(key);
571
+ _fileLineRanges.delete(key);
572
+ _fileLineRangeIdentities.delete(key);
573
+ _fileLineRangesReset.add(key);
355
574
  }
356
575
  var MAX_SERVED_OUTPUTS_PER_FILE = 8;
357
576
  var GENERIC_SERVED_OUTPUT_KEY = "\0<bash-generic-served>";
@@ -381,7 +600,8 @@ function markFileTruncated(filePath, isFullRead = true) {
381
600
  wasEdited: false,
382
601
  sizeBytes: fileSize(normalized),
383
602
  wasTruncated: true,
384
- ...isFullRead ? { lastFullReadAt: now, fullReadCount: 1 } : {}
603
+ ...isFullRead ? { lastFullReadAt: now, fullReadCount: 1 } : {},
604
+ ...newEntryEpochBase()
385
605
  });
386
606
  return;
387
607
  }
@@ -422,18 +642,23 @@ function exportSessionState() {
422
642
  bashReruns: Array.from(_bashReruns),
423
643
  curlDownloads: Array.from(_curlDownloads.entries()),
424
644
  fileLineRanges: Array.from(_fileLineRanges.entries()),
645
+ readRangeEvasion: exportReadRangeEvasion(),
646
+ ..._fileLineRangeIdentities.size > 0 ? { fileLineRangeIdentities: Array.from(_fileLineRangeIdentities.entries()) } : {},
425
647
  ..._fileServedOutputs.size > 0 ? { fileServedOutputs: Array.from(_fileServedOutputs.entries()) } : {},
426
648
  cliReads: Array.from(_cliReads),
427
649
  pendingLargeFileHints: Array.from(_pendingLargeFileHints.entries()),
650
+ ..._bashStartCwds.size > 0 ? { bashStartCwds: Array.from(_bashStartCwds.entries()) } : {},
428
651
  grepQueries: Array.from(_grepQueries.entries()),
429
652
  globQueries: Array.from(_globQueries.entries()),
430
653
  outstandingAgentSpawns: _outstandingAgentSpawns.map((e) => [e.prompt, e.ts]),
431
654
  ..._lastTabContext !== null ? { lastTabContextDigest: _lastTabContext } : {},
432
655
  ..._seenImageHashes.length > 0 ? { seenImageHashes: [..._seenImageHashes] } : {},
656
+ ..._verificationRuns.length > 0 ? { verificationRuns: [..._verificationRuns] } : {},
433
657
  ..._compactedAt > 0 ? { compactedAt: _compactedAt } : {}
434
658
  };
435
659
  }
436
660
  function importSessionState(s) {
661
+ importReadRangeEvasion(s.readRangeEvasion ?? []);
437
662
  _files = /* @__PURE__ */ new Map();
438
663
  for (const e of s.files) {
439
664
  if (e && typeof e.path === "string") _files.set(e.path, e);
@@ -449,20 +674,26 @@ function importSessionState(s) {
449
674
  _curlDownloadsAtLoad = new Map(_curlDownloads);
450
675
  _fileLineRanges = new Map(s.fileLineRanges ?? []);
451
676
  _fileLineRangesAtLoad = new Map(_fileLineRanges);
677
+ _fileLineRangesReset = /* @__PURE__ */ new Set();
678
+ _fileLineRangeIdentities = new Map(s.fileLineRangeIdentities ?? []);
452
679
  _fileServedOutputs = new Map(s.fileServedOutputs ?? []);
453
680
  _fileServedOutputsAtLoad = new Map(_fileServedOutputs);
454
681
  _cliReads = new Set(s.cliReads ?? []);
455
682
  _pendingLargeFileHints = new Map(s.pendingLargeFileHints ?? []);
456
683
  _pendingLargeFileHintsAtLoad = new Map(_pendingLargeFileHints);
684
+ _bashStartCwds = new Map(s.bashStartCwds ?? []);
685
+ _bashStartCwdsAtLoad = new Map(_bashStartCwds);
457
686
  _grepQueries = new Map(s.grepQueries ?? []);
458
687
  _globQueries = new Map(s.globQueries ?? []);
459
688
  _outstandingAgentSpawns = (s.outstandingAgentSpawns ?? []).map(([prompt, ts]) => ({ prompt, ts }));
460
689
  _outstandingAgentSpawnsAtLoad = [..._outstandingAgentSpawns];
461
690
  _lastTabContext = s.lastTabContextDigest ?? null;
462
691
  _seenImageHashes = [...s.seenImageHashes ?? []];
692
+ _verificationRuns = [...s.verificationRuns ?? []];
463
693
  _compactedAt = s.compactedAt ?? 0;
464
694
  }
465
695
  registerReset(() => {
696
+ clearAllReadRangeEvasion();
466
697
  _files = /* @__PURE__ */ new Map();
467
698
  _filesAtLoad = /* @__PURE__ */ new Map();
468
699
  _filesFullReadCountAtLoad = /* @__PURE__ */ new Map();
@@ -475,24 +706,39 @@ registerReset(() => {
475
706
  _curlDownloadsAtLoad = /* @__PURE__ */ new Map();
476
707
  _fileLineRanges = /* @__PURE__ */ new Map();
477
708
  _fileLineRangesAtLoad = /* @__PURE__ */ new Map();
709
+ _fileLineRangesReset = /* @__PURE__ */ new Set();
710
+ _fileLineRangeIdentities = /* @__PURE__ */ new Map();
478
711
  _fileServedOutputs = /* @__PURE__ */ new Map();
479
712
  _fileServedOutputsAtLoad = /* @__PURE__ */ new Map();
480
713
  _cliReads = /* @__PURE__ */ new Set();
481
714
  _pendingLargeFileHints = /* @__PURE__ */ new Map();
482
715
  _pendingLargeFileHintsAtLoad = /* @__PURE__ */ new Map();
716
+ _bashStartCwds = /* @__PURE__ */ new Map();
717
+ _bashStartCwdsAtLoad = /* @__PURE__ */ new Map();
483
718
  _grepQueries = /* @__PURE__ */ new Map();
484
719
  _globQueries = /* @__PURE__ */ new Map();
485
720
  _outstandingAgentSpawns = [];
486
721
  _outstandingAgentSpawnsAtLoad = [];
487
722
  _lastTabContext = null;
488
723
  _seenImageHashes = [];
724
+ _verificationRuns = [];
489
725
  _compactedAt = 0;
490
726
  _sessionId = null;
491
727
  _transcriptPath = null;
492
728
  }, { perRequest: true });
493
729
 
494
730
  export {
731
+ evaluateRangeEvasion,
732
+ getReadRangeDenials,
733
+ lockReadRange,
734
+ recordRecentReadRange,
735
+ getRecentReadRanges,
736
+ clearReadRangeIfChanged,
737
+ coerceReadRangeEvasion,
738
+ mergeReadRangeEvasion,
739
+ rangeLockMessage,
495
740
  recordFileRead,
741
+ unrecordRefusedRead,
496
742
  recordSymbolRead,
497
743
  filesReadCountAtLoad,
498
744
  filesFullReadCountAtLoad,
@@ -500,6 +746,9 @@ export {
500
746
  getSessionFiles,
501
747
  wasFileReadThisSession,
502
748
  wasFileFullyReadThisSession,
749
+ epochReadCounts,
750
+ wasEditedSinceCompaction,
751
+ mergeEpochBase,
503
752
  getCompactedAt,
504
753
  markCompacted,
505
754
  getSessionFileEntry,
@@ -512,6 +761,11 @@ export {
512
761
  takePendingLargeFileHint,
513
762
  consumedPendingLargeFileHintKeys,
514
763
  pendingLargeFileHintsAtLoad,
764
+ MAX_BASH_START_CWDS,
765
+ recordBashStartCwd,
766
+ takeBashStartCwd,
767
+ bashStartCwdsAtLoad,
768
+ consumedBashStartCwdKeys,
515
769
  WEB_FETCH_KEY_SEP,
516
770
  recordWebFetch,
517
771
  migrateCurlDownloadKey,
@@ -528,6 +782,8 @@ export {
528
782
  getGlobMatchCount,
529
783
  setLastTabContext,
530
784
  lastTabContextMatches,
785
+ MAX_VERIFICATION_RUNS,
786
+ recordVerificationRun,
531
787
  MAX_SEEN_IMAGE_HASHES,
532
788
  hasSeenImage,
533
789
  recordSeenImage,
@@ -547,6 +803,7 @@ export {
547
803
  consumedFileServedOutputKeys,
548
804
  MAX_RANGES_PER_FILE,
549
805
  recordFileLineRange,
806
+ dropFileLineRangesIfChanged,
550
807
  getFileLineRanges,
551
808
  resetFileLineRanges,
552
809
  MAX_SERVED_OUTPUTS_PER_FILE,