@maycombhq/atticus 2.0.0-beta.25 → 2.0.0-beta.27

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 (326) hide show
  1. package/dist/bin.js +3 -3
  2. package/dist/chunk-22A2K555.js +653 -0
  3. package/dist/{chunk-UTZMF5CV.js → chunk-23TTURB2.js} +1 -1
  4. package/dist/{chunk-F36DIKJ3.js → chunk-2666BPJE.js} +19 -19
  5. package/dist/{chunk-E2OP6JNF.js → chunk-2ALBHI4Q.js} +28 -27
  6. package/dist/chunk-2ANBMA74.js +107 -0
  7. package/dist/{chunk-S7UQFI4B.js → chunk-2HCW6HXK.js} +27 -26
  8. package/dist/{chunk-HV3KPEFH.js → chunk-2ISR6MWD.js} +15 -15
  9. package/dist/{chunk-QQD25YNF.js → chunk-2MRYL45Z.js} +50 -9
  10. package/dist/{chunk-KN4UQJ7R.js → chunk-3GNUHLAN.js} +4 -4
  11. package/dist/chunk-3GURU22K.js +44 -0
  12. package/dist/{chunk-4U3JLIRC.js → chunk-3M3MDBOG.js} +1 -1
  13. package/dist/{chunk-DJ4C5ELF.js → chunk-3PBIZBWN.js} +1 -1
  14. package/dist/{chunk-XUCHGEF5.js → chunk-3PWXVBCB.js} +83 -40
  15. package/dist/chunk-3W2QX6TT.js +58 -0
  16. package/dist/{chunk-CPFAWYVC.js → chunk-3Z7ATALI.js} +5 -5
  17. package/dist/{chunk-ZGULQAPZ.js → chunk-44SWXDD7.js} +8 -5
  18. package/dist/{chunk-LGE6H4UP.js → chunk-46N5O5H7.js} +5 -5
  19. package/dist/{chunk-SRLUADSY.js → chunk-4D4DNTFE.js} +4 -4
  20. package/dist/{chunk-DMQJDHXG.js → chunk-4EAT7HOX.js} +7 -5
  21. package/dist/{chunk-DPZD7WVX.js → chunk-4FLIW5PJ.js} +4 -4
  22. package/dist/{chunk-SGTAQNOP.js → chunk-4LWA5VMJ.js} +52 -37
  23. package/dist/{chunk-D45K3XKK.js → chunk-4ODVHNA6.js} +18 -17
  24. package/dist/{chunk-7QZDGM5V.js → chunk-4POSAXNC.js} +6 -6
  25. package/dist/{chunk-A3J75BO2.js → chunk-4PQ4KDOA.js} +16 -15
  26. package/dist/{chunk-2Y5FJQSF.js → chunk-4UVTNHA6.js} +1 -1
  27. package/dist/{chunk-KVVNAUIG.js → chunk-4XK3HLOH.js} +1 -0
  28. package/dist/{chunk-V7T6URII.js → chunk-523NRKHF.js} +4 -4
  29. package/dist/{chunk-7EAH2MFY.js → chunk-5GCCG3GJ.js} +11 -5
  30. package/dist/{chunk-7U6PBBXG.js → chunk-5XW6RUDV.js} +8 -8
  31. package/dist/{chunk-Y3J365UC.js → chunk-5YEUAZZE.js} +8 -8
  32. package/dist/{chunk-JWLABUXL.js → chunk-62LD7CSY.js} +13 -13
  33. package/dist/{chunk-LOJGNSPA.js → chunk-67Y2J55V.js} +22 -21
  34. package/dist/{chunk-UCKG6UE7.js → chunk-6DSZ4CL7.js} +37 -22
  35. package/dist/{chunk-FNP4M4VL.js → chunk-6G67LSBG.js} +283 -61
  36. package/dist/{chunk-5GLGLWAJ.js → chunk-6OEB4FTC.js} +20 -19
  37. package/dist/{chunk-5RKN5QIX.js → chunk-6OTGCKYH.js} +9 -9
  38. package/dist/{chunk-UI7ID4HG.js → chunk-6XLCMDIP.js} +13 -13
  39. package/dist/chunk-76DZJTU7.js +190 -0
  40. package/dist/chunk-7764GVJK.js +37 -0
  41. package/dist/{chunk-TKCNJJ2S.js → chunk-7BOGXFZ3.js} +11 -11
  42. package/dist/{chunk-Q52KWTG5.js → chunk-7CVHKNAF.js} +16 -15
  43. package/dist/{chunk-XF5UMMQL.js → chunk-7FEIS3KV.js} +25 -24
  44. package/dist/{chunk-UTYL4XVA.js → chunk-7GXM45T5.js} +26 -23
  45. package/dist/{chunk-4PW5SRKJ.js → chunk-7YMAMNMT.js} +17 -16
  46. package/dist/chunk-7YWS47SE.js +56 -0
  47. package/dist/{chunk-LZFKJ2BR.js → chunk-A3LVMCA5.js} +1 -1
  48. package/dist/{chunk-7YFUNWFM.js → chunk-A7ZJKLFC.js} +11 -11
  49. package/dist/chunk-AANQC5QP.js +47 -0
  50. package/dist/{chunk-LP5QGTCR.js → chunk-AIQLTDC3.js} +3 -3
  51. package/dist/{chunk-EPXYFJTY.js → chunk-AKZTCZ6F.js} +4 -4
  52. package/dist/{chunk-5267F4BS.js → chunk-ALCSTVWQ.js} +3 -3
  53. package/dist/{chunk-NMBHFSJQ.js → chunk-ALUHO7SE.js} +26 -25
  54. package/dist/{chunk-3WO7ASU7.js → chunk-AMZ4XMES.js} +8 -8
  55. package/dist/{chunk-JKEUPSCE.js → chunk-AOQG37K4.js} +8 -6
  56. package/dist/{chunk-3NA2VE45.js → chunk-ARXZTHEI.js} +16 -15
  57. package/dist/{chunk-W2W7YCFL.js → chunk-AS4CTARY.js} +16 -15
  58. package/dist/{chunk-7AKJ2XTW.js → chunk-AVUPW23W.js} +18 -17
  59. package/dist/{chunk-CMUJSPP4.js → chunk-B56FCIEJ.js} +12 -12
  60. package/dist/{chunk-K3OIBTCV.js → chunk-BABATPOZ.js} +18 -17
  61. package/dist/{chunk-VAZYNF6I.js → chunk-BIOKDLLX.js} +21 -19
  62. package/dist/{chunk-23QHP4JJ.js → chunk-BUBKKEUV.js} +5 -5
  63. package/dist/{chunk-N3OEBQTA.js → chunk-CDC6VECU.js} +3 -3
  64. package/dist/chunk-CHEFUNZ4.js +425 -0
  65. package/dist/{chunk-MM7YWUBB.js → chunk-CIFR3DPV.js} +6 -6
  66. package/dist/{chunk-JCKKAELC.js → chunk-CLBVKD4P.js} +16 -15
  67. package/dist/{chunk-HHZEXF7V.js → chunk-CLM5Z3R5.js} +5 -5
  68. package/dist/{chunk-M7XNX5IC.js → chunk-CLYV5MB6.js} +9 -9
  69. package/dist/{chunk-SHWHRCMU.js → chunk-CRYIBCGP.js} +37 -19
  70. package/dist/{chunk-6576X5BJ.js → chunk-D3L5SO27.js} +5 -5
  71. package/dist/chunk-DAZM2INZ.js +34 -0
  72. package/dist/{chunk-VBJHIRKV.js → chunk-DF4BXBB2.js} +6 -6
  73. package/dist/{chunk-U4HZ5CXL.js → chunk-E7Q52EOO.js} +11 -11
  74. package/dist/{chunk-MZTU5L6S.js → chunk-EFDUC35B.js} +3 -3
  75. package/dist/{chunk-GIOOA2ZO.js → chunk-EHXEJFHD.js} +5 -5
  76. package/dist/{chunk-M6HI36T3.js → chunk-ELJ5Q4J2.js} +2 -2
  77. package/dist/{chunk-MJAIBPI5.js → chunk-EM6DKBTJ.js} +3 -3
  78. package/dist/{chunk-YGS2YVF2.js → chunk-EMC46SU4.js} +38 -17
  79. package/dist/{chunk-CB6H7MH2.js → chunk-EQEDIWFQ.js} +25 -24
  80. package/dist/chunk-EW574EZI.js +57 -0
  81. package/dist/{chunk-JJEPU4VS.js → chunk-EYINWNXL.js} +5 -5
  82. package/dist/{chunk-MJOIMGS4.js → chunk-EYVYHYCA.js} +8 -8
  83. package/dist/{chunk-WGOQZ4PQ.js → chunk-F66542M6.js} +34 -9
  84. package/dist/{chunk-EUCATH2U.js → chunk-F74OMLNU.js} +6 -6
  85. package/dist/{chunk-G5P7F6RQ.js → chunk-FADIWOA5.js} +3 -3
  86. package/dist/{chunk-JMOZ6K5A.js → chunk-FC3ZVD3O.js} +3 -3
  87. package/dist/{chunk-XXJSGCDO.js → chunk-FG65LXED.js} +8 -8
  88. package/dist/{chunk-5WZV37WS.js → chunk-FKAUBC4Y.js} +8 -8
  89. package/dist/{chunk-WA644MUQ.js → chunk-FM3EEDS2.js} +15 -15
  90. package/dist/{chunk-XZQBFF65.js → chunk-FS4E7F6O.js} +403 -148
  91. package/dist/{chunk-Q6UYUCNS.js → chunk-FSYJPYLE.js} +16 -15
  92. package/dist/{chunk-H7GAPNGQ.js → chunk-G33UIUG3.js} +46 -20
  93. package/dist/{chunk-OEUTV6EL.js → chunk-G3F4BYML.js} +15 -14
  94. package/dist/{chunk-7UYRN4ON.js → chunk-GBJRFFDW.js} +5 -5
  95. package/dist/{chunk-7HW2CMIN.js → chunk-GF6GBHFN.js} +13 -11
  96. package/dist/{chunk-DCPI3ETH.js → chunk-GLHOUT5E.js} +26 -25
  97. package/dist/{chunk-VOBG7BLB.js → chunk-GM6GXO2A.js} +20 -19
  98. package/dist/{chunk-KJPKIU2R.js → chunk-GSJ2RXE7.js} +29 -28
  99. package/dist/{chunk-HU7VXMFV.js → chunk-GT72FDER.js} +6 -6
  100. package/dist/{chunk-SBNBVUOF.js → chunk-GW6ZH77P.js} +37 -36
  101. package/dist/{chunk-6WYOJCB4.js → chunk-GZILYRGC.js} +3 -3
  102. package/dist/{chunk-4SS5ZK47.js → chunk-GZSOZYEP.js} +3 -3
  103. package/dist/{chunk-N6SSI6XO.js → chunk-H25QNDKK.js} +58 -36
  104. package/dist/{chunk-DYVUNT4O.js → chunk-H3RKW4RF.js} +7 -7
  105. package/dist/chunk-H7M7ZH6H.js +52 -0
  106. package/dist/chunk-H7NRWSMP.js +55 -0
  107. package/dist/{chunk-KW4DIXUL.js → chunk-HDWVR5KD.js} +4 -4
  108. package/dist/{chunk-HR34F2AJ.js → chunk-HG24EF5S.js} +16 -15
  109. package/dist/chunk-HPNYSY5M.js +1068 -0
  110. package/dist/{chunk-3VC2XJ53.js → chunk-HUMM4S5I.js} +6 -6
  111. package/dist/{chunk-K373N5U6.js → chunk-HVPS2YCW.js} +11 -11
  112. package/dist/{chunk-IGOE6KPG.js → chunk-I34CXV2C.js} +185 -11
  113. package/dist/{chunk-U7YZ3IRI.js → chunk-I57IH5X6.js} +360 -271
  114. package/dist/{chunk-P56N3NPT.js → chunk-I5X4WU7U.js} +6 -6
  115. package/dist/chunk-IAVVJ34R.js +55 -0
  116. package/dist/chunk-IBJE2E2S.js +51 -0
  117. package/dist/{chunk-EXCXNDTQ.js → chunk-IF3X6FMO.js} +1 -1
  118. package/dist/{chunk-GAVEIYKH.js → chunk-IJHJIL6T.js} +154 -25
  119. package/dist/chunk-IM435QAM.js +72 -0
  120. package/dist/{chunk-7NLYSTEK.js → chunk-IMBJ7WAO.js} +6 -6
  121. package/dist/{chunk-EM7F6XEU.js → chunk-INCFIDCB.js} +2 -2
  122. package/dist/{chunk-AYWJMHSX.js → chunk-IPMPLTEG.js} +3 -3
  123. package/dist/{chunk-PGKCRK77.js → chunk-IPSZDVLI.js} +12 -12
  124. package/dist/{chunk-IMTAHDME.js → chunk-IX2EOYOU.js} +50 -13
  125. package/dist/{chunk-QE444DZ2.js → chunk-IXNMGPF7.js} +61 -28
  126. package/dist/{chunk-NL6GIEJU.js → chunk-J6GO3K7G.js} +19 -18
  127. package/dist/chunk-JBLM6IUA.js +42 -0
  128. package/dist/{chunk-IWQEZFVV.js → chunk-JL2VOYSL.js} +91 -93
  129. package/dist/{chunk-K77ILFUQ.js → chunk-JRXFZB6J.js} +8 -8
  130. package/dist/{chunk-UR6JGVX2.js → chunk-JTOLBS7R.js} +988 -410
  131. package/dist/{chunk-GD6FXN6R.js → chunk-K73BHPTQ.js} +19 -18
  132. package/dist/{chunk-PYVFLITV.js → chunk-KF7KVUNJ.js} +5 -5
  133. package/dist/{chunk-F4WKGX7K.js → chunk-KKUCBKJE.js} +20 -19
  134. package/dist/{chunk-U7F6E5M3.js → chunk-KLFFHBWG.js} +27 -26
  135. package/dist/{chunk-ROVOAF2O.js → chunk-KMYB2XO7.js} +21 -13
  136. package/dist/chunk-KNYQUWFN.js +52 -0
  137. package/dist/{chunk-KFDOL2Y4.js → chunk-KOAJPMU2.js} +31 -20
  138. package/dist/chunk-KRTSE73S.js +55 -0
  139. package/dist/{chunk-IW3QMW3X.js → chunk-L3AM5YRP.js} +28 -9
  140. package/dist/{chunk-334N6EI2.js → chunk-LCIIFAID.js} +22 -21
  141. package/dist/{chunk-DLNQ3HUM.js → chunk-LCQIRCOT.js} +55 -10
  142. package/dist/{chunk-QFOJ3UPU.js → chunk-LFHBAWIM.js} +13 -13
  143. package/dist/chunk-LIHEMWIT.js +39 -0
  144. package/dist/{chunk-T5QYYB5L.js → chunk-LJLYWILK.js} +14 -14
  145. package/dist/{chunk-E7PR4WMM.js → chunk-LNJKDS5C.js} +26 -25
  146. package/dist/{chunk-HHZ2ZKUD.js → chunk-LTHY7E2P.js} +16 -15
  147. package/dist/{chunk-4WIVTPGE.js → chunk-LTVOQJKT.js} +7 -7
  148. package/dist/{chunk-TIOYZDRB.js → chunk-LZO3JABE.js} +6 -6
  149. package/dist/{chunk-PXMV2LLY.js → chunk-M65AZ4ZE.js} +3 -5
  150. package/dist/chunk-MPNTEWNY.js +492 -0
  151. package/dist/chunk-MQGQ3AWK.js +58 -0
  152. package/dist/{chunk-NQLTWGF4.js → chunk-MUXYUIBV.js} +6 -6
  153. package/dist/{chunk-5R3FRI6H.js → chunk-MWRRJDXQ.js} +34 -31
  154. package/dist/{chunk-XY6FVBBV.js → chunk-MZDHFWTN.js} +2 -2
  155. package/dist/chunk-N2XCT5OX.js +68 -0
  156. package/dist/{chunk-C5LX54QK.js → chunk-N3JGYAMD.js} +15 -15
  157. package/dist/{chunk-RL7PETU6.js → chunk-N5DLB74D.js} +367 -71
  158. package/dist/{chunk-MJMEF7SD.js → chunk-NC3Q7RIB.js} +10 -10
  159. package/dist/{chunk-4GWQVT2C.js → chunk-NCNLX4DL.js} +19 -18
  160. package/dist/{chunk-3D74UADA.js → chunk-NGSGJLKW.js} +2 -2
  161. package/dist/{chunk-OOU4N2JQ.js → chunk-NN7K2LLN.js} +25 -24
  162. package/dist/{chunk-ELNIQYLR.js → chunk-NNURP7VO.js} +15 -15
  163. package/dist/chunk-NSQB24WR.js +56 -0
  164. package/dist/{chunk-MWOPED6I.js → chunk-NV5S63YK.js} +7 -7
  165. package/dist/{chunk-CTJHEG6A.js → chunk-NWMFVPEP.js} +2 -0
  166. package/dist/{chunk-7E3G5NCH.js → chunk-NYT6QGZA.js} +22 -18
  167. package/dist/chunk-OB2DAIJX.js +62 -0
  168. package/dist/{chunk-YAUMNRCB.js → chunk-OC3OXDTG.js} +13 -8
  169. package/dist/{chunk-DAHKLVHU.js → chunk-OD6RNYMQ.js} +16 -16
  170. package/dist/{chunk-7FUQAT2R.js → chunk-OFYBRMRG.js} +6 -6
  171. package/dist/chunk-OGTELPDN.js +43 -0
  172. package/dist/{chunk-BS52P2CM.js → chunk-OQ7SBQ2Z.js} +7 -7
  173. package/dist/{chunk-OMSH46JK.js → chunk-OUDGBJC2.js} +16 -9
  174. package/dist/{chunk-USH4VU5D.js → chunk-OUGTAOGA.js} +2 -2
  175. package/dist/chunk-OWP5FCYM.js +60 -0
  176. package/dist/{chunk-YEGGQG5E.js → chunk-P36PTWBM.js} +8 -8
  177. package/dist/{chunk-IKRM64KR.js → chunk-P6Y2J2QY.js} +12 -12
  178. package/dist/{chunk-P4QTTCVK.js → chunk-PDJL2HO5.js} +24 -22
  179. package/dist/{chunk-WDJGJ3HV.js → chunk-PPKH6ULR.js} +152 -20
  180. package/dist/{chunk-5OVSDV77.js → chunk-Q4PFF2ZE.js} +8 -8
  181. package/dist/chunk-Q7EUPQEG.js +5 -0
  182. package/dist/{chunk-YRKAJ42V.js → chunk-QC6GSNIK.js} +7074 -3456
  183. package/dist/chunk-QCRQNYGI.js +211 -0
  184. package/dist/chunk-QDF533AW.js +90 -0
  185. package/dist/chunk-QDGNDNBG.js +50 -0
  186. package/dist/{chunk-2ULVUSIP.js → chunk-QGMD3PYL.js} +31 -24
  187. package/dist/{chunk-QEP4HTJE.js → chunk-QLT3WYTD.js} +6 -6
  188. package/dist/{chunk-GX67TNFA.js → chunk-QNDMAKQS.js} +11 -3
  189. package/dist/{chunk-XM3JE4QY.js → chunk-QNXMVJMA.js} +8 -8
  190. package/dist/{chunk-XP5DF5MC.js → chunk-QPAANKUR.js} +13 -12
  191. package/dist/{chunk-SD3PGZSR.js → chunk-QS4VX3HZ.js} +1 -1
  192. package/dist/{chunk-ZD64ZR64.js → chunk-QSM4K6LI.js} +7 -7
  193. package/dist/{chunk-Z4N7BKLN.js → chunk-QUFZDWPC.js} +8 -8
  194. package/dist/{chunk-ELNLHU7Y.js → chunk-QXXEOH3A.js} +18 -6
  195. package/dist/{chunk-QA4O2GGC.js → chunk-R4TUWD4C.js} +17 -1
  196. package/dist/{chunk-TAIYQDIV.js → chunk-ROI64BAI.js} +22 -21
  197. package/dist/{chunk-NMGFXT4S.js → chunk-RPVL3RTX.js} +19 -18
  198. package/dist/{chunk-62FMA437.js → chunk-RUNHVUCW.js} +16 -15
  199. package/dist/{chunk-I2M7MXSV.js → chunk-RWYPLODE.js} +9 -9
  200. package/dist/{chunk-5K6ZKHZR.js → chunk-RZYRUXSU.js} +4 -4
  201. package/dist/{chunk-TVFADTAT.js → chunk-S6TLXRBR.js} +7 -7
  202. package/dist/{chunk-PCZ4C2V7.js → chunk-SCOP3J6X.js} +7 -7
  203. package/dist/{chunk-JXLUHMTC.js → chunk-SCP24MJX.js} +24 -23
  204. package/dist/{chunk-R6HJ4SDB.js → chunk-SF3HXNXR.js} +6 -6
  205. package/dist/{chunk-7F4GZ7U2.js → chunk-SFCFL7Y5.js} +1 -1
  206. package/dist/{chunk-5RDKQOY3.js → chunk-SHFY73RI.js} +53 -112
  207. package/dist/{chunk-H75SPCAW.js → chunk-SHIARIEZ.js} +20 -19
  208. package/dist/chunk-SMFFUFMN.js +1876 -0
  209. package/dist/{chunk-JQGWP3SC.js → chunk-SVOGRJO6.js} +197 -124
  210. package/dist/chunk-SVZAAOHJ.js +46 -0
  211. package/dist/{chunk-BJDVI5W6.js → chunk-SZOU32VF.js} +21 -20
  212. package/dist/{chunk-MXPKXCGP.js → chunk-T2MN24LZ.js} +1 -1
  213. package/dist/{chunk-A3AADMM2.js → chunk-TD5WWJLN.js} +6 -6
  214. package/dist/{chunk-SXF66YNZ.js → chunk-TFN2N227.js} +6 -6
  215. package/dist/{chunk-RSA5JJMN.js → chunk-TFXNOQEU.js} +28 -27
  216. package/dist/{chunk-BEDZNT62.js → chunk-TMETWJFO.js} +11 -11
  217. package/dist/chunk-TNSAIISO.js +50 -0
  218. package/dist/{chunk-IDTVBZQI.js → chunk-TRJO2I4S.js} +3 -3
  219. package/dist/{chunk-IFDCCCEN.js → chunk-TRSNIJNM.js} +7 -7
  220. package/dist/{chunk-GDGE7ZHC.js → chunk-U3Z2QZE3.js} +6 -6
  221. package/dist/{chunk-GVOQJPKA.js → chunk-U7L3ORPK.js} +22 -21
  222. package/dist/{chunk-5UJ7C7IH.js → chunk-UDM6HGF4.js} +6 -6
  223. package/dist/{chunk-Z3KEX7ON.js → chunk-UDM7LXNJ.js} +7 -7
  224. package/dist/chunk-UDTO3U6E.js +35 -0
  225. package/dist/{chunk-UVKJVTKX.js → chunk-UEUPEUZX.js} +3 -3
  226. package/dist/chunk-UWBODTY7.js +514 -0
  227. package/dist/{chunk-KGT5RIGE.js → chunk-UYYYQTPD.js} +84 -51
  228. package/dist/{chunk-LKRMVWXB.js → chunk-V34N6JAN.js} +32 -31
  229. package/dist/{chunk-RX56MZLX.js → chunk-V3Y5P7OS.js} +24 -23
  230. package/dist/chunk-V6MLVGTP.js +89 -0
  231. package/dist/chunk-VC2XHC7P.js +424 -0
  232. package/dist/{chunk-MM5OAVSW.js → chunk-VCYE4MUD.js} +29 -28
  233. package/dist/{chunk-AGAFNUYZ.js → chunk-VN2VJ6BV.js} +19 -15
  234. package/dist/{chunk-DBVQEPZB.js → chunk-VVLWEM2Y.js} +6 -6
  235. package/dist/{chunk-F56DNMDD.js → chunk-VWCNMDMZ.js} +5 -5
  236. package/dist/{chunk-LNGFTPU7.js → chunk-W2A4NHQD.js} +25 -24
  237. package/dist/{chunk-LQD3R6NZ.js → chunk-W6OY2PMB.js} +10 -10
  238. package/dist/{chunk-IP6TSICI.js → chunk-WC6DHBVG.js} +16 -15
  239. package/dist/{chunk-MELS6T5J.js → chunk-WCA3WIGG.js} +5 -5
  240. package/dist/{chunk-GLISHJ4G.js → chunk-WJWSB65O.js} +1602 -452
  241. package/dist/{chunk-77REYYY5.js → chunk-WNPGLGCJ.js} +5 -5
  242. package/dist/chunk-WTOVWEY3.js +67 -0
  243. package/dist/{chunk-WS7KBKP4.js → chunk-X5B7KYPD.js} +507 -20
  244. package/dist/{chunk-O6DJMDBR.js → chunk-X73WLHSN.js} +7 -7
  245. package/dist/{chunk-YGNQUFVZ.js → chunk-XIIT4PVT.js} +3 -3
  246. package/dist/{chunk-5P4PNGPL.js → chunk-XLTT5QCX.js} +28 -25
  247. package/dist/{chunk-NPZ4KXIV.js → chunk-XMIS25ZJ.js} +21 -20
  248. package/dist/{chunk-NB664KWQ.js → chunk-XPDQ4T6G.js} +27 -26
  249. package/dist/{chunk-EAGSM3XY.js → chunk-XRWUYOX3.js} +138 -22
  250. package/dist/{chunk-2VN4TLGI.js → chunk-XZY4GTCX.js} +14 -9
  251. package/dist/{chunk-QSKY7FE3.js → chunk-Y2TVTI4P.js} +121 -15
  252. package/dist/{chunk-XVQQ3BQS.js → chunk-Y2U4CSCA.js} +28 -27
  253. package/dist/chunk-Y2U63JKE.js +41 -0
  254. package/dist/{chunk-UJ535VWR.js → chunk-Y6S7VCYN.js} +6 -6
  255. package/dist/{chunk-SEBBJQWK.js → chunk-YAPMGK7E.js} +11 -11
  256. package/dist/{chunk-CNF7D3A7.js → chunk-YAPVAYZN.js} +3 -3
  257. package/dist/{chunk-B2U4AOZ5.js → chunk-YCBDNWX3.js} +78 -57
  258. package/dist/{chunk-CGVRLQAY.js → chunk-YIGSUTW2.js} +1329 -92
  259. package/dist/{chunk-J65TN6QU.js → chunk-YJTBE6AJ.js} +5 -5
  260. package/dist/chunk-YQ3IXQIH.js +185 -0
  261. package/dist/{chunk-ZJQ64T6M.js → chunk-YRHKEXTP.js} +11 -11
  262. package/dist/{chunk-MN2XDLDM.js → chunk-YSSFS3YC.js} +17 -17
  263. package/dist/{chunk-BPDS7KUR.js → chunk-YXG2VQJJ.js} +200 -56
  264. package/dist/{chunk-XC5ZDFW7.js → chunk-Z4GLFTEH.js} +8 -8
  265. package/dist/{chunk-7X3WLAKP.js → chunk-Z65FWO6A.js} +157 -89
  266. package/dist/{chunk-OW53P52N.js → chunk-ZDG637ZT.js} +22 -21
  267. package/dist/{chunk-BIQNPWGX.js → chunk-ZIAMPN7N.js} +6 -6
  268. package/dist/chunk-ZIIBQHCX.js +53 -0
  269. package/dist/{chunk-RFQW7XT3.js → chunk-ZJJMYPGZ.js} +57 -27
  270. package/dist/{chunk-Y6KPWRZJ.js → chunk-ZOAX7W5S.js} +11 -11
  271. package/dist/chunk-ZSSR5GGB.js +48 -0
  272. package/dist/files.json +655 -551
  273. package/dist/fixtures/forge/expected/crosscheck.json +726 -0
  274. package/dist/fixtures/forge/slots/README.md +13 -0
  275. package/dist/fixtures/forge/slots/build.json +2686 -0
  276. package/dist/fixtures/forge/slots/crosscheck/forge-ledger.crosscheck.yaml +8 -0
  277. package/dist/fixtures/forge/slots/facts/forge-ledger.jsonl +17 -0
  278. package/dist/fixtures/forge/slots/facts/forge-ledger.meta.json +9 -0
  279. package/dist/fixtures/forge/slots/legacy/joins.json +113 -0
  280. package/dist/fixtures/forge/slots/readers/forge-events.json +306 -0
  281. package/dist/fixtures/forge/slots/readers/forge-gateway.json +238 -0
  282. package/dist/fixtures/forge/slots/readers/forge-infra.json +264 -0
  283. package/dist/fixtures/forge/slots/readers/forge-ledger.json +756 -0
  284. package/dist/fixtures/forge/slots/readers/forge-portal-bff.json +349 -0
  285. package/dist/fixtures/forge/slots/readers/forge-portal-ui.json +214 -0
  286. package/dist/fixtures/forge/slots/readers/forge-reports-job.json +258 -0
  287. package/dist/packages/sdk/npm/index.js +3859 -2939
  288. package/dist/packages/ui/dist/assets/{elk-api-ts8TigYQ.js → elk-api-CPE6PVL8.js} +2 -2
  289. package/dist/packages/ui/dist/assets/index-BYcVqj0l.js +65 -0
  290. package/dist/packages/ui/dist/assets/index-DF52Ejvz.css +1 -0
  291. package/dist/packages/ui/dist/index.html +2 -2
  292. package/package.json +5 -5
  293. package/dist/chunk-24OXGB3P.js +0 -82
  294. package/dist/chunk-2RABF6RT.js +0 -36
  295. package/dist/chunk-5CPZIWIN.js +0 -38
  296. package/dist/chunk-7YSMZEO3.js +0 -55
  297. package/dist/chunk-AENMOZMM.js +0 -42
  298. package/dist/chunk-BDKYHCGI.js +0 -71
  299. package/dist/chunk-BMMTWRWE.js +0 -50
  300. package/dist/chunk-CQRFCWQV.js +0 -45
  301. package/dist/chunk-CVWKS6GO.js +0 -50
  302. package/dist/chunk-D2CGJ7RR.js +0 -46
  303. package/dist/chunk-D7QIZLWB.js +0 -38
  304. package/dist/chunk-DM3H4V2G.js +0 -62
  305. package/dist/chunk-EJGUEUXG.js +0 -51
  306. package/dist/chunk-ELKTDXV3.js +0 -67
  307. package/dist/chunk-EP7ZBZLT.js +0 -170
  308. package/dist/chunk-EXGXCVWC.js +0 -52
  309. package/dist/chunk-FJS2FZFZ.js +0 -41
  310. package/dist/chunk-G3ZFEHCX.js +0 -925
  311. package/dist/chunk-GAU2IFIC.js +0 -33
  312. package/dist/chunk-GPOL5H3B.js +0 -55
  313. package/dist/chunk-HD72AL3L.js +0 -43
  314. package/dist/chunk-K4C2DWOZ.js +0 -232
  315. package/dist/chunk-KY3BUZYI.js +0 -54
  316. package/dist/chunk-LMNCRSER.js +0 -257
  317. package/dist/chunk-LPXH2DA4.js +0 -40
  318. package/dist/chunk-MLUHBVCI.js +0 -45
  319. package/dist/chunk-ONB7M2AF.js +0 -52
  320. package/dist/chunk-QBK33722.js +0 -51
  321. package/dist/chunk-S7I7SLZN.js +0 -59
  322. package/dist/chunk-UCQB6NKS.js +0 -192
  323. package/dist/chunk-UKMA5JFE.js +0 -52
  324. package/dist/chunk-X7QLAUNS.js +0 -47
  325. package/dist/packages/ui/dist/assets/index-CIfmX7DJ.css +0 -1
  326. package/dist/packages/ui/dist/assets/index-DNtpSfZS.js +0 -63
@@ -5,10 +5,10 @@ var __atticusUrl = (p) => new URL("./" + p, import.meta.url).href;
5
5
  var __atticusPath = (p) => __atticusFileURLToPath(__atticusUrl(p));
6
6
  import {
7
7
  readOpenApiDocument
8
- } from "./chunk-2VN4TLGI.js";
8
+ } from "./chunk-XZY4GTCX.js";
9
9
  import {
10
10
  globToRegExp
11
- } from "./chunk-4U3JLIRC.js";
11
+ } from "./chunk-3M3MDBOG.js";
12
12
  import {
13
13
  DECLARED_TOPIC,
14
14
  Fact,
@@ -24,37 +24,47 @@ import {
24
24
  LINK_EVIDENCE_NOT_GAPS,
25
25
  MOCK_FILE,
26
26
  SHARED_MAP_EVIDENCE,
27
+ canaryClaimText,
28
+ canaryNeedleOf,
27
29
  citedFiles,
28
- claimOnLines,
29
30
  clusterServiceAddress,
30
31
  configSecretField,
31
32
  credentialLike,
32
33
  decodeText,
33
34
  dependencyLinkId,
34
35
  factIdPart,
36
+ foldCanary,
35
37
  forwardSlashes,
36
- hasSecretShape,
37
38
  isBinaryText,
38
39
  isLfsPointer,
39
40
  isPatternPath,
40
- isSecretPath,
41
- lineNamesClaim,
42
41
  linksFor,
43
42
  listRepoFilesSync,
44
43
  looksLikeSecret,
45
44
  noteProblem,
46
- partsBuildWord,
47
- partsNamePath,
48
45
  placedComponentOf,
49
46
  plainPathPrefix,
50
- quoteHoldsSecret,
51
- quoteMatches,
52
- quoteNotRequired,
53
- redactSecrets,
47
+ removedBy,
48
+ seededShuffle,
54
49
  staleCite,
55
50
  toCanonicalYaml,
56
51
  tokenUnits
57
- } from "./chunk-GLISHJ4G.js";
52
+ } from "./chunk-WJWSB65O.js";
53
+ import {
54
+ claimOnLines,
55
+ declaresConventionalRoute,
56
+ hasSecretShape,
57
+ isSecretPath,
58
+ keyIsSecret,
59
+ lineNamesClaim,
60
+ partsBuildWord,
61
+ partsNamePath,
62
+ pathPieceOnlyInComment,
63
+ quoteHoldsSecret,
64
+ quoteMatches,
65
+ quoteNotRequired,
66
+ redactSecrets
67
+ } from "./chunk-SMFFUFMN.js";
58
68
  import {
59
69
  DEFAULT_CONVENTIONS,
60
70
  DEFAULT_GATEWAY_BUNDLE_FOLDERS,
@@ -63,7 +73,7 @@ import {
63
73
  normalizePath,
64
74
  notDeviceName,
65
75
  underFolders
66
- } from "./chunk-LZFKJ2BR.js";
76
+ } from "./chunk-A3LVMCA5.js";
67
77
 
68
78
  // packages/verify/dist/source.js
69
79
  import { lstatSync, readFileSync, realpathSync, statSync } from "node:fs";
@@ -174,8 +184,8 @@ function dirSource(root) {
174
184
  };
175
185
  }
176
186
  var MAX_SOURCE_BYTES = 5 * 1024 * 1024;
177
- function tooBigToRead(source, path) {
178
- const n = source.size?.(path);
187
+ function tooBigToRead(source2, path) {
188
+ const n = source2.size?.(path);
179
189
  return n !== void 0 && n > MAX_SOURCE_BYTES;
180
190
  }
181
191
 
@@ -2335,7 +2345,7 @@ var deviseFor = (file, lines, idx, env) => {
2335
2345
  const m = new RegExp(`\\b${k}:\\s*(?:\\[([^\\]]*)\\]|:(\\w+))`).exec(opts);
2336
2346
  return m ? (m[1] ?? `:${m[2]}`).split(",").map((s) => singularize(s.trim().replace(/^:/, ""))).filter(Boolean) : void 0;
2337
2347
  };
2338
- const skip = list2("skip") ?? [];
2348
+ const skip2 = list2("skip") ?? [];
2339
2349
  const only = list2("only");
2340
2350
  const names = { registration: "" };
2341
2351
  const pn = /\bpath_names:\s*\{([^}]*)\}/.exec(opts)?.[1] ?? "";
@@ -2357,7 +2367,7 @@ var deviseFor = (file, lines, idx, env) => {
2357
2367
  break;
2358
2368
  }
2359
2369
  const modules = new Set([...call.replace(/\w+:\s*\[[^\]]*\]|\w+:\s*[^,]+/g, "").matchAll(/:(\w+)/g)].map((m) => m[1]));
2360
- const allowed = (c) => !skip.includes(c) && !skip.includes("all") && (!only || only.includes(c));
2370
+ const allowed = (c) => !skip2.includes(c) && !skip2.includes("all") && (!only || only.includes(c));
2361
2371
  const at = `${prefix}${resource ? `/${resource}` : ""}`;
2362
2372
  const out = [];
2363
2373
  for (const m of DEVISE)
@@ -2616,26 +2626,6 @@ function tokenKeyNear(lines, i) {
2616
2626
  }
2617
2627
  return void 0;
2618
2628
  }
2619
- function keyIsSecret(key) {
2620
- if (hasSecretShape(key))
2621
- return true;
2622
- for (const run of key.match(/[0-9a-f]{24,}|[0-9A-F]{24,}/g) ?? [])
2623
- if (/\d/.test(run) && /[a-f]/i.test(run))
2624
- return true;
2625
- const digitsAndLetters = /\d/.test(key) && /[A-Za-z]/.test(key);
2626
- if (key.length >= 32 && /^[A-Za-z0-9+/=]+$/.test(key) && digitsAndLetters)
2627
- return true;
2628
- if (key.length >= 32 && /^[A-Za-z0-9_-]+$/.test(key) && /\d/.test(key) && /[a-z]/.test(key) && /[A-Z]/.test(key))
2629
- return true;
2630
- if (key.length < 16 || !/^[A-Za-z0-9+/=]+$/.test(key) || !/\d/.test(key))
2631
- return false;
2632
- const kind = (c) => /\d/.test(c) ? 0 : /[a-z]/.test(c) ? 1 : 2;
2633
- let switches = 0;
2634
- for (let i = 1; i < key.length; i++)
2635
- if (kind(key[i]) !== kind(key[i - 1]))
2636
- switches++;
2637
- return switches >= key.length / 2;
2638
- }
2639
2629
  function itemNameAbove(lines, i) {
2640
2630
  const col = /^\s*/.exec(lines[i])[0].length;
2641
2631
  for (let j = i - 1; j >= 0 && i - j <= 6; j--) {
@@ -2690,11 +2680,419 @@ function liveSecretsIn(file, lines) {
2690
2680
  return out;
2691
2681
  }
2692
2682
 
2683
+ // packages/verify/dist/comments.js
2684
+ var JS = /\.(m?[jt]sx?|c[jt]s|mts)$/i;
2685
+ var NESTING = /\.(kt|kts|rs|swift|scala|sc|dart)$/i;
2686
+ var TRIPLE_DOUBLE = /\.(java|kt|kts|scala|sc|swift|dart|groovy|gradle|cs|csx)$|(^|\/)Jenkinsfile(\.[\w.-]+)?$/i;
2687
+ var TRIPLE_SINGLE = /\.(dart|groovy|gradle)$|(^|\/)Jenkinsfile(\.[\w.-]+)?$/i;
2688
+ var RAW_TRIPLE = /\.(kt|kts|scala|sc|cs|csx)$/i;
2689
+ function commentLexisOf(file, php) {
2690
+ const triple = [
2691
+ ...php || !TRIPLE_DOUBLE.test(file) ? [] : ['"""'],
2692
+ ...php || !TRIPLE_SINGLE.test(file) ? [] : ["'''"]
2693
+ ];
2694
+ const rust = !php && /\.rs$/i.test(file);
2695
+ return {
2696
+ slashSlash: !/\.css$/i.test(file),
2697
+ hash: php,
2698
+ nest: !php && NESTING.test(file),
2699
+ js: !php && JS.test(file),
2700
+ jsx: !php && /\.[jt]sx$/i.test(file),
2701
+ goRaw: !php && /\.go$/i.test(file),
2702
+ tickIdent: !php && /\.(kt|kts|scala|sc|swift)$/i.test(file),
2703
+ triple,
2704
+ tripleEscapes: !RAW_TRIPLE.test(file),
2705
+ verbatim: !php && /\.(cs|csx)$/i.test(file),
2706
+ rustChar: rust,
2707
+ dartRaw: !php && /\.dart$/i.test(file),
2708
+ // Beta.27 re-review 5: PHP's `'…'` runs across lines too (its escapes, `\\` and `\'`, are read
2709
+ // as any `\` is: the character after one never closes it unless it is a quote escaped)
2710
+ spanQuotes: php ? `"'` : rust ? '"' : "",
2711
+ php,
2712
+ blade: php && /\.blade\.php$/i.test(file)
2713
+ };
2714
+ }
2715
+ var DOC_STAR_START = /^\s*\*(?![A-Za-z_$[])/;
2716
+ var LIVE_PHP_ANNOTATION = /@(?:(?:Route|Method|Get|Post|Put|Patch|Delete|Head|Options|ApiResource)\s*\(|Rest\\\w+|ORM\\\w+)/y;
2717
+ var SPACES = /\s*/y;
2718
+ var skipSpaces = (l, i) => {
2719
+ SPACES.lastIndex = i;
2720
+ SPACES.test(l);
2721
+ return SPACES.lastIndex;
2722
+ };
2723
+ function livePhpAnnotation(l) {
2724
+ let i = skipSpaces(l, 0);
2725
+ if (l.startsWith("/**", i))
2726
+ i = skipSpaces(l, i + 3);
2727
+ if (l[i] === "*")
2728
+ i = skipSpaces(l, i + 1);
2729
+ LIVE_PHP_ANNOTATION.lastIndex = i;
2730
+ return LIVE_PHP_ANNOTATION.test(l);
2731
+ }
2732
+ var HEREDOC_OPEN = /[ \t]*(["']?)([A-Za-z_\x80-\uFFFF][A-Za-z0-9_\x80-\uFFFF]*)\1[ \t\r]*$/y;
2733
+ var isLabelChar = (c) => c !== void 0 && c !== "$" && (isWord(c) || c >= "\x80");
2734
+ var REGEX_AFTER_WORD = new Set("return typeof instanceof in of new delete void throw case do else yield await".split(" "));
2735
+ var REGEX_AFTER = "(,=:[!&|?{};+-*%~^";
2736
+ var BRACKETS = "{}(),";
2737
+ var isSpace = (c) => c <= " " || c === "\uFEFF" || c === "\xA0";
2738
+ var isWord = (c) => c >= "a" && c <= "z" || c >= "A" && c <= "Z" || c >= "0" && c <= "9" || c === "_" || c === "$";
2739
+ var PHP_OPEN = /<\?(?:php(?=\s|$)|=|(?=\s|$))/iy;
2740
+ function lexCommentLines(lines, lx, codeOut, alone = false) {
2741
+ const out = new Array(lines.length);
2742
+ let mode = lx.php && !alone ? "html" : "code";
2743
+ let depth = 0;
2744
+ let doc = false;
2745
+ let close = "";
2746
+ let escapes = true;
2747
+ let doubled = false;
2748
+ let tripled = false;
2749
+ const frames = [];
2750
+ let prev = "";
2751
+ let prev2 = "";
2752
+ let word = "";
2753
+ let base2 = 0;
2754
+ let prevAt = -2;
2755
+ let pair = false;
2756
+ const sawCode = (c, at) => {
2757
+ if (word && isWord(c) && isWord(prev))
2758
+ word += c;
2759
+ else
2760
+ word = isWord(c) ? c : "";
2761
+ pair = c === prev && at === prevAt + 1;
2762
+ prev2 = prev;
2763
+ prev = c;
2764
+ prevAt = at;
2765
+ };
2766
+ const openString = (to, o) => {
2767
+ mode = o.lines ? "raw" : "str";
2768
+ close = to;
2769
+ escapes = o.escapes;
2770
+ doubled = false;
2771
+ tripled = o.triple === true;
2772
+ };
2773
+ for (let n = 0; n < lines.length; base2 += lines[n].length + 1, n++) {
2774
+ const l = lines[n];
2775
+ const len = l.length;
2776
+ let comment = mode === "block" || mode === "blade";
2777
+ let code2 = false;
2778
+ let docLine = mode === "block" && doc;
2779
+ let synthetic = false;
2780
+ let cont = false;
2781
+ let regexOk = lx.js;
2782
+ if (alone && mode === "code" && DOC_STAR_START.test(l)) {
2783
+ mode = "block";
2784
+ depth = 1;
2785
+ doc = docLine = synthetic = comment = true;
2786
+ }
2787
+ let i = 0;
2788
+ if (mode === "heredoc") {
2789
+ const k = skipSpaces(l, 0);
2790
+ if (l.startsWith(close, k) && !isLabelChar(l[k + close.length])) {
2791
+ mode = "code";
2792
+ prev = '"';
2793
+ word = "";
2794
+ i = k + close.length;
2795
+ } else
2796
+ i = len;
2797
+ code2 = l.trim() !== "";
2798
+ }
2799
+ let seg = mode === "block" || mode === "blade" ? -1 : 0;
2800
+ let cut = len;
2801
+ let text = "";
2802
+ while (i < len) {
2803
+ const c = l[i];
2804
+ if (mode === "html") {
2805
+ PHP_OPEN.lastIndex = i;
2806
+ if (c === "<" && l[i + 1] === "?" && PHP_OPEN.test(l)) {
2807
+ mode = "code";
2808
+ prev = ";";
2809
+ word = "";
2810
+ i = PHP_OPEN.lastIndex;
2811
+ } else if (lx.blade && c === "{" && l.startsWith("{{--", i)) {
2812
+ if (codeOut && seg >= 0)
2813
+ text += `${l.slice(seg, i)} `;
2814
+ seg = -1;
2815
+ comment = true;
2816
+ mode = "blade";
2817
+ i += 4;
2818
+ } else {
2819
+ if (!isSpace(c))
2820
+ code2 = true;
2821
+ i++;
2822
+ }
2823
+ continue;
2824
+ }
2825
+ if (mode === "blade") {
2826
+ const k = l.indexOf("--}}", i);
2827
+ if (k < 0)
2828
+ i = len;
2829
+ else {
2830
+ mode = "html";
2831
+ i = seg = k + 4;
2832
+ }
2833
+ continue;
2834
+ }
2835
+ if (mode === "block") {
2836
+ if (c === "*" && l[i + 1] === "/") {
2837
+ i += 2;
2838
+ if (--depth === 0) {
2839
+ mode = "code";
2840
+ seg = i;
2841
+ }
2842
+ } else if (lx.nest && c === "/" && l[i + 1] === "*") {
2843
+ depth++;
2844
+ i += 2;
2845
+ } else
2846
+ i++;
2847
+ continue;
2848
+ }
2849
+ if (mode !== "code") {
2850
+ if (!isSpace(c))
2851
+ code2 = true;
2852
+ if (escapes && c === "\\") {
2853
+ if (i === len - 1)
2854
+ cont = true;
2855
+ i += 2;
2856
+ } else if (mode === "tpl") {
2857
+ if (c === "`") {
2858
+ mode = "code";
2859
+ prev = '"';
2860
+ word = "";
2861
+ i++;
2862
+ } else if (c === "$" && l[i + 1] === "{") {
2863
+ frames.push(0);
2864
+ mode = "code";
2865
+ prev = "{";
2866
+ word = "";
2867
+ i += 2;
2868
+ } else
2869
+ i++;
2870
+ } else if (doubled && c === '"' && l[i + 1] === '"')
2871
+ i += 2;
2872
+ else if (c === close[0] && l.startsWith(close, i)) {
2873
+ mode = "code";
2874
+ prev = '"';
2875
+ word = "";
2876
+ i += close.length;
2877
+ if (tripled)
2878
+ while (l[i] === close[0])
2879
+ i++;
2880
+ } else
2881
+ i++;
2882
+ continue;
2883
+ }
2884
+ const d = l[i + 1];
2885
+ if (lx.php && c === "?" && d === ">") {
2886
+ mode = "html";
2887
+ i += 2;
2888
+ continue;
2889
+ }
2890
+ const lineComment = c === "/" && d === "/" && lx.slashSlash || c === "#" && lx.hash && d !== "[";
2891
+ if (lineComment) {
2892
+ comment = true;
2893
+ const k = lx.php ? l.indexOf("?>", i + (c === "#" ? 1 : 2)) : -1;
2894
+ if (k < 0) {
2895
+ cut = i;
2896
+ break;
2897
+ }
2898
+ if (codeOut && seg >= 0)
2899
+ text += `${l.slice(seg, i)} `;
2900
+ mode = "html";
2901
+ i = seg = k + 2;
2902
+ continue;
2903
+ }
2904
+ if (c === "/" && d === "*") {
2905
+ if (codeOut && seg >= 0)
2906
+ text += `${l.slice(seg, i)} `;
2907
+ seg = -1;
2908
+ comment = true;
2909
+ mode = "block";
2910
+ depth = 1;
2911
+ doc = l[i + 2] === "*" && l[i + 3] !== "/";
2912
+ if (doc)
2913
+ docLine = true;
2914
+ i += 2;
2915
+ continue;
2916
+ }
2917
+ if ((lx.rustChar || lx.dartRaw) && !(i > 0 && isWord(l[i - 1]))) {
2918
+ if (lx.rustChar && (c === "r" || (c === "b" || c === "c") && d === "r")) {
2919
+ let j = c === "r" ? i + 1 : i + 2;
2920
+ const h = j;
2921
+ while (l[j] === "#")
2922
+ j++;
2923
+ if (l[j] === '"') {
2924
+ code2 = true;
2925
+ openString(`"${"#".repeat(j - h)}`, { escapes: false, lines: true });
2926
+ i = j + 1;
2927
+ continue;
2928
+ }
2929
+ } else if (lx.dartRaw && c === "r" && (d === "'" || d === '"')) {
2930
+ code2 = true;
2931
+ const t = lx.triple.find((q) => l.startsWith(q, i + 1));
2932
+ if (t)
2933
+ openString(t, { escapes: false, lines: true, triple: true });
2934
+ else
2935
+ openString(d, { escapes: false, lines: false });
2936
+ i += t ? 4 : 2;
2937
+ continue;
2938
+ }
2939
+ }
2940
+ if (lx.php && c === "<" && d === "<" && l[i + 2] === "<") {
2941
+ HEREDOC_OPEN.lastIndex = i + 3;
2942
+ const m = HEREDOC_OPEN.exec(l);
2943
+ if (m) {
2944
+ code2 = true;
2945
+ mode = "heredoc";
2946
+ close = m[2];
2947
+ break;
2948
+ }
2949
+ }
2950
+ if (c === '"' || c === "'" || c === "`") {
2951
+ code2 = true;
2952
+ const t = lx.triple.find((q) => q[0] === c && l.startsWith(q, i));
2953
+ if (t) {
2954
+ openString(t, { escapes: lx.tripleEscapes, lines: true, triple: true });
2955
+ i += 3;
2956
+ } else if (c === "`") {
2957
+ if (lx.js) {
2958
+ mode = "tpl";
2959
+ escapes = true;
2960
+ doubled = false;
2961
+ } else if (lx.php)
2962
+ openString("`", { escapes: true, lines: true });
2963
+ else if (lx.goRaw)
2964
+ openString("`", { escapes: false, lines: true });
2965
+ else if (lx.tickIdent)
2966
+ openString("`", { escapes: false, lines: false });
2967
+ else
2968
+ sawCode(c, base2 + i);
2969
+ i++;
2970
+ } else if (c === '"' && lx.verbatim && (prev === "@" || prev === "$" && prev2 === "@")) {
2971
+ openString('"', { escapes: false, lines: true });
2972
+ doubled = true;
2973
+ i++;
2974
+ } else if (c === "'" && lx.rustChar && d !== "\\" && l[i + 2] !== "'") {
2975
+ sawCode(c, base2 + i);
2976
+ i++;
2977
+ } else {
2978
+ openString(c, { escapes: true, lines: lx.spanQuotes.includes(c) });
2979
+ i++;
2980
+ }
2981
+ continue;
2982
+ }
2983
+ if (c === "/" && regexOk) {
2984
+ const division = prev === "}" && (lx.jsx || d === ">") || pair && (prev === "+" || prev === "-");
2985
+ const after = !division && (REGEX_AFTER.includes(prev) || prev === "" || prev === ">" && prev2 === "=");
2986
+ if (after || isWord(prev) && REGEX_AFTER_WORD.has(word)) {
2987
+ let j = i + 1;
2988
+ let cls = false;
2989
+ for (; j < len; j++) {
2990
+ const ch = l[j];
2991
+ if (ch === "\\")
2992
+ j++;
2993
+ else if (ch === "[")
2994
+ cls = true;
2995
+ else if (ch === "]")
2996
+ cls = false;
2997
+ else if (ch === "/" && !cls)
2998
+ break;
2999
+ }
3000
+ if (j < len) {
3001
+ code2 = true;
3002
+ prev = "a";
3003
+ word = "";
3004
+ i = j + 1;
3005
+ continue;
3006
+ }
3007
+ regexOk = false;
3008
+ }
3009
+ }
3010
+ if (frames.length && c === "{")
3011
+ frames[frames.length - 1]++;
3012
+ else if (frames.length && c === "}") {
3013
+ if (frames[frames.length - 1] === 0) {
3014
+ frames.pop();
3015
+ mode = "tpl";
3016
+ i++;
3017
+ continue;
3018
+ }
3019
+ frames[frames.length - 1]--;
3020
+ }
3021
+ if (!isSpace(c)) {
3022
+ if (!BRACKETS.includes(c))
3023
+ code2 = true;
3024
+ sawCode(c, base2 + i);
3025
+ }
3026
+ i++;
3027
+ }
3028
+ if (mode === "str" && !cont)
3029
+ mode = "code";
3030
+ if (synthetic && mode === "block") {
3031
+ mode = "code";
3032
+ depth = 0;
3033
+ }
3034
+ const live = lx.php && docLine && livePhpAnnotation(l);
3035
+ out[n] = comment && !code2 && !live;
3036
+ if (codeOut)
3037
+ codeOut[n] = live ? l : out[n] ? "" : seg >= 0 ? text + l.slice(seg, cut) : text.trimEnd();
3038
+ }
3039
+ return out;
3040
+ }
3041
+
2693
3042
  // packages/verify/dist/skipped.js
2694
3043
  function notReadForSkipped(path, rules = DEFAULT_READ_RULES) {
2695
3044
  return rules.notRead.test(path);
2696
3045
  }
2697
- var isCommentLine = (l) => /^\s*(\/\/|\/\*|\*|<!--|-- |#(?!\s*(region|endregion|if|elif|else|endif|define|undef|pragma|nullable|include|import)\b)(?!!))/.test(l);
3046
+ var HASH_EXT = /\.(py|pyi|pyw|pyx|rb|rake|gemspec|ru|sh|bash|zsh|ksh|fish|ya?ml|toml|conf|cfg|ini|properties|env|r|pl|pm|ps1|psm1|coffee|ex|exs|jl|cr|nim|tcl|awk|gql|graphql|cmake|mk|dockerfile|gitignore|dockerignore|editorconfig|gitattributes)$/i;
3047
+ var HASH_NAME = /(^|\/)(Dockerfile(\.[\w.-]+)?|Containerfile|Makefile|GNUmakefile|Caddyfile|Gemfile|Rakefile|Podfile|Vagrantfile|Procfile|Brewfile|Fastfile|Appfile|Pipfile|CMakeLists\.txt|requirements[\w.-]*\.(txt|in)|\.env(\.[\w.-]+)?)$/;
3048
+ var C_EXT = /\.(m?[jt]sx?|c[jt]s|mts|java|kt|kts|scala|sc|groovy|gradle|cs|csx|go|rs|swift|c|cc|cpp|cxx|c\+\+|h|hh|hpp|hxx|m|mm|dart|proto|scss|less|css|json5|jsonc|zig|sol|hx|fs|fsx)$/i;
3049
+ var C_NAME = /(^|\/)Jenkinsfile(\.[\w.-]+)?$/;
3050
+ var PHP_EXT = /\.(php|phtml|php[3-8]|phps|phpt|module)$/i;
3051
+ var SQL_EXT = /\.(sql|ddl|dml|pgsql|psql|plsql|hql|cql)$/i;
3052
+ var XML_EXT = /\.(xml|xaml|axaml|csproj|vbproj|fsproj|props|targets|nuspec|resx|xsd|xslt?|wsdl|plist|svg|config|tld|jspx)$/i;
3053
+ function commentStyleOf(file, head) {
3054
+ if (PHP_EXT.test(file))
3055
+ return "php";
3056
+ if (/\.inc$/i.test(file))
3057
+ return head !== void 0 && /<\?php/i.test(head) ? "php" : "c";
3058
+ if (C_EXT.test(file) || C_NAME.test(file))
3059
+ return "c";
3060
+ if (SQL_EXT.test(file))
3061
+ return "sql";
3062
+ if (XML_EXT.test(file))
3063
+ return "xml";
3064
+ if (HASH_EXT.test(file) || HASH_NAME.test(file))
3065
+ return "hash";
3066
+ return "generic";
3067
+ }
3068
+ var headOf = (lines) => {
3069
+ let h = "";
3070
+ for (let i = 0; i < lines.length && i < 5 && h.length < 512; i++)
3071
+ h += `${lines[i]}
3072
+ `;
3073
+ return h;
3074
+ };
3075
+ var isCommentLine = (l, file, lines) => lineIsComment(l, file, commentStyleOf(file, lines && headOf(lines)));
3076
+ function lineIsComment(l, file, style) {
3077
+ if (style === "c" || style === "php")
3078
+ return lexCommentLines([l], commentLexisOf(file, style === "php"), void 0, true)[0];
3079
+ const marker = style !== "hash" ? COMMENT_OF[style] : /\.ini$/i.test(file) ? INI_COMMENT : /\.properties$/i.test(file) ? PROPERTIES_COMMENT : COMMENT_OF.hash;
3080
+ return marker.test(l) && !(style === "xml" ? XML_THEN_CODE : BLOCK_THEN_CODE).test(l);
3081
+ }
3082
+ var DIRECTIVE = "(region|endregion|if|elif|else|endif|define|undef|pragma|nullable|include|import)";
3083
+ var DOC_STAR = "\\*(?![A-Za-z_$[])";
3084
+ var COMMENT_OF = {
3085
+ hash: /^\s*#(?!!)/,
3086
+ c: new RegExp(`^\\s*(\\/\\/|\\/\\*|${DOC_STAR})`),
3087
+ php: new RegExp(`^\\s*(\\/\\/|\\/\\*|${DOC_STAR}|#(?![[!]))`),
3088
+ sql: /^\s*(--|\/\*)/,
3089
+ xml: /^\s*<!--/,
3090
+ generic: new RegExp(`^\\s*(\\/\\/|\\/\\*|\\*|<!--|-- |#(?!\\s*${DIRECTIVE}\\b)(?!!))`)
3091
+ };
3092
+ var INI_COMMENT = /^\s*[;#]/;
3093
+ var PROPERTIES_COMMENT = /^\s*[#!]/;
3094
+ var BLOCK_THEN_CODE = /^\s*\/\*.*?\*\/\s*[^\s/]/;
3095
+ var XML_THEN_CODE = /^\s*<!--.*?-->\s*\S/;
2698
3096
  var IMPORT_LINE = /^\s*(import|export\s+[^=]*\bfrom\b|from\s+\S+\s+import|package|using|require|#\s*include|@import|@use|use|library)\b/;
2699
3097
  var IMPORT_CALL = /\brequire\s*\(|\bimport\s*\(|\bfrom\s+["'`]/;
2700
3098
  var NAMESPACE_LINE = /\bxmlns(:\w+)?\s*=|schemaLocation\s*=|<!DOCTYPE|^\s*<\?xml/i;
@@ -2765,6 +3163,12 @@ function topicOf(s, context) {
2765
3163
  }
2766
3164
  return void 0;
2767
3165
  }
3166
+ function commentLinesOf(file, lines) {
3167
+ const style = commentStyleOf(file, headOf(lines));
3168
+ if (style === "c" || style === "php")
3169
+ return lexCommentLines(lines, commentLexisOf(file, style === "php"));
3170
+ return lines.map((l) => lineIsComment(l, file, style));
3171
+ }
2768
3172
  function codeOf(raw, state) {
2769
3173
  let s = raw;
2770
3174
  let out = "";
@@ -2787,12 +3191,16 @@ function codeOf(raw, state) {
2787
3191
  }
2788
3192
  function candidatesIn(path, lines) {
2789
3193
  const out = [];
3194
+ const style = commentStyleOf(path, headOf(lines));
3195
+ const lexed = style === "c" || style === "php" ? [] : void 0;
3196
+ if (lexed)
3197
+ lexCommentLines(lines, commentLexisOf(path, style === "php"), lexed);
2790
3198
  const state = {};
2791
3199
  let xmlDepth = 0;
2792
3200
  let braceDepth = 0;
2793
3201
  lines.forEach((raw, i) => {
2794
- const wasBlock = state.block !== void 0;
2795
- let code2 = codeOf(raw, state);
3202
+ const wasBlock = lexed !== void 0 || state.block !== void 0;
3203
+ let code2 = lexed ? lexed[i] : codeOf(raw, state);
2796
3204
  const inBuild = xmlDepth > 0 || braceDepth > 0;
2797
3205
  for (const m of code2.matchAll(BUILD_BLOCK_TAG))
2798
3206
  if (!m[3])
@@ -2803,7 +3211,7 @@ function candidatesIn(path, lines) {
2803
3211
  }
2804
3212
  if (!code2.trim())
2805
3213
  return;
2806
- if (!wasBlock && isCommentLine(raw))
3214
+ if (!wasBlock && lineIsComment(raw, path, style))
2807
3215
  return;
2808
3216
  if (IMPORT_LINE.test(code2) || IMPORT_CALL.test(code2) || NAMESPACE_LINE.test(code2))
2809
3217
  return;
@@ -3069,10 +3477,11 @@ function helperBuildsKey(key, cite2, linesOf2) {
3069
3477
  return false;
3070
3478
  const last = segs[segs.length - 1];
3071
3479
  const prefix = segs.slice(0, -1);
3072
- const line = linesOf2(cite2.file)?.[cite2.line - 1];
3480
+ const fileLines = linesOf2(cite2.file);
3481
+ const line = fileLines?.[cite2.line - 1];
3073
3482
  if (line === void 0)
3074
3483
  return false;
3075
- const code2 = isCommentLine(line) ? line : line.replace(/\/\*.*?\*\//g, "").replace(/(^|\s)\/\/.*$/, "");
3484
+ const code2 = isCommentLine(line, cite2.file, fileLines) ? line : line.replace(/\/\*.*?\*\//g, "").replace(/(^|\s)\/\/.*$/, "");
3076
3485
  const literals = [];
3077
3486
  const bare2 = code2.replace(/(["'`])((?:(?!\1)[^\\]|\\.)*)\1/g, (_all, _q, text) => {
3078
3487
  literals.push(text);
@@ -3256,6 +3665,27 @@ function configLineProblem(f, linesOf2, listed2, bundleFolders = DEFAULT_GATEWAY
3256
3665
  }
3257
3666
  return void 0;
3258
3667
  }
3668
+ if (/(^|\/)config\.json$/i.test(f.cite.file)) {
3669
+ const around = jsonFrames(lines).filter((x) => x.type === "{" && x.start <= f.cite.line && x.end >= f.cite.line).sort((a, b) => b.start - a.start);
3670
+ const token = around[0];
3671
+ const own = token ? lines.slice(token.start - 1, token.end) : [];
3672
+ if (token?.name !== void 0 && /^(policies|targets|proxies)$/i.test(token.under ?? "") && own.some((l) => jsonValueOn(l) !== void 0)) {
3673
+ const dir = f.cite.file.replace(/[^/]*$/, "");
3674
+ if (!listed2().some((p) => bundleFolders.some((b) => p.startsWith(`${dir}${b}/`))))
3675
+ return `config ${where} is a config.json beside no gateway bundle (no ${bundleFolders.map((b) => `${dir}${b}/`).join(" or ")}); a token's setting is read only from the bundle's own`;
3676
+ const bare2 = (s) => s.trim().replace(/^@(.+)@$/, "$1").replace(/^\{\{\s*(.+?)\s*\}\}$/, "$1");
3677
+ if (bare2(token.name) !== bare2(f.key))
3678
+ return `the token at ${where} is named ${token.name}, not ${f.key}; give the key the token's name`;
3679
+ if (value !== void 0 && !own.some((l) => same(jsonValueOn(l))))
3680
+ return `the token at ${where} sets no such value; cite the token whose "value" it is`;
3681
+ if (f.env !== void 0) {
3682
+ const conf = around.find((x) => /^configurations$/i.test(x.under ?? ""));
3683
+ if (!conf?.name || conf.name.trim() !== f.env.trim())
3684
+ return `the token at ${where} is in ${conf?.name ? `the ${conf.name} configuration` : "no named configuration"}, not ${f.env}; give the env its configuration is named`;
3685
+ }
3686
+ return void 0;
3687
+ }
3688
+ }
3259
3689
  if (isYaml(f.cite.file)) {
3260
3690
  const y = yamlLine(at);
3261
3691
  const path = yamlPathAt(lines, f.cite.line);
@@ -3847,9 +4277,26 @@ async function verifyFacts(o) {
3847
4277
  linesCache.delete(linesCache.keys().next().value);
3848
4278
  return lines;
3849
4279
  };
4280
+ const commentCache = /* @__PURE__ */ new WeakMap();
4281
+ const commentFlagsOf = (file, lines) => {
4282
+ let flags = commentCache.get(lines);
4283
+ if (!flags)
4284
+ commentCache.set(lines, flags = commentLinesOf(file, lines));
4285
+ return flags;
4286
+ };
4287
+ const commentAt = (file, lines, n) => commentFlagsOf(file, lines)[n - 1] === true;
4288
+ const codeCache = /* @__PURE__ */ new WeakMap();
4289
+ const codeLinesOf = (file, lines) => {
4290
+ let code2 = codeCache.get(lines);
4291
+ if (!code2) {
4292
+ const flags = commentFlagsOf(file, lines);
4293
+ codeCache.set(lines, code2 = lines.map((l, i) => flags[i] ? "" : l));
4294
+ }
4295
+ return code2;
4296
+ };
3850
4297
  const deriveEnv = { lines: linesOf2, files: listed2 };
3851
4298
  const lineAt = (file, n) => n >= 1 ? linesOf2(file)?.[n - 1] : void 0;
3852
- const checkCite = (cite2, claims, label, withHint = true, alsoHolds, quiet = false) => {
4299
+ const checkCite = (cite2, claims2, label, withHint = true, alsoHolds, quiet = false, httpRoute = false) => {
3853
4300
  const where = `${cite2.file}:${cite2.line}`;
3854
4301
  if (!insideRepo(cite2.file))
3855
4302
  return {
@@ -3875,6 +4322,7 @@ async function verifyFacts(o) {
3875
4322
  const parts = cite2.with ?? [];
3876
4323
  const near = (ls, n) => ls.slice(Math.max(0, n - 2), n + 1);
3877
4324
  const partLines = [];
4325
+ const partWindows = [];
3878
4326
  for (const [i, p] of parts.entries()) {
3879
4327
  const pl = `${label} part ${i + 1}`;
3880
4328
  if (!insideRepo(p.file))
@@ -3904,32 +4352,59 @@ async function verifyFacts(o) {
3904
4352
  code: "claim-not-on-line",
3905
4353
  message: quiet ? `${pl} is not written at ${p.file}:${p.line} (or the line either side); cite the line that writes it (its text is not repeated here: it may be a secret)` : `${pl} says "${p.value}" is written at ${p.file}:${p.line} (or the line either side), and it isn't`
3906
4354
  };
3907
- partLines.push(...near(ls, p.line));
4355
+ const partNear = near(ls, p.line);
4356
+ const from = Math.max(0, p.line - 2);
4357
+ const isComment2 = partNear.map((_, i2) => commentAt(p.file, ls, from + i2 + 1));
4358
+ const naming = claims2 && isComment2.some(Boolean) ? partNear.map((l, i2) => ({ l, comment: isComment2[i2] })).filter(({ l }) => lineNamesClaim(l, routeOrWord(p.value)) || lineNamesClaim(l, { kind: "word", value: p.value.replace(/^\/+|\/+$/g, "") }) || partsNamePath([l], p.value)) : [];
4359
+ if (claims2 && naming.length && !/(^|\/)_redirects$/.test(p.file) && naming.every((x) => x.comment))
4360
+ return {
4361
+ code: "claim-in-comment",
4362
+ message: quiet ? `${pl} is written at ${p.file}:${p.line} (or the line either side) only in a comment; cite the code that does it` : `${pl} says "${p.value}", which ${p.file}:${p.line} (or the line either side) writes only in a comment; cite the code that does it`
4363
+ };
4364
+ const kept2 = /(^|\/)_redirects$/.test(p.file) ? partNear : partNear.filter((_, i2) => !isComment2[i2]);
4365
+ partLines.push(...kept2);
4366
+ partWindows.push(kept2.join("\n"));
3908
4367
  }
4368
+ const codeLines = parts.length && !/(^|\/)_redirects$/.test(cite2.file) ? codeLinesOf(cite2.file, lines) : lines;
3909
4369
  let derived;
3910
4370
  const derivedHere = () => derived ??= [
3911
4371
  { file: cite2.file, line: cite2.line },
3912
4372
  ...parts.map((p) => ({ file: p.file, line: p.line }))
3913
4373
  ].flatMap((at) => derivedNamesAt(at.file, linesOf2(at.file) ?? [], at.line, deriveEnv));
3914
- const holds = (c) => claimOnLines(lines, cite2.line, c) || // a framework that routes by file place (Razor Pages, WebForms, Next.js)
3915
- c.kind === "route" && pageRouteMatches(cite2.file, lines, (p) => linesOf2(p) !== void 0, c.value) || parts.length > 0 && (c.kind === "route" ? partsNamePath([...near(lines, cite2.line), ...partLines], c.value) : partLines.some((l) => lineNamesClaim(l, c)) || // a word put together from parts (`namespace:task`, a key a helper prefixes)
3916
- c.kind === "word" && partsBuildWord(c.value, parts.map((p) => p.value), near(lines, cite2.line))) || o.derivedNames !== false && derivedHolds(c, derivedHere(), partLines, partsNamePath) || alsoHolds !== void 0 && alsoHolds(lines, cite2.line);
3917
- if (claims && !claims.some(holds))
4374
+ const conventional = declaresConventionalRoute([
4375
+ ...parts.map((p) => p.value),
4376
+ ...partWindows,
4377
+ near(codeLines, cite2.line).join("\n")
4378
+ ]);
4379
+ const onlyInComment = (c) => httpRoute && parts.length > 0 && c.kind === "route" && codeLines !== lines && !conventional && pathPieceOnlyInComment(near(lines, cite2.line), (_, i) => commentAt(cite2.file, lines, Math.max(0, cite2.line - 2) + i + 1), partLines, c.value) !== void 0;
4380
+ const holdsOn = (lines2) => (c) => claimOnLines(lines2, cite2.line, c) || // a framework that routes by file place (Razor Pages, WebForms, Next.js)
4381
+ c.kind === "route" && pageRouteMatches(cite2.file, lines2, (p) => linesOf2(p) !== void 0, c.value) || parts.length > 0 && (c.kind === "route" ? partsNamePath([...near(lines2, cite2.line), ...partLines], c.value) && !onlyInComment(c) : partLines.some((l) => lineNamesClaim(l, c)) || // a word put together from parts (`namespace:task`, a key a helper prefixes)
4382
+ c.kind === "word" && partsBuildWord(c.value, parts.map((p) => p.value), near(lines2, cite2.line))) || o.derivedNames !== false && derivedHolds(c, derivedHere(), partLines, partsNamePath) || alsoHolds !== void 0 && alsoHolds(lines2, cite2.line);
4383
+ if (claims2 && !claims2.some(holdsOn(codeLines))) {
4384
+ if (codeLines !== lines && (claims2.some(holdsOn(lines)) || claims2.some(onlyInComment)))
4385
+ return {
4386
+ code: "claim-in-comment",
4387
+ message: `${label} claims ${claims2.map((c) => `"${c.value}"`).join(" or ")}, which ${where} (or the line either side) and its parts write only in a comment; cite the code that does it`
4388
+ };
3918
4389
  return {
3919
4390
  code: "claim-not-on-line",
3920
- message: `${label} claims ${claims.map((c) => `"${c.value}"`).join(" or ")}, which ${where} (or the line either side)${parts.length ? " and its parts" : ""} does not name${parts.length || !withHint ? "" : "; if it is put together from other lines (a base URL, a prefix, a context path), cite them in cite.with"}`
4391
+ message: `${label} claims ${claims2.map((c) => `"${c.value}"`).join(" or ")}, which ${where} (or the line either side)${parts.length ? " and its parts" : ""} does not name${parts.length || !withHint ? "" : "; if it is put together from other lines (a base URL, a prefix, a context path), cite them in cite.with"}`
3921
4392
  };
3922
- if (claims && parts.length && isCommentLine(lines[cite2.line - 1] ?? "") && !/(^|\/)_redirects$/.test(cite2.file))
4393
+ }
4394
+ if (claims2 && parts.length && commentAt(cite2.file, lines, cite2.line) && !/(^|\/)_redirects$/.test(cite2.file))
3923
4395
  return {
3924
4396
  code: "claim-in-comment",
3925
4397
  message: `${label} cites ${where}, which is a comment; cite the code that does it`
3926
4398
  };
3927
- if (claims && !parts.length) {
3928
- const naming = [cite2.line - 1, cite2.line, cite2.line + 1].map((n) => lines[n - 1]).filter((l) => l !== void 0 && claims.some((c) => lineNamesClaim(l, c)));
3929
- if (naming.length && !/(^|\/)_redirects$/.test(cite2.file) && naming.every(isCommentLine))
4399
+ if (claims2 && !parts.length) {
4400
+ const naming = [cite2.line - 1, cite2.line, cite2.line + 1].filter((n) => {
4401
+ const l = lines[n - 1];
4402
+ return l !== void 0 && claims2.some((c) => lineNamesClaim(l, c));
4403
+ });
4404
+ if (naming.length && !/(^|\/)_redirects$/.test(cite2.file) && naming.every((n) => commentAt(cite2.file, lines, n)))
3930
4405
  return {
3931
4406
  code: "claim-in-comment",
3932
- message: `${label} claims ${claims.map((c) => `"${c.value}"`).join(" or ")}, which ${where} writes only in a comment; cite the code that does it`
4407
+ message: `${label} claims ${claims2.map((c) => `"${c.value}"`).join(" or ")}, which ${where} writes only in a comment; cite the code that does it`
3933
4408
  };
3934
4409
  }
3935
4410
  const line = lines[cite2.line - 1] ?? "";
@@ -3977,7 +4452,7 @@ async function verifyFacts(o) {
3977
4452
  // beta.24): a helper puts the key together (a `@ConfigurationProperties` prefix, a
3978
4453
  // map field, the name passed to a lookup). The cited line is code naming the key's
3979
4454
  // last segment, and one file among the parts proves the rest of the key nests so.
3980
- f.kind === "call" && PLACEHOLDER_KEY.test(f.path.trim()) && helperBuildsKey(PLACEHOLDER_KEY.exec(f.path.trim())[1], f.cite, linesOf2) : void 0, quietFact(f, lineAt)));
4455
+ f.kind === "call" && PLACEHOLDER_KEY.test(f.path.trim()) && helperBuildsKey(PLACEHOLDER_KEY.exec(f.path.trim())[1], f.cite, linesOf2) : void 0, quietFact(f, lineAt), f.kind === "entry" && f.entryType === "rest" || f.kind === "call" && f.callType === "rest"));
3981
4456
  if (f.kind === "config" && !found.has(f.id)) {
3982
4457
  const bad = configLineProblem(f, linesOf2, listed2, rules.gatewayBundleFolders);
3983
4458
  if (bad)
@@ -4548,9 +5023,9 @@ function numberedSlice(text, s) {
4548
5023
  return linesOf(text).slice(s.from - 1, s.to).map((l, i) => `${s.from + i}| ${shownLine(l)}`).join("\n");
4549
5024
  }
4550
5025
  var header = (s) => `${s.path} lines ${s.from}-${s.to} of ${s.of} (numbered as in the file)`;
4551
- function sliceText(source, s) {
5026
+ function sliceText(source2, s) {
4552
5027
  return `${header(s)}
4553
- ${numberedSlice(source.read(s.path) ?? "", s)}`;
5028
+ ${numberedSlice(source2.read(s.path) ?? "", s)}`;
4554
5029
  }
4555
5030
  var tokensOf = (units) => Math.ceil(units / 4);
4556
5031
  var wrapUnits = (path) => tokenUnits(`<atticus-data id="1-file-0000" kind="code" origin="${path}#L0000000-0000000">
@@ -4558,7 +5033,7 @@ var wrapUnits = (path) => tokenUnits(`<atticus-data id="1-file-0000" kind="code"
4558
5033
  </atticus-data>
4559
5034
 
4560
5035
  `);
4561
- function planBatches(source, o) {
5036
+ function planBatches(source2, o) {
4562
5037
  const room = Math.max(1, o.room);
4563
5038
  const rules = readRulesOf(o.conventions);
4564
5039
  const excludeRes = (o.exclude ?? []).map(globToRegExp);
@@ -4567,10 +5042,10 @@ function planBatches(source, o) {
4567
5042
  const notReached = [];
4568
5043
  const paths = [];
4569
5044
  const texts = /* @__PURE__ */ new Map();
4570
- for (const p of source.list()) {
4571
- if (!isSourceFile(p, "", void 0, rules) || tooBigToRead(source, p))
5045
+ for (const p of source2.list()) {
5046
+ if (!isSourceFile(p, "", void 0, rules) || tooBigToRead(source2, p))
4572
5047
  continue;
4573
- const text = source.read(p);
5048
+ const text = source2.read(p);
4574
5049
  if (text === void 0)
4575
5050
  continue;
4576
5051
  const ls = linesOf(text);
@@ -6036,11 +6511,11 @@ function toDrawio(view, o = {}) {
6036
6511
  y += Math.max(...row.map((b) => b.h)) + GAP;
6037
6512
  }
6038
6513
  for (const e of view.edges) {
6039
- const source = cellOf.get(e.from);
6514
+ const source2 = cellOf.get(e.from);
6040
6515
  const target = cellOf.get(e.to);
6041
- if (!source || !target)
6516
+ if (!source2 || !target)
6042
6517
  continue;
6043
- cells.push(` <mxCell id="${attr(`edge.${e.id}`)}" value="${attr(e.label)}" style="${attr(edgeStyle(e))}" edge="1" parent="1" source="${attr(source)}" target="${attr(target)}">
6518
+ cells.push(` <mxCell id="${attr(`edge.${e.id}`)}" value="${attr(e.label)}" style="${attr(edgeStyle(e))}" edge="1" parent="1" source="${attr(source2)}" target="${attr(target)}">
6044
6519
  <mxGeometry relative="1" as="geometry"/>
6045
6520
  </mxCell>`);
6046
6521
  }
@@ -6086,7 +6561,7 @@ function shapeLibrary() {
6086
6561
  return `<mxlibrary>${JSON.stringify(entries)}</mxlibrary>
6087
6562
  `;
6088
6563
  }
6089
- function viewFromDiagram(diagram, source) {
6564
+ function viewFromDiagram(diagram, source2) {
6090
6565
  const multi = new Set(diagram.nodes.map((n) => n.page)).size > 1;
6091
6566
  const key = (page, cell) => multi ? `${page}:${cell}` : cell;
6092
6567
  const nodes = diagram.nodes.map((n) => ({
@@ -6111,7 +6586,7 @@ function viewFromDiagram(diagram, source) {
6111
6586
  ...e.legend ? { legend: e.legend } : {}
6112
6587
  });
6113
6588
  }
6114
- return { type: "diagram", title: "Diagram view", source, groups: [], nodes, edges };
6589
+ return { type: "diagram", title: "Diagram view", source: source2, groups: [], nodes, edges };
6115
6590
  }
6116
6591
 
6117
6592
  // packages/diagrams/dist/hierarchy.js
@@ -6536,18 +7011,24 @@ function buildEstate(records2, o = {}) {
6536
7011
  }
6537
7012
  });
6538
7013
  const partNode = (ref) => components.has(ref) ? `component:${ref}` : systems.has(ref) ? `system:${ref}` : unknown(ref);
7014
+ const withRepo = new Set(repoSystem.values());
7015
+ const hasRepo = (id) => withRepo.has(id) || (systemRecords.get(id)?.repos.length ?? 0) > 0;
7016
+ const outsideSystem = (id) => !hasRepo(id) && systemRecords.get(id)?.boundary === "vendor";
6539
7017
  for (const c of components.values()) {
6540
7018
  const gaps = [];
6541
7019
  let parent;
7020
+ const outsideOne = !c.repo && outsideSystem(c.system);
6542
7021
  if (c.repo)
6543
7022
  parent = repoNode(c.repo);
6544
7023
  else {
6545
- gaps.push("no-repo");
7024
+ if (!outsideOne)
7025
+ gaps.push("no-repo");
6546
7026
  parent = systems.has(c.system) ? `system:${c.system}` : "estate";
6547
7027
  }
6548
7028
  if (!systems.has(c.system))
6549
7029
  gaps.push("no-system");
6550
- add(fromRecord(c, `component:${c.id}`, "component", c.id, parent, { type: c.type, runtime: c.runtime, repo: c.repo, path: c.path }, gaps));
7030
+ const node = fromRecord(c, `component:${c.id}`, "component", c.id, parent, { type: c.type, runtime: c.runtime, repo: c.repo, path: c.path }, gaps);
7031
+ add(outsideOne ? { ...node, gaps: node.gaps.filter((g) => g !== "inferred") } : node);
6551
7032
  }
6552
7033
  const endpointNode = /* @__PURE__ */ new Map();
6553
7034
  const topicByPath = /* @__PURE__ */ new Map();
@@ -6635,10 +7116,10 @@ function buildEstate(records2, o = {}) {
6635
7116
  const ev = evidenceOf(i.evidence);
6636
7117
  const gaps = [...recordGaps(i), ...i.conflicts.length ? ["conflicts"] : []];
6637
7118
  const target = i.endpoint ? endpointNode.get(i.endpoint) : void 0;
6638
- const join2 = joinOf(i);
7119
+ const join3 = joinOf(i);
6639
7120
  if (target?.startsWith("topic:")) {
6640
- atoms.push({ from, to: target, type: "publishes", evidence: ev, gaps, join: join2 });
6641
- atoms.push({ from: to, to: target, type: "subscribes", evidence: ev, gaps, join: join2 });
7121
+ atoms.push({ from, to: target, type: "publishes", evidence: ev, gaps, join: join3 });
7122
+ atoms.push({ from: to, to: target, type: "subscribes", evidence: ev, gaps, join: join3 });
6642
7123
  continue;
6643
7124
  }
6644
7125
  if (!i.endpoint && (i.via === "event-bus" || i.via === "mq") && i.normalizedPath) {
@@ -6652,16 +7133,16 @@ function buildEstate(records2, o = {}) {
6652
7133
  if (outside.has(homeRef) || b === "vendor" || b === "outside")
6653
7134
  owner.properties.ownerOutside = true;
6654
7135
  }
6655
- if (join2.shared)
6656
- owner.properties = { ...owner.properties, owner: join2.shared.team, ownerOutside: true };
7136
+ if (join3.shared)
7137
+ owner.properties = { ...owner.properties, owner: join3.shared.team, ownerOutside: true };
6657
7138
  if (i.flags?.includes(DECLARED_TOPIC)) {
6658
7139
  owner.properties = { ...owner.properties, declared: true };
6659
7140
  owner.gaps = [.../* @__PURE__ */ new Set([...owner.gaps, DECLARED_TOPIC])];
6660
7141
  owner.evidence = mergeEvidence(owner.evidence, evidenceOf(i.evidence.filter((e) => e.source === "manual")));
6661
7142
  }
6662
- atoms.push({ from, to: t, type: "publishes", evidence: ev, gaps, join: join2 });
7143
+ atoms.push({ from, to: t, type: "publishes", evidence: ev, gaps, join: join3 });
6663
7144
  if (to.startsWith("component:"))
6664
- atoms.push({ from: to, to: t, type: "subscribes", evidence: ev, gaps, join: join2 });
7145
+ atoms.push({ from: to, to: t, type: "subscribes", evidence: ev, gaps, join: join3 });
6665
7146
  continue;
6666
7147
  }
6667
7148
  let caller = from;
@@ -6693,7 +7174,7 @@ function buildEstate(records2, o = {}) {
6693
7174
  via: i.via,
6694
7175
  evidence: ev,
6695
7176
  gaps: [...gaps, ...i.endpoint && !target ? ["no-endpoint"] : []],
6696
- join: join2
7177
+ join: join3
6697
7178
  });
6698
7179
  }
6699
7180
  for (const u of all(records2, "Unresolved")) {
@@ -6724,14 +7205,14 @@ function buildEstate(records2, o = {}) {
6724
7205
  for (const l of o.dependsOn ?? []) {
6725
7206
  if (!components.has(l.from.component) || !components.has(l.to.component))
6726
7207
  continue;
6727
- const join2 = dependencyJoin(l);
7208
+ const join3 = dependencyJoin(l);
6728
7209
  atoms.push({
6729
7210
  from: `component:${l.from.component}`,
6730
7211
  to: `component:${l.to.component}`,
6731
7212
  type: "depends-on",
6732
- evidence: mergeEvidence(join2.caller.slice(0, 1), join2.callee.slice(0, 1)),
7213
+ evidence: mergeEvidence(join3.caller.slice(0, 1), join3.callee.slice(0, 1)),
6733
7214
  gaps: [],
6734
- join: join2
7215
+ join: join3
6735
7216
  });
6736
7217
  }
6737
7218
  for (const t of tables) {
@@ -6924,9 +7405,9 @@ function reduceUses(edges) {
6924
7405
  const out = /* @__PURE__ */ new Map();
6925
7406
  for (const e of uses)
6926
7407
  out.set(e.from, [...out.get(e.from) ?? [], e.to]);
6927
- const reachesWithout = (from, to, skip) => {
7408
+ const reachesWithout = (from, to, skip2) => {
6928
7409
  const seen = /* @__PURE__ */ new Set();
6929
- const stack = (out.get(from) ?? []).filter((n) => !(from === skip.from && n === skip.to));
7410
+ const stack = (out.get(from) ?? []).filter((n) => !(from === skip2.from && n === skip2.to));
6930
7411
  while (stack.length) {
6931
7412
  const n = stack.pop();
6932
7413
  if (n === to)
@@ -7694,9 +8175,9 @@ function rereadPlan(o) {
7694
8175
  unknown: [...unknown].sort()
7695
8176
  };
7696
8177
  }
7697
- function onlyFiles(source, paths) {
8178
+ function onlyFiles(source2, paths) {
7698
8179
  const keep = new Set(paths);
7699
- return { list: () => source.list().filter((p) => keep.has(p)), read: (p) => source.read(p) };
8180
+ return { list: () => source2.list().filter((p) => keep.has(p)), read: (p) => source2.read(p) };
7700
8181
  }
7701
8182
 
7702
8183
  // packages/verify/dist/slips.js
@@ -7845,6 +8326,759 @@ function repairFormSlips(facts, bad, onFile = []) {
7845
8326
  return { facts: kept, bad: still, slips };
7846
8327
  }
7847
8328
 
8329
+ // packages/verify/dist/canary.js
8330
+ var CANARY_DEFAULT_REMOVALS = 3;
8331
+ var WORDS = [
8332
+ "amber",
8333
+ "aspen",
8334
+ "basalt",
8335
+ "birch",
8336
+ "bramble",
8337
+ "cedar",
8338
+ "cobalt",
8339
+ "coral",
8340
+ "cypress",
8341
+ "dune",
8342
+ "ember",
8343
+ "fennel",
8344
+ "fjord",
8345
+ "garnet",
8346
+ "glacier",
8347
+ "hazel",
8348
+ "heron",
8349
+ "indigo",
8350
+ "juniper",
8351
+ "kelp",
8352
+ "kestrel",
8353
+ "larch",
8354
+ "lumen",
8355
+ "maple",
8356
+ "marlin",
8357
+ "meadow",
8358
+ "nimbus",
8359
+ "nutmeg",
8360
+ "onyx",
8361
+ "orchid",
8362
+ "pebble",
8363
+ "plover",
8364
+ "quartz",
8365
+ "quill",
8366
+ "raven",
8367
+ "reed",
8368
+ "saffron",
8369
+ "sorrel",
8370
+ "spruce",
8371
+ "tamarack",
8372
+ "thistle",
8373
+ "tundra",
8374
+ "umber",
8375
+ "vale",
8376
+ "willow",
8377
+ "wren",
8378
+ "yarrow",
8379
+ "zephyr"
8380
+ ];
8381
+ var SPRING = /\borg\.springframework\b/;
8382
+ var SPRING_APP = /@SpringBootApplication\b/;
8383
+ var TEST_PATH = /(^|\/)(tests?|__tests__|spec|e2e|fixtures?)\//i;
8384
+ var TEST_FILE = /(\.(test|spec)\.[cm]?[jt]sx?$|_test\.py$|^test_.*\.py$|Test\.java$|Tests\.java$)/;
8385
+ var NODE_SOURCE = /\.(ts|tsx|js|jsx|mjs)$/;
8386
+ var NOT_NODE_SOURCE = /(\.d\.ts$|\.config\.[cm]?[jt]s$|\.min\.js$)/;
8387
+ var NEVER_COPIED = [
8388
+ // registries, hosts, databases, clouds and vaults (second review of ADR 0196: the rest of them)
8389
+ /(^|\/)[._]?(npmrc|pypirc|netrc|git-credentials|htpasswd|envrc|pgpass|my\.cnf|s3cfg|boto|vault-token|dockercfg|yarnrc|terraformrc|bowerrc)$/i,
8390
+ /(^|\/)\.yarnrc\.yml$/i,
8391
+ /(^|\/)kubeconfig([._-][^/]*)?$/i,
8392
+ /(^|\/)\.kube\/config$/i,
8393
+ /(^|\/)\.docker\/config\.json$/i,
8394
+ /(^|\/)\.ssh\//i,
8395
+ /(^|\/)\.config\/gh\/hosts\.ya?ml$/i,
8396
+ /(^|\/)\.cargo\/credentials(\.toml)?$/i,
8397
+ /(^|\/)\.gradle\/gradle\.properties$/i,
8398
+ /(^|\/)credentials\.tfrc\.json$/i,
8399
+ /(^|\/)settings-security\.xml$/i,
8400
+ /(^|\/)wallet\.dat$/i,
8401
+ /\.env$/i,
8402
+ /(^|\/)\.env\.[^/]+$/i,
8403
+ /(^|\/|[-_.])secrets?\.(ya?ml|json)$/i,
8404
+ /(^|\/)local\.settings\.json$/i,
8405
+ /(^|\/)appsettings\.[^/]*secrets?[^/]*\.json$/i,
8406
+ /(^|\/)auth\.json$/i,
8407
+ /(^|\/)service[-_]?account[^/]*\.json$/i,
8408
+ /(^|\/)[^/]*sa[-_]key[^/]*\.json$/i,
8409
+ /(^|\/)[^/]*[-_]key\.json$/i,
8410
+ /(^|\/)firebase-adminsdk[^/]*\.json$/i,
8411
+ /(^|\/)client_secret[^/]*\.json$/i,
8412
+ /\.tfvars(\.json)?$/i,
8413
+ /\.tfstate([.][^/]*)?$/i,
8414
+ /\.(p8|p12|pfx|kdbx|keystore|jks|pem|key|ppk|keytab|asc|gpg|ovpn)$/i
8415
+ ];
8416
+ var BACKUP = /(\.(bak|old|orig|backup|save|swp|tmp)|~)$/i;
8417
+ function canaryNeverCopied(path) {
8418
+ if (isSecretPath(path))
8419
+ return true;
8420
+ let p = path.replace(/\\/g, "/").split("/").map((x) => x.replace(/:.*$/, "").replace(/[. ]+$/, "")).join("/");
8421
+ for (; ; ) {
8422
+ if (NEVER_COPIED.some((re) => re.test(p)))
8423
+ return true;
8424
+ const q = p.replace(BACKUP, "");
8425
+ if (q === p)
8426
+ return false;
8427
+ if (isSecretPath(q))
8428
+ return true;
8429
+ p = q;
8430
+ }
8431
+ }
8432
+ var CANARY_SECRET_PREFIX = 64 * 1024;
8433
+ function canaryHoldsSecret(prefix) {
8434
+ return /-----BEGIN [A-Z ]*PRIVATE KEY( BLOCK)?-----/.test(prefix) || /\baws_secret_access_key\s*[=:]/i.test(prefix) || /"private_key"\s*:/.test(prefix) || /_authToken\s*=/.test(prefix);
8435
+ }
8436
+ var dirOf3 = (p) => p.includes("/") ? p.slice(0, p.lastIndexOf("/")) : "";
8437
+ var baseOf = (p) => p.slice(p.lastIndexOf("/") + 1);
8438
+ var join2 = (dir, name) => dir ? `${dir}/${name}` : name;
8439
+ var source = (p) => !TEST_PATH.test(p) && !TEST_FILE.test(baseOf(p));
8440
+ function hostOf2(file, text, re) {
8441
+ const m = re.exec(text);
8442
+ if (!m)
8443
+ return void 0;
8444
+ return { file, v: m[1], line: text.slice(0, m.index).split("\n").length, call: m[2] };
8445
+ }
8446
+ var NODE_APP = /^(?:export\s+)?(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*(?::\s*[\w$.<>[\], ]+?\s*)?=\s*(express\s*\.\s*Router|express|Router)\s*\(\s*(?:\{[^(){}]*\}\s*)?\)/m;
8447
+ var PY_APP = /^([A-Za-z_]\w*)\s*(?::\s*[\w.[\], ]+?\s*)?=\s*(APIRouter|FastAPI|Flask|Blueprint)\s*\(/m;
8448
+ var PY_FACTORY = /^\s+[A-Za-z_]\w*\s*(?::[^=\n]+)?=\s*(Flask|FastAPI)\s*\(/m;
8449
+ var within = (dir, of) => of === "" || dir === of || dir.startsWith(`${of}/`);
8450
+ function buildFilesOf(files, file, isBuild) {
8451
+ const at = dirOf3(file);
8452
+ return files.filter((f) => {
8453
+ if (!isBuild(f))
8454
+ return false;
8455
+ const home = /(^|\/)requirements\/[^/]+$/.test(f) ? dirOf3(dirOf3(f)) : dirOf3(f);
8456
+ return within(at, home);
8457
+ });
8458
+ }
8459
+ var GRADLE_BUILD2 = /(^|\/)(pom\.xml|build\.gradle(\.kts)?)$/;
8460
+ var CONVENTION = /(^|\/)(buildSrc|build-logic)\/.*\.gradle(\.kts)?$/;
8461
+ var CATALOG = /(^|\/)gradle\/([^/]+)\.versions\.toml$/;
8462
+ var dashed = (s) => s.replace(/[._]/g, "-");
8463
+ var escapeRe = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8464
+ function springBuildText(src, files, file) {
8465
+ const parts = buildFilesOf(files, file, (f) => GRADLE_BUILD2.test(f) && !CONVENTION.test(f)).map((f) => src.read(f) ?? "");
8466
+ const conventions = files.filter((f) => CONVENTION.test(f)).map((f) => ({ id: baseOf(f).replace(/\.gradle(\.kts)?$/, ""), text: src.read(f) ?? "" }));
8467
+ const applied = /* @__PURE__ */ new Set();
8468
+ for (let more = true; more; ) {
8469
+ more = false;
8470
+ const all2 = parts.join("\n");
8471
+ for (const c of conventions)
8472
+ if (!applied.has(c.id) && new RegExp(`["'\`]${escapeRe(c.id)}["'\`]`).test(all2)) {
8473
+ applied.add(c.id);
8474
+ parts.push(c.text);
8475
+ more = true;
8476
+ }
8477
+ }
8478
+ let text = dashed(parts.join("\n"));
8479
+ for (const f of files.filter((x) => CATALOG.test(x))) {
8480
+ const name = dashed(CATALOG.exec(f)[2]);
8481
+ for (const l of (src.read(f) ?? "").split("\n")) {
8482
+ const m = /^\s*([A-Za-z0-9_.-]+)\s*=\s*(?:\{[^}]*?\bmodule\s*=\s*"[^":]+:([^":]+)"|\{[^}]*?\bname\s*=\s*"([^"]+)"|"[^":]+:([^":]+)(?::[^"]*)?")/.exec(l);
8483
+ const artifact = m && (m[2] ?? m[3] ?? m[4]);
8484
+ if (!artifact)
8485
+ continue;
8486
+ if (new RegExp(`\\b${escapeRe(`${name}-${dashed(m[1])}`)}(?![A-Za-z0-9-])`).test(text))
8487
+ text += `
8488
+ ${artifact}`;
8489
+ }
8490
+ }
8491
+ return text;
8492
+ }
8493
+ var SPRING_WEB = /spring-boot-starter-web\b|spring-boot-starter-webflux|spring-webmvc|spring-webflux|spring-web\b/;
8494
+ var SPRING_KAFKA = /\bspring-kafka\b|\bspring-cloud-stream-binder-kafka\b|\bspring-cloud-starter-stream-kafka\b/;
8495
+ var NODE_SERVERS = ["express", "fastify", "koa", "@hapi/hapi", "@nestjs/core", "hono", "next"];
8496
+ var BROWSER_LIBS = [
8497
+ "react",
8498
+ "react-dom",
8499
+ "vue",
8500
+ "svelte",
8501
+ "@angular/core",
8502
+ "preact",
8503
+ "solid-js",
8504
+ "vite",
8505
+ "@vitejs/plugin-react",
8506
+ "webpack",
8507
+ "parcel"
8508
+ ];
8509
+ function packageOf(files, file) {
8510
+ const all2 = new Set(files);
8511
+ for (let d = dirOf3(file); ; d = dirOf3(d)) {
8512
+ if (all2.has(join2(d, "package.json")))
8513
+ return join2(d, "package.json");
8514
+ if (d === "")
8515
+ return void 0;
8516
+ }
8517
+ }
8518
+ function nodePackages(src, files) {
8519
+ const out = /* @__PURE__ */ new Set();
8520
+ for (const f of files) {
8521
+ try {
8522
+ const j = JSON.parse(src.read(f) ?? "");
8523
+ for (const k of [
8524
+ "dependencies",
8525
+ "devDependencies",
8526
+ "peerDependencies",
8527
+ "optionalDependencies"
8528
+ ]) {
8529
+ const d = j[k];
8530
+ if (d && typeof d === "object")
8531
+ for (const n of Object.keys(d))
8532
+ out.add(n);
8533
+ }
8534
+ } catch {
8535
+ }
8536
+ }
8537
+ return out;
8538
+ }
8539
+ var skip = (what, reason) => what.map((w) => ({ what: w, reason }));
8540
+ function canaryStacks(src, seed) {
8541
+ const files = src.list();
8542
+ const pick = (list2, what) => seededShuffle(list2.map((id) => ({ id })), `${seed}:${what}`)[0]?.id;
8543
+ const out = [];
8544
+ const springFiles = files.filter((f) => f.endsWith(".java") && source(f) && SPRING.test(src.read(f) ?? ""));
8545
+ if (springFiles.length) {
8546
+ const app = pick(springFiles.filter((f) => SPRING_APP.test(src.read(f) ?? "")), "spring-app");
8547
+ const spring = app ?? pick(springFiles, "spring");
8548
+ const pkg = /^\s*package\s+([\w.]+)\s*;/m.exec(src.read(spring) ?? "")?.[1];
8549
+ const module = buildFilesOf(files, spring, (f) => GRADLE_BUILD2.test(f) && !CONVENTION.test(f)).map(dirOf3).sort((a, b) => b.length - a.length)[0];
8550
+ const configs = files.filter((f) => /(^|\/)application\.(ya?ml|properties)$/.test(f) && source(f)).sort((a, b) => a.length - b.length || (a < b ? -1 : 1));
8551
+ const config2 = configs.find((f) => module !== void 0 && within(dirOf3(f), module)) ?? (module === void 0 || module === "" ? configs[0] : void 0);
8552
+ const build = springBuildText(src, files, spring);
8553
+ const web = SPRING_WEB.test(build);
8554
+ const kafka = SPRING_KAFKA.test(build);
8555
+ const can = /* @__PURE__ */ new Set();
8556
+ const skipped = [];
8557
+ if (!app)
8558
+ skipped.push(...skip(["entry", "call", "topic-in", "topic-out"], "no @SpringBootApplication class, so no scan would find a new class"));
8559
+ else {
8560
+ if (web)
8561
+ can.add("entry").add("call");
8562
+ else
8563
+ skipped.push(...skip(["entry", "call"], "the app's module's build files declare no Spring web library (spring-web)"));
8564
+ if (kafka)
8565
+ can.add("topic-in").add("topic-out");
8566
+ else
8567
+ skipped.push(...skip(["topic-in", "topic-out"], "the app's module's build files declare no Kafka client (spring-kafka, or Spring Cloud Stream's Kafka binder)"));
8568
+ }
8569
+ if (config2 || can.has("entry"))
8570
+ can.add("config");
8571
+ else
8572
+ skipped.push(...skip(["config"], "no application config file, and no web class to read a key in"));
8573
+ out.push({
8574
+ stack: "spring",
8575
+ dir: dirOf3(spring),
8576
+ ...pkg ? { pkg } : {},
8577
+ ...config2 ? { config: config2 } : {},
8578
+ can,
8579
+ skipped
8580
+ });
8581
+ }
8582
+ if (files.some((f) => baseOf(f) === "package.json")) {
8583
+ const nodeFiles = files.filter((f) => NODE_SOURCE.test(f) && !NOT_NODE_SOURCE.test(f) && source(f));
8584
+ const ext = nodeFiles.some((f) => /\.tsx?$/.test(f)) ? "ts" : "js";
8585
+ const pkgsCache = /* @__PURE__ */ new Map();
8586
+ const pkgsOf = (f) => {
8587
+ const p = packageOf(files, f) ?? "";
8588
+ if (!pkgsCache.has(p))
8589
+ pkgsCache.set(p, nodePackages(src, p ? [p] : []));
8590
+ return pkgsCache.get(p);
8591
+ };
8592
+ const app = pick(nodeFiles.filter((f) => pkgsOf(f).has("express") && NODE_APP.test(src.read(f) ?? "")), "node-app");
8593
+ const under4 = nodeFiles.filter((f) => /(^|\/)src\//.test(f));
8594
+ const node = app ?? pick(under4.length ? under4 : nodeFiles, "node");
8595
+ if (node) {
8596
+ const pkgs = pkgsOf(node);
8597
+ const text = app ? src.read(app) ?? "" : "";
8598
+ const cjs = !/^\s*(import|export)\s/m.test(text) && /\brequire\(/.test(text);
8599
+ const browser = !NODE_SERVERS.some((s) => pkgs.has(s)) && BROWSER_LIBS.some((s) => pkgs.has(s));
8600
+ const can = /* @__PURE__ */ new Set(["call"]);
8601
+ const skipped = [];
8602
+ if (browser)
8603
+ skipped.push(...skip(["config"], "a browser app (its package declares no server) has no process.env"));
8604
+ else
8605
+ can.add("config");
8606
+ if (app)
8607
+ can.add("entry");
8608
+ else
8609
+ skipped.push(...skip(["entry"], pkgs.has("express") ? "no express app or router made at a module's top level to serve a route on" : "its package declares no server (express): a browser app serves no route"));
8610
+ if (pkgs.has("kafkajs") && !browser)
8611
+ can.add("topic-in").add("topic-out");
8612
+ else
8613
+ skipped.push(...skip(["topic-in", "topic-out"], "its package declares no Kafka client (kafkajs)"));
8614
+ const h = app ? hostOf2(app, text, NODE_APP) : void 0;
8615
+ out.push({
8616
+ stack: "node",
8617
+ dir: dirOf3(node),
8618
+ ext,
8619
+ ...h ? { host: { file: h.file, v: h.v, line: h.line, ...cjs ? { cjs } : {} } } : {},
8620
+ ...browser ? { browser } : {},
8621
+ can,
8622
+ skipped
8623
+ });
8624
+ }
8625
+ }
8626
+ const pyFiles = files.filter((f) => f.endsWith(".py") && source(f) && baseOf(f) !== "__init__.py");
8627
+ const pyText = (f) => src.read(f) ?? "";
8628
+ const PY_BUILD = /(^|\/)(pyproject\.toml|setup\.py|setup\.cfg|Pipfile|requirements[^/]*\.(txt|in)|requirements\/[^/]+\.(txt|in))$/;
8629
+ const declaresIn = (f) => {
8630
+ const text = buildFilesOf(files, f, (p) => PY_BUILD.test(p)).map(pyText).join("\n");
8631
+ return (name) => new RegExp(`(^|[^A-Za-z0-9_.-])${name}([^A-Za-z0-9_.-]|$)`, "im").test(text);
8632
+ };
8633
+ const allPy = files.filter((f) => f.endsWith(".py") && source(f));
8634
+ const registered = (v, call) => call !== "Blueprint" && call !== "APIRouter" ? true : allPy.some((f) => new RegExp(`\\b${call === "Blueprint" ? "register_blueprint" : "include_router"}\\s*\\(\\s*(?:[A-Za-z_]\\w*\\.)?${v}\\b`).test(pyText(f)));
8635
+ const served = (f) => {
8636
+ const m = PY_APP.exec(pyText(f));
8637
+ if (!m || !registered(m[1], m[2]))
8638
+ return false;
8639
+ return m[2] === "Flask" || m[2] === "Blueprint" ? declaresIn(f)("flask") : declaresIn(f)("fastapi");
8640
+ };
8641
+ const pyApp = pick(pyFiles.filter((f) => PY_APP.test(pyText(f)) && served(f)), "python-app");
8642
+ const py = pyApp ?? pick(pyFiles, "python");
8643
+ if (py) {
8644
+ const declares = declaresIn(py);
8645
+ const h = pyApp ? hostOf2(pyApp, pyText(pyApp), PY_APP) : void 0;
8646
+ const http = declares("httpx") ? "httpx" : declares("requests") ? "requests" : void 0;
8647
+ const can = /* @__PURE__ */ new Set(["config"]);
8648
+ const skipped = [];
8649
+ if (h)
8650
+ can.add("entry");
8651
+ else
8652
+ skipped.push(...skip(["entry"], files.some((f) => f.endsWith(".py") && PY_FACTORY.test(pyText(f))) ? "the app is made inside a function (an app factory), and no module-level router or blueprint is registered on it to serve a route on" : "no app or router the build files' web framework makes to serve a route on"));
8653
+ if (http)
8654
+ can.add("call");
8655
+ else
8656
+ skipped.push(...skip(["call"], "the build files declare no HTTP client (httpx, requests)"));
8657
+ if (declares("kafka-python"))
8658
+ can.add("topic-in").add("topic-out");
8659
+ else
8660
+ skipped.push(...skip(["topic-in", "topic-out"], "the build files declare no Kafka client (kafka-python)"));
8661
+ out.push({
8662
+ stack: "python",
8663
+ dir: dirOf3(py),
8664
+ ...h ? {
8665
+ host: {
8666
+ file: h.file,
8667
+ v: h.v,
8668
+ line: h.line,
8669
+ ...h.call === "Flask" || h.call === "Blueprint" ? { flask: true } : {}
8670
+ }
8671
+ } : {},
8672
+ ...http ? { http } : {},
8673
+ can,
8674
+ skipped
8675
+ });
8676
+ }
8677
+ return out;
8678
+ }
8679
+ var pascal = (w) => w[0].toUpperCase() + w.slice(1);
8680
+ function claims(n, stack) {
8681
+ const key = stack === "spring" ? `${n.config[0]}.${n.config[1]}-url` : `${n.config[0]}_${n.config[1]}_url`.toUpperCase();
8682
+ return {
8683
+ entry: { claim: `entry GET /${n.entry.join("-")}/{id}`, needle: n.entry.join("-") },
8684
+ call: { claim: `call GET /${n.call.join("-")}/{id}`, needle: n.call.join("-") },
8685
+ "topic-in": {
8686
+ claim: `entry topic ${n.topicIn.join(".")}.updated`,
8687
+ needle: foldCanary(`${n.topicIn.join(".")}.updated`)
8688
+ },
8689
+ "topic-out": {
8690
+ claim: `call topic ${n.topicOut.join(".")}.viewed`,
8691
+ needle: foldCanary(`${n.topicOut.join(".")}.viewed`)
8692
+ },
8693
+ config: { claim: `config ${key}`, needle: foldCanary(key) }
8694
+ };
8695
+ }
8696
+ function springPlanting(h, n, taken) {
8697
+ const name = `${pascal(n.entry[0])}${pascal(n.entry[1])}`;
8698
+ const key = `${n.config[0]}.${n.config[1]}-url`;
8699
+ const head = h.pkg ? [`package ${h.pkg};`, ""] : [];
8700
+ const resource = [
8701
+ ...head,
8702
+ "import org.springframework.beans.factory.annotation.Value;",
8703
+ "import org.springframework.web.bind.annotation.GetMapping;",
8704
+ "import org.springframework.web.bind.annotation.PathVariable;",
8705
+ "import org.springframework.web.bind.annotation.RestController;",
8706
+ "import org.springframework.web.client.RestTemplate;",
8707
+ "",
8708
+ "@RestController",
8709
+ `public class ${name}Resource {`,
8710
+ " private final RestTemplate http = new RestTemplate();",
8711
+ "",
8712
+ // with a default, so an app whose config file doesn't set the key still starts
8713
+ h.config ? ` @Value("\${${key}:}")` : { text: ` @Value("\${${key}:}")`, what: "config" },
8714
+ " private String baseUrl;",
8715
+ "",
8716
+ { text: ` @GetMapping("/${n.entry.join("-")}/{id}")`, what: "entry" },
8717
+ " public String find(@PathVariable String id) {",
8718
+ {
8719
+ text: ` return http.getForObject(baseUrl + "/${n.call.join("-")}/{id}", String.class, id);`,
8720
+ what: "call"
8721
+ },
8722
+ " }",
8723
+ "}",
8724
+ ""
8725
+ ];
8726
+ const events = [
8727
+ ...head,
8728
+ "import org.springframework.kafka.annotation.KafkaListener;",
8729
+ "import org.springframework.kafka.core.KafkaTemplate;",
8730
+ "import org.springframework.stereotype.Component;",
8731
+ "",
8732
+ "@Component",
8733
+ `public class ${name}Events {`,
8734
+ " private final KafkaTemplate<String, String> kafka;",
8735
+ "",
8736
+ ` public ${name}Events(KafkaTemplate<String, String> kafka) {`,
8737
+ " this.kafka = kafka;",
8738
+ " }",
8739
+ "",
8740
+ { text: ` @KafkaListener(topics = "${n.topicIn.join(".")}.updated")`, what: "topic-in" },
8741
+ " public void onUpdated(String id) {",
8742
+ { text: ` kafka.send("${n.topicOut.join(".")}.viewed", id);`, what: "topic-out" },
8743
+ " }",
8744
+ "}",
8745
+ ""
8746
+ ];
8747
+ const out = {
8748
+ files: [
8749
+ ...h.can.has("entry") ? [{ path: free(join2(h.dir, `${name}Resource.java`), taken), lines: resource }] : [],
8750
+ ...h.can.has("topic-in") ? [{ path: free(join2(h.dir, `${name}Events.java`), taken), lines: events }] : []
8751
+ ]
8752
+ };
8753
+ if (h.config && h.can.has("config"))
8754
+ out.append = {
8755
+ path: h.config,
8756
+ lines: h.config.endsWith(".properties") ? [{ text: `${key}=https://${n.config.join("-")}.example`, what: "config" }] : [
8757
+ `${n.config[0]}:`,
8758
+ { text: ` ${n.config[1]}-url: https://${n.config.join("-")}.example`, what: "config" }
8759
+ ]
8760
+ };
8761
+ return out;
8762
+ }
8763
+ var camel = (w) => `${w[0]}${pascal(w[1])}`;
8764
+ var snake = (w) => w.join("_");
8765
+ function nodePlanting(h, n, taken) {
8766
+ const env = `${n.config[0]}_${n.config[1]}_URL`.toUpperCase();
8767
+ const at = h.host;
8768
+ const kafkaOn = h.can.has("topic-in");
8769
+ const kafka = `${camel(n.entry)}Kafka`;
8770
+ const producer = `${camel(n.topicOut)}Events`;
8771
+ const consumer = `${camel(n.topicIn)}Updates`;
8772
+ const url = `${camel(n.config)}Url`;
8773
+ const kafkaLines = kafkaOn ? [`const ${kafka} = () => new Kafka({ brokers: [] });`] : [];
8774
+ const pad = at ? " " : " ";
8775
+ const send = kafkaOn ? [
8776
+ `${pad}const ${producer} = ${kafka}().producer();`,
8777
+ `${pad}await ${producer}.connect();`,
8778
+ {
8779
+ text: `${pad}await ${producer}.send({ topic: "${n.topicOut.join(".")}.viewed", messages: [{ value: ${at ? "req.params.id" : "id"} }] });`,
8780
+ what: "topic-out"
8781
+ },
8782
+ `${pad}await ${producer}.disconnect();`
8783
+ ] : [];
8784
+ const subscribe = kafkaOn ? [
8785
+ "",
8786
+ `async function ${consumer}() {`,
8787
+ ` const consumer = ${kafka}().consumer({ groupId: "${n.topicIn.join("-")}" });`,
8788
+ " await consumer.connect();",
8789
+ {
8790
+ text: ` await consumer.subscribe({ topic: "${n.topicIn.join(".")}.updated" });`,
8791
+ what: "topic-in"
8792
+ },
8793
+ "}",
8794
+ `${consumer}().catch(() => undefined);`
8795
+ ] : [];
8796
+ const kafkaImport = kafkaOn ? [at?.cjs ? 'const { Kafka } = require("kafkajs");' : 'import { Kafka } from "kafkajs";'] : [];
8797
+ const config2 = h.can.has("config") ? [{ text: `const ${url} = process.env.${env} ?? "";`, what: "config" }] : [];
8798
+ const base2 = h.can.has("config") ? `\${${url}}` : "";
8799
+ if (at) {
8800
+ const body = [
8801
+ ...kafkaLines,
8802
+ ...config2,
8803
+ "",
8804
+ { text: `${at.v}.get("/${n.entry.join("-")}/:id", async (req, res) => {`, what: "entry" },
8805
+ " try {",
8806
+ {
8807
+ text: ` const r = await fetch(\`${base2}/${n.call.join("-")}/\${req.params.id}\`);`,
8808
+ what: "call"
8809
+ },
8810
+ ...send,
8811
+ " res.json(await r.json());",
8812
+ " } catch {",
8813
+ " res.status(502).end();",
8814
+ " }",
8815
+ "});",
8816
+ ...subscribe
8817
+ ];
8818
+ return {
8819
+ files: [],
8820
+ append: { path: at.file, lines: ["", ...kafkaImport, ...kafkaOn ? [""] : [], ...body] }
8821
+ };
8822
+ }
8823
+ const id = h.ext === "ts" ? "id: string" : "id";
8824
+ return {
8825
+ files: [
8826
+ {
8827
+ path: free(join2(h.dir, `${n.entry.join("-")}.${h.ext ?? "js"}`), taken),
8828
+ lines: [
8829
+ ...kafkaImport,
8830
+ ...kafkaOn ? [""] : [],
8831
+ ...kafkaLines,
8832
+ ...config2,
8833
+ ...kafkaLines.length || config2.length ? [""] : [],
8834
+ `export async function ${camel(n.entry)}(${id}) {`,
8835
+ {
8836
+ text: ` const r = await fetch(\`${base2}/${n.call.join("-")}/\${id}\`);`,
8837
+ what: "call"
8838
+ },
8839
+ ...send,
8840
+ " return r.json();",
8841
+ "}",
8842
+ ...subscribe,
8843
+ ""
8844
+ ]
8845
+ }
8846
+ ]
8847
+ };
8848
+ }
8849
+ function pythonPlanting(h, n, taken) {
8850
+ const env = `${n.config[0]}_${n.config[1]}_URL`.toUpperCase();
8851
+ const at = h.host;
8852
+ const kafkaOn = h.can.has("topic-in");
8853
+ const url = `${snake(n.config)}_url`;
8854
+ const producer = `${snake(n.topicOut)}_events`;
8855
+ const param = at?.flask ? "<item_id>" : "{item_id}";
8856
+ const work = [
8857
+ ...h.http ? [
8858
+ {
8859
+ text: ` body = ${h.http}.get(f"{${url}}/${n.call.join("-")}/{item_id}").json()`,
8860
+ what: "call"
8861
+ }
8862
+ ] : [],
8863
+ // the producer made where it sends (second review of ADR 0196: one made at import would
8864
+ // fail the import with no broker), so a failure is the route's own, answered 500
8865
+ ...kafkaOn ? [
8866
+ {
8867
+ text: ` ${producer}().send("${n.topicOut.join(".")}.viewed", item_id.encode())`,
8868
+ what: "topic-out"
8869
+ }
8870
+ ] : []
8871
+ ];
8872
+ const fn = at || work.length ? [
8873
+ "",
8874
+ "",
8875
+ ...at ? [{ text: `@${at.v}.get("/${n.entry.join("-")}/${param}")`, what: "entry" }] : [],
8876
+ `def ${snake(n.entry)}(item_id: str):`,
8877
+ ...work,
8878
+ h.http ? " return body" : ' return {"id": item_id}'
8879
+ ] : [];
8880
+ const body = [
8881
+ { text: `${url} = os.environ.get("${env}", "")`, what: "config" },
8882
+ ...kafkaOn ? ["", "", `def ${producer}():`, " return KafkaProducer()"] : [],
8883
+ ...fn,
8884
+ ...kafkaOn ? [
8885
+ "",
8886
+ "",
8887
+ `def ${snake(n.topicIn)}_updates():`,
8888
+ {
8889
+ text: ` return KafkaConsumer("${n.topicIn.join(".")}.updated")`,
8890
+ what: "topic-in"
8891
+ }
8892
+ ] : []
8893
+ ];
8894
+ const imports = [
8895
+ "import os",
8896
+ ...h.http ? ["", `import ${h.http}`] : [],
8897
+ ...kafkaOn ? ["from kafka import KafkaConsumer, KafkaProducer"] : []
8898
+ ];
8899
+ if (at)
8900
+ return {
8901
+ files: [],
8902
+ append: { path: at.file, lines: ["", "", ...imports, "", ...body] }
8903
+ };
8904
+ return {
8905
+ files: [
8906
+ {
8907
+ path: free(join2(h.dir, `${snake(n.entry)}.py`), taken),
8908
+ lines: [...imports, "", ...body, ""]
8909
+ }
8910
+ ]
8911
+ };
8912
+ }
8913
+ function free(path, taken) {
8914
+ let p = path;
8915
+ for (let i = 2; taken.has(p); i++)
8916
+ p = path.replace(/(\.[^./]+)$/, `${i}$1`);
8917
+ taken.add(p);
8918
+ return p;
8919
+ }
8920
+ var KIND_OF = {
8921
+ entry: "entry",
8922
+ call: "call",
8923
+ "topic-in": "entry",
8924
+ "topic-out": "call",
8925
+ config: "config"
8926
+ };
8927
+ function commentFor(path) {
8928
+ if (/\.(java|kt|kts|groovy|scala|ts|tsx|js|jsx|mjs|cjs|go|cs|gradle)$/.test(path))
8929
+ return "//";
8930
+ if (/\.(py|ya?ml|properties)$/.test(path))
8931
+ return "#";
8932
+ return void 0;
8933
+ }
8934
+ var COMMENTED = /^\s*(\/\/|#|\/\*|\*|<!--|--)/;
8935
+ function balanced(line) {
8936
+ const n = (c) => line.split(c).length - 1;
8937
+ return n("(") === n(")") && n("[") === n("]") && n("{") === n("}");
8938
+ }
8939
+ function removable(f, line) {
8940
+ if (line === void 0 || !line.trim())
8941
+ return false;
8942
+ if (!line.toLowerCase().includes(f.cite.value.toLowerCase()))
8943
+ return false;
8944
+ if (COMMENTED.test(line) || !balanced(line))
8945
+ return false;
8946
+ if (/\.ya?ml$/.test(f.cite.file))
8947
+ return /^\s*(-\s+)?[^#:\s][^:]*:\s+[^\s|>#]/.test(line);
8948
+ if (f.cite.file.endsWith(".properties"))
8949
+ return /[=:]/.test(line);
8950
+ return true;
8951
+ }
8952
+ function planCanary(o) {
8953
+ const files = o.source.list();
8954
+ const taken = new Set(files);
8955
+ const texts = /* @__PURE__ */ new Map();
8956
+ const linesOf2 = (p) => {
8957
+ if (!texts.has(p))
8958
+ texts.set(p, (o.source.read(p) ?? "").split("\n"));
8959
+ return texts.get(p);
8960
+ };
8961
+ const stacks = canaryStacks(o.source, o.seed);
8962
+ const hostLine = (f) => stacks.some((h) => h.host?.file === f.cite.file && h.host.line === f.cite.line);
8963
+ const kept = o.facts.filter((f) => f.verified !== "none" && f.by !== "person" && (f.kind === "entry" || f.kind === "call" || f.kind === "config"));
8964
+ const near = (a, b) => a.id !== b.id && removedBy({
8965
+ id: `remove:${a.id}`,
8966
+ fact: a.id,
8967
+ kind: a.kind,
8968
+ file: a.cite.file,
8969
+ line: a.cite.line,
8970
+ claim: a.kind,
8971
+ value: a.cite.value || "-",
8972
+ needle: canaryNeedleOf(a),
8973
+ how: "commented"
8974
+ }, b) === "near";
8975
+ const claimCount = /* @__PURE__ */ new Map();
8976
+ for (const f of o.facts) {
8977
+ const k = `${f.kind}\0${canaryNeedleOf(f)}`;
8978
+ claimCount.set(k, (claimCount.get(k) ?? 0) + 1);
8979
+ }
8980
+ const candidates = kept.filter((f) => claimCount.get(`${f.kind}\0${canaryNeedleOf(f)}`) === 1 && !hostLine(f) && taken.has(f.cite.file) && !canaryNeverCopied(f.cite.file) && commentFor(f.cite.file) !== void 0 && !o.facts.some((g) => near(f, g)) && removable(f, linesOf2(f.cite.file)[f.cite.line - 1]?.replace(/\r$/, "")));
8981
+ const byKind = ["entry", "call", "config"].map((k) => seededShuffle(candidates.filter((f) => f.kind === k), `${o.seed}:remove:${k}`));
8982
+ const order = seededShuffle(byKind.map((l, i) => ({ id: String(i), l })), `${o.seed}:remove`).map((x) => x.l);
8983
+ const want = Math.max(0, Math.floor(o.removals ?? CANARY_DEFAULT_REMOVALS));
8984
+ const chosen = [];
8985
+ for (let round = 0; chosen.length < want && order.some((l) => l.length > round); round++)
8986
+ for (const l of order) {
8987
+ const f = l[round];
8988
+ if (!f || chosen.length >= want)
8989
+ continue;
8990
+ if (chosen.some((c) => c.cite.file === f.cite.file && c.cite.line === f.cite.line))
8991
+ continue;
8992
+ chosen.push(f);
8993
+ }
8994
+ const changed = /* @__PURE__ */ new Set();
8995
+ const removed = chosen.map((f) => {
8996
+ const lines = linesOf2(f.cite.file);
8997
+ const line = lines[f.cite.line - 1];
8998
+ const indent = /^\s*/.exec(line)[0];
8999
+ lines[f.cite.line - 1] = `${indent}${commentFor(f.cite.file)} ${line.slice(indent.length)}`;
9000
+ changed.add(f.cite.file);
9001
+ return {
9002
+ id: `remove:${f.id}`,
9003
+ fact: f.id,
9004
+ kind: f.kind,
9005
+ file: f.cite.file,
9006
+ line: f.cite.line,
9007
+ claim: `${f.kind} ${canaryClaimOf(f)}`,
9008
+ value: f.cite.value,
9009
+ needle: canaryNeedleOf(f),
9010
+ how: "commented"
9011
+ };
9012
+ }).sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
9013
+ const used = new Set(o.facts.flatMap((f) => `${canaryClaimText(f)} ${foldCanary(f.cite.file)}`.split(/[\s-]+/)));
9014
+ const words = seededShuffle(WORDS.filter((w) => !used.has(w)).map((id) => ({ id })), `${o.seed}:words`).map((w) => w.id);
9015
+ const planted = [];
9016
+ const skipped = [];
9017
+ const writes = {};
9018
+ stacks.forEach((h) => {
9019
+ skipped.push(...h.skipped.map((x) => ({ stack: h.stack, ...x })));
9020
+ if (!h.can.size)
9021
+ return;
9022
+ const w = words.splice(0, 10);
9023
+ if (w.length < 10)
9024
+ return;
9025
+ const names = {
9026
+ entry: [w[0], w[1]],
9027
+ call: [w[2], w[3]],
9028
+ topicIn: [w[4], w[5]],
9029
+ topicOut: [w[6], w[7]],
9030
+ config: [w[8], w[9]]
9031
+ };
9032
+ const said = claims(names, h.stack);
9033
+ const p = h.stack === "spring" ? springPlanting(h, names, taken) : h.stack === "node" ? nodePlanting(h, names, taken) : pythonPlanting(h, names, taken);
9034
+ const place = (path, lines, from) => lines.forEach((l, i) => {
9035
+ if (typeof l === "string")
9036
+ return;
9037
+ planted.push({
9038
+ id: "",
9039
+ kind: KIND_OF[l.what],
9040
+ what: l.what,
9041
+ stack: h.stack,
9042
+ file: path,
9043
+ line: from + i + 1,
9044
+ ...said[l.what]
9045
+ });
9046
+ });
9047
+ for (const f of p.files) {
9048
+ place(f.path, f.lines, 0);
9049
+ writes[f.path] = f.lines.map((l) => typeof l === "string" ? l : l.text).join("\n");
9050
+ }
9051
+ if (p.append) {
9052
+ const lines = linesOf2(p.append.path);
9053
+ if (lines.length && lines[lines.length - 1] !== "")
9054
+ lines.push("");
9055
+ const eol = lines.some((l) => l.endsWith("\r")) ? "\r" : "";
9056
+ const from = lines.length - 1;
9057
+ lines.splice(from, 1, ...p.append.lines.map((l) => (typeof l === "string" ? l : l.text) + eol), "");
9058
+ place(p.append.path, p.append.lines, from);
9059
+ changed.add(p.append.path);
9060
+ }
9061
+ });
9062
+ planted.forEach((p, i) => p.id = `plant:${i + 1}`);
9063
+ for (const path of changed)
9064
+ writes[path] = linesOf2(path).join("\n");
9065
+ return {
9066
+ stacks: stacks.filter((s) => planted.some((p) => p.stack === s.stack)).map((s) => s.stack),
9067
+ planted,
9068
+ removed,
9069
+ skipped,
9070
+ writes
9071
+ };
9072
+ }
9073
+ function canaryClaimOf(f) {
9074
+ const x = f;
9075
+ if (f.kind === "entry" || f.kind === "call")
9076
+ return [x.method?.toUpperCase(), x.path].filter(Boolean).join(" ") || f.cite.value;
9077
+ if (f.kind === "config")
9078
+ return x.key ?? f.cite.value;
9079
+ return f.cite.value;
9080
+ }
9081
+
7848
9082
  // packages/verify/dist/house-imports.js
7849
9083
  var CODE2 = /\.(java|kt|kts|scala|groovy|cs|vb|fs|ts|tsx|js|jsx|mjs|cjs|vue|svelte|py|go|rb|php|swift)$/i;
7850
9084
  var IMPORTS = [
@@ -7873,7 +9107,7 @@ function modulesOf(line, go) {
7873
9107
  }
7874
9108
  var lower = (s) => s.toLowerCase();
7875
9109
  var under3 = (module, pkg) => module === pkg || module.startsWith(pkg) && (/[./]$/.test(pkg) || /[./]/.test(module[pkg.length] ?? ""));
7876
- function packageOf(module, prefix) {
9110
+ function packageOf2(module, prefix) {
7877
9111
  let i = prefix.length;
7878
9112
  while (i < module.length && /[./]/.test(module[i]))
7879
9113
  i++;
@@ -7887,16 +9121,16 @@ function nameOf2(pkg) {
7887
9121
  parts.shift();
7888
9122
  return parts.join("-") || "house-framework";
7889
9123
  }
7890
- function houseImportsUntaught(source, o) {
9124
+ function houseImportsUntaught(source2, o) {
7891
9125
  if (!o.prefixes.length)
7892
9126
  return [];
7893
9127
  const rules = o.rules ?? DEFAULT_READ_RULES;
7894
9128
  const prefixes = o.prefixes.map(lower);
7895
9129
  const taught = o.taught.map(lower);
7896
9130
  const found = /* @__PURE__ */ new Map();
7897
- const paths = source.list().filter((p) => CODE2.test(p) && !rules.notRead.test(p) && !(o.exclude ?? []).some((re) => re.test(p)) && isSourceFile(p, "", void 0, rules)).sort();
9131
+ const paths = source2.list().filter((p) => CODE2.test(p) && !rules.notRead.test(p) && !(o.exclude ?? []).some((re) => re.test(p)) && isSourceFile(p, "", void 0, rules)).sort();
7898
9132
  for (const p of paths) {
7899
- const text = source.read(p);
9133
+ const text = source2.read(p);
7900
9134
  if (text === void 0)
7901
9135
  continue;
7902
9136
  const lines = text.split(/\r?\n/);
@@ -7911,7 +9145,7 @@ function houseImportsUntaught(source, o) {
7911
9145
  continue;
7912
9146
  if (taught.some((t) => under3(ml, t)))
7913
9147
  continue;
7914
- const pkg = packageOf(m, prefix);
9148
+ const pkg = packageOf2(m, prefix);
7915
9149
  const f = found.get(pkg) ?? { files: /* @__PURE__ */ new Set(), first: `${p}:${i + 1}` };
7916
9150
  f.files.add(p);
7917
9151
  found.set(pkg, f);
@@ -7944,7 +9178,6 @@ export {
7944
9178
  frameworkGaps,
7945
9179
  frameworksToLearn,
7946
9180
  readRulesOf,
7947
- keyIsSecret,
7948
9181
  lineRangeOf,
7949
9182
  parseReviewed,
7950
9183
  readingRank,
@@ -7986,5 +9219,9 @@ export {
7986
9219
  rereadPlan,
7987
9220
  onlyFiles,
7988
9221
  repairFormSlips,
7989
- houseImportsUntaught
9222
+ houseImportsUntaught,
9223
+ canaryNeverCopied,
9224
+ CANARY_SECRET_PREFIX,
9225
+ canaryHoldsSecret,
9226
+ planCanary
7990
9227
  };