@maycombhq/atticus 2.0.0-beta.2 → 2.0.0-beta.22

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 (284) hide show
  1. package/dist/bin.js +8 -4
  2. package/dist/chunk-23XVSEV5.js +49 -0
  3. package/dist/{chunk-ZDPAS56H.js → chunk-24OXGB3P.js} +8 -2
  4. package/dist/{chunk-7EOBHUMC.js → chunk-24XLDU72.js} +4 -3
  5. package/dist/{chunk-CR3MTH32.js → chunk-2F4CYZKJ.js} +86 -11
  6. package/dist/{chunk-6IU67AEK.js → chunk-2GF7OLF3.js} +23 -15
  7. package/dist/chunk-2IIMFOPM.js +41 -0
  8. package/dist/chunk-2LGRMVCA.js +617 -0
  9. package/dist/{chunk-XPCM366L.js → chunk-2MMCFP5C.js} +10 -8
  10. package/dist/{chunk-JBTK5OP2.js → chunk-2Q56PQPS.js} +6 -4
  11. package/dist/{chunk-Z6LF7HQN.js → chunk-2Q5EDGEO.js} +7 -5
  12. package/dist/{chunk-3USYZGRF.js → chunk-2RLKFUUL.js} +38 -27
  13. package/dist/chunk-2SKB4O2E.js +59 -0
  14. package/dist/{chunk-SP2I63OO.js → chunk-34S2WGOB.js} +87 -4
  15. package/dist/{chunk-GQ4N4WKF.js → chunk-3NFFJL5D.js} +33 -27
  16. package/dist/{chunk-SJRGMG6A.js → chunk-3NWDLGG6.js} +28 -25
  17. package/dist/{chunk-4WBVUHXN.js → chunk-3RM4UK6W.js} +20 -18
  18. package/dist/chunk-42SIDKEU.js +583 -0
  19. package/dist/{chunk-GLUX4EEP.js → chunk-4EURQWQD.js} +20 -15
  20. package/dist/chunk-4U276ICE.js +39 -0
  21. package/dist/{chunk-ZMFPW66A.js → chunk-53T4O55J.js} +4 -3
  22. package/dist/{chunk-6J5OKA4Y.js → chunk-57TDNMI3.js} +17 -15
  23. package/dist/chunk-5BD2KYLE.js +57 -0
  24. package/dist/{chunk-7EFILTCI.js → chunk-5F7GFN2F.js} +28 -0
  25. package/dist/chunk-5NMKONLP.js +95 -0
  26. package/dist/{chunk-7ZUIMTOU.js → chunk-5SJZW52K.js} +26 -24
  27. package/dist/{chunk-4RS5KZQD.js → chunk-63YRMR6J.js} +6 -5
  28. package/dist/chunk-66PPNOON.js +62 -0
  29. package/dist/chunk-6H3Z5JHH.js +64 -0
  30. package/dist/{chunk-CEXSU4S6.js → chunk-6MUGR4LS.js} +775 -89
  31. package/dist/{chunk-QSXK2RGH.js → chunk-6OJQOPUN.js} +5 -3
  32. package/dist/{chunk-MVZVGYXH.js → chunk-6PPOWY5E.js} +84 -14
  33. package/dist/{chunk-7EKXJZ2Y.js → chunk-6ZGLAACW.js} +299 -38
  34. package/dist/chunk-6ZJ5A7AF.js +222 -0
  35. package/dist/{chunk-L24C55VN.js → chunk-745DAZ4L.js} +142 -30
  36. package/dist/{chunk-Q4D5X7QB.js → chunk-7ASNL4Q4.js} +46 -24
  37. package/dist/chunk-7BR7IPOH.js +35 -0
  38. package/dist/{chunk-7WD63HU2.js → chunk-7DOR27HL.js} +6 -6
  39. package/dist/chunk-7FTTA3HD.js +341 -0
  40. package/dist/{chunk-OLQJTJJU.js → chunk-7GJS6DNX.js} +12 -3
  41. package/dist/{chunk-7JUKDRSZ.js → chunk-7IGKHZ4Z.js} +347 -226
  42. package/dist/{chunk-G2B4ZQGH.js → chunk-7IOWA5D5.js} +11 -6
  43. package/dist/{chunk-EBEW3XXQ.js → chunk-7JITZFJC.js} +7 -5
  44. package/dist/chunk-7MJSQTL5.js +174 -0
  45. package/dist/{chunk-I4JRCD6M.js → chunk-7UOMVMFG.js} +25 -17
  46. package/dist/{chunk-YY6ZQQBP.js → chunk-AFWUDXEM.js} +19 -7
  47. package/dist/chunk-AFZ3QA6W.js +47 -0
  48. package/dist/chunk-AJQ72EBM.js +420 -0
  49. package/dist/chunk-AJYXNTNZ.js +317 -0
  50. package/dist/chunk-AVTBS4OW.js +49 -0
  51. package/dist/{chunk-FHH4I4ZV.js → chunk-BDKC6H5P.js} +12 -6
  52. package/dist/{chunk-IPKHE5D6.js → chunk-BEVTIBRH.js} +1526 -875
  53. package/dist/chunk-BHT7QK4G.js +162 -0
  54. package/dist/{chunk-6JUBZBMW.js → chunk-BIGDQDHD.js} +6 -4
  55. package/dist/{chunk-2BFCZ3RK.js → chunk-BO4KX37X.js} +20 -18
  56. package/dist/chunk-BPK5P77O.js +115 -0
  57. package/dist/chunk-BQ4SQQC6.js +59 -0
  58. package/dist/chunk-BQGDB6ZL.js +7342 -0
  59. package/dist/{chunk-2ANOROX3.js → chunk-BTGPE6CR.js} +11 -9
  60. package/dist/chunk-BTY3HZBO.js +93 -0
  61. package/dist/{chunk-DPZHZQKE.js → chunk-BXYMYEJ4.js} +44 -10
  62. package/dist/{chunk-2RMYG36Q.js → chunk-C3RY6KU6.js} +309 -346
  63. package/dist/chunk-C4R4JLHE.js +40 -0
  64. package/dist/chunk-CADWLE2T.js +18 -0
  65. package/dist/chunk-CBGGOQWU.js +82 -0
  66. package/dist/chunk-CMDXGQTS.js +47 -0
  67. package/dist/{chunk-MC3H7736.js → chunk-CQDGOPGH.js} +58 -18
  68. package/dist/{chunk-HFQCFSJR.js → chunk-CX4RZ2KS.js} +4 -3
  69. package/dist/{chunk-PAMPPUR6.js → chunk-CXJ6FUKN.js} +1852 -207
  70. package/dist/{chunk-ABWHYWNI.js → chunk-D73UEXYW.js} +3 -3
  71. package/dist/chunk-DCZWQLYT.js +1205 -0
  72. package/dist/chunk-DLOBCJL6.js +48 -0
  73. package/dist/{chunk-4BN53TG3.js → chunk-DOBQKHIF.js} +31 -23
  74. package/dist/chunk-E3ISYXO3.js +423 -0
  75. package/dist/{chunk-7SW2QWLU.js → chunk-E6ZIEVOI.js} +16 -13
  76. package/dist/chunk-EBL2R3YG.js +43 -0
  77. package/dist/{chunk-AIOQPLA5.js → chunk-EGQRREQH.js} +41 -15
  78. package/dist/chunk-EHA7RMZ3.js +58 -0
  79. package/dist/{chunk-M766ZJ6W.js → chunk-EIPTLPFC.js} +38 -27
  80. package/dist/chunk-EMRIQUND.js +517 -0
  81. package/dist/{chunk-DFBCSHVT.js → chunk-EPCJQQWD.js} +6 -4
  82. package/dist/{chunk-RZPYKDWS.js → chunk-F3P7N7SF.js} +1 -1
  83. package/dist/{chunk-R77KLRB3.js → chunk-FFLNS6VP.js} +21 -18
  84. package/dist/chunk-FFTRTL6R.js +26 -0
  85. package/dist/{chunk-IHMLFRVV.js → chunk-FPJPLKDW.js} +62 -16
  86. package/dist/{chunk-JCZIKA4C.js → chunk-FSMSFDLD.js} +5 -4
  87. package/dist/{chunk-AVJDSJ2F.js → chunk-FUJM6RTF.js} +8 -7
  88. package/dist/chunk-FZOJFH7Q.js +132 -0
  89. package/dist/{chunk-QRAOANID.js → chunk-G6X77UJZ.js} +23 -21
  90. package/dist/{chunk-3ALD2W2A.js → chunk-GCWRWSU7.js} +10 -4
  91. package/dist/chunk-GIW4ZVDB.js +39 -0
  92. package/dist/{chunk-B2WLAWNJ.js → chunk-GUX3PTYM.js} +3 -3
  93. package/dist/{chunk-DPUYDDQG.js → chunk-GZY6RUZ6.js} +25 -3
  94. package/dist/chunk-H4VO6WG3.js +10 -0
  95. package/dist/{chunk-MMOSZPWJ.js → chunk-H5HBGNXU.js} +5 -4
  96. package/dist/chunk-H7KM7LZE.js +229 -0
  97. package/dist/{chunk-AA6YULYB.js → chunk-HNM2YQT2.js} +7 -7
  98. package/dist/{chunk-3C7EYRFZ.js → chunk-HYU5VLGA.js} +1 -1
  99. package/dist/{chunk-XY3P7JW7.js → chunk-IDKCWSM5.js} +1032 -172
  100. package/dist/chunk-IFKEI4SA.js +237 -0
  101. package/dist/{chunk-F7HYOUFF.js → chunk-IGOE6KPG.js} +67 -22
  102. package/dist/{chunk-TDD55CJH.js → chunk-IH2XURVQ.js} +6 -5
  103. package/dist/chunk-INQHESFB.js +38 -0
  104. package/dist/chunk-IP74LCOQ.js +57 -0
  105. package/dist/chunk-IPHHDDC6.js +45 -0
  106. package/dist/{chunk-T6AIP7H5.js → chunk-ISUAAMGS.js} +110 -153
  107. package/dist/{chunk-A7UPUQFY.js → chunk-IUPG3UKI.js} +624 -319
  108. package/dist/{chunk-L6SGQIR3.js → chunk-IVBOQAGB.js} +7 -3
  109. package/dist/{chunk-27NKUS3X.js → chunk-J2JAKCIW.js} +2205 -796
  110. package/dist/{chunk-V2YTAIQO.js → chunk-J3IOLXWM.js} +24 -7
  111. package/dist/chunk-JA5FI3QV.js +142 -0
  112. package/dist/chunk-JAVI7JSP.js +49 -0
  113. package/dist/{chunk-HLJAXMM4.js → chunk-JB5LINEM.js} +6 -2
  114. package/dist/{chunk-2VHF7OXM.js → chunk-JENSEMXF.js} +1 -1
  115. package/dist/{chunk-6BVONWJ7.js → chunk-JJF6HALY.js} +4 -3
  116. package/dist/chunk-JLUCKAEL.js +38 -0
  117. package/dist/chunk-JRBFANFE.js +221 -0
  118. package/dist/{chunk-R6XF6UR3.js → chunk-KDNTAPLX.js} +4 -4
  119. package/dist/chunk-KFAVQZSX.js +33 -0
  120. package/dist/chunk-KJXD4PNL.js +50 -0
  121. package/dist/chunk-KN5BXMWN.js +44 -0
  122. package/dist/{chunk-PCVDV3UZ.js → chunk-KQGURXFU.js} +9 -7
  123. package/dist/{chunk-WY6PP6AA.js → chunk-KXITGYLF.js} +40 -6
  124. package/dist/{chunk-66YVAGGM.js → chunk-L27SV425.js} +22 -20
  125. package/dist/{chunk-NE2W3OO7.js → chunk-LDLL7LB3.js} +24 -22
  126. package/dist/chunk-LFGTYX5U.js +379 -0
  127. package/dist/{chunk-EYWIDJFU.js → chunk-LGBMTVNT.js} +7 -5
  128. package/dist/{chunk-Q5AMFEWD.js → chunk-LGFL54FP.js} +3 -2
  129. package/dist/{chunk-6TACQN3N.js → chunk-LJXMYKZJ.js} +7 -5
  130. package/dist/{chunk-BKVWTZ6A.js → chunk-LKOR5UET.js} +29 -26
  131. package/dist/chunk-LNBQOP7D.js +294 -0
  132. package/dist/{chunk-O3WI5KWW.js → chunk-LO6P2VYG.js} +2 -2
  133. package/dist/chunk-LQJPN536.js +122 -0
  134. package/dist/{chunk-YEDDOYSC.js → chunk-LYBNHMVZ.js} +29 -5
  135. package/dist/{chunk-A3GY6SOA.js → chunk-LZ7NUC62.js} +20 -18
  136. package/dist/chunk-M32BLWDH.js +37 -0
  137. package/dist/{chunk-VYDBJ73M.js → chunk-M3NANSDZ.js} +17 -15
  138. package/dist/chunk-MFHL5URL.js +31 -0
  139. package/dist/chunk-MFR5OPBD.js +109 -0
  140. package/dist/{chunk-DE76JROX.js → chunk-MG4ZL5RW.js} +32 -20
  141. package/dist/{chunk-N7IXEHK3.js → chunk-MO6P2JZH.js} +10 -8
  142. package/dist/{chunk-65NYPGRC.js → chunk-MUWDB4R4.js} +1 -1
  143. package/dist/chunk-MZCGSXVR.js +34 -0
  144. package/dist/{chunk-MGYZM27B.js → chunk-N3XIYPU3.js} +51 -23
  145. package/dist/chunk-NDCF4R6S.js +172 -0
  146. package/dist/{chunk-DHPACDG7.js → chunk-NR2UJWOC.js} +10 -8
  147. package/dist/chunk-NXJ5URP6.js +51 -0
  148. package/dist/{chunk-UNM6ZOKP.js → chunk-NY2XSR5K.js} +147 -18
  149. package/dist/{chunk-5GDRCDQB.js → chunk-O45HFTFS.js} +3 -2
  150. package/dist/{chunk-ONLS5QA5.js → chunk-O4GXGGBX.js} +14 -12
  151. package/dist/chunk-O5PXQR67.js +249 -0
  152. package/dist/{chunk-PRPPGYZG.js → chunk-O66DM6DJ.js} +6 -4
  153. package/dist/{chunk-KEM4SDDP.js → chunk-O7FDLW7L.js} +11 -8
  154. package/dist/{chunk-T2UYZSCQ.js → chunk-O7XLYEFA.js} +169 -29
  155. package/dist/{chunk-FITWGOJ2.js → chunk-OHNCWBKF.js} +4 -4
  156. package/dist/{chunk-652QWTLZ.js → chunk-OHVTTOPS.js} +3 -3
  157. package/dist/chunk-OMI6FPPN.js +43 -0
  158. package/dist/chunk-ONUPY3H6.js +53 -0
  159. package/dist/chunk-OTLDSZDV.js +69 -0
  160. package/dist/chunk-OUBGGKDU.js +22 -0
  161. package/dist/chunk-OWNCM4ZN.js +330 -0
  162. package/dist/{chunk-YISXLPHN.js → chunk-P2V7QW4D.js} +235 -35
  163. package/dist/{chunk-CNUKCS2T.js → chunk-P32RUW3B.js} +1632 -93
  164. package/dist/{chunk-BWZ77RQT.js → chunk-PAQ2AS5E.js} +1 -1
  165. package/dist/{chunk-ZMAINWBW.js → chunk-PBPBMP2B.js} +4 -3
  166. package/dist/{chunk-ZVM6AKKM.js → chunk-PJSJPMJI.js} +3 -3
  167. package/dist/{chunk-EFHQ3TWP.js → chunk-PKBHS4AA.js} +233 -56
  168. package/dist/{chunk-GT4I4ZWM.js → chunk-PMUAJGLI.js} +20 -16
  169. package/dist/chunk-PPD7HTDP.js +152 -0
  170. package/dist/chunk-PSOFBQWB.js +42 -0
  171. package/dist/{chunk-S2A7YC3Q.js → chunk-Q2TECDIT.js} +10694 -8896
  172. package/dist/chunk-Q4K5WB2W.js +42 -0
  173. package/dist/{chunk-UGLN7QHV.js → chunk-Q6DFNVRJ.js} +14 -12
  174. package/dist/chunk-QA4O2GGC.js +265 -0
  175. package/dist/chunk-QAXW2N3B.js +1216 -0
  176. package/dist/chunk-QBNWF5ZU.js +19 -0
  177. package/dist/chunk-QFWA2DPH.js +224 -0
  178. package/dist/{chunk-23W7VWKR.js → chunk-QKUJMING.js} +1363 -114
  179. package/dist/{chunk-NXFPS2LR.js → chunk-R44CYFPV.js} +16 -13
  180. package/dist/{chunk-CKSITVS4.js → chunk-R7NYHMUU.js} +2687 -786
  181. package/dist/chunk-REWWDVQB.js +162 -0
  182. package/dist/{chunk-JMSCMUCA.js → chunk-RGERPOIV.js} +145 -21
  183. package/dist/{chunk-6JCPI55B.js → chunk-RLDGWLQ7.js} +49 -7
  184. package/dist/chunk-RUGXBPWI.js +384 -0
  185. package/dist/{chunk-CPA6HPVR.js → chunk-RXPJMEOW.js} +18 -12
  186. package/dist/{chunk-3HI6Z55Y.js → chunk-S4PMJU6H.js} +339 -43
  187. package/dist/chunk-S5LSDXV4.js +40 -0
  188. package/dist/chunk-S7FCV7S5.js +51 -0
  189. package/dist/{chunk-5GGOLAKC.js → chunk-SDKLKB6I.js} +28 -26
  190. package/dist/chunk-SFSPGFCV.js +62 -0
  191. package/dist/{chunk-ZNCEKR4J.js → chunk-SFUP7TTO.js} +12 -8
  192. package/dist/{chunk-64EQYWCA.js → chunk-SLXZOMA6.js} +69 -19
  193. package/dist/chunk-SQV37XO2.js +273 -0
  194. package/dist/{chunk-K65BJIMT.js → chunk-SU74NDMQ.js} +19 -17
  195. package/dist/chunk-SYV5LHML.js +165 -0
  196. package/dist/chunk-T4YPZIQN.js +36 -0
  197. package/dist/chunk-T6DQR5TV.js +323 -0
  198. package/dist/{chunk-JIITQXFB.js → chunk-THDMSZ3R.js} +3075 -802
  199. package/dist/{chunk-JGZCG5VM.js → chunk-TNR75OXT.js} +7 -7
  200. package/dist/{chunk-D3PO4DOZ.js → chunk-TUULXQRW.js} +174 -15
  201. package/dist/chunk-TYQBFTBR.js +516 -0
  202. package/dist/chunk-U76OWS3Q.js +49 -0
  203. package/dist/{chunk-YYQN46FY.js → chunk-UCROWG2D.js} +27 -24
  204. package/dist/{chunk-6M5NK3K3.js → chunk-UF4AZOZB.js} +50 -10
  205. package/dist/chunk-UF4GLFBX.js +345 -0
  206. package/dist/{chunk-OT2O76OS.js → chunk-UGUP3ZM6.js} +240 -39
  207. package/dist/chunk-UNAGJYET.js +45 -0
  208. package/dist/{chunk-5WG5YP4T.js → chunk-UOR2DTHH.js} +16 -14
  209. package/dist/{chunk-S3QNRWYR.js → chunk-UPOY4YSQ.js} +14 -12
  210. package/dist/{chunk-EPTBZ3GP.js → chunk-UPS2DGFC.js} +1 -1
  211. package/dist/{chunk-4AK7IBVP.js → chunk-UUU4CLJG.js} +4 -2
  212. package/dist/{chunk-W3BQAZ3Q.js → chunk-UWMJKX5U.js} +14 -12
  213. package/dist/{chunk-QZSX3F7C.js → chunk-UWOJLHFT.js} +27 -23
  214. package/dist/chunk-VBTP56CE.js +535 -0
  215. package/dist/chunk-VCTWPLAO.js +211 -0
  216. package/dist/chunk-VNU26RCO.js +1215 -0
  217. package/dist/{chunk-CSZ4C5N6.js → chunk-VTZMAJ3W.js} +93 -10
  218. package/dist/{chunk-TXLH6WHQ.js → chunk-VW62D6QE.js} +14 -12
  219. package/dist/{chunk-CAQZUNOH.js → chunk-VY72R2XZ.js} +610 -3
  220. package/dist/{chunk-2DIQQJCB.js → chunk-VZALIKIF.js} +18 -15
  221. package/dist/{chunk-TYAID7B7.js → chunk-W62H2XSO.js} +25 -23
  222. package/dist/{chunk-HVUPKCGJ.js → chunk-W7VWI2YH.js} +9 -6
  223. package/dist/{chunk-TANFV3MZ.js → chunk-WERM6KPJ.js} +7 -4
  224. package/dist/{chunk-BOHJZTEQ.js → chunk-WF7B67YE.js} +208 -87
  225. package/dist/{chunk-7FBGJFEE.js → chunk-WG5U3F5V.js} +14 -12
  226. package/dist/{chunk-4NDAAFQT.js → chunk-WJF2CS6M.js} +8 -5
  227. package/dist/{chunk-XAKWMCXI.js → chunk-WKUJ3KPV.js} +4 -4
  228. package/dist/chunk-WMTRHUI5.js +103 -0
  229. package/dist/chunk-WNKPRSGI.js +36 -0
  230. package/dist/chunk-WXFLMQSR.js +223 -0
  231. package/dist/{chunk-RRTKKSLQ.js → chunk-X3WY6MN3.js} +8 -6
  232. package/dist/{chunk-ZCJDOK2S.js → chunk-X4CXA2IL.js} +47 -23
  233. package/dist/{chunk-UBBC2XSG.js → chunk-X5F3Q5LV.js} +560 -105
  234. package/dist/{chunk-C6EKFH7J.js → chunk-XD75VZIH.js} +9 -7
  235. package/dist/chunk-XERYFDB5.js +297 -0
  236. package/dist/chunk-XI2LCCYQ.js +420 -0
  237. package/dist/chunk-Y2EQNWKV.js +933 -0
  238. package/dist/{chunk-LR3R6Z2A.js → chunk-YHCMZC2J.js} +7 -7
  239. package/dist/chunk-YYY3AZFE.js +122 -0
  240. package/dist/{chunk-GDLULHTC.js → chunk-Z5IA3WDR.js} +19 -31
  241. package/dist/{chunk-T6XQL73F.js → chunk-ZFFYNRIO.js} +63 -23
  242. package/dist/{chunk-EDS2L2LD.js → chunk-ZFL7NY4F.js} +56 -27
  243. package/dist/{chunk-YMZ3TNYB.js → chunk-ZGULQAPZ.js} +7 -4
  244. package/dist/{chunk-4SKZDI62.js → chunk-ZIUFM5HT.js} +3 -1
  245. package/dist/{chunk-DKJA76CJ.js → chunk-ZJFRMSJT.js} +15 -13
  246. package/dist/chunk-ZJXLNDH4.js +239 -0
  247. package/dist/chunk-ZQ3ON2VQ.js +252 -0
  248. package/dist/{chunk-HITVBIJS.js → chunk-ZQ7SKESZ.js} +150 -415
  249. package/dist/{chunk-6QSERWXH.js → chunk-ZQXZ2SES.js} +24 -21
  250. package/dist/chunk-ZX57KSEQ.js +39 -0
  251. package/dist/{chunk-I3E7CX4H.js → chunk-ZZK56BLP.js} +5 -3
  252. package/dist/files.json +664 -368
  253. package/dist/packages/naysayer/constitution/constitution.yaml +19 -0
  254. package/dist/packages/sdk/npm/index.js +6194 -2542
  255. package/dist/packages/ui/dist/assets/{elk-api-tma0MCuh.js → elk-api-CIf-0gz5.js} +2 -2
  256. package/dist/packages/ui/dist/assets/index-CoK_Dl0D.js +47 -0
  257. package/dist/packages/ui/dist/assets/index-Dw20IRhQ.css +1 -0
  258. package/dist/packages/ui/dist/index.html +3 -2
  259. package/package.json +5 -5
  260. package/dist/chunk-2BF2EYJV.js +0 -174
  261. package/dist/chunk-42EVSKME.js +0 -37
  262. package/dist/chunk-4BKGMUIK.js +0 -53
  263. package/dist/chunk-5KLGBXG5.js +0 -48
  264. package/dist/chunk-6BNC6EQ4.js +0 -41
  265. package/dist/chunk-6D2CQ5II.js +0 -41
  266. package/dist/chunk-7AVHLZGD.js +0 -45
  267. package/dist/chunk-D46WUV3T.js +0 -33
  268. package/dist/chunk-E36QOJMD.js +0 -47
  269. package/dist/chunk-FQXYPF7E.js +0 -147
  270. package/dist/chunk-GBRFVT63.js +0 -45
  271. package/dist/chunk-ICY36XCH.js +0 -34
  272. package/dist/chunk-J4K3KVLD.js +0 -131
  273. package/dist/chunk-JZU3H6UQ.js +0 -54
  274. package/dist/chunk-NN2ZQEB4.js +0 -38
  275. package/dist/chunk-PCOCACY3.js +0 -385
  276. package/dist/chunk-RTEYOSJY.js +0 -29
  277. package/dist/chunk-RUVFXE2L.js +0 -666
  278. package/dist/chunk-RVH5SUW5.js +0 -69
  279. package/dist/chunk-VN3DP4LQ.js +0 -43
  280. package/dist/chunk-W5BVQF44.js +0 -36
  281. package/dist/chunk-WVPJSRRJ.js +0 -52
  282. package/dist/chunk-XPTOBS2D.js +0 -48
  283. package/dist/packages/ui/dist/assets/index-B54fm9FQ.js +0 -29
  284. package/dist/packages/ui/dist/assets/index-DD_hufQz.css +0 -1
@@ -3,92 +3,130 @@ import { fileURLToPath as __atticusFileURLToPath } from "node:url";
3
3
  var require = __atticusCreateRequire(import.meta.url);
4
4
  var __atticusUrl = (p) => new URL("./" + p, import.meta.url).href;
5
5
  var __atticusPath = (p) => __atticusFileURLToPath(__atticusUrl(p));
6
+ import {
7
+ componentTypeIds,
8
+ componentTypesAt
9
+ } from "./chunk-OUBGGKDU.js";
10
+ import {
11
+ modelsData,
12
+ modelsLine,
13
+ reachHeadOf,
14
+ reachPlanOf,
15
+ readPathsOf
16
+ } from "./chunk-BPK5P77O.js";
17
+ import {
18
+ houseUntaughtLines,
19
+ houseUntaughtOf
20
+ } from "./chunk-EHA7RMZ3.js";
21
+ import {
22
+ effectiveRules,
23
+ notesAt,
24
+ readingRulesText,
25
+ ruleIds
26
+ } from "./chunk-WXFLMQSR.js";
6
27
  import {
7
28
  loadReadPlan,
29
+ modelsModeOf,
8
30
  partOfWords,
9
31
  readPlanProgress,
10
32
  readPlanRelOf,
33
+ recordNotReached,
34
+ saveReadPlan,
11
35
  writeReadPlan
12
- } from "./chunk-FQXYPF7E.js";
36
+ } from "./chunk-TYQBFTBR.js";
13
37
  import {
14
38
  carryOf,
15
39
  checkoutOf,
40
+ conventionsAt,
41
+ estateComponentsOf,
16
42
  excludesOf,
17
43
  headOf,
18
44
  raiseReadQuestions,
19
45
  readCorrections,
20
46
  readReviewed,
21
47
  reviewedProblemsOf,
48
+ slipNoteLines,
22
49
  writeVerifyFiles
23
- } from "./chunk-CR3MTH32.js";
24
- import "./chunk-O3WI5KWW.js";
50
+ } from "./chunk-2F4CYZKJ.js";
25
51
  import {
26
52
  ABOUT_RULE,
53
+ MODELS_RULE,
54
+ RULE_SETS,
27
55
  assistantTier,
28
56
  mapBatchInstructions,
29
57
  readProbes,
58
+ rulesNow,
59
+ taughtFrameworksText,
30
60
  tierSource,
31
61
  tierWords
32
- } from "./chunk-IPKHE5D6.js";
62
+ } from "./chunk-BEVTIBRH.js";
33
63
  import {
34
64
  FILE_KINDS,
35
- SESSION_TOKENS,
36
65
  SHOWN_PROPOSALS,
37
66
  dirSource,
38
67
  exclusionYaml,
39
68
  frameworkTopics,
40
69
  frameworkTopicsOfType,
41
70
  kindsOf,
71
+ lineRangeOf,
42
72
  numberedSlice,
43
73
  onlyFiles,
44
74
  planBatches,
45
75
  planParts,
46
76
  proposeExclusions,
77
+ repairFormSlips,
47
78
  rereadPlan,
48
79
  sameCommit,
80
+ sessionTokensFor,
49
81
  sliceText,
50
82
  staleMessage,
51
83
  verifyFacts
52
- } from "./chunk-PAMPPUR6.js";
84
+ } from "./chunk-CXJ6FUKN.js";
53
85
  import {
54
86
  loadRepos
55
- } from "./chunk-EFHQ3TWP.js";
56
- import "./chunk-GQ4N4WKF.js";
87
+ } from "./chunk-PKBHS4AA.js";
57
88
  import {
58
89
  DATA_RULE,
59
90
  HandoffRuntime,
60
91
  PromptTooLong,
92
+ RequiredSourceLeftOut,
61
93
  buildContextPack,
62
94
  currentPromptLimit,
63
- estimateTokens,
95
+ defendSource,
64
96
  promptBudget,
97
+ quarantineReason,
65
98
  wrapData
66
- } from "./chunk-CNUKCS2T.js";
99
+ } from "./chunk-P32RUW3B.js";
67
100
  import {
68
101
  AgentDefinition,
69
102
  Fact,
70
103
  REPO_DESCRIPTION_MAX,
71
104
  citedFiles,
105
+ componentTypesText,
106
+ conventionsOf,
72
107
  descriptionNote,
73
108
  descriptionTrust,
109
+ estimateTokens,
74
110
  factsDirOf,
75
111
  factsRelOf,
76
112
  listQuestions,
77
113
  loadOrgPack,
114
+ normalizeFactPaths,
115
+ notesText,
78
116
  orgPackDirOf,
79
117
  parseFacts,
80
118
  runsDirOf,
81
- saysNotProduct
82
- } from "./chunk-S2A7YC3Q.js";
119
+ saysNotProduct,
120
+ stackHelpersOff
121
+ } from "./chunk-Q2TECDIT.js";
83
122
  import {
84
123
  writeFileAtomic
85
- } from "./chunk-D3PO4DOZ.js";
86
- import "./chunk-TV45EUGM.js";
124
+ } from "./chunk-TUULXQRW.js";
87
125
 
88
126
  // packages/cli/dist/map-commands.js
89
127
  import { existsSync } from "node:fs";
90
128
  import { mkdir, readFile, writeFile } from "node:fs/promises";
91
- import { dirname, join, relative } from "node:path";
129
+ import { dirname, join, relative, sep } from "node:path";
92
130
  var REPO_READER = "repo-reader";
93
131
  var OUTPUT = "facts.jsonl";
94
132
  var KEPT_RESERVE = 1500;
@@ -115,6 +153,9 @@ var plural = (n, w) => `${n} ${w}${n === 1 ? "" : "s"}`;
115
153
  var batches = (n) => `${n} ${n === 1 ? "batch" : "batches"}`;
116
154
  var changeOf = (repo) => `map-${repo}`;
117
155
  var stateFile = (root, repo) => join(runsDirOf(root), changeOf(repo), "state.json");
156
+ async function mapStateOf(root, repo) {
157
+ return readState(root, repo).catch(() => void 0);
158
+ }
118
159
  async function readState(root, repo) {
119
160
  const text = await readFile(stateFile(root, repo), "utf8").catch(() => void 0);
120
161
  return text ? JSON.parse(text) : void 0;
@@ -151,7 +192,7 @@ var overheadOf = (repo, commit, frameworks) => {
151
192
  return (kinds) => instructionTokens(repo, commit, kinds, frameworks) - core;
152
193
  };
153
194
  async function frameworksFor(root, repo, facts) {
154
- const fromFacts = frameworkTopics(facts);
195
+ const fromFacts = frameworkTopics(facts, (await conventionsAt(root)).frameworks);
155
196
  if (fromFacts)
156
197
  return fromFacts;
157
198
  const type = (await loadRepos(root).catch(() => [])).find((r) => r.id === repo)?.type;
@@ -175,12 +216,17 @@ function claimOf(f) {
175
216
  return `${f.name}${f.version ? ` ${f.version}` : ""}`;
176
217
  case "flow":
177
218
  return f.name;
219
+ case "term":
220
+ return `${f.term} ${f.value} (${f.role})`;
221
+ case "component":
222
+ return `${f.component ?? f.repo} is a ${f.type}`;
178
223
  }
179
224
  }
180
- function readAnswer(text, repo, commit) {
225
+ function readAnswer(text, repo, commit, onFile = []) {
181
226
  const facts = /* @__PURE__ */ new Map();
182
227
  const questions = [];
183
228
  const problems = [];
229
+ const refused = [];
184
230
  let about;
185
231
  text.split(/\r?\n/).forEach((raw, i) => {
186
232
  const line = raw.trim();
@@ -190,14 +236,17 @@ function readAnswer(text, repo, commit) {
190
236
  try {
191
237
  json = JSON.parse(line);
192
238
  } catch {
193
- problems.push(`line ${i + 1} is not one JSON object: ${line.slice(0, 80)}`);
239
+ problems.push({
240
+ line: i + 1,
241
+ message: `line ${i + 1} is not one JSON object: ${line.slice(0, 80)}`
242
+ });
194
243
  return;
195
244
  }
196
245
  if (!json || typeof json !== "object" || Array.isArray(json)) {
197
- problems.push(`line ${i + 1} is not one JSON object`);
246
+ problems.push({ line: i + 1, message: `line ${i + 1} is not one JSON object` });
198
247
  return;
199
248
  }
200
- const o = json;
249
+ const o = normalizeFactPaths(json);
201
250
  if ("question" in o && !("kind" in o)) {
202
251
  questions.push(o);
203
252
  return;
@@ -205,7 +254,10 @@ function readAnswer(text, repo, commit) {
205
254
  if ("about" in o && !("kind" in o)) {
206
255
  const text2 = typeof o.about === "string" ? o.about.trim() : "";
207
256
  if (!text2) {
208
- problems.push(`line ${i + 1}: "about" needs one line saying what the repo is`);
257
+ problems.push({
258
+ line: i + 1,
259
+ message: `line ${i + 1}: "about" needs one line saying what the repo is`
260
+ });
209
261
  return;
210
262
  }
211
263
  const cites = (Array.isArray(o.cites) ? o.cites : []).flatMap((c) => {
@@ -213,19 +265,43 @@ function readAnswer(text, repo, commit) {
213
265
  return typeof x.file === "string" && Number.isInteger(x.line) && Number(x.line) > 0 ? [{ file: x.file, line: Number(x.line) }] : [];
214
266
  }).slice(0, 6);
215
267
  if (!cites.length) {
216
- problems.push(`line ${i + 1}: "about" needs "cites": the file and line it was read from, as a fact cites its line`);
268
+ problems.push({
269
+ line: i + 1,
270
+ message: `line ${i + 1}: "about" needs "cites": the file and line it was read from, as a fact cites its line`
271
+ });
217
272
  return;
218
273
  }
219
274
  about ??= { text: text2.slice(0, REPO_DESCRIPTION_MAX), cites };
220
275
  return;
221
276
  }
222
- const r = Fact.safeParse({ repo, commit, ...o, verified: "none", by: "assistant" });
277
+ const marked = { repo, commit, ...o, verified: "none", by: "assistant" };
278
+ const r = Fact.safeParse(marked);
223
279
  if (r.success)
224
280
  facts.set(r.data.id, r.data);
225
281
  else
226
- problems.push(`line ${i + 1}${typeof o.id === "string" ? ` (${o.id})` : ""}: ${r.error.issues.map((x) => `${x.path.join(".") || "(fact)"}: ${x.message}`).join("; ")}`);
282
+ refused.push({
283
+ line: i + 1,
284
+ raw: JSON.stringify(marked),
285
+ issues: [
286
+ {
287
+ line: i + 1,
288
+ code: "schema",
289
+ message: `line ${i + 1}${typeof o.id === "string" ? ` (${o.id})` : ""}: ${r.error.issues.map((x) => `${x.path.join(".") || "(fact)"}: ${x.message}`).join("; ")}`
290
+ }
291
+ ]
292
+ });
227
293
  });
228
- return { facts: [...facts.values()], questions, problems, ...about ? { about } : {} };
294
+ const repaired = repairFormSlips([...facts.values()], refused, onFile);
295
+ for (const b of repaired.bad)
296
+ problems.push({ line: b.line, message: b.issues.map((x) => x.message).join("; ") });
297
+ problems.sort((x, y) => x.line - y.line);
298
+ return {
299
+ facts: repaired.facts,
300
+ questions,
301
+ problems: problems.map((x) => x.message),
302
+ slips: repaired.slips,
303
+ ...about ? { about } : {}
304
+ };
229
305
  }
230
306
  function rejectedText(r, source) {
231
307
  const text = source.read(r.fact.cite.file);
@@ -241,10 +317,26 @@ function rejectedText(r, source) {
241
317
  ] : []
242
318
  ].join("\n");
243
319
  }
244
- function questionsText(qs) {
320
+ async function rulesCovering(root, repo, op) {
321
+ const type = op.profiles.flatMap((p) => p.repos?.repos ?? []).find((r) => r.id === repo)?.type;
322
+ const all = (await listQuestions(root, { state: "answered" }).catch(() => ({ questions: [] }))).questions;
323
+ return all.filter((q) => q.repo !== repo && !!q.answer?.match && (q.answer.scope.level === "repo" ? q.answer.scope.id === repo : !!type && q.answer.scope.id === type)).map((q) => ({
324
+ id: q.id,
325
+ from: q.repo,
326
+ match: q.answer.match,
327
+ answer: q.answer.text ?? q.options[(q.answer.option ?? 1) - 1]?.label ?? "",
328
+ scope: q.answer.scope.level === "repo" ? repo : `every ${q.answer.scope.id} repo`
329
+ })).sort((a, b) => a.id.localeCompare(b.id));
330
+ }
331
+ var ruleLineOf = (r) => `Rule ${r.id} (answered for ${r.from}, covers ${r.scope}): the calls matching ${r.match} go to ${r.answer}.`;
332
+ function questionsText(qs, rules = []) {
245
333
  return [
246
334
  "Questions already on file for this repo. Don't ask them again; follow each answer a person gave.",
247
- ...qs.map((q) => `- ${q.question} (${q.evidence.join(", ")}): ${q.state === "answered" ? `answered: ${q.answer?.text ?? q.options[(q.answer?.option ?? 1) - 1]?.label ?? ""}` : "waiting for a person"}`)
335
+ ...qs.map((q) => `- ${q.question} (${q.evidence.join(", ")}): ${q.state === "answered" ? `answered: ${q.answer?.text ?? q.options[(q.answer?.option ?? 1) - 1]?.label ?? ""}` : "waiting for a person"}`),
336
+ ...rules.length ? [
337
+ "Answers by rule that cover this repo, from other repos' questions. A call one matches goes where it says: don't ask about it.",
338
+ ...rules.map((r) => `- ${ruleLineOf(r)}`)
339
+ ] : []
248
340
  ].join("\n");
249
341
  }
250
342
  function keptText(facts, budgetTokens) {
@@ -282,15 +374,44 @@ function rereadInstructions(s) {
282
374
  "Write a fact for anything new in the changed files, as in a first read."
283
375
  ].join("\n");
284
376
  }
285
- async function rereadOf(dir, facts, commit, source, exclude, git) {
377
+ async function rereadOf(dir, facts, commit, source, exclude, git, conventions) {
286
378
  if (!facts.some((f) => !sameCommit(f.commit, commit)))
287
379
  return { missing: [] };
288
380
  const { carry, missing } = await carryOf(dir, facts, commit, git);
289
381
  if (!Object.keys(carry).length)
290
382
  return { missing };
291
- return { plan: rereadPlan({ facts, commit, carry, source, exclude }), missing };
383
+ return {
384
+ plan: rereadPlan({
385
+ facts,
386
+ commit,
387
+ carry,
388
+ source,
389
+ exclude,
390
+ ...conventions ? { conventions } : {}
391
+ }),
392
+ missing
393
+ };
292
394
  }
293
- async function packFor(root, s, batch, source, op, now) {
395
+ var taughtOption = (models) => {
396
+ const taught = taughtFrameworksText(models);
397
+ return taught ? { taught } : {};
398
+ };
399
+ var BUILD_FILE = /(^|\/)(pom\.xml|build\.gradle(\.kts)?|package\.json|[^/]+\.csproj|requirements[^/]*\.txt|pyproject\.toml|go\.mod)$/;
400
+ function taughtIn(source, op) {
401
+ if (stackHelpersOff().has("framework-models"))
402
+ return [];
403
+ const models = op.frameworks.filter((m) => m.artifacts.length);
404
+ if (!models.length)
405
+ return [];
406
+ const texts = source.list().filter((p) => BUILD_FILE.test(p)).map((p) => source.read(p) ?? "");
407
+ const esc = (x) => x.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
408
+ return models.filter((m) => m.artifacts.some((a) => {
409
+ const artifact = a.split(":")[1] ?? a;
410
+ const declared = new RegExp(`<artifactId>\\s*${esc(artifact)}\\s*</artifactId>|["':]${esc(artifact)}["':@]`);
411
+ return texts.some((t) => declared.test(t));
412
+ }));
413
+ }
414
+ async function packFor(root, s, batch, source, op, now, notes) {
294
415
  const agent = repoReaderAgent(op);
295
416
  const budget = op.runtime.budgets.perAgent[agent.id] ?? agent.tokenBudget;
296
417
  const fix = batch >= s.batches.length;
@@ -299,7 +420,31 @@ async function packFor(root, s, batch, source, op, now) {
299
420
  const kept = await readFactsFile(root, s.repo);
300
421
  const facts = typeof kept === "string" ? [] : kept;
301
422
  const onFile = (await listQuestions(root, { repo: s.repo })).questions.filter((q) => q.state !== "retired");
423
+ const rules = await rulesCovering(root, s.repo, op);
302
424
  const slices = fix ? [] : s.batches[batch];
425
+ const leftOut = [];
426
+ const fileSources = [];
427
+ slices.forEach((x, i) => {
428
+ const file = {
429
+ id: `1-file-${String(i + 1).padStart(4, "0")}`,
430
+ kind: "code",
431
+ origin: `${x.path}#L${x.from}-${x.to}`,
432
+ text: sliceText(source, x),
433
+ classification: "internal",
434
+ priority: 10
435
+ };
436
+ const d = defendSource(file);
437
+ if (d.decision.action === "quarantined" || d.text === void 0)
438
+ leftOut.push(`left out ${file.origin}: ${quarantineReason(d.decision)}`);
439
+ else
440
+ fileSources.push(file);
441
+ });
442
+ const inBatch = new Set(slices.map((x) => x.path));
443
+ const reachedHere = (s.reached ?? []).filter((r) => inBatch.has(r.path));
444
+ const models = reachedHere.length ? [
445
+ "Model classes in this batch the entry points and calls reach (read these, and write their fields):",
446
+ ...reachedHere.map((r) => `- ${r.path} (${r.types.join(", ")}), from ${r.from}`)
447
+ ].join("\n") : void 0;
303
448
  const rejected = s.rejected.map((r) => rejectedText(r, source));
304
449
  const own = kindsOf(slices.map((x) => x.path));
305
450
  const theirs = kindsOf(s.rejected.flatMap((r) => citedFiles(r.fact)));
@@ -322,11 +467,31 @@ async function packFor(root, s, batch, source, op, now) {
322
467
  // build files are read first, so from the second batch on this is what the code says.
323
468
  frameworks: await frameworksFor(root, s.repo, facts),
324
469
  // Nothing says what this repo is: ask for one line, cited, for a person to confirm.
325
- ...about ? {} : { askAbout: true }
470
+ ...about || s.sets ? {} : { askAbout: true },
471
+ // ADR 0167: a top-up carries only the rule sets the read lacked.
472
+ ...s.sets ? {
473
+ sets: s.sets.filter((x) => RULE_SETS.includes(x))
474
+ } : {},
475
+ // A-taught: how to read the wrapper calls and annotations of the frameworks it is built on.
476
+ ...taughtOption(taughtIn(source, op)),
477
+ // ADR 0163: what the organisation's terms mean here and what must hold, as data.
478
+ ...notes ? { notes } : {},
479
+ // ADR 0169: the model classes of this batch the read reaches, listed beside it.
480
+ ...models ? { models: true } : {}
326
481
  }),
327
482
  classification: "public",
328
483
  trusted: true
329
484
  },
485
+ ...models ? [
486
+ {
487
+ id: "1-models",
488
+ kind: "document",
489
+ origin: "atticus/reachable",
490
+ text: models,
491
+ classification: "internal",
492
+ priority: 9
493
+ }
494
+ ] : [],
330
495
  ...s.reread ? [
331
496
  {
332
497
  id: "0-reread",
@@ -337,16 +502,7 @@ async function packFor(root, s, batch, source, op, now) {
337
502
  trusted: true
338
503
  }
339
504
  ] : [],
340
- ...slices.length ? [
341
- {
342
- id: "1-files",
343
- kind: "code",
344
- origin: slices.map((x) => `${x.path}#L${x.from}-${x.to}`).join(", "),
345
- text: slices.map((x) => sliceText(source, x)).join("\n\n"),
346
- classification: "internal",
347
- priority: 10
348
- }
349
- ] : [],
505
+ ...fileSources,
350
506
  ...s.rejected.map((r, i) => ({
351
507
  id: `2-rejected-${String(i + 1).padStart(3, "0")}`,
352
508
  kind: "document",
@@ -366,12 +522,12 @@ ${s.problems.map((p) => `- ${p}`).join("\n")}`,
366
522
  priority: 5
367
523
  }
368
524
  ] : [],
369
- ...onFile.length ? [
525
+ ...onFile.length || rules.length ? [
370
526
  {
371
527
  id: "4-questions",
372
528
  kind: "document",
373
529
  origin: "questions/",
374
- text: questionsText(onFile),
530
+ text: questionsText(onFile, rules),
375
531
  classification: "internal",
376
532
  priority: 4
377
533
  }
@@ -392,6 +548,9 @@ ${s.problems.map((p) => `- ${p}`).join("\n")}`,
392
548
  const levels = op.pack?.classification ?? LEVELS;
393
549
  return {
394
550
  agent,
551
+ leftOut,
552
+ /** Every file of a batch was left out: nothing to hand. */
553
+ empty: slices.length > 0 && fileSources.length === 0,
395
554
  pack: buildContextPack({
396
555
  change: changeOf(s.repo),
397
556
  agent: agent.id,
@@ -401,7 +560,7 @@ ${s.problems.map((p) => `- ${p}`).join("\n")}`,
401
560
  maxClassification: levels.includes("internal") ? "internal" : levels.at(-1),
402
561
  now,
403
562
  ...s.maxTokens ? { maxTokens: s.maxTokens } : {},
404
- required: slices.length ? ["1-files"] : [],
563
+ required: fileSources.map((f) => f.id),
405
564
  step: `map ${s.repo}`
406
565
  })
407
566
  };
@@ -443,9 +602,60 @@ async function mapCommand(root, repo, o, io, deps = {}) {
443
602
  return 2;
444
603
  }
445
604
  const op = await loadOrgPack(orgPackDirOf(root));
605
+ const conventions = conventionsOf(op);
446
606
  const source = dirSource(dir);
447
607
  const exclude = await excludesOf(root, repo);
448
608
  const factsFile = `${factsRelOf(root)}/${repo}.jsonl`;
609
+ const repoNotes = await notesAt(root, repo, dir, op);
610
+ const orgRules = await effectiveRules(root, repo, { dir, op });
611
+ const notesPrompt = [
612
+ notesText(repoNotes.notes, repoNotes.type),
613
+ readingRulesText(orgRules),
614
+ // ADR 0180: the component types, the same for every batch.
615
+ componentTypesText(await componentTypesAt(root, op))
616
+ ].filter(Boolean).join("\n\n");
617
+ if (o.gaps) {
618
+ const { mapGaps } = await import("./chunk-ZJXLNDH4.js");
619
+ const tier = await tierHere(root, op);
620
+ let part;
621
+ if (o.part !== void 0) {
622
+ const p = (await readPlanProgress(root, repo))?.parts.find((x) => x.part === o.part);
623
+ if (!p) {
624
+ io.err(`${repo}'s read plan has no part ${o.part} (${readPlanRelOf(root, repo)}): atticus map ${repo} --estimate plans it.`);
625
+ return 2;
626
+ }
627
+ part = {
628
+ n: p.part,
629
+ left: [...p.paths.filter((g) => !lineRangeOf(g)), ...p.left.filter((g) => lineRangeOf(g))]
630
+ };
631
+ }
632
+ return mapGaps(root, repo, {
633
+ commit,
634
+ source,
635
+ session: sessionTokensFor(limitOf(o, op, tier).limit),
636
+ checkout: relative(root, dir).split(sep).join("/") || ".",
637
+ ...o.json ? { json: true } : {},
638
+ ...part ? { part } : {},
639
+ ...o.models ? { models: o.models } : {},
640
+ exclude,
641
+ conventions
642
+ }, io);
643
+ }
644
+ if (o.rules && !deps.runtime) {
645
+ const { mapRules } = await import("./chunk-23XVSEV5.js");
646
+ const tier = await tierHere(root, op);
647
+ return mapRules(root, repo, {
648
+ commit,
649
+ source,
650
+ exclude,
651
+ conventions,
652
+ session: sessionTokensFor(limitOf(o, op, tier).limit),
653
+ notes: notesPrompt,
654
+ checkout: relative(root, dir).split(sep).join("/") || ".",
655
+ ...o.json ? { json: true } : {},
656
+ ...o.models ? { models: o.models } : {}
657
+ }, io);
658
+ }
449
659
  if (o.estimate)
450
660
  return estimate(root, repo, { o, op, dir, commit, source, exclude, factsFile, ...deps.git ? { git: deps.git } : {} }, io);
451
661
  const runtime = deps.runtime;
@@ -518,44 +728,133 @@ async function mapCommand(root, repo, o, io, deps = {}) {
518
728
  if (room < MIN_ROOM)
519
729
  return tooSmall(0);
520
730
  const frameworks = await frameworksFor(root, repo, existing);
521
- const re = await rereadOf(dir, existing, commit, source, exclude, deps.git);
522
- const reread = re.plan && !re.plan.unknown.length ? re.plan : void 0;
523
- const since = reread?.from.map((x) => x.commit.slice(0, 12)).join(", ");
524
- if (reread && !reread.files.length && !reread.reread.length) {
525
- io.out(`Nothing ${repo}'s facts cite changed since ${since}, and no source file did: atticus verify ${repo} carries its ${plural(reread.carried, "fact")} to ${commit.slice(0, 12)}.`);
526
- return 0;
527
- }
528
- const plan = planBatches(reread ? onlyFiles(source, reread.files.map((f) => f.path)) : source, { room, exclude, overhead: overheadOf(repo, commit, frameworks) });
529
- if (plan.leastRoom < MIN_ROOM)
530
- return tooSmall(room - plan.leastRoom);
531
- if (!plan.batches.length && !reread) {
532
- io.out(`${repo} has no source files to read${plan.excluded.length ? ` (${plural(plan.excluded.length, "file")} excluded)` : ""}.`);
533
- return 0;
731
+ if (o.rules) {
732
+ const { topUpOf, recordRulesNow, ruleSetsOfFiles } = await import("./chunk-23XVSEV5.js");
733
+ const t = await topUpOf(root, repo, {
734
+ commit,
735
+ facts: existing,
736
+ source,
737
+ exclude,
738
+ conventions,
739
+ ...o.models ? { models: o.models } : {}
740
+ });
741
+ if ("error" in t) {
742
+ io.err(t.error);
743
+ return 2;
744
+ }
745
+ if (!t.lacking.length) {
746
+ io.out(`${repo} was read under the reading rules there are now: nothing to top up.`);
747
+ return 0;
748
+ }
749
+ if (!t.files.length) {
750
+ await recordRulesNow(root, repo, commit, t.lacking);
751
+ io.out(`No file of ${repo} is one the reading rules added since it was read apply to (${t.lacking.join(", ")}): its read is recorded as under the rules there are now.`);
752
+ return 0;
753
+ }
754
+ const sets = ruleSetsOfFiles(t.files);
755
+ const plan = planBatches(onlyFiles(source, t.files.map((f) => f.path)), { room, exclude, overhead: overheadOf(repo, commit, frameworks), conventions });
756
+ if (plan.leastRoom < MIN_ROOM)
757
+ return tooSmall(room - plan.leastRoom);
758
+ s = {
759
+ schemaVersion: 1,
760
+ repo,
761
+ commit,
762
+ ...limit ? { maxTokens: limit } : {},
763
+ room,
764
+ batches: plan.batches,
765
+ next: 0,
766
+ rejected: [],
767
+ problems: [],
768
+ sets,
769
+ // ADR 0169: the reached model classes, listed in the prompts of the batches holding them.
770
+ ...t.reach?.reach.rooted && t.reach.reach.reached.length ? {
771
+ reached: t.reach.reach.reached.map((r) => ({
772
+ path: r.path,
773
+ types: r.types,
774
+ from: r.from
775
+ }))
776
+ } : {}
777
+ };
778
+ if (t.reach)
779
+ await recordNotReached(root, repo, {
780
+ commit,
781
+ session: sessionTokensFor(limit),
782
+ models: t.reach.mode,
783
+ ...t.reach.notReached ? { notReached: t.reach.notReached } : {}
784
+ });
785
+ await saveState(root, s);
786
+ io.out(`Topping up ${repo} at ${commit.slice(0, 12)} for the reading rules added since it was read (${sets.join(", ")}): ${plural(plan.files, "source file")} in ${batches(plan.batches.length)}; facts go to ${factsFile}.`);
787
+ } else {
788
+ const re = await rereadOf(dir, existing, commit, source, exclude, deps.git, conventions);
789
+ const reread = re.plan && !re.plan.unknown.length ? re.plan : void 0;
790
+ const since = reread?.from.map((x) => x.commit.slice(0, 12)).join(", ");
791
+ if (reread && !reread.files.length && !reread.reread.length) {
792
+ io.out(`Nothing ${repo}'s facts cite changed since ${since}, and no source file did: atticus verify ${repo} carries its ${plural(reread.carried, "fact")} to ${commit.slice(0, 12)}.`);
793
+ return 0;
794
+ }
795
+ const mode = await modelsModeOf(root, repo, o.models);
796
+ const rp = reread ? void 0 : reachPlanOf({
797
+ paths: readPathsOf(source, exclude, conventions),
798
+ source,
799
+ facts: existing,
800
+ mode
801
+ });
802
+ const plan = planBatches(reread ? onlyFiles(source, reread.files.map((f) => f.path)) : source, {
803
+ room,
804
+ exclude,
805
+ overhead: overheadOf(repo, commit, frameworks),
806
+ conventions,
807
+ ...rp?.reach.rooted && rp.reach.models ? { reach: { first: rp.first, leaveOut: rp.leaveOut } } : {}
808
+ });
809
+ if (plan.leastRoom < MIN_ROOM)
810
+ return tooSmall(room - plan.leastRoom);
811
+ if (!plan.batches.length && !reread) {
812
+ io.out(`${repo} has no source files to read${plan.excluded.length ? ` (${plural(plan.excluded.length, "file")} excluded)` : ""}.`);
813
+ return 0;
814
+ }
815
+ const byId = new Map(existing.map((f) => [f.id, f]));
816
+ s = {
817
+ schemaVersion: 1,
818
+ repo,
819
+ commit,
820
+ ...limit ? { maxTokens: limit } : {},
821
+ room,
822
+ batches: plan.batches,
823
+ next: 0,
824
+ rejected: (reread?.reread ?? []).map((r) => {
825
+ const fact = byId.get(r.id);
826
+ return { id: r.id, code: "cite-changed", message: staleMessage(fact, r, commit), fact };
827
+ }),
828
+ problems: [],
829
+ ...rp?.reach.rooted && rp.reach.reached.length ? {
830
+ reached: rp.reach.reached.map((r) => ({
831
+ path: r.path,
832
+ types: r.types,
833
+ from: r.from
834
+ }))
835
+ } : {},
836
+ ...reread ? {
837
+ reread: {
838
+ from: reread.from.map((x) => x.commit),
839
+ carried: reread.carried,
840
+ facts: reread.reread.length
841
+ }
842
+ } : {}
843
+ };
844
+ await saveState(root, s);
845
+ if (rp)
846
+ await recordNotReached(root, repo, {
847
+ commit,
848
+ session: sessionTokensFor(limit),
849
+ models: mode,
850
+ ...rp.notReached ? { notReached: rp.notReached } : {}
851
+ });
852
+ if (rp?.clientOnly.length)
853
+ io.out(`${rp.clientOnly.length} model ${rp.clientOnly.length === 1 ? "class" : "classes"} only an outbound client reaches are left out (ADR 0170, --models entries; recorded in ${readPlanRelOf(root, repo)}): atticus map ${repo} --models reachable reads them.`);
854
+ if (rp && rp.leaveOut.length > rp.clientOnly.length)
855
+ io.out(`${rp.leaveOut.length - rp.clientOnly.length} model ${rp.leaveOut.length - rp.clientOnly.length === 1 ? "class" : "classes"} no entry or call reaches are left out (ADR 0169; recorded in ${readPlanRelOf(root, repo)}): atticus map ${repo} --models all reads them.`);
856
+ io.out(reread ? `Re-reading ${repo} at ${commit.slice(0, 12)}: ${plural(plan.files, "source file")} changed since ${since}, in ${batches(plan.batches.length)}${plan.batches.length ? ` (about ${plan.tokens} tokens${limit ? `, each prompt within ${limit} tokens` : ""})` : ""}; ${plural(reread.reread.length, "fact")} to rewrite, ${reread.carried} carried as they are; facts go to ${factsFile}.` : `Reading ${repo} at ${commit.slice(0, 12)} in ${batches(plan.batches.length)} (${plural(plan.files, "source file")}, about ${plan.tokens} tokens${limit ? `, each prompt within ${limit} tokens` : ""}); facts go to ${factsFile}.`);
534
857
  }
535
- const byId = new Map(existing.map((f) => [f.id, f]));
536
- s = {
537
- schemaVersion: 1,
538
- repo,
539
- commit,
540
- ...limit ? { maxTokens: limit } : {},
541
- room,
542
- batches: plan.batches,
543
- next: 0,
544
- rejected: (reread?.reread ?? []).map((r) => {
545
- const fact = byId.get(r.id);
546
- return { id: r.id, code: "cite-changed", message: staleMessage(fact, r, commit), fact };
547
- }),
548
- problems: [],
549
- ...reread ? {
550
- reread: {
551
- from: reread.from.map((x) => x.commit),
552
- carried: reread.carried,
553
- facts: reread.reread.length
554
- }
555
- } : {}
556
- };
557
- await saveState(root, s);
558
- io.out(reread ? `Re-reading ${repo} at ${commit.slice(0, 12)}: ${plural(plan.files, "source file")} changed since ${since}, in ${batches(plan.batches.length)}${plan.batches.length ? ` (about ${plan.tokens} tokens${limit ? `, each prompt within ${limit} tokens` : ""})` : ""}; ${plural(reread.reread.length, "fact")} to rewrite, ${reread.carried} carried as they are; facts go to ${factsFile}.` : `Reading ${repo} at ${commit.slice(0, 12)} in ${batches(plan.batches.length)} (${plural(plan.files, "source file")}, about ${plan.tokens} tokens${limit ? `, each prompt within ${limit} tokens` : ""}); facts go to ${factsFile}.`);
559
858
  }
560
859
  if (!s)
561
860
  return 2;
@@ -565,7 +864,23 @@ async function mapCommand(root, repo, o, io, deps = {}) {
565
864
  break;
566
865
  if (fixRound)
567
866
  s.fixRound = true;
568
- const { agent, pack } = await packFor(root, s, s.next, source, op, now());
867
+ let made;
868
+ try {
869
+ made = await packFor(root, s, s.next, source, op, now(), notesPrompt);
870
+ } catch (e) {
871
+ if (!(e instanceof RequiredSourceLeftOut))
872
+ throw e;
873
+ io.err(`Batch ${s.next + 1} of ${s.batches.length}: ${e.message}`);
874
+ return 2;
875
+ }
876
+ const { agent, pack, leftOut, empty } = made;
877
+ for (const l of leftOut)
878
+ io.out(`Batch ${s.next + 1} of ${s.batches.length}: ${l}. Its lines aren't read; a person reviews the file, or the repo's exclusions leave it out.`);
879
+ if (empty) {
880
+ s.next++;
881
+ await saveState(root, s);
882
+ continue;
883
+ }
569
884
  const prepared = await runtime.prepare({
570
885
  change: changeOf(repo),
571
886
  agent,
@@ -617,36 +932,50 @@ async function takeAnswer(root, s, run, batch, source, exclude, now, io, at) {
617
932
  await saveState(root, { ...rest2, next: batch });
618
933
  return 1;
619
934
  }
620
- const answer = readAnswer(run.output ?? "", s.repo, s.commit);
621
935
  const existing = await readFactsFile(root, s.repo);
622
936
  if (typeof existing === "string") {
623
937
  io.err(existing);
624
938
  return 2;
625
939
  }
940
+ const answer = readAnswer(run.output ?? "", s.repo, s.commit, existing);
626
941
  const merged = new Map(existing.map((f) => [f.id, f]));
627
942
  for (const f of answer.facts)
628
943
  merged.set(f.id, f);
629
944
  const { carry } = await carryOf(at.dir, [...merged.values()], s.commit, at.git);
630
945
  const reviewed = await readReviewed(root, s.repo);
946
+ const estate = await estateComponentsOf(root);
947
+ const off = stackHelpersOff();
631
948
  const report = await verifyFacts({
632
949
  facts: [...merged.values()],
633
950
  source,
634
951
  commit: s.commit,
952
+ // G4: the stack helpers this run switched off (ATTICUS_HELPERS_OFF).
953
+ ...off.has("derived-names") ? { derivedNames: false } : {},
954
+ ...off.has("readers") ? { readers: false } : {},
635
955
  carry,
636
956
  exclude,
637
957
  // ADR 0124 addendum D-app: a person's corrections hold through every batch of a read.
638
958
  corrections: (await readCorrections(root, s.repo)).corrections,
639
959
  // ADR 0124 addendum A-read: files the reader read and found nothing in, if it wrote any.
640
- reviewed: reviewed.entries
960
+ reviewed: reviewed.entries,
961
+ // J1 (ADR 0143): an exposure names a component the manifest lists.
962
+ ...estate ? { estate } : {},
963
+ conventions: await conventionsAt(root),
964
+ // ADR 0163: a term's note is one of those the batch was handed.
965
+ notes: (await notesAt(root, s.repo, at.dir)).notes,
966
+ // ADR 0180: a component's type is one of the organisation's.
967
+ componentTypes: componentTypeIds(await componentTypesAt(root)),
968
+ // ADR 0169: the model files the read leaves out, counted apart.
969
+ notReached: (await loadReadPlan(root, s.repo))?.notReached?.files ?? []
641
970
  });
642
971
  const q = await raiseReadQuestions(root, s.repo, answer.questions, source, {
643
972
  command: `atticus map ${s.repo}`,
644
973
  run: run.runId,
645
974
  at: now().toISOString()
646
975
  });
647
- const summary = await writeVerifyFiles(root, s.repo, report, s.commit, q.problems, [], reviewedProblemsOf(reviewed.bad, report));
976
+ const summary = await writeVerifyFiles(root, s.repo, report, s.commit, q.problems, [], reviewedProblemsOf(reviewed.bad, report), answer.slips);
648
977
  if (answer.about) {
649
- const { keepDraftedDescription } = await import("./chunk-DPZHZQKE.js");
978
+ const { keepDraftedDescription } = await import("./chunk-BXYMYEJ4.js");
650
979
  const d = await keepDraftedDescription(root, s.repo, answer.about, now());
651
980
  if (d.kept)
652
981
  io.out(`Your assistant says ${s.repo} is: "${answer.about.text}" \u2014 written to the manifest as a draft, unconfirmed. Confirm it (atticus repo describe ${s.repo} --accept), change it (--description "...") or drop it (--reject).`);
@@ -656,6 +985,8 @@ async function takeAnswer(root, s, run, batch, source, exclude, now, io, at) {
656
985
  const fresh = new Set(answer.facts.map((f) => f.id));
657
986
  const kept = report.accepted.filter((f) => fresh.has(f.id)).length;
658
987
  io.out(`${label}: ${plural(kept, "fact")} kept (${report.accepted.length} in all${report.carried.length ? `, ${report.carried.length} carried from an earlier commit` : ""}), ${report.rejected.length} rejected${q.raised.length ? `, ${plural(q.raised.length, "question")} raised for a person` : ""}${answer.problems.length ? `, ${plural(answer.problems.length, "line")} not read` : ""}.`);
988
+ for (const l of slipNoteLines(answer.slips, `${factsRelOf(root)}/${s.repo}.verify.yaml`))
989
+ io.out(l);
659
990
  const { waiting: _w, ...rest } = s;
660
991
  const rejected = report.rejected.map((r) => ({
661
992
  id: r.fact.id,
@@ -677,6 +1008,10 @@ async function finish(root, s, io, o) {
677
1008
  s.done = true;
678
1009
  await saveState(root, s);
679
1010
  const last = s.last;
1011
+ if (last && !last.rejected && !s.reread) {
1012
+ const { recordRulesNow } = await import("./chunk-23XVSEV5.js");
1013
+ await recordRulesNow(root, s.repo, s.commit, s.sets);
1014
+ }
680
1015
  const rel = factsRelOf(root);
681
1016
  if (o.json) {
682
1017
  io.out(JSON.stringify({ state: "done", repo: s.repo, batches: s.batches.length, ...last }, null, 2));
@@ -686,7 +1021,7 @@ async function finish(root, s, io, o) {
686
1021
  io.out(`Read ${s.repo}: nothing was kept.`);
687
1022
  return 0;
688
1023
  }
689
- io.out(`Read ${s.repo} in ${batches(s.batches.length)}: ${plural(last.accepted, "fact")} kept in ${rel}/${s.repo}.jsonl, ${last.rejected} still rejected; coverage ${Math.round(last.coverage.ratio * 100)}% (${last.coverage.read} read, ${last.coverage.reviewed ? `${last.coverage.reviewed} reviewed with nothing to record, ` : ""}${last.coverage.unknown.length} unknown).`);
1024
+ io.out(`Read ${s.repo} in ${batches(s.batches.length)}: ${plural(last.accepted, "fact")} kept in ${rel}/${s.repo}.jsonl, ${last.rejected} still rejected; coverage ${Math.round(last.coverage.ratio * 100)}% (${last.coverage.read} read, ${last.coverage.reviewed ? `${last.coverage.reviewed} reviewed with nothing to record, ` : ""}${last.coverage.unknown.length} unknown${last.coverage.notReached?.length ? `, ${last.coverage.notReached.length} model files no entry or call reaches` : ""}).`);
690
1025
  if (last.rejected)
691
1026
  io.out(`The rejected facts are in ${rel}/${s.repo}.rejected.jsonl; fix them by hand or with your assistant, then atticus verify ${s.repo}.`);
692
1027
  if (last.coverage.unknown.length)
@@ -718,37 +1053,103 @@ function rereadLines(repo, r) {
718
1053
  }
719
1054
  async function estimate(root, repo, c, io) {
720
1055
  const tier = await tierHere(root, c.op);
1056
+ const conventions = conventionsOf(c.op);
721
1057
  const { limit: given, from } = limitOf(c.o, c.op, tier);
722
1058
  const limit = given ?? EXAMPLE_LIMIT;
723
1059
  const about = await aboutOf(root, repo);
724
1060
  const room = roomFor(limit, c.op, repo, c.commit);
725
1061
  const existing = await readFactsFile(root, repo);
726
- const re = typeof existing === "string" ? { missing: [] } : await rereadOf(c.dir, existing, c.commit, c.source, c.exclude, c.git);
1062
+ const re = typeof existing === "string" ? { missing: [] } : await rereadOf(c.dir, existing, c.commit, c.source, c.exclude, c.git, conventions);
727
1063
  const reread = re.plan && !re.plan.unknown.length ? re.plan : void 0;
728
1064
  const readSource = reread ? onlyFiles(c.source, reread.files.map((f) => f.path)) : c.source;
729
- const repoWhole = reread ? planBatches(c.source, { room: Number.MAX_SAFE_INTEGER, exclude: c.exclude }) : void 0;
730
- const whole = planBatches(readSource, { room: Number.MAX_SAFE_INTEGER, exclude: c.exclude });
731
- const planned = room >= MIN_ROOM ? planBatches(readSource, {
732
- room,
1065
+ const repoWhole = reread ? planBatches(c.source, { room: Number.MAX_SAFE_INTEGER, exclude: c.exclude, conventions }) : void 0;
1066
+ const whole = planBatches(readSource, {
1067
+ room: Number.MAX_SAFE_INTEGER,
733
1068
  exclude: c.exclude,
734
- overhead: overheadOf(repo, c.commit, await frameworksFor(root, repo, typeof existing === "string" ? [] : existing))
735
- }) : void 0;
736
- const plan = planned && planned.leastRoom >= MIN_ROOM ? planned : void 0;
1069
+ conventions
1070
+ });
737
1071
  const files = whole.batches.flat().map((s) => ({ path: s.path, tokens: s.tokens }));
738
1072
  const proposed = reread ? { proposals: [], before: whole.tokens, after: whole.tokens } : proposeExclusions(files, c.source.list(), (p) => c.source.read(p), {
739
1073
  // What the person's description plainly says this repo holds (ADR 0128).
740
1074
  saysNotProduct: saysNotProduct(about)
741
1075
  });
742
1076
  const left = proposed.proposals.map((p) => p.path.slice(0, -2));
743
- const session = Math.max(SESSION_TOKENS, Math.floor(0.75 * (given ?? 0)));
744
- const product = files.filter((f) => !left.some((d) => f.path.startsWith(d)));
745
- const parts = planParts(product, session);
1077
+ const session = sessionTokensFor(given);
1078
+ const product = files.filter((f) => !left.some((d) => f.path.startsWith(d))).map((f) => {
1079
+ if (f.tokens <= session)
1080
+ return f;
1081
+ const text = c.source.read(f.path);
1082
+ return text === void 0 ? f : { ...f, lines: text.split(/\r?\n/).length };
1083
+ });
1084
+ const mode = await modelsModeOf(root, repo, c.o.models);
1085
+ const facts0 = typeof existing === "string" ? [] : existing;
1086
+ const rp = reread ? void 0 : reachPlanOf({ paths: product.map((f) => f.path), source: c.source, facts: facts0, mode });
1087
+ const leave = new Set(rp?.leaveOut ?? []);
1088
+ const kept = product.filter((f) => !leave.has(f.path));
1089
+ const ordered = rp && rp.reach.rooted && rp.reach.models > 0;
1090
+ const parts = planParts(kept, session, ordered ? {
1091
+ head: reachHeadOf(kept.map((f) => f.path), rp),
1092
+ models: rp.reach.reached.map((r) => r.path),
1093
+ leftOut: rp.leaveOut
1094
+ } : void 0);
1095
+ const planned = room >= MIN_ROOM ? planBatches(readSource, {
1096
+ room,
1097
+ exclude: c.exclude,
1098
+ conventions,
1099
+ overhead: overheadOf(repo, c.commit, await frameworksFor(root, repo, facts0)),
1100
+ ...rp && ordered ? { reach: { first: rp.first, leaveOut: rp.leaveOut } } : {}
1101
+ }) : void 0;
1102
+ const plan = planned && planned.leastRoom >= MIN_ROOM ? planned : void 0;
746
1103
  const plan0 = await loadReadPlan(root, repo);
747
1104
  const same = plan0 !== void 0 && plan0.commit === c.commit && plan0.session === session && plan0.parts.length === parts.length && plan0.parts.every((p, i) => p.paths.length === parts[i].paths.length && p.paths.every((x, j) => x === parts[i].paths[j]));
748
- if (parts.length && !same)
749
- await writeReadPlan(root, repo, { commit: c.commit, session, parts });
1105
+ const estimate2 = {
1106
+ files: kept.length,
1107
+ tokens: kept.reduce((n, f) => n + f.tokens, 0),
1108
+ sessions: parts.length || 1,
1109
+ ...reread ? { reread: true } : {}
1110
+ };
1111
+ const sameEstimate = plan0?.estimate !== void 0 && plan0.estimate.files === estimate2.files && plan0.estimate.tokens === estimate2.tokens && plan0.estimate.sessions === estimate2.sessions && plan0.estimate.reread === estimate2.reread;
1112
+ const firstRead = typeof existing !== "string" && existing.length === 0 && !reread;
1113
+ const orgRuleIds = ruleIds(await effectiveRules(root, repo, { dir: c.dir, op: c.op }));
1114
+ const readRules = firstRead ? { hash: rulesNow().hash, sets: [...rulesNow().sets, ...orgRuleIds] } : plan0?.rules;
1115
+ const notReached = rp ? rp.notReached : plan0?.notReached;
1116
+ const sameModels = plan0 !== void 0 && (plan0.models ?? "reachable") === mode && JSON.stringify(plan0.notReached ?? null) === JSON.stringify(notReached ?? null);
1117
+ if (!same)
1118
+ await writeReadPlan(root, repo, {
1119
+ commit: c.commit,
1120
+ session,
1121
+ parts,
1122
+ estimate: estimate2,
1123
+ // What the reader reported of an earlier plan stays, under the commit it was of.
1124
+ ...plan0?.reported ? { reported: plan0.reported } : {},
1125
+ ...readRules ? { rules: readRules } : {},
1126
+ models: mode,
1127
+ ...notReached ? { notReached } : {}
1128
+ });
1129
+ else if (!sameEstimate || !sameModels || firstRead && plan0.rules?.hash !== readRules?.hash) {
1130
+ const { notReached: _n, models: _m, ...rest0 } = plan0;
1131
+ await saveReadPlan(root, {
1132
+ ...rest0,
1133
+ estimate: estimate2,
1134
+ ...readRules ? { rules: readRules } : {},
1135
+ ...mode !== "reachable" ? { models: mode } : {},
1136
+ ...notReached ? { notReached } : {}
1137
+ });
1138
+ }
750
1139
  const progress = parts.length ? await readPlanProgress(root, repo, { commit: c.commit }) : void 0;
751
1140
  const questions = (await listQuestions(root, { repo })).questions.filter((q) => q.state !== "retired");
1141
+ const notes = await notesAt(root, repo, c.dir, c.op);
1142
+ const rules = await rulesCovering(root, repo, c.op);
1143
+ const house = await houseUntaughtOf(root, repo, {
1144
+ dir: c.dir,
1145
+ source: c.source,
1146
+ op: c.op,
1147
+ exclude: c.exclude
1148
+ });
1149
+ if (c.o.part !== void 0 && !parts[c.o.part - 1]) {
1150
+ io.err(`${repo} is read in ${parts.length ? `parts 1 to ${parts.length}` : "one session (no parts)"} at this limit: there is no part ${c.o.part}.`);
1151
+ return 2;
1152
+ }
752
1153
  if (c.o.json) {
753
1154
  io.out(JSON.stringify({
754
1155
  repo,
@@ -763,6 +1164,8 @@ async function estimate(root, repo, c, io) {
763
1164
  maxTokensGiven: given !== void 0,
764
1165
  maxTokensFrom: from ?? "example",
765
1166
  batches: plan?.batches.length ?? null,
1167
+ // ADR 0169: what the read plans to read (the model classes it leaves out, out).
1168
+ read: { files: estimate2.files, tokens: estimate2.tokens },
766
1169
  order: whole.batches.flat().map((x) => x.path),
767
1170
  // ADR 0128: what a person says the repo is, and whether that eased the proposals.
768
1171
  about: about ? { text: about.text, trust: about.trust, eased: saysNotProduct(about) } : null,
@@ -786,13 +1189,29 @@ async function estimate(root, repo, c, io) {
786
1189
  }
787
1190
  } : {}
788
1191
  },
1192
+ // ADR 0169: the model classes reached from the entry points and calls, and those left out.
1193
+ models: rp ? {
1194
+ mode,
1195
+ roots: rp.reach.roots,
1196
+ reached: rp.reach.reached,
1197
+ notReached: rp.leaveOut
1198
+ } : null,
789
1199
  tier,
1200
+ // A-taught: the frameworks of the organisation it is built on, as taught to Atticus.
1201
+ taughtFrameworks: taughtIn(c.source, c.op).map((m) => m.name),
1202
+ // R3: the house packages to teach before the first read.
1203
+ houseUntaught: house,
1204
+ // ADR 0163: the org notes the reader is handed, numbered, and the repo type they are of.
1205
+ notes: { ...notes.type ? { repoType: notes.type } : {}, notes: notes.notes },
1206
+ // G4 (ADR 0176): the organisation's reading rules for this repo, as the reader follows them.
1207
+ readingRules: readingRulesText(await effectiveRules(root, repo, { dir: c.dir, op: c.op })),
790
1208
  questions: questions.map((q) => ({
791
1209
  id: q.id,
792
1210
  question: q.question,
793
1211
  state: q.state,
794
1212
  ...q.answer ? { answer: q.answer } : {}
795
1213
  })),
1214
+ rules,
796
1215
  // A re-read: what the files and batches above are, and the facts to revisit.
797
1216
  reread: reread ? {
798
1217
  ...reread,
@@ -809,6 +1228,23 @@ async function estimate(root, repo, c, io) {
809
1228
  io.out(`${repo} at ${c.commit} in ${c.dir}`);
810
1229
  io.out(about ? `What it is (${descriptionTrust(about)}${about.by ? `, ${about.by}` : ""}): ${about.text} \u2014 a person's note from the manifest, not read from the code: where the code says otherwise, the code is right.` : `What it is: nothing says yet. A person writes one line (atticus repo describe ${repo} --description "..."); if the files say plainly, hand yours over with atticus repo describe ${repo} --drafted "..." --cites <file>:<line>, and it waits for a person.`);
811
1230
  io.out(`Facts file: ${c.factsFile}`);
1231
+ const taught = taughtFrameworksText(taughtIn(c.source, c.op));
1232
+ if (taught)
1233
+ for (const l of taught.split("\n"))
1234
+ io.out(l);
1235
+ const notesLines = notesText(notes.notes, notes.type);
1236
+ if (notesLines)
1237
+ for (const l of notesLines.split("\n"))
1238
+ io.out(l);
1239
+ for (const l of componentTypesText(await componentTypesAt(root, c.op)).split("\n"))
1240
+ if (l)
1241
+ io.out(l);
1242
+ const orgRulesLines = readingRulesText(await effectiveRules(root, repo, { dir: c.dir, op: c.op }));
1243
+ if (orgRulesLines)
1244
+ for (const l of orgRulesLines.split("\n"))
1245
+ io.out(l);
1246
+ for (const l of houseUntaughtLines(repo, house))
1247
+ io.out(l);
812
1248
  if (reread)
813
1249
  for (const l of rereadLines(repo, reread))
814
1250
  io.out(l);
@@ -839,13 +1275,25 @@ repo: ${repo}`);
839
1275
  const stateOf = (i) => progress?.parts[i]?.state;
840
1276
  const words = (s) => s === "done" ? "done" : s === "in-progress" ? "part-read" : "to read";
841
1277
  parts.forEach((p, i) => io.out(` part ${i + 1} (${words(stateOf(i))}, about ${p.tokens} tokens, ${plural(p.files, "file")}): ${p.paths.join(", ")}`));
842
- if (progress) {
1278
+ const asked = c.o.part !== void 0 ? parts[c.o.part - 1] : void 0;
1279
+ if (asked)
1280
+ io.out(`This session reads part ${c.o.part} of ${parts.length} (--part ${c.o.part}): ${asked.paths.join(", ")}. The facts on file stay, as already kept: name one by its id and don't write it again.`);
1281
+ if (progress && !asked) {
843
1282
  io.out(`Read plan: ${readPlanRelOf(root, repo)}. ${progress.next ? `${partOfWords({ part: progress.next.part, total: progress.total })} is next (${progress.done ? `${progress.done} of ${progress.total} read` : `none of ${progress.total} read yet`}): ${progress.next.paths.join(", ")}.` : `All ${progress.total} parts are read.`} A part counts as read when every folder it covers is in the facts (a fact citing a file, or a line of ${factsRelOf(root)}/${repo}.reviewed.jsonl); atticus next says which comes next.`);
844
1283
  for (const p of progress.parts)
845
1284
  if (p.state === "in-progress")
846
1285
  io.out(` part ${p.part} is part-read: nothing in the facts yet for ${p.left.join(", ")}.`);
847
1286
  }
848
1287
  }
1288
+ const line = rp ? modelsLine(repo, rp) : void 0;
1289
+ if (rp && line) {
1290
+ io.out(line);
1291
+ const data = modelsData(repo, rp);
1292
+ if (data) {
1293
+ io.out(MODELS_RULE);
1294
+ io.out(data);
1295
+ }
1296
+ }
849
1297
  io.out(`Your assistant: ${tierWords(tier)}, ${tierSource(tier)}. ${tier.how}`);
850
1298
  io.out(`Another agentic assistant (Claude Code, Cursor, Gemini CLI) reads it the same way: /atticus-map ${repo}; one without file tools gets batches with atticus map ${repo} --handoff --max-tokens <its limit>.`);
851
1299
  if (tier.fallback)
@@ -861,13 +1309,20 @@ repo: ${repo}`);
861
1309
  io.out(plan ? `In batches at ${limit} tokens a prompt${given === void 0 ? " (GPT-4o mini through Copilot; --max-tokens n for your model's limit)" : from === "probe" ? ` (the limit stated when your assistant was measured on ${tier.measured?.at})` : ""}: ${plural(plan.batches.length, "prompt")}, one more if facts are rejected in the last.` : `A model of ${limit} tokens leaves too little room for the files beside the instructions: use a model with a bigger limit.`);
862
1310
  for (const q of questions)
863
1311
  io.out(`Question ${q.id}: ${q.question} (${q.state === "answered" ? `answered: ${q.answer?.text ?? q.options[(q.answer?.option ?? 1) - 1]?.label ?? ""}` : "open"})`);
864
- if (questions.length)
865
- io.out("Follow each answer; don't ask these again.");
1312
+ for (const r of rules)
1313
+ io.out(ruleLineOf(r));
1314
+ if (questions.length || rules.length)
1315
+ io.out("Follow each answer and each rule; don't ask what they settle again.");
866
1316
  return 0;
867
1317
  }
1318
+
868
1319
  export {
869
1320
  REPO_READER,
870
- mapCommand,
1321
+ repoReaderAgent,
1322
+ mapStateOf,
871
1323
  readAnswer,
872
- repoReaderAgent
1324
+ rulesCovering,
1325
+ ruleLineOf,
1326
+ taughtIn,
1327
+ mapCommand
873
1328
  };