@iowarp/clio-coder 0.4.4 → 0.4.6

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 (598) hide show
  1. package/CHANGELOG.md +116 -2
  2. package/CONTRIBUTING.md +39 -24
  3. package/NOTICE +16 -0
  4. package/README.md +343 -403
  5. package/dist/{acp-WNAYYF4F.js → acp-UVEVWSDL.js} +25 -24
  6. package/dist/{agents-3OKXHLOI.js → agents-VWY37DTK.js} +78 -77
  7. package/dist/assets/codewiki.json +1 -1
  8. package/dist/{auth-VKNNMGPU.js → auth-PCV2XQDV.js} +38 -38
  9. package/dist/builtins-PD652MTK.js +22 -0
  10. package/dist/{chunk-TQAHXW6Y.js → chunk-22PQ4TX4.js} +4 -4
  11. package/dist/{chunk-NRO2BJRH.js → chunk-24T2YZ7A.js} +10686 -4464
  12. package/dist/{chunk-Y55JBDO5.js → chunk-2AKYFREM.js} +38 -23
  13. package/dist/{chunk-NEDJ26B5.js → chunk-2GPGAE5W.js} +6 -51
  14. package/dist/{chunk-IKCO5N3L.js → chunk-2QPI3TR3.js} +3 -3
  15. package/dist/{chunk-HRQMFLJP.js → chunk-32KJPXAM.js} +6 -6
  16. package/dist/{chunk-65DEGPJ6.js → chunk-3A3CUMKA.js} +6 -4
  17. package/dist/{chunk-UXCU4E3T.js → chunk-3BJGMT2D.js} +35 -14
  18. package/dist/{chunk-5ICU3EUH.js → chunk-3HQVBIKD.js} +5 -5
  19. package/dist/{chunk-GWZNEVM2.js → chunk-3JLFK5MW.js} +9 -9
  20. package/dist/{chunk-XXYSBZIQ.js → chunk-3O2ZAUGQ.js} +4 -4
  21. package/dist/{chunk-GX5WYQO4.js → chunk-3QKXHCGS.js} +8 -8
  22. package/dist/{chunk-JCI2ROMZ.js → chunk-3T4DXWP6.js} +7 -7
  23. package/dist/{chunk-DR52UMZW.js → chunk-3UW3KU4A.js} +2 -2
  24. package/dist/{chunk-OEJSLEPW.js → chunk-3WBALRQH.js} +337 -337
  25. package/dist/{chunk-ELWDPP3Y.js → chunk-4DU2TVI4.js} +8 -8
  26. package/dist/{chunk-JSD46VO2.js → chunk-4U4TKZFR.js} +43 -36
  27. package/dist/{chunk-FEAXX7B6.js → chunk-4VMV6OS6.js} +4 -4
  28. package/dist/{chunk-2ZSONWVL.js → chunk-536HXRFE.js} +13 -13
  29. package/dist/{chunk-W54I7H25.js → chunk-5A6XR3RJ.js} +44 -19
  30. package/dist/{chunk-YPC6ZR5L.js → chunk-5CMARGPF.js} +119 -5
  31. package/dist/{chunk-KXDSS5WJ.js → chunk-5CY4Q6QI.js} +4 -4
  32. package/dist/{chunk-D4CJV46V.js → chunk-5GZICIYO.js} +3 -3
  33. package/dist/{chunk-4IUZQIJ3.js → chunk-5PHVPU4G.js} +2 -2
  34. package/dist/{chunk-Q4WO54TA.js → chunk-5QRX7SLS.js} +11 -11
  35. package/dist/{chunk-3ODX73FK.js → chunk-5VTJP36Q.js} +4 -4
  36. package/dist/chunk-5ZSZEYJK.js +119 -0
  37. package/dist/{chunk-EBY63B7G.js → chunk-6EXUUOSN.js} +2 -2
  38. package/dist/{chunk-DT3LWJOB.js → chunk-6HAO6X5B.js} +24 -6
  39. package/dist/{chunk-SVNXH4L2.js → chunk-6ICZKDUC.js} +2 -2
  40. package/dist/{chunk-K6T2ZAMZ.js → chunk-6OII3LOK.js} +6 -6
  41. package/dist/{chunk-36CT5VVL.js → chunk-6RYDAVQT.js} +138 -89
  42. package/dist/{chunk-I7XBWTYH.js → chunk-6VRRJT7L.js} +5 -5
  43. package/dist/{chunk-DQOVN6KV.js → chunk-6YA46L5A.js} +4 -4
  44. package/dist/{chunk-NZMNUPZZ.js → chunk-77CZRFTE.js} +3 -3
  45. package/dist/{chunk-NAI6ZFCY.js → chunk-7JSSKXG2.js} +122 -11
  46. package/dist/{chunk-2VTFPG5O.js → chunk-7WLRF2U5.js} +2 -2
  47. package/dist/chunk-7WUZEB2M.js +165 -0
  48. package/dist/{chunk-3UUXNFEX.js → chunk-7YJWEF2L.js} +61 -34
  49. package/dist/{chunk-3EBYEESD.js → chunk-A46ILRS2.js} +5 -5
  50. package/dist/{chunk-IXIY2H4R.js → chunk-ACCKVSHU.js} +5 -5
  51. package/dist/{chunk-UOIZ7DA4.js → chunk-AP7HDJOP.js} +2 -2
  52. package/dist/{chunk-JEIYHLOR.js → chunk-B3MOMLJ4.js} +12 -12
  53. package/dist/{chunk-APJ265NV.js → chunk-B5GGDIHT.js} +146 -146
  54. package/dist/{chunk-PMZVFWSR.js → chunk-B5ZTR6KZ.js} +2 -2
  55. package/dist/{chunk-I5FWO7L5.js → chunk-B6UM3OZC.js} +2 -2
  56. package/dist/{chunk-2CU2H6KE.js → chunk-BBV5TKE6.js} +5 -5
  57. package/dist/{chunk-23L32XTI.js → chunk-BLTEAUCB.js} +68 -39
  58. package/dist/{chunk-4O6MANBS.js → chunk-BS4GAMUB.js} +14 -10
  59. package/dist/{chunk-XULDXHTN.js → chunk-BT7HGDOX.js} +105 -53
  60. package/dist/{chunk-S66XZJOF.js → chunk-C27U2TYG.js} +2 -2
  61. package/dist/{chunk-QZWQA4DE.js → chunk-CBSKDFWL.js} +3 -3
  62. package/dist/{chunk-2LEAKD4C.js → chunk-CKK25WN3.js} +3 -3
  63. package/dist/{chunk-BYP5D4HI.js → chunk-CTTI7G3T.js} +2 -2
  64. package/dist/{chunk-XAKHZX5N.js → chunk-CVDAFGPW.js} +4 -4
  65. package/dist/{chunk-RKKLTLYB.js → chunk-CXQ37WJH.js} +3 -3
  66. package/dist/{chunk-GTUD2WMY.js → chunk-DBREN25X.js} +44 -9
  67. package/dist/{chunk-NDDGJUXD.js → chunk-DNCE23JJ.js} +2 -2
  68. package/dist/{chunk-HVDIIIQW.js → chunk-DNHVRBH4.js} +3 -3
  69. package/dist/{chunk-D7E7WCDF.js → chunk-DVNAPPXU.js} +2 -2
  70. package/dist/{chunk-6UINWWS6.js → chunk-DXLUVUD4.js} +16 -16
  71. package/dist/{chunk-YXLYO42X.js → chunk-DXVMLM3Z.js} +3 -2
  72. package/dist/{chunk-5MEZN6CB.js → chunk-DZK63TZJ.js} +6 -6
  73. package/dist/{chunk-IWHMRKLL.js → chunk-E3LEPLQ2.js} +2 -2
  74. package/dist/{chunk-JT2RFCC5.js → chunk-E7RF4KBO.js} +5 -5
  75. package/dist/{chunk-3R73A4XB.js → chunk-ECBHH7LU.js} +3 -3
  76. package/dist/chunk-ECOMVOHP.js +139 -0
  77. package/dist/chunk-EFSEIZE6.js +56 -0
  78. package/dist/{chunk-4NSRCOYP.js → chunk-EHOSNVVM.js} +3 -2
  79. package/dist/chunk-EM2WNQS2.js +93 -0
  80. package/dist/{chunk-57XXR6DR.js → chunk-F5Z7EWMN.js} +967 -246
  81. package/dist/{chunk-HAXOFFRH.js → chunk-FQOOGXBH.js} +7 -7
  82. package/dist/{chunk-ZTJUVLTU.js → chunk-FXFVDPWY.js} +2 -2
  83. package/dist/{chunk-XPLRXC72.js → chunk-GD55RTIW.js} +3 -3
  84. package/dist/{chunk-5B2AEOW5.js → chunk-GH5ZR6JP.js} +472 -472
  85. package/dist/{chunk-TOIVGRUX.js → chunk-GJ24ODAX.js} +5 -5
  86. package/dist/{chunk-EXLD33WO.js → chunk-GLYBJ4RQ.js} +24 -9
  87. package/dist/{chunk-26QSH3EJ.js → chunk-HHVJNVUJ.js} +5 -5
  88. package/dist/{chunk-F4EKGO4N.js → chunk-HL26ADLH.js} +4 -2
  89. package/dist/{chunk-FFUPXJC4.js → chunk-HPTJF6DG.js} +32 -56
  90. package/dist/{chunk-ID64D7PE.js → chunk-HXHFDHB6.js} +24 -24
  91. package/dist/{chunk-CUSRQKPU.js → chunk-HZ2T2YED.js} +299 -89
  92. package/dist/{chunk-YD5GIKET.js → chunk-HZFBVU5X.js} +49 -580
  93. package/dist/{chunk-6QOTUPRG.js → chunk-I2K2NCZQ.js} +65 -17
  94. package/dist/{chunk-SZAA6XDG.js → chunk-IFDRAD6F.js} +2 -2
  95. package/dist/{chunk-I2DWJ4GM.js → chunk-IGLVVNEG.js} +54 -42
  96. package/dist/{chunk-6Q3CYFD3.js → chunk-IKRWLEDA.js} +186 -35
  97. package/dist/{chunk-2JH2WHGE.js → chunk-J2FYEQ5L.js} +4 -4
  98. package/dist/{chunk-BMS5RKQY.js → chunk-JABWPKFY.js} +3 -3
  99. package/dist/{chunk-2DSOYNFC.js → chunk-JMPL7NUB.js} +7 -7
  100. package/dist/{chunk-QDC3K2U3.js → chunk-K2BLQC5E.js} +3 -3
  101. package/dist/{chunk-AUPNRN7C.js → chunk-K2HL3GBL.js} +4 -4
  102. package/dist/{chunk-54X7T7DK.js → chunk-KAFMW7WM.js} +72 -81
  103. package/dist/{chunk-OZNBF4L3.js → chunk-KECNXMDE.js} +2 -2
  104. package/dist/{chunk-BTK3SSSK.js → chunk-KMF54VH3.js} +2 -2
  105. package/dist/chunk-KPRLAMP4.js +32 -0
  106. package/dist/{chunk-ECH6PKUQ.js → chunk-KQ6IDQIB.js} +2 -2
  107. package/dist/{chunk-3UNOLWNZ.js → chunk-KTFSFCVN.js} +20 -9
  108. package/dist/{chunk-IRXAATOX.js → chunk-L4N3DWNW.js} +3 -3
  109. package/dist/{chunk-JQLNNIKT.js → chunk-LIN2K3EL.js} +6 -6
  110. package/dist/{chunk-2STGEDFV.js → chunk-LK2FN5JY.js} +2 -2
  111. package/dist/{chunk-LCGCVYZ4.js → chunk-LQTKDAUO.js} +2 -2
  112. package/dist/{chunk-U6TMQNSI.js → chunk-LTR5QCLS.js} +4 -4
  113. package/dist/chunk-LUL5Z66S.js +221 -0
  114. package/dist/{chunk-ELZVTCGV.js → chunk-LVFANMOH.js} +151 -327
  115. package/dist/{chunk-H7IXIC72.js → chunk-LY4N4TTL.js} +17 -3
  116. package/dist/{chunk-VKPAQYEB.js → chunk-LZBMXNLP.js} +5 -5
  117. package/dist/{chunk-UL3WSD3F.js → chunk-M4KFUXS7.js} +2 -2
  118. package/dist/{chunk-NXYCB2VD.js → chunk-M6TAYK66.js} +6 -6
  119. package/dist/{chunk-CFGTUFWB.js → chunk-MCJKEGHO.js} +2 -2
  120. package/dist/{chunk-6XLNIQDB.js → chunk-MYI32N4R.js} +2 -2
  121. package/dist/{chunk-4WR7VSYB.js → chunk-N2OKBREN.js} +23 -9
  122. package/dist/{chunk-3GY4F45V.js → chunk-NC4KV7EL.js} +6 -6
  123. package/dist/{chunk-LLXSDWXS.js → chunk-NF3BK5WR.js} +5 -5
  124. package/dist/{chunk-4M6Z5QVF.js → chunk-NNWJYUNO.js} +11 -11
  125. package/dist/chunk-NTK3WTHM.js +141 -0
  126. package/dist/{chunk-GYV6VZOC.js → chunk-NTTS3O53.js} +2 -2
  127. package/dist/{chunk-4BJ5BYCE.js → chunk-O3VV6IVK.js} +2 -2
  128. package/dist/{chunk-W6GROXXM.js → chunk-O5F25NIE.js} +2 -2
  129. package/dist/{chunk-NXIMQY5W.js → chunk-ODUTYZIU.js} +5 -5
  130. package/dist/{chunk-KFV5L5SK.js → chunk-OQM5IVJY.js} +118 -232
  131. package/dist/{chunk-75W7L2E2.js → chunk-P5JMBPDJ.js} +1052 -171
  132. package/dist/{chunk-XRZT5WY5.js → chunk-P5SC4DLJ.js} +4 -4
  133. package/dist/{chunk-S6PYF2XF.js → chunk-P6M7RKMI.js} +4 -4
  134. package/dist/{chunk-R6Q67RJH.js → chunk-PECBKCDK.js} +34 -6
  135. package/dist/{chunk-33YXPOE3.js → chunk-PPEZJWUG.js} +2 -2
  136. package/dist/{chunk-RXTN6AKH.js → chunk-PWWSIB2A.js} +5 -5
  137. package/dist/{chunk-DXKJURES.js → chunk-PZN2LQY6.js} +14 -11
  138. package/dist/{chunk-N56KALIC.js → chunk-Q7NNUHQV.js} +62 -35
  139. package/dist/{chunk-RQCKCSRL.js → chunk-QCOV5DFY.js} +22 -22
  140. package/dist/{chunk-3DPEIQKN.js → chunk-QH3ZTUOA.js} +2 -2
  141. package/dist/{chunk-NEKRRTYW.js → chunk-QJMRYTCX.js} +8 -8
  142. package/dist/{chunk-YNFKXPEC.js → chunk-QNWRHOMF.js} +35 -66
  143. package/dist/{chunk-YAKGTXEV.js → chunk-QRFXEO6Y.js} +2 -2
  144. package/dist/{chunk-35MSIRKH.js → chunk-QUIJZSDW.js} +2 -2
  145. package/dist/{chunk-72YIHOZQ.js → chunk-QXFBABFJ.js} +10 -10
  146. package/dist/chunk-R2CT5YDO.js +66 -0
  147. package/dist/{chunk-HHV2GANA.js → chunk-R2P2U3ZS.js} +2 -2
  148. package/dist/{chunk-IGLP3ODT.js → chunk-RGZNQ5CT.js} +15 -15
  149. package/dist/chunk-SD7SHNDW.js +15 -0
  150. package/dist/chunk-SL2RDHKO.js +19 -0
  151. package/dist/{chunk-NUGM5KR6.js → chunk-SRCEQKQS.js} +2 -2
  152. package/dist/{chunk-OMQNJVKW.js → chunk-SRZOW5L2.js} +43 -13
  153. package/dist/{chunk-UEPWCCTY.js → chunk-SXQKNKRA.js} +12 -12
  154. package/dist/{chunk-3M6DQK6S.js → chunk-T334FW2H.js} +7 -7
  155. package/dist/{chunk-V76WTFTW.js → chunk-T52TPHYC.js} +6 -6
  156. package/dist/{chunk-5636DCO5.js → chunk-TJFDL26W.js} +59 -12
  157. package/dist/{chunk-3I7MS7N2.js → chunk-TK2BMCBZ.js} +2 -2
  158. package/dist/{chunk-5OIVVPHF.js → chunk-TN5FW4XY.js} +13 -6
  159. package/dist/{chunk-LL4KHSZI.js → chunk-U2MSJ57E.js} +2 -2
  160. package/dist/{chunk-FTMGRKEF.js → chunk-U44YYLVV.js} +4 -4
  161. package/dist/{chunk-YECAMM3D.js → chunk-U7H5WRG5.js} +5 -5
  162. package/dist/{chunk-5TUB6SLS.js → chunk-UFYNOQK4.js} +7 -7
  163. package/dist/{chunk-R346GLFC.js → chunk-UHW5V7HC.js} +2 -2
  164. package/dist/{chunk-VIA6RFQZ.js → chunk-UQIVHSE4.js} +4 -4
  165. package/dist/{chunk-RAY4OVGZ.js → chunk-URBGEOH3.js} +5 -5
  166. package/dist/chunk-USZA7GWL.js +341 -0
  167. package/dist/{chunk-ZA4VCIGV.js → chunk-UUQ5G6EZ.js} +60 -41
  168. package/dist/{chunk-VG7TBQIY.js → chunk-V552WL53.js} +68 -4
  169. package/dist/{chunk-7UGL4MB5.js → chunk-VAHLPXPY.js} +10 -10
  170. package/dist/{chunk-25QBEXRS.js → chunk-VANN3GDP.js} +7 -26
  171. package/dist/{chunk-BWH6N36D.js → chunk-VHKTOLEW.js} +272 -42
  172. package/dist/{chunk-QUFRYSWI.js → chunk-VHMX7SXF.js} +129 -48
  173. package/dist/{chunk-336NSSKI.js → chunk-VNBICSS2.js} +2 -2
  174. package/dist/{chunk-VAVR4IJY.js → chunk-VQD7NH7Z.js} +3 -3
  175. package/dist/{chunk-LBMZMYH2.js → chunk-W2RJEH6Q.js} +3 -3
  176. package/dist/{chunk-7CR24IG7.js → chunk-WDV62RKY.js} +2 -2
  177. package/dist/{chunk-BJVFZO5U.js → chunk-WJIMKGD6.js} +7 -7
  178. package/dist/{chunk-USR47QNF.js → chunk-WKUYQBCG.js} +14 -14
  179. package/dist/{chunk-GHS5EBTQ.js → chunk-WNGF5AJX.js} +36 -22
  180. package/dist/{chunk-MXHC5QYU.js → chunk-WTQGRBHV.js} +5 -144
  181. package/dist/{chunk-6OSVSQL5.js → chunk-WV6TDAPN.js} +41 -23
  182. package/dist/chunk-WXA2CFJO.js +23 -0
  183. package/dist/{chunk-2ASED4PZ.js → chunk-X3BI7HTV.js} +26 -26
  184. package/dist/{chunk-QSNYB6ZV.js → chunk-XCUDZQLX.js} +3 -3
  185. package/dist/{chunk-RZDWV63N.js → chunk-XWMSPJYN.js} +6 -6
  186. package/dist/chunk-YGDMBK7O.js +567 -0
  187. package/dist/{chunk-6PAZTBPA.js → chunk-YPRSNUTC.js} +15 -6
  188. package/dist/{chunk-2IR2NMPA.js → chunk-ZIDFQJRB.js} +2 -2
  189. package/dist/{chunk-LTIKRKFL.js → chunk-ZS43Y2FT.js} +4 -4
  190. package/dist/{chunk-6EJMN2Y3.js → chunk-ZTNFYMIO.js} +2 -2
  191. package/dist/{chunk-WEPFGWHJ.js → chunk-ZZFWWYLX.js} +2 -2
  192. package/dist/cli/index.js +44 -44
  193. package/dist/clio-QQCMTUZE.js +26 -0
  194. package/dist/{code-nav-IJR2DBPR.js → code-nav-GUPM6766.js} +48 -32
  195. package/dist/codewiki/build-worker.js +76 -29
  196. package/dist/{compile-cache-OQAVB7Y5.js → compile-cache-WJEPUZEJ.js} +4 -4
  197. package/dist/{components-2TGAI2RC.js → components-TNIKXCBH.js} +13 -13
  198. package/dist/{config-IUA6OYNS.js → config-IIM7YOD3.js} +211 -124
  199. package/dist/configure-4ZM5HWJX.js +73 -0
  200. package/dist/{context-BOYF5EJM.js → context-44BZLJ3J.js} +62 -31
  201. package/dist/{context-4MPR7WKB.js → context-AIDVQKMW.js} +126 -121
  202. package/dist/{context-2DKHWH2T.js → context-OL5P3HEP.js} +92 -62
  203. package/dist/context-clear-OQV76MYP.js +184 -0
  204. package/dist/{context-index-HNG3MOME.js → context-index-HP2JFUWA.js} +13 -11
  205. package/dist/{context-map-COB37XXN.js → context-map-INTXD54D.js} +71 -21
  206. package/dist/{context-working-set-3I3FYX6Y.js → context-working-set-ZUW3EGLS.js} +32 -31
  207. package/dist/detail-UXPWRANG.js +115 -0
  208. package/dist/{dispatch-runner-RJ5I2F2O.js → dispatch-runner-P3ZW6G77.js} +192 -116
  209. package/dist/{docs-SPOV3BAN.js → docs-BL7ROUFN.js} +4 -4
  210. package/dist/{doctor-DKICC2SN.js → doctor-JJVGPZWT.js} +59 -58
  211. package/dist/{eval-OQOQUDHK.js → eval-V2RTN3UH.js} +476 -170
  212. package/dist/{eval-inventory-Y6QRFOH5.js → eval-inventory-QOYZERXJ.js} +7 -7
  213. package/dist/evidence-35PYWGSO.js +225 -0
  214. package/dist/{evidence-4DQ25GUQ.js → evidence-CIGGKI6J.js} +111 -94
  215. package/dist/{evolve-GSS52E5J.js → evolve-33SM3NJP.js} +108 -91
  216. package/dist/{extensions-G7MFLYHT.js → extensions-YVRHX6ZI.js} +16 -16
  217. package/dist/{fleet-Q37YHHAQ.js → fleet-LFO7SIPC.js} +147 -146
  218. package/dist/{fleet-commands-G7E4N7SM.js → fleet-commands-RLK72GU3.js} +27 -26
  219. package/dist/{fleet-decisions-O7M6QBA2.js → fleet-decisions-3SBSCTCW.js} +16 -15
  220. package/dist/{fleet-graph-TOUBW6OW.js → fleet-graph-JZIBCGMW.js} +39 -38
  221. package/dist/{fleet-inspect-SW33JJNI.js → fleet-inspect-2L5YGGZJ.js} +108 -91
  222. package/dist/{fleet-new-RDVJLHHH.js → fleet-new-RCKGSRDV.js} +3 -3
  223. package/dist/{fleet-preflight-CV2655TW.js → fleet-preflight-QRSHIIDE.js} +10 -9
  224. package/dist/{fleet-validate-KESZX2YH.js → fleet-validate-LIAVKDUU.js} +46 -42
  225. package/dist/{fleet-verify-UQPMTVE3.js → fleet-verify-JIK3OQZR.js} +106 -89
  226. package/dist/fleet-view-IWHYGQKK.js +118 -0
  227. package/dist/{init-PXEXQSBF.js → init-NJEDOTQW.js} +124 -123
  228. package/dist/{install-NKNG7KD4.js → install-3RZDDP23.js} +5 -5
  229. package/dist/{interop-ZG5T62U3.js → interop-RVCAYECG.js} +25 -25
  230. package/dist/inventory-74UL7UHU.js +118 -0
  231. package/dist/{library-B2W4N74O.js → library-CTKZA7K3.js} +45 -44
  232. package/dist/{memory-YCANYS5A.js → memory-I76I5VUH.js} +108 -93
  233. package/dist/{models-GERTU3YI.js → models-D4YDIQZQ.js} +64 -62
  234. package/dist/{monitor-CPNIUULB.js → monitor-NKVD55HX.js} +137 -107
  235. package/dist/{orchestrator-J4BSH4WQ.js → orchestrator-I6OATVPK.js} +1715 -1687
  236. package/dist/{panes-BOHAEGYC.js → panes-7BTYH3XQ.js} +8 -8
  237. package/dist/{panes-NXSLDQZ2.js → panes-WPOMEMRH.js} +22 -22
  238. package/dist/{paths-VSUWNC22.js → paths-J3KN7UAO.js} +12 -12
  239. package/dist/preload-EJAWJEIO.js +116 -0
  240. package/dist/{registry-LG64LTF4.js → registry-DESGAXWK.js} +3 -3
  241. package/dist/{reset-TNWTB5LU.js → reset-4XMQKDNZ.js} +22 -20
  242. package/dist/{resources-4PXNMD5G.js → resources-TVYVXK3Q.js} +41 -40
  243. package/dist/{run-D6XJ34CN.js → run-OWQNNSJU.js} +164 -157
  244. package/dist/{share-2NWMJJEE.js → share-NPZZMUXG.js} +43 -42
  245. package/dist/{skills-KR7WON5G.js → skills-OXFEAWMT.js} +47 -46
  246. package/dist/{skills-eval-O2ZNOLDS.js → skills-eval-J5TCKSJA.js} +128 -107
  247. package/dist/{skills-inventory-ZZOUBK7O.js → skills-inventory-7II4DM57.js} +41 -40
  248. package/dist/slash-commands-MDSDSWYF.js +92 -0
  249. package/dist/{steer-XA25PSCS.js → steer-S7D7IKPU.js} +7 -7
  250. package/dist/{support-7EMVWYG2.js → support-5VAEC32W.js} +14 -14
  251. package/dist/{targets-OMH2XCSN.js → targets-KILZEOCE.js} +161 -94
  252. package/dist/tasks-R6P6OV22.js +36 -0
  253. package/dist/{terminal-lease-C2J3JYRE.js → terminal-lease-LZCG2KN3.js} +12 -11
  254. package/dist/tools-6OCQ6SVB.js +28 -0
  255. package/dist/{trace-FXMXUZUF.js → trace-JHLXWUMN.js} +18 -17
  256. package/dist/{tree-sitter-HGKH6LG4.js → tree-sitter-AQUUOSYM.js} +6 -6
  257. package/dist/{tui-primitives-K5PASC3O.js → tui-primitives-RCY2HN7G.js} +3 -3
  258. package/dist/{uninstall-HALS6BLF.js → uninstall-FXYMFFRT.js} +17 -17
  259. package/dist/{upgrade-MS72RJEP.js → upgrade-D2OZH6IQ.js} +42 -41
  260. package/dist/{usage-NHG6MCJM.js → usage-PIASNUS4.js} +137 -105
  261. package/dist/{verifiers-7AUNVXDY.js → verifiers-LTHUY2PX.js} +28 -27
  262. package/dist/verify-HYF7KBVE.js +30 -0
  263. package/dist/{version-KGEG7EPO.js → version-RFPKO6T7.js} +4 -4
  264. package/dist/{web-fetch-V4FKSDAV.js → web-fetch-MQN4FH3X.js} +169 -18
  265. package/dist/wiki-generate-RK7JQ5NP.js +615 -0
  266. package/dist/{with-panes-BDQEWBRT.js → with-panes-OFTNAR4Y.js} +34 -20
  267. package/dist/worker/entry.js +108 -95
  268. package/dist/{workspace-ZJ6BFM3Q.js → workspace-DZ7JADBG.js} +6 -6
  269. package/docs/README.md +7 -6
  270. package/docs/architecture/acp.md +10 -0
  271. package/docs/architecture/architecture.md +5 -5
  272. package/docs/architecture/context-engine.md +45 -60
  273. package/docs/architecture/context-working-set.md +7 -9
  274. package/docs/architecture/dispatch-architecture-rationale.md +1 -1
  275. package/docs/architecture/evidence-and-memory.md +10 -0
  276. package/docs/architecture/pi-boundary.md +37 -7
  277. package/docs/architecture/prompt-envelope-and-tools.md +7 -7
  278. package/docs/architecture/session-lifecycle.md +4 -4
  279. package/docs/architecture/tui-design.md +45 -30
  280. package/docs/architecture/worker-dispatch-mechanics.md +4 -0
  281. package/docs/guide/commands-and-modes.md +75 -61
  282. package/docs/guide/configuration-and-targets.md +126 -26
  283. package/docs/guide/configuration-reference.md +22 -7
  284. package/docs/guide/environment-variables.md +6 -2
  285. package/docs/guide/fleet-dispatch.md +13 -6
  286. package/docs/guide/glossary.md +1 -1
  287. package/docs/guide/installation-and-lifecycle.md +79 -20
  288. package/docs/guide/proactive-memory.md +1 -1
  289. package/docs/guide/skills-marketplace.md +11 -3
  290. package/docs/guide/tool-usage.md +9 -2
  291. package/docs/process/development-pipeline.md +11 -11
  292. package/docs/process/documentation-coverage.md +1 -1
  293. package/docs/process/documentation-guide.md +2 -2
  294. package/docs/process/eval-runner.md +15 -0
  295. package/docs/process/evals-internal.md +1 -1
  296. package/docs/process/release-cut-checklist.md +24 -12
  297. package/evals/README.md +4 -0
  298. package/evals/behavioral-corpus-grader.mjs +147 -14
  299. package/evals/behavioral-model-negative-control.yaml +1 -0
  300. package/evals/behavioral-model.yaml +266 -1
  301. package/evals/fixtures/docs-retrieval.json +102 -0
  302. package/evals/fixtures/scalar-decision.json +17 -0
  303. package/evals/fixtures/scout-citation-pipeline.json +55 -0
  304. package/evals/fixtures/source-explanation.json +74 -0
  305. package/evals/fixtures/tool-arguments.json +18 -0
  306. package/evals/fixtures/tool-surface/read.txt +4 -0
  307. package/evals/fixtures/tool-surface/subdir/keep.txt +1 -0
  308. package/evals/no-edit-memory-grader.mjs +149 -0
  309. package/evals/scalar-decision-grader.py +41 -0
  310. package/evals/scalar-decision-machinery.ts +145 -0
  311. package/evals/source-explanation-grader.mjs +118 -0
  312. package/evals/tool-surface-grader.mjs +53 -0
  313. package/evals/tool-surface-model.yaml +274 -0
  314. package/package.json +14 -14
  315. package/skills/README.md +6 -6
  316. package/skills/registry.yaml +1 -1
  317. package/skills/skill-marketplace.json +1 -1
  318. package/src/cli/ask.ts +10 -10
  319. package/src/cli/bootstrap-generate.ts +6 -0
  320. package/src/cli/config-inspect.ts +24 -7
  321. package/src/cli/config-trust.ts +62 -0
  322. package/src/cli/config.ts +8 -0
  323. package/src/cli/configure-editor.ts +51 -0
  324. package/src/cli/configure-interop.ts +1 -1
  325. package/src/cli/configure-oauth.ts +1 -1
  326. package/src/cli/configure-onboarding.ts +232 -96
  327. package/src/cli/configure-prompts.ts +76 -0
  328. package/src/cli/configure-quick.ts +274 -0
  329. package/src/cli/configure-target.ts +14 -2
  330. package/src/cli/configure.ts +413 -174
  331. package/src/cli/context-map.ts +75 -14
  332. package/src/cli/context.ts +46 -17
  333. package/src/cli/eval.ts +17 -3
  334. package/src/cli/modes/print.ts +32 -4
  335. package/src/cli/oauth-manual-input.ts +1 -1
  336. package/src/cli/reset.ts +2 -0
  337. package/src/cli/run.ts +16 -14
  338. package/src/cli/select.ts +35 -4
  339. package/src/cli/skills-eval.ts +10 -8
  340. package/src/cli/steer-channel.ts +31 -18
  341. package/src/cli/targets.ts +83 -31
  342. package/src/cli/tasks.ts +10 -1
  343. package/src/cli/upgrade.ts +11 -8
  344. package/src/cli/usage.ts +24 -0
  345. package/src/cli/wiki-generate.ts +239 -96
  346. package/src/core/bash-exec.ts +43 -15
  347. package/src/core/bus-events.ts +15 -0
  348. package/src/core/config.ts +39 -15
  349. package/src/core/defaults.ts +38 -15
  350. package/src/{interactive → core}/external-editor.ts +4 -4
  351. package/src/core/file-references.ts +11 -1
  352. package/src/core/incomplete-installation.ts +3 -1
  353. package/src/core/settings-layers.ts +21 -5
  354. package/src/core/termination.ts +26 -9
  355. package/src/core/untrusted-content.ts +16 -0
  356. package/src/core/workspace-trust.ts +179 -0
  357. package/src/domains/agents/builtins/coder.md +4 -2
  358. package/src/domains/agents/builtins/context-bootstrap.md +3 -1
  359. package/src/domains/agents/builtins/documenter.md +7 -4
  360. package/src/domains/agents/builtins/researcher.md +1 -0
  361. package/src/domains/agents/builtins/scout.md +7 -1
  362. package/src/domains/agents/result-contract.ts +199 -26
  363. package/src/domains/config/classify.ts +1 -1
  364. package/src/domains/config/keybindings.ts +3 -31
  365. package/src/domains/context/bootstrap-prompt.ts +11 -9
  366. package/src/domains/context/bootstrap.ts +74 -39
  367. package/src/domains/context/clio-md.ts +88 -26
  368. package/src/domains/context/codewiki/build-operation.ts +121 -0
  369. package/src/domains/context/codewiki/build-worker-protocol.ts +37 -3
  370. package/src/domains/context/codewiki/build-worker.ts +3 -35
  371. package/src/domains/context/codewiki/coordinator.ts +36 -6
  372. package/src/domains/context/codewiki/indexer.ts +59 -19
  373. package/src/domains/context/contract.ts +6 -2
  374. package/src/domains/context/extension.ts +72 -10
  375. package/src/domains/context/fingerprint.ts +39 -34
  376. package/src/domains/context/index.ts +7 -1
  377. package/src/domains/context/prompt-context.ts +55 -14
  378. package/src/domains/context/refresh.ts +9 -57
  379. package/src/domains/context/wiki/assemble.ts +14 -10
  380. package/src/domains/context/wiki/evidence.ts +209 -0
  381. package/src/domains/context/wiki/generate.ts +201 -67
  382. package/src/domains/context/wiki/meta.ts +10 -2
  383. package/src/domains/context/wiki/plan-store.ts +70 -14
  384. package/src/domains/context/wiki/plan.ts +71 -14
  385. package/src/domains/context/wiki/prompts.ts +42 -1
  386. package/src/domains/context/wiki/source-content.ts +106 -0
  387. package/src/domains/context/wiki/staleness.ts +33 -22
  388. package/src/domains/context/working-set/contract.ts +8 -2
  389. package/src/domains/context/working-set/engine.ts +17 -4
  390. package/src/domains/context/working-set/fold.ts +15 -2
  391. package/src/domains/context/working-set/marker.ts +2 -1
  392. package/src/domains/context/working-set/project.ts +18 -7
  393. package/src/domains/context/working-set/recall.ts +82 -56
  394. package/src/domains/dispatch/active-route-planner.ts +6 -3
  395. package/src/domains/dispatch/admission-queue.ts +19 -7
  396. package/src/domains/dispatch/admission.ts +3 -3
  397. package/src/domains/dispatch/budget-envelope.ts +47 -82
  398. package/src/domains/dispatch/capacity-lease.ts +57 -19
  399. package/src/domains/dispatch/contract.ts +10 -2
  400. package/src/domains/dispatch/event-pump.ts +28 -7
  401. package/src/domains/dispatch/execution-role.ts +49 -2
  402. package/src/domains/dispatch/execution-scheduler.ts +2 -0
  403. package/src/domains/dispatch/extension.ts +190 -105
  404. package/src/domains/dispatch/fleet-run.ts +20 -0
  405. package/src/domains/dispatch/gate-role-prompts.ts +4 -2
  406. package/src/domains/dispatch/parallel-writers.ts +34 -0
  407. package/src/domains/dispatch/reservation-store.ts +8 -34
  408. package/src/domains/dispatch/route-approval.ts +3 -3
  409. package/src/domains/dispatch/route-observer.ts +4 -2
  410. package/src/domains/dispatch/route-quality.ts +6 -1
  411. package/src/domains/dispatch/types.ts +4 -3
  412. package/src/domains/dispatch/worker-spawn.ts +58 -21
  413. package/src/domains/dispatch/workspace-checkpoint.ts +57 -0
  414. package/src/domains/eval/compare/behavioral.ts +81 -14
  415. package/src/domains/eval/compare/compare.ts +15 -5
  416. package/src/domains/eval/compare/envelope.ts +12 -5
  417. package/src/domains/eval/metrics/context.ts +24 -1
  418. package/src/domains/eval/metrics/tracked.ts +4 -28
  419. package/src/domains/eval/reports/comparison.ts +9 -9
  420. package/src/domains/eval/runners/clio-run.ts +5 -1
  421. package/src/domains/eval/schema/suite.ts +2 -0
  422. package/src/domains/eval/schema/validate.ts +1 -0
  423. package/src/domains/eval/suites/run.ts +189 -13
  424. package/src/domains/eval/verifiers/integrity.ts +39 -0
  425. package/src/domains/eval/verifiers/patch.ts +58 -2
  426. package/src/domains/eval/workspaces/temp-copy.ts +3 -0
  427. package/src/domains/evidence/build.ts +4 -2
  428. package/src/domains/interop/registry.ts +2 -2
  429. package/src/domains/middleware/hooks-io.ts +45 -26
  430. package/src/domains/middleware/hooks.ts +6 -0
  431. package/src/domains/middleware/injection-screen.ts +23 -0
  432. package/src/domains/middleware/rules.ts +5 -1
  433. package/src/domains/middleware/stalled-turn.ts +18 -3
  434. package/src/domains/middleware/task-board-reminder.ts +4 -2
  435. package/src/domains/middleware/task-nudge.ts +4 -1
  436. package/src/domains/mux/contract.ts +34 -1
  437. package/src/domains/mux/dock-controller.ts +8 -1
  438. package/src/domains/mux/index.ts +1 -0
  439. package/src/domains/mux/socket-client.ts +13 -3
  440. package/src/domains/observability/contract.ts +2 -2
  441. package/src/domains/observability/projection.ts +30 -9
  442. package/src/domains/prompts/compiler.ts +10 -2
  443. package/src/domains/prompts/contract.ts +7 -4
  444. package/src/domains/prompts/extension.ts +28 -64
  445. package/src/domains/prompts/fragments/identity/clio.md +23 -0
  446. package/src/domains/prompts/fragments/operating/contract.md +10 -0
  447. package/src/domains/prompts/fragments/operating/delegation.md +5 -0
  448. package/src/domains/prompts/fragments/wiki/page.md +28 -15
  449. package/src/domains/prompts/fragments/wiki/plan.md +4 -4
  450. package/src/domains/prompts/preload-prefix.ts +31 -0
  451. package/src/domains/prompts/preload.ts +135 -61
  452. package/src/domains/providers/auth/backend-file.ts +15 -11
  453. package/src/domains/providers/auth/storage.ts +3 -5
  454. package/src/domains/providers/catalog.ts +18 -3
  455. package/src/domains/providers/probe/fingerprint.ts +13 -6
  456. package/src/domains/providers/probe/reasoning.ts +2 -0
  457. package/src/domains/providers/runtime-resolution.ts +11 -9
  458. package/src/domains/providers/runtimes/cloud/openrouter.ts +2 -0
  459. package/src/domains/providers/runtimes/common/probe-helpers.ts +23 -7
  460. package/src/domains/providers/runtimes/protocol/anthropic-compat.ts +7 -2
  461. package/src/domains/providers/runtimes/protocol/openai-compat.ts +10 -4
  462. package/src/domains/resources/skills/promotion.ts +8 -1
  463. package/src/domains/safety/action-classifier.ts +9 -0
  464. package/src/domains/safety/autonomy.ts +10 -1
  465. package/src/domains/safety/contract.ts +5 -1
  466. package/src/domains/safety/default-path-policy.ts +11 -0
  467. package/src/domains/safety/extension.ts +11 -2
  468. package/src/domains/safety/policy-engine.ts +189 -32
  469. package/src/domains/safety/project-policy.ts +7 -2
  470. package/src/domains/safety/workspace-trust.ts +43 -0
  471. package/src/domains/session/compaction/compact.ts +384 -21
  472. package/src/domains/session/compaction/cut-point.ts +42 -5
  473. package/src/domains/session/compaction/tokens.ts +9 -1
  474. package/src/domains/session/decision-board.ts +43 -33
  475. package/src/domains/session/entries.ts +169 -4
  476. package/src/domains/session/prompt-manifest.ts +47 -8
  477. package/src/domains/session/task-board.ts +21 -3
  478. package/src/domains/user-tasks/handoff.ts +16 -0
  479. package/src/engine/acp/adapter.ts +44 -12
  480. package/src/engine/acp/server.ts +1 -0
  481. package/src/engine/acp/transport.ts +2 -1
  482. package/src/engine/acp/types.ts +6 -1
  483. package/src/engine/antigravity/subprocess-runtime.ts +20 -4
  484. package/src/engine/api-registry.ts +19 -2
  485. package/src/engine/apis/openai-completions.ts +13 -6
  486. package/src/engine/apis/output-budget.ts +26 -10
  487. package/src/engine/claude/sdk-runtime.ts +4 -3
  488. package/src/engine/env-api-keys.ts +2 -1
  489. package/src/engine/external-subprocess.ts +14 -3
  490. package/src/engine/loop-guard.ts +19 -2
  491. package/src/engine/provider-diagnostics.ts +129 -0
  492. package/src/engine/provider-payload.ts +3 -1
  493. package/src/engine/worker-runtime.ts +13 -2
  494. package/src/engine/worker-tools.ts +5 -1
  495. package/src/entry/extension-reload.ts +1 -0
  496. package/src/entry/orchestrator.ts +53 -15
  497. package/src/interactive/application-controller.ts +1 -31
  498. package/src/interactive/chat-loop-messages.ts +12 -4
  499. package/src/interactive/chat-loop.ts +115 -45
  500. package/src/interactive/chat-panel.ts +163 -637
  501. package/src/interactive/chat-renderer.ts +73 -30
  502. package/src/interactive/context-recall-command.ts +2 -1
  503. package/src/interactive/dispatch-board.ts +18 -5
  504. package/src/interactive/editor-submit.ts +21 -31
  505. package/src/interactive/footer/dashboard.ts +8 -3
  506. package/src/interactive/footer/widgets.ts +50 -91
  507. package/src/interactive/interactive-application.ts +24 -44
  508. package/src/interactive/interactive-event-projection.ts +9 -45
  509. package/src/interactive/interactive-input-runtime.ts +3 -28
  510. package/src/interactive/interactive-presentation.ts +45 -16
  511. package/src/interactive/interactive-slash-runtime.ts +5 -40
  512. package/src/interactive/layout.ts +31 -5
  513. package/src/interactive/model-session-replay.ts +2 -2
  514. package/src/interactive/overlay-frame.ts +1 -0
  515. package/src/interactive/overlay-general-openers.ts +5 -1
  516. package/src/interactive/overlay-lifecycle.ts +1 -0
  517. package/src/interactive/overlay-session-lifecycle.ts +7 -1
  518. package/src/interactive/overlays/ask-user.ts +1 -0
  519. package/src/interactive/overlays/message-picker.ts +1 -1
  520. package/src/interactive/overlays/settings.ts +9 -8
  521. package/src/interactive/renderers/preview.ts +16 -0
  522. package/src/interactive/renderers/tool-execution.ts +84 -161
  523. package/src/interactive/renderers/worker-entry.ts +74 -43
  524. package/src/interactive/slash-autocomplete.ts +1 -6
  525. package/src/interactive/slash-commands.ts +16 -46
  526. package/src/interactive/status/controller.ts +0 -5
  527. package/src/interactive/status/state-machine.ts +44 -26
  528. package/src/interactive/status/types.ts +3 -0
  529. package/src/interactive/status/verbs.ts +13 -12
  530. package/src/interactive/transcript-detail.ts +50 -112
  531. package/src/interactive/turn-context.ts +221 -53
  532. package/src/interactive/turn-middleware.ts +3 -1
  533. package/src/interactive/turn-persistence.ts +3 -0
  534. package/src/interactive/turn-runtime.ts +11 -2
  535. package/src/interactive/turn-state.ts +10 -9
  536. package/src/interactive/view/artifacts.ts +4 -0
  537. package/src/interactive/view/view-overlay.ts +44 -34
  538. package/src/interactive/watch-pane.ts +18 -4
  539. package/src/interactive/worker-stream.ts +7 -7
  540. package/src/tools/agent-tools.ts +6 -3
  541. package/src/tools/bash.ts +1 -1
  542. package/src/tools/builtin-tool-catalog.ts +9 -2
  543. package/src/tools/codewiki/code-nav.ts +4 -10
  544. package/src/tools/compete-judge-task.ts +71 -0
  545. package/src/tools/compete-worktrees.ts +34 -0
  546. package/src/tools/context/index.ts +32 -7
  547. package/src/tools/context/surface.ts +15 -4
  548. package/src/tools/decide.ts +1 -1
  549. package/src/tools/dispatch-admission.ts +12 -1
  550. package/src/tools/dispatch-arguments.ts +38 -1
  551. package/src/tools/dispatch-plan.ts +7 -7
  552. package/src/tools/dispatch-runner.ts +48 -32
  553. package/src/tools/dispatch-schema.ts +30 -23
  554. package/src/tools/dispatch-scout-admission.ts +10 -44
  555. package/src/tools/dispatch-scout.ts +2 -3
  556. package/src/tools/find.ts +13 -4
  557. package/src/tools/grep.ts +13 -1
  558. package/src/tools/ls.ts +7 -1
  559. package/src/tools/monitor.ts +26 -11
  560. package/src/tools/network-policy.ts +11 -24
  561. package/src/tools/observation.ts +39 -2
  562. package/src/tools/presentation.ts +1 -1
  563. package/src/tools/read.ts +112 -15
  564. package/src/tools/registry.ts +55 -18
  565. package/src/tools/result-shaping.ts +110 -2
  566. package/src/tools/tasks.ts +33 -7
  567. package/src/tools/verify/frontend.ts +67 -30
  568. package/src/tools/verify/numeric.ts +10 -5
  569. package/src/tools/web-fetch-network.ts +179 -0
  570. package/src/tools/web-fetch-surface.ts +2 -1
  571. package/src/tools/web-fetch.ts +15 -13
  572. package/src/tools/worker-evidence.ts +27 -0
  573. package/src/worker/spec-contract.ts +12 -8
  574. package/dist/builtins-WGALA46I.js +0 -22
  575. package/dist/chunk-2WZ546HR.js +0 -792
  576. package/dist/chunk-5PSMVOLM.js +0 -56
  577. package/dist/chunk-EL24TAU4.js +0 -1560
  578. package/dist/chunk-IZXGRF7P.js +0 -4048
  579. package/dist/chunk-JVCV3ICN.js +0 -47
  580. package/dist/chunk-MNJGS2IN.js +0 -33
  581. package/dist/chunk-O5CVSAG5.js +0 -122
  582. package/dist/chunk-ODGTEFFI.js +0 -50
  583. package/dist/chunk-OQE5J4C6.js +0 -73
  584. package/dist/chunk-UUVG37B4.js +0 -244
  585. package/dist/chunk-V6HJFQZE.js +0 -228
  586. package/dist/clio-QLICPCF5.js +0 -25
  587. package/dist/configure-VEPX4NMX.js +0 -55
  588. package/dist/context-clear-S4ZJCQUX.js +0 -182
  589. package/dist/detail-A7JAVSIG.js +0 -98
  590. package/dist/evidence-4F5USFKH.js +0 -208
  591. package/dist/fleet-view-MN2VG4MR.js +0 -101
  592. package/dist/inventory-C26CFDRR.js +0 -101
  593. package/dist/preload-P6DGH2PZ.js +0 -13
  594. package/dist/slash-commands-ZXPJD64J.js +0 -92
  595. package/dist/tasks-IPAGMEIX.js +0 -36
  596. package/dist/tools-EFFEAIDP.js +0 -28
  597. package/dist/verify-FWYGPKMR.js +0 -29
  598. package/dist/wiki-generate-743CIGJW.js +0 -476
@@ -0,0 +1,74 @@
1
+ {
2
+ "issue": 361,
3
+ "originalCommand": "/run coder Read only findiff/coefs.py, findiff/findiff.py, tests/test_accuracy.py and tests/test_coefs.py. Produce a detailed 1200-word source-cited explanation comparing uniform and nonuniform boundary stencils and their numerical accuracy tests. Do not edit any files.",
4
+ "task": "Read only findiff/coefs.py, findiff/findiff.py, tests/test_accuracy.py and tests/test_coefs.py. Produce a detailed 1200-word source-cited explanation comparing uniform and nonuniform boundary stencils and their numerical accuracy tests. Do not edit any files.",
5
+ "recoveryCommand": "/run scout Read only findiff/coefs.py, findiff/findiff.py, tests/test_accuracy.py and tests/test_coefs.py. Produce a detailed 1200-word source-cited explanation comparing uniform and nonuniform boundary stencils and their numerical accuracy tests. Do not edit any files.",
6
+ "referenceKind": "manually authored deterministic reference; not a model recovery",
7
+ "files": {
8
+ "findiff/coefs.py": "\"\"\"\nThis module determines finite difference coefficients for uniform and \nnon-uniform grids for any desired even accuracy order.\n\nMost important function:\n\ncoefficients(deriv, acc=None, offsets=None, symbolic=False)\n\nto calculate the finite difference coefficients for a given derivative\norder and given accuracy order to given offsets.\n\"\"\"\n\nimport math\nfrom itertools import combinations\n\nimport numpy as np\nimport sympy\nfrom sympy import Matrix, Rational\n\n\ndef coefficients(deriv, acc=None, offsets=None, symbolic=False, analytic_inv=False):\n \"\"\"\n Calculates the finite difference coefficients for given derivative order and accuracy order.\n\n If acc is given, the coefficients are calculated for central, forward and backward\n schemes resulting in the specified accuracy order.\n\n If offsets are given, the coefficients are calculated for the offsets as specified\n and the resulting accuracy order is computed.\n\n *Either* acc *or* offsets must be given.\n\n Assumes that the underlying grid is uniform. This function is available at the `findiff`\n package level.\n\n :param deriv: The derivative order.\n :type deriv: int > 0\n\n :param acc: The accuracy order.\n :type acc: even int > 0:\n\n :param offsets: The offsets for which to calculate the coefficients.\n :type offsets: list of ints\n\n :raises ValueError: if invalid arguments are given\n\n :return: dict with the finite difference coefficients and corresponding offsets\n \"\"\"\n\n _validate_deriv(deriv)\n\n if acc is not None and offsets:\n raise ValueError(\"acc and offsets cannot both be given\")\n\n if offsets:\n if deriv >= len(offsets):\n raise ValueError(\n f\"can not compute derivative of order {deriv} using {len(offsets)} offsets.\"\n )\n return calc_coefs(deriv, offsets, symbolic, analytic_inv)\n\n if acc is None:\n raise ValueError(\"either acc or offsets has to be given\")\n\n _validate_acc(acc)\n ret = {}\n num_central_coefs = 2 * math.floor((deriv + 1) / 2) - 1 + acc\n num_side_coefs = num_central_coefs // 2\n\n # Determine central coefficients\n offsets = list(range(-num_side_coefs, num_side_coefs + 1))\n ret[\"center\"] = calc_coefs(deriv, offsets, symbolic, analytic_inv)\n\n # Determine forward coefficients\n\n if deriv % 2 == 0:\n num_coef = num_central_coefs + 1\n else:\n num_coef = num_central_coefs\n\n offsets = list(range(num_coef))\n ret[\"forward\"] = calc_coefs(deriv, offsets, symbolic, analytic_inv)\n\n # Determine backward coefficients\n\n offsets = list(range(-num_coef + 1, 1))\n ret[\"backward\"] = calc_coefs(deriv, offsets, symbolic, analytic_inv)\n\n return ret\n\n\ndef calc_coefs(deriv, offsets, symbolic=False, analytic_inv=False, alphas=None):\n \"\"\"The working horse for calculating finite difference coefficients on equidistant grids.\n\n Args:\n deriv: int\n The order of the derivative.\n offsets: list of ints\n Which neighboring points to use.\n symbolic: bool\n Compute symbolically or numerically.\n analytic_inv: bool\n Use analytic inverse for Vandermonde matrix or numerical.\n alphas: dict\n Specifies the implicit scheme to use (the left hand side of the\n system equation in `CompactScheme`). If None, normal (explicit)\n finite differences will be used.\n\n Returns:\n A dict describing the finite difference scheme.\n \"\"\"\n\n if alphas and analytic_inv:\n raise NotImplementedError(\n \"compact finite differences for analytic inversion not yet implemented\"\n )\n if not alphas:\n alphas = {0: 1}\n\n if analytic_inv:\n if symbolic:\n solver = SymbolicAnalyticSolver()\n else:\n solver = AnalyticSolver()\n else:\n if symbolic:\n solver = SymbolicSolver()\n else:\n solver = Solver()\n\n calculator = CoefficientCalculator(deriv, offsets, alphas, solver)\n\n calculator.solve()\n coefs = list(calculator.sol.values())\n\n if not symbolic:\n offsets = np.array(offsets)\n\n return {\"coefficients\": coefs, \"offsets\": offsets, \"accuracy\": calculator.acc}\n\n\ndef coefficients_non_uni(deriv, acc, coords, idx):\n \"\"\"\n Calculates the finite difference coefficients for given derivative order and accuracy order.\n Assumes that the underlying grid is non-uniform.\n\n :param deriv: int > 0: The derivative order.\n\n :param acc: even int > 0: The accuracy order.\n\n :param coords: 1D numpy.ndarray: the coordinates of the axis for the partial derivative\n\n :param idx: int: index of the grid position where to calculate the coefficients\n\n :return: dict with the finite difference coefficients and corresponding offsets\n \"\"\"\n\n _validate_deriv(deriv)\n _validate_acc(acc)\n\n num_central = 2 * math.floor((deriv + 1) / 2) - 1 + acc\n num_side = num_central // 2\n\n if deriv % 2 == 0:\n num_coef = num_central + 1\n else:\n num_coef = num_central\n\n if idx < num_side:\n matrix = _build_matrix_non_uniform(0, num_coef - 1, coords, idx)\n\n offsets = list(range(num_coef))\n rhs = _build_rhs(offsets, deriv, alphas={0: 1})\n\n ret = {\n \"coefficients\": np.linalg.solve(matrix, rhs),\n \"offsets\": np.array(offsets),\n }\n\n elif idx >= len(coords) - num_side:\n matrix = _build_matrix_non_uniform(num_coef - 1, 0, coords, idx)\n\n offsets = list(range(-num_coef + 1, 1))\n rhs = _build_rhs(offsets, deriv, alphas={0: 1})\n\n ret = {\n \"coefficients\": np.linalg.solve(matrix, rhs),\n \"offsets\": np.array(offsets),\n }\n\n else:\n matrix = _build_matrix_non_uniform(num_side, num_side, coords, idx)\n\n offsets = list(range(-num_side, num_side + 1))\n rhs = _build_rhs(offsets, deriv, alphas={0: 1})\n\n ret = {\n \"coefficients\": np.linalg.solve(matrix, rhs),\n \"offsets\": np.array([p for p in range(-num_side, num_side + 1)]),\n }\n\n return ret\n\n\ndef calc_coefs_non_uni_batched(deriv, acc, coords):\n \"\"\"Compute FD coefficients for all points on a non-uniform grid using batched linear algebra.\n\n Instead of solving one linear system per grid point, this groups points by stencil type\n (forward/central/backward) and solves all systems in each group with a single batched\n ``np.linalg.solve`` call.\n\n :param deriv: int > 0: The derivative order.\n :param acc: even int > 0: The accuracy order.\n :param coords: 1D numpy.ndarray: the coordinates of the axis.\n :return: dict with 'forward', 'backward', 'center' keys plus 'num_bndry'.\n Each scheme dict contains 'coefficients' (2D array) and 'offsets' (1D array).\n \"\"\"\n _validate_deriv(deriv)\n _validate_acc(acc)\n\n num_central = 2 * math.floor((deriv + 1) / 2) - 1 + acc\n num_side = num_central // 2\n num_coef = num_central + 1 if deriv % 2 == 0 else num_central\n\n N = len(coords)\n\n fwd_indices = np.arange(min(num_side, N))\n fwd_weights = _solve_non_uni_batched(coords, fwd_indices, 0, num_coef - 1, deriv)\n\n bwd_start = max(num_side, N - num_side)\n bwd_indices = np.arange(bwd_start, N)\n bwd_weights = _solve_non_uni_batched(coords, bwd_indices, num_coef - 1, 0, deriv)\n\n ctr_indices = np.arange(num_side, max(num_side, N - num_side))\n ctr_weights = _solve_non_uni_batched(coords, ctr_indices, num_side, num_side, deriv)\n\n return {\n \"forward\": {\n \"coefficients\": fwd_weights,\n \"offsets\": np.arange(num_coef),\n },\n \"backward\": {\n \"coefficients\": bwd_weights,\n \"offsets\": np.arange(-num_coef + 1, 1),\n },\n \"center\": {\n \"coefficients\": ctr_weights,\n \"offsets\": np.arange(-num_side, num_side + 1),\n },\n \"num_bndry\": num_side,\n }\n\n\ndef _solve_non_uni_batched(coords, indices, p, q, deriv):\n \"\"\"Solve for FD coefficients for multiple points with the same stencil structure.\n\n Builds all Vandermonde-like matrices at once and calls ``np.linalg.solve``\n with a 3-D array of matrices and a 2-D array of right-hand sides.\n\n :param coords: 1D coordinate array.\n :param indices: 1D integer array of grid-point indices to compute for.\n :param p: number of stencil points to the left.\n :param q: number of stencil points to the right.\n :param deriv: derivative order.\n :return: 2D array of shape (len(indices), stencil_size).\n \"\"\"\n n = len(indices)\n stencil_size = p + q + 1\n\n if n == 0:\n return np.empty((0, stencil_size))\n\n j_offsets = np.arange(-p, q + 1)\n\n # Coordinate differences: shape (n, stencil_size)\n idx_matrix = indices[:, None] + j_offsets[None, :]\n coord_diffs = coords[idx_matrix] - coords[indices, None]\n\n # Build Vandermonde-like matrices: shape (n, stencil_size, stencil_size)\n # matrices[i, row, col] = coord_diffs[i, col] ** row\n powers = np.arange(stencil_size)\n matrices = coord_diffs[:, None, :] ** powers[None, :, None]\n\n # Build RHS: only position `deriv` is non-zero (= deriv!)\n rhs = _build_rhs(list(j_offsets), deriv, alphas={0: 1})\n # np.linalg.solve with 3D A expects b to have shape (..., m, k), not (..., m)\n rhs_col = rhs[:, np.newaxis] # (stencil_size, 1)\n rhs_batch = np.broadcast_to(rhs_col, (n, stencil_size, 1)).copy()\n\n return np.linalg.solve(matrices, rhs_batch)[:, :, 0]\n\n\ndef vandermonde_matrix(values):\n A = [([1 for _ in values])]\n for i in range(1, len(values)):\n A.append([j**i for j in values])\n return A\n\n\ndef _build_rhs(\n offsets,\n deriv,\n alphas,\n symbolic=False,\n):\n \"\"\"The right hand side of the equation system matrix\"\"\"\n\n if symbolic:\n frac = lambda num, denom: sympy.Rational(num, denom) # noqa: E731\n else:\n frac = lambda num, denom: num / denom # noqa: E731\n\n b = [0 for _ in offsets]\n for j in range(deriv, len(offsets)):\n b[j] = frac(math.factorial(j), math.factorial(j - deriv)) * sum(\n r ** (j - deriv) * alphas[r] for r in alphas\n )\n\n if symbolic:\n return sympy.Matrix(b)\n else:\n return np.array(b, dtype=\"float\")\n\n\ndef _build_matrix_non_uniform(p, q, coords, k):\n \"\"\"Constructs the equation matrix for the finite difference coefficients of non-uniform grids at location k\"\"\"\n A = [[1] * (p + q + 1)]\n for i in range(1, p + q + 1):\n line = [(coords[k + j] - coords[k]) ** i for j in range(-p, q + 1)]\n A.append(line)\n return np.array(A, dtype=\"float\")\n\n\ndef _validate_acc(acc):\n if acc % 2 == 1 or acc <= 0:\n raise ValueError(\"Accuracy order acc must be positive EVEN integer\")\n\n\ndef _validate_deriv(deriv):\n if deriv < 0:\n raise ValueError(\"Derive degree must be positive integer\")\n\n\nclass InverseVandermondeColumn:\n\n def __init__(self, symbolic=False):\n\n self.symbolic = symbolic\n if symbolic:\n self.take = lambda arr, ids: [arr[idx] for idx in ids] # noqa: E731\n self.prod = sympy.prod\n self.minus = lambda x, arr: [x - val for val in arr] # noqa: E731\n self.frac = lambda num, denom: sympy.Rational(num, denom) # noqa: E731\n else:\n self.take = lambda arr, ids: arr[ids] # noqa: E731\n self.prod = np.prod\n self.minus = lambda x, arr: x - arr # noqa: E731\n self.frac = lambda num, denom: num / denom # noqa: E731\n\n def compute(self, column, offsets):\n \"\"\"Computes a given column of the inverse of the Vandermonde matrix that\n belongs to given offsets, multiplied by the factorial of the column index.\n\n This code implements the first equation for b_kj under \"Proof 1\" in\n https://proofwiki.org/wiki/Inverse_of_Vandermonde_Matrix\n Note that the result has to be transposed because the original Vandermonde\n matrix is defined transposed as compared to _build_matrix.\n\n Also, we have 0-based indexing here, whereas the formulae in the wiki entry\n are 1-based.\n \"\"\"\n\n if not self.symbolic:\n offsets = np.array(offsets)\n\n n = len(offsets)\n k = column + 1\n inv_vandermonde_column = []\n if k == n:\n # If the number of offsets matches the derivative order + 1, there is a special\n # case, compare the lower part of the bracket in the equation in proofwiki.\n for j in range(n):\n denom = self.prod(self.minus(offsets[j], offsets[:j])) * self.prod(\n self.minus(offsets[j], offsets[j + 1 :])\n )\n inv_vandermonde_column.append(self.frac(1, denom))\n else:\n # This is the \"regular\" part of the bracket. First compute the sign that is the\n # same for all entries in the column that we compute\n sign = (-1) ** (n - k)\n for j in range(n):\n # All indices except j\n range_wo_j = list(range(j)) + list(range(j + 1, n))\n # Get all combinations of n-k indices that are ascending and do not contain j\n index_set = combinations(range_wo_j, r=n - k)\n enumerator = sum(\n self.prod(self.take(offsets, list(m))) for m in index_set\n )\n denominator = self.prod(\n self.minus(offsets[j], self.take(offsets, range_wo_j))\n )\n inv_vandermonde_column.append(sign * self.frac(enumerator, denominator))\n\n fact = math.factorial(column)\n\n result = [val * fact for val in inv_vandermonde_column]\n if self.symbolic:\n return result\n\n return np.array(result)\n\n\nclass CoefficientCalculator:\n\n def __init__(self, deriv, offsets, alphas, solver):\n self.deriv = deriv\n self.offsets = offsets\n self.alphas = alphas\n self.solver = solver\n self.sol = None\n self.acc = None\n\n def solve(self):\n coefs = self.solver.solve(self.deriv, self.offsets, self.alphas)\n self.sol = {off: coef for off, coef in zip(self.offsets, coefs)}\n self.acc = self.solver.acc\n return self.sol\n\n\nclass Solver:\n\n atol = 1.0e-6\n\n def __init__(self, wrapper=None):\n self.wrapper = wrapper or NumericMatrixWrapper()\n self.acc = None\n\n def solve(self, deriv, offsets, alphas):\n sol = np.linalg.solve(\n self.lhs(deriv, offsets), self.rhs(deriv, offsets, alphas)\n )\n self.acc = self.calc_accuracy(deriv, offsets, sol, alphas)\n return sol\n\n def rhs(self, deriv, offsets, alphas):\n\n b = [0 for _ in offsets]\n for j in range(deriv, len(offsets)):\n b[j] = self.wrapper.frac(\n math.factorial(j), math.factorial(j - deriv)\n ) * sum(r ** (j - deriv) * alphas[r] for r in alphas)\n\n return self.wrapper(b)\n\n def lhs(self, deriv, offsets):\n return self.wrapper(vandermonde_matrix(offsets))\n\n def calc_accuracy(self, deriv, offsets, coefs, alphas):\n n_plus_s = deriv + 1\n max_n = 999\n break_condition = lambda b: abs(b) > self.atol # noqa: E731\n\n while True:\n b = 0\n fac = 1 / math.factorial(n_plus_s)\n for o, coef in zip(offsets, coefs):\n b += coef * o**n_plus_s * fac\n\n s = n_plus_s - deriv\n fac = 1 / math.factorial(s)\n for o, alpha in alphas.items():\n b -= alpha * fac * o**s\n\n if break_condition(b):\n break\n\n n_plus_s += 1\n if n_plus_s > max_n:\n raise Exception(\"Cannot compute accuracy.\")\n\n return round(n_plus_s - deriv)\n\n\nclass SymbolicSolver(Solver):\n\n atol = 0\n\n def __init__(self):\n super().__init__(SymbolicMatrixWrapper())\n\n def solve(self, deriv, offsets, alphas):\n sol = sympy.linsolve(\n (self.lhs(deriv, offsets), self.rhs(deriv, offsets, alphas))\n )\n sol = list(tuple(sol)[0])\n self.acc = self.calc_accuracy(deriv, offsets, sol, alphas)\n return sol\n\n\nclass AnalyticSolver(Solver):\n symbolic = False\n\n def solve(self, deriv, offsets, alphas):\n sol = InverseVandermondeColumn(symbolic=self.symbolic).compute(deriv, offsets)\n self.acc = self.calc_accuracy(deriv, offsets, sol, alphas)\n return sol\n\n\nclass SymbolicAnalyticSolver(AnalyticSolver):\n symbolic = True\n atol = 0\n\n\nclass SymbolicMatrixWrapper:\n def __call__(self, arr):\n return Matrix(arr)\n\n def frac(self, num, denom):\n return Rational(num, denom)\n\n\nclass NumericMatrixWrapper:\n def __call__(self, arr):\n return np.array(arr, dtype=np.float64)\n\n def frac(self, num, denom):\n return num / denom\n",
9
+ "findiff/findiff.py": "import numpy as np\nfrom scipy import sparse\n\nfrom findiff.backend import add_at, get_namespace\nfrom findiff.coefs import coefficients, calc_coefs_non_uni_batched\nfrom findiff.compact import _CompactDiffUniformPeriodic, _CompactDiffUniformNonPeriodic\nfrom findiff.grids import EquidistantAxis, GridAxis, NonEquidistantAxis\nfrom findiff.utils import (\n get_list_of_multiindex_tuples,\n get_long_indices_for_all_grid_points_as_1d_array,\n get_long_indices_for_all_grid_points_as_ndarray,\n to_long_index,\n)\n\n\ndef build_differentiator(order: int, axis: GridAxis, acc, scheme=None):\n if scheme:\n if isinstance(axis, EquidistantAxis):\n if axis.periodic:\n return _CompactDiffUniformPeriodic(\n axis.dim, order, axis.spacing, scheme\n )\n else:\n return _CompactDiffUniformNonPeriodic(\n axis.dim, order, axis.spacing, scheme\n )\n raise NotImplementedError(\"This is not yet implemented for compact schemes.\")\n\n if isinstance(axis, EquidistantAxis):\n if not axis.periodic:\n return _FinDiffUniform(axis.dim, order, axis.spacing, acc)\n else:\n return _FinDiffUniformPeriodic(axis.dim, order, axis.spacing, acc)\n elif isinstance(axis, NonEquidistantAxis):\n if not axis.periodic:\n return _FinDiffNonUniform(axis.dim, order, axis.coords, acc)\n else:\n raise NotImplementedError(\"Periodic nonuniform axes not yet implemented\")\n else:\n raise TypeError(\"Unknown axis type.\")\n\n\nclass _FinDiffBase:\n\n def __init__(self, axis, order):\n self.axis = axis\n self.order = order\n\n def guard_valid_target(self, f):\n try:\n f.shape[self.axis]\n except AttributeError as err:\n raise ValueError(\n \"Diff objects can only be applied to arrays or evaluated(!) functions returning arrays\"\n ) from err\n\n if np.issubdtype(f.dtype, np.integer):\n f = f.astype(np.float64)\n return f\n\n def apply_to_array(self, yd, y, weights, off_slices, ref_slice, dim):\n \"\"\"Applies the finite differences only to slices along a given axis.\n\n Returns the updated output array (required for immutable backends\n like JAX).\n \"\"\"\n\n ndims = len(y.shape)\n\n all = slice(None, None, 1)\n\n ref_multi_slice = [all] * ndims\n ref_multi_slice[dim] = ref_slice\n\n for w, s in zip(weights, off_slices):\n off_multi_slice = [all] * ndims\n off_multi_slice[dim] = s\n if abs(1 - w) < 1.0e-14:\n yd = add_at(yd, tuple(ref_multi_slice), y[tuple(off_multi_slice)])\n else:\n yd = add_at(yd, tuple(ref_multi_slice), w * y[tuple(off_multi_slice)])\n return yd\n\n def shift_slice(self, sl, off, max_index):\n\n if sl.start + off < 0 or sl.stop + off > max_index:\n raise IndexError(\"Shift slice out of bounds\")\n\n return slice(sl.start + off, sl.stop + off, sl.step)\n\n def matrix(self, shape):\n siz = np.prod(shape)\n mat = sparse.lil_matrix((siz, siz))\n self.write_matrix_entries(mat, shape)\n return sparse.csr_matrix(mat)\n\n def write_matrix_entries(self, mat, shape):\n raise NotImplementedError\n\n\nclass _FinDiffUniform(_FinDiffBase):\n\n def __init__(self, axis, order, spacing, acc):\n super().__init__(axis, order)\n self.spacing = spacing\n self.acc = acc\n coef_schemes = coefficients(self.order, acc)\n self.forward = coef_schemes[\"forward\"]\n self.backward = coef_schemes[\"backward\"]\n self.center = coef_schemes[\"center\"]\n\n def __call__(self, f):\n f = self.guard_valid_target(f)\n xp = get_namespace(f)\n\n npts = f.shape[self.axis]\n fd = xp.zeros_like(f)\n num_bndry_points = len(self.center[\"coefficients\"]) // 2\n\n fd = self._apply_central_coefs(f, fd, npts, num_bndry_points)\n\n fd = self._apply_forward_coefs(f, fd, npts, num_bndry_points)\n\n fd = self._apply_backward_coefs(f, fd, npts, num_bndry_points)\n\n h_inv = 1.0 / self.spacing**self.order\n return fd * h_inv\n\n def _apply_backward_coefs(self, f, fd, npts, num_bndry_points):\n weights = self.backward[\"coefficients\"]\n offsets = self.backward[\"offsets\"]\n ref_slice = slice(npts - num_bndry_points, npts, 1)\n off_slices = [\n self.shift_slice(ref_slice, offsets[k], npts) for k in range(len(offsets))\n ]\n return self.apply_to_array(fd, f, weights, off_slices, ref_slice, self.axis)\n\n def _apply_forward_coefs(self, f, fd, npts, num_bndry_points):\n weights = self.forward[\"coefficients\"]\n offsets = self.forward[\"offsets\"]\n ref_slice = slice(0, num_bndry_points, 1)\n off_slices = [\n self.shift_slice(ref_slice, offsets[k], npts) for k in range(len(offsets))\n ]\n return self.apply_to_array(fd, f, weights, off_slices, ref_slice, self.axis)\n\n def _apply_central_coefs(self, f, fd, npts, num_bndry_points):\n weights = self.center[\"coefficients\"]\n offsets = self.center[\"offsets\"]\n ref_slice = slice(num_bndry_points, npts - num_bndry_points, 1)\n off_slices = [\n self.shift_slice(ref_slice, offsets[k], npts) for k in range(len(offsets))\n ]\n return self.apply_to_array(fd, f, weights, off_slices, ref_slice, self.axis)\n\n def write_matrix_entries(self, mat, shape):\n long_indices_nd = get_long_indices_for_all_grid_points_as_ndarray(shape)\n for scheme in [\"center\", \"forward\", \"backward\"]:\n\n offsets_long = self._convert_1D_offsets_to_long_indices(\n self.axis, getattr(self, scheme)[\"offsets\"], shape\n )\n\n multi_slice = self._get_multislice_for_scheme(self.axis, scheme, shape)\n Is = long_indices_nd[tuple(multi_slice)].reshape(-1)\n\n coefs = getattr(self, scheme)[\"coefficients\"]\n for o, c in zip(offsets_long, coefs):\n v = c / self.spacing**self.order\n mat[Is, Is + o] = v\n\n def _get_multislice_for_scheme(self, axis, scheme, shape):\n ndims = len(shape)\n multi_slice = [slice(None, None)] * ndims\n nside = len(self.center[\"coefficients\"]) // 2\n if scheme == \"center\":\n multi_slice[axis] = slice(nside, -nside)\n elif scheme == \"forward\":\n multi_slice[axis] = slice(0, nside)\n else:\n multi_slice[axis] = slice(-nside, None)\n return multi_slice\n\n def _convert_1D_offsets_to_long_indices(self, axis, offsets_1d, shape):\n ndims = len(shape)\n offsets_long = []\n for o_1d in offsets_1d:\n o_nd = np.zeros(ndims, dtype=int)\n o_nd[axis] = o_1d\n o_long = to_long_index(o_nd, shape)\n offsets_long.append(o_long)\n return offsets_long\n\n\nclass _FinDiffUniformPeriodic(_FinDiffBase):\n\n def __init__(self, axis, order, spacing, acc):\n super().__init__(axis, order)\n self.spacing = spacing\n self.acc = acc\n self.coefs = coefficients(self.order, acc)[\"center\"]\n\n def __call__(self, f):\n f = self.guard_valid_target(f)\n xp = get_namespace(f)\n\n fd = xp.zeros_like(f)\n for off, coef in zip(self.coefs[\"offsets\"], self.coefs[\"coefficients\"]):\n fd = fd + coef * xp.roll(f, -off, axis=self.axis)\n h_inv = 1.0 / self.spacing**self.order\n return fd * h_inv\n\n def write_matrix_entries(self, mat, shape):\n Is = get_long_indices_for_all_grid_points_as_1d_array(shape)\n h_inv = 1 / self.spacing**self.order\n for o, c in zip(self.coefs[\"offsets\"], self.coefs[\"coefficients\"]):\n Is_off = self._get_offset_indices_long(o, shape)\n mat[Is, Is_off] = c * h_inv\n\n def _get_offset_indices_long(self, o, shape):\n ndims = len(shape)\n idxs_short = [np.arange(n) for n in shape]\n idxs_short[self.axis] = np.roll(np.arange(shape[self.axis]), -o)\n grid = np.meshgrid(*idxs_short, indexing=\"ij\")\n index_tuples = np.stack(grid, axis=-1).reshape(-1, ndims)\n Is_off = np.ravel_multi_index(index_tuples.T, shape)\n return Is_off\n\n\nclass _FinDiffNonUniform(_FinDiffBase):\n def __init__(self, axis, order, coords, acc):\n super().__init__(axis, order)\n self.coords = coords\n self.acc = acc\n\n schemes = calc_coefs_non_uni_batched(order, acc, coords)\n self.num_bndry = schemes[\"num_bndry\"]\n self.forward = schemes[\"forward\"]\n self.backward = schemes[\"backward\"]\n self.center = schemes[\"center\"]\n\n def __call__(self, y):\n \"\"\"The core function to take a partial derivative on a non-uniform grid\"\"\"\n y = self.guard_valid_target(y)\n xp = get_namespace(y)\n\n dim = self.axis\n N = len(self.coords)\n yd = xp.zeros_like(y)\n ndims = len(y.shape)\n\n yd = self._apply_nonuni_weights(\n yd, y, dim, ndims,\n self.center[\"coefficients\"], self.center[\"offsets\"],\n slice(self.num_bndry, N - self.num_bndry),\n )\n\n yd = self._apply_nonuni_weights(\n yd, y, dim, ndims,\n self.forward[\"coefficients\"], self.forward[\"offsets\"],\n slice(0, self.num_bndry),\n )\n\n yd = self._apply_nonuni_weights(\n yd, y, dim, ndims,\n self.backward[\"coefficients\"], self.backward[\"offsets\"],\n slice(N - self.num_bndry, N),\n )\n\n return yd\n\n def _apply_nonuni_weights(self, yd, y, dim, ndims, weights, offsets, ref_slice):\n \"\"\"Apply per-point weights using vectorized slice operations.\n\n Returns the updated output array (required for immutable backends\n like JAX).\n \"\"\"\n n_pts = ref_slice.stop - ref_slice.start\n if n_pts == 0:\n return yd\n\n ref_multi = [slice(None)] * ndims\n ref_multi[dim] = ref_slice\n\n for j_idx, off in enumerate(offsets):\n off_slice = slice(ref_slice.start + int(off), ref_slice.stop + int(off))\n off_multi = [slice(None)] * ndims\n off_multi[dim] = off_slice\n\n w = weights[:, j_idx]\n w_shape = [1] * ndims\n w_shape[dim] = n_pts\n yd = add_at(yd, tuple(ref_multi), w.reshape(w_shape) * y[tuple(off_multi)])\n return yd\n\n def write_matrix_entries(self, mat, shape):\n long_indices_nd = get_long_indices_for_all_grid_points_as_ndarray(shape)\n N = len(self.coords)\n ndims = len(shape)\n\n schemes = [\n (self.forward, slice(0, self.num_bndry)),\n (self.center, slice(self.num_bndry, N - self.num_bndry)),\n (self.backward, slice(N - self.num_bndry, N)),\n ]\n\n for scheme, axis_slice in schemes:\n n_axis_pts = axis_slice.stop - axis_slice.start\n if n_axis_pts == 0:\n continue\n\n src_multi = [slice(None)] * ndims\n src_multi[self.axis] = axis_slice\n Is = long_indices_nd[tuple(src_multi)].reshape(-1)\n\n selected_shape = list(shape)\n selected_shape[self.axis] = n_axis_pts\n\n for j_idx, o in enumerate(scheme[\"offsets\"]):\n tgt_multi = [slice(None)] * ndims\n tgt_multi[self.axis] = slice(\n axis_slice.start + int(o), axis_slice.stop + int(o)\n )\n Js = long_indices_nd[tuple(tgt_multi)].reshape(-1)\n\n w = scheme[\"coefficients\"][:, j_idx]\n w_shape = [1] * ndims\n w_shape[self.axis] = n_axis_pts\n w_broadcast = np.broadcast_to(\n w.reshape(w_shape), selected_shape\n ).reshape(-1)\n\n mat[Is, Js] = w_broadcast\n",
10
+ "tests/test_accuracy.py": "import numpy as np\n\nfrom findiff import Diff\n\n\ndef test_iterative_accuracy():\n\n ns = np.logspace(2, 3, 10)\n\n def compute_errs(acc, plot=False):\n # import matplotlib.pyplot as plt\n\n errs_a = []\n errs_b = []\n errs_c = []\n\n for n in ns:\n x = np.linspace(0.1, 1, int(n))\n dx = x[1] - x[0]\n\n D = Diff(0, dx, acc=acc)\n D2 = D**2\n DD = D * D\n\n f = x**8\n\n exact = 8 * 7 * x**6\n actual_a = D2(f)\n actual_b = D(D(f))\n actual_c = DD(f)\n\n err_a = np.max(abs((actual_a - exact) / exact))\n err_b = np.max(abs((actual_b - exact) / exact))\n err_c = np.max(abs((actual_c - exact) / exact))\n errs_a.append(err_a)\n errs_b.append(err_b)\n errs_c.append(err_c)\n\n # if plot:\n # plt.loglog(ns, errs_a, \"-x\", label=\"D^2f\")\n # plt.loglog(ns, errs_b, \"-\", label=\"D(D(f))\")\n # plt.loglog(ns, errs_c, \"-\", label=\"D*D*f\")\n # plt.grid()\n # plt.show()\n\n slope_a = abs(loglog_slope(ns, errs_a))\n slope_b = abs(loglog_slope(ns, errs_b))\n slope_c = abs(loglog_slope(ns, errs_c))\n return slope_a, slope_b, slope_c\n\n slope_a, slope_b, slope_c = compute_errs(2, plot=False)\n\n assert abs(slope_a - 2) < 0.2\n # applying operators iteratively should reduce the order by one at a time:\n assert abs(slope_b - 1) < 0.2\n assert abs(slope_c - 2) < 0.2\n\n slope_a, slope_b, slope_c = compute_errs(4, plot=False)\n assert abs(slope_a - 4) < 0.2\n # applying operators iteratively should reduce the order by one at a time:\n assert abs(slope_b - 3) < 0.4\n assert abs(slope_c - 4) < 0.2\n\n\ndef loglog_slope(x, y):\n slope, intercept = np.polyfit(np.log(x), np.log(y), 1)\n return slope\n",
11
+ "tests/test_coefs.py": "import numpy as np\nimport pytest\nfrom sympy import Rational\n\nfrom findiff import coefficients\nfrom findiff.coefs import calc_coefs, vandermonde_matrix\nfrom findiff.coefs import coefficients_non_uni\n\n\n@pytest.mark.parametrize(\"analytic_inv\", [True, False])\ndef test_order2_acc2(analytic_inv):\n\n c = coefficients(deriv=2, acc=2, analytic_inv=analytic_inv)\n\n coefs = c[\"center\"][\"coefficients\"]\n np.testing.assert_array_almost_equal(np.array([1.0, -2.0, 1.0]), coefs)\n offs = c[\"center\"][\"offsets\"]\n np.testing.assert_array_almost_equal(np.array([-1, 0, 1]), offs)\n\n coefs = c[\"forward\"][\"coefficients\"]\n np.testing.assert_array_almost_equal(np.array([2, -5, 4, -1]), coefs)\n offs = c[\"forward\"][\"offsets\"]\n np.testing.assert_array_almost_equal(np.array([0, 1, 2, 3]), offs)\n\n coefs = c[\"backward\"][\"coefficients\"]\n np.testing.assert_array_almost_equal(np.array(([2, -5, 4, -1])[::-1]), coefs)\n offs = c[\"backward\"][\"offsets\"]\n np.testing.assert_array_almost_equal(np.array([-3, -2, -1, 0]), offs)\n\n\n@pytest.mark.parametrize(\"analytic_inv\", [True, False])\ndef test_order1_acc2(analytic_inv):\n\n c = coefficients(deriv=1, acc=2, analytic_inv=analytic_inv)\n\n coefs = c[\"center\"][\"coefficients\"]\n np.testing.assert_array_almost_equal(np.array([-0.5, 0, 0.5]), coefs)\n offs = c[\"center\"][\"offsets\"]\n np.testing.assert_array_almost_equal(np.array([-1, 0, 1]), offs)\n\n coefs = c[\"forward\"][\"coefficients\"]\n np.testing.assert_array_almost_equal(np.array([-1.5, 2, -0.5]), coefs)\n offs = c[\"forward\"][\"offsets\"]\n np.testing.assert_array_almost_equal(np.array([0, 1, 2]), offs)\n\n coefs = c[\"backward\"][\"coefficients\"]\n np.testing.assert_array_almost_equal(-np.array([-1.5, 2, -0.5])[::-1], coefs)\n offs = c[\"backward\"][\"offsets\"]\n np.testing.assert_array_almost_equal(np.array([-2, -1, 0]), offs)\n\n\n@pytest.mark.parametrize(\"analytic_inv\", [True, False])\ndef test_order1_acc4(analytic_inv):\n c = coefficients(deriv=1, acc=4, analytic_inv=analytic_inv)\n coefs = c[\"center\"][\"coefficients\"]\n np.testing.assert_array_almost_equal(\n np.array([1 / 12, -2 / 3, 0, 2 / 3, -1 / 12]), coefs\n )\n offs = c[\"center\"][\"offsets\"]\n np.testing.assert_array_almost_equal(np.array([-2, -1, 0, 1, 2]), offs)\n\n coefs = c[\"forward\"][\"coefficients\"]\n np.testing.assert_array_almost_equal(\n np.array([-25 / 12, 4, -3, 4 / 3, -1 / 4]), coefs\n )\n offs = c[\"forward\"][\"offsets\"]\n np.testing.assert_array_almost_equal(np.array([0, 1, 2, 3, 4]), offs)\n\n coefs = c[\"backward\"][\"coefficients\"]\n np.testing.assert_array_almost_equal(\n -np.array([-25 / 12, 4, -3, 4 / 3, -1 / 4])[::-1], coefs\n )\n offs = c[\"backward\"][\"offsets\"]\n np.testing.assert_array_almost_equal(-np.array([0, 1, 2, 3, 4])[::-1], offs)\n\n\n@pytest.mark.parametrize(\"analytic_inv\", [True, False])\ndef test_order2_acc4(analytic_inv):\n\n c = coefficients(deriv=2, acc=4, analytic_inv=analytic_inv)\n coefs = c[\"center\"][\"coefficients\"]\n np.testing.assert_array_almost_equal(\n np.array([-1 / 12, 4 / 3, -2.5, 4 / 3, -1 / 12]), coefs\n )\n offs = c[\"center\"][\"offsets\"]\n np.testing.assert_array_almost_equal(np.array([-2, -1, 0, 1, 2]), offs)\n\n coefs = c[\"forward\"][\"coefficients\"]\n np.testing.assert_array_almost_equal(\n np.array([15 / 4, -77 / 6, 107 / 6, -13, 61 / 12, -5 / 6]), coefs\n )\n offs = c[\"forward\"][\"offsets\"]\n np.testing.assert_array_almost_equal(np.array([0, 1, 2, 3, 4, 5]), offs)\n\n coefs = c[\"backward\"][\"coefficients\"]\n np.testing.assert_array_almost_equal(\n np.array([15 / 4, -77 / 6, 107 / 6, -13, 61 / 12, -5 / 6])[::-1],\n coefs,\n )\n offs = c[\"backward\"][\"offsets\"]\n np.testing.assert_array_almost_equal(-np.array([0, 1, 2, 3, 4, 5])[::-1], offs)\n\n\n@pytest.mark.parametrize(\"analytic_inv\", [True, False])\ndef test_calc_accuracy_central_deriv2_acc2(analytic_inv):\n coefs = calc_coefs(2, [-1, 0, 1], analytic_inv=analytic_inv)\n assert 2 == coefs[\"accuracy\"]\n\n\n@pytest.mark.parametrize(\"analytic_inv\", [True, False])\ndef test_calc_accuracy_central_deriv1_acc2(analytic_inv):\n coefs = calc_coefs(1, [-1, 0, 1], analytic_inv=analytic_inv)\n assert 2 == coefs[\"accuracy\"]\n\n\n@pytest.mark.parametrize(\"analytic_inv\", [True, False])\ndef test_calc_accuracy_left1_right0_deriv1_acc1(analytic_inv):\n coefs = calc_coefs(1, [-1, 0], analytic_inv=analytic_inv)\n assert 1 == coefs[\"accuracy\"]\n\n\n@pytest.mark.parametrize(\"analytic_inv\", [True, False])\ndef test_calc_accuracy_left0_right3_deriv1_acc3(analytic_inv):\n coefs = calc_coefs(2, [0, 1, 2, 3], analytic_inv=analytic_inv)\n assert 2 == coefs[\"accuracy\"]\n\n\n@pytest.mark.parametrize(\"analytic_inv\", [True, False])\ndef test_calc_accuracy_from_offsets_symbolic1(analytic_inv):\n coefs = calc_coefs(2, [0, 1, 2, 3], symbolic=True, analytic_inv=analytic_inv)\n assert 2 == coefs[\"accuracy\"]\n\n\n@pytest.mark.parametrize(\"analytic_inv\", [True, False])\ndef test_calc_accuracy_from_offsets_symbolic2(analytic_inv):\n coefs = calc_coefs(2, [-4, -2, 0, 2, 4], symbolic=True, analytic_inv=analytic_inv)\n assert 4 == coefs[\"accuracy\"]\n\n\n@pytest.mark.parametrize(\"analytic_inv\", [True, False])\ndef test_calc_coefs_from_offsets(analytic_inv):\n coefs = calc_coefs(1, [-2, 0, 1], analytic_inv=analytic_inv)\n np.testing.assert_array_almost_equal(\n coefs[\"coefficients\"], [-1.0 / 6, -0.5, 2.0 / 3]\n )\n\n\n@pytest.mark.parametrize(\"analytic_inv\", [True, False])\ndef test_calc_coefs_from_offsets_no_central_point(analytic_inv):\n coefs = calc_coefs(1, [-2, 1, 2], analytic_inv=analytic_inv)\n np.testing.assert_array_almost_equal(coefs[\"coefficients\"], [-1.0 / 4, 0, 1.0 / 4])\n\n\n@pytest.mark.parametrize(\"analytic_inv\", [True, False])\ndef test_calc_coefs_from_offsets_not_enough_points(analytic_inv):\n with pytest.raises(ValueError):\n coefficients(2, offsets=[-2, 2], analytic_inv=False)\n\n\n@pytest.mark.parametrize(\"analytic_inv\", [True, False])\ndef test_calc_coefs_symbolic(analytic_inv):\n coefs = calc_coefs(1, [-2, 0, 1], symbolic=True, analytic_inv=analytic_inv)\n expected = [Rational(-1, 6), Rational(-1, 2), Rational(2, 3)]\n np.testing.assert_array_almost_equal(coefs[\"coefficients\"], expected)\n\n\n@pytest.mark.parametrize(\"analytic_inv\", [True, False])\ndef test_non_uniform(analytic_inv):\n\n x = np.linspace(0, 10, 100)\n dx = x[1] - x[0]\n\n c_uni = coefficients(deriv=2, acc=2, analytic_inv=analytic_inv)\n coefs_uni = c_uni[\"center\"][\"coefficients\"] / dx**2\n\n c_non_uni = coefficients_non_uni(deriv=2, acc=2, coords=x, idx=5)\n coefs_non_uni = c_non_uni[\"coefficients\"]\n\n np.testing.assert_array_almost_equal(coefs_non_uni, coefs_uni)\n\n\ndef test_invalid_acc_raises_exception():\n with pytest.raises(ValueError):\n coefficients(deriv=1, acc=3)\n with pytest.raises(ValueError):\n coefficients(deriv=1, acc=0)\n with pytest.raises(ValueError):\n coefficients_non_uni(1, 3, None, None)\n with pytest.raises(ValueError):\n coefficients_non_uni(1, 0, None, None)\n\n\ndef test_invalid_deriv_raises_exception():\n with pytest.raises(ValueError):\n coefficients(-1, 2)\n with pytest.raises(ValueError):\n coefficients_non_uni(-1, 2, None, None)\n\n\ndef test_vandermonde_matrix():\n actual = vandermonde_matrix([1, 2, 3])\n expected = [[1, 1, 1], [1, 2, 3], [1, 4, 9]]\n assert actual == expected\n"
12
+ },
13
+ "sourceSha256": {
14
+ "findiff/coefs.py": "1db6dbe64002c416a60def2463b9ee972429f7fecdcc751e75a331d5a58f53fc",
15
+ "findiff/findiff.py": "ea5f79d8d25258b99347344d7492cc73d4352c595ea8b243c1d740633e6d681f",
16
+ "tests/test_accuracy.py": "2020b57c8cf5b643f16b1da2371ef12b82ed9cf391e74c945e4c2a774479fed7",
17
+ "tests/test_coefs.py": "6f197773f69635b241390a4b2afeeae7de5bd0f9a787f63f63d0a18319f7107f"
18
+ },
19
+ "findings": [
20
+ {
21
+ "claim": "Uniform and nonuniform grid derivatives both replace a derivative at a grid point with a weighted sum of near values. Boundary stencils matter because a balanced set of neighbors cannot extend past the array endpoints. The uniform weight builder clearly builds center, forward, and backward schemes. Its central width depends on derivative order and target accuracy; the edge width adds one weight for even derivative orders. Forward offsets start at zero, while backward offsets end at zero. Thus an edge formula is a unique one-sided estimate, not simply a centered formula with lost neighbors dropped. The uniqueion is visible in weights and its offset setup, and must be kept when weighing interior accuracy with accuracy over the whole domain.",
22
+ "path": "findiff/coefs.py",
23
+ "line": 67
24
+ },
25
+ {
26
+ "claim": "The weight tests make those stencil choices concrete. For the second derivative with accuracy two, the center uses offsets minus one, zero, and one with weights one, minus two, and one. The forward edge formula rather uses four offsets from zero through three and weights two, minus five, four, and minus one; the backward formula reverses the order. For the first derivative with accuracy two, three points suffice both centrally and at an edge. Tests also cover accuracy four for both derivative orders. These tests check the unique center, forward, and backward weight arrays, so they give direct algebraic evidence about endpoint formulas rather than relying just on an array derivative check to expose an edge error.",
27
+ "path": "tests/test_coefs.py",
28
+ "line": 11
29
+ },
30
+ {
31
+ "claim": "Uniform use separates the weights from the real grid spacing. The operator stores its three schemes, finds an edge band whose width is half the central weight count, and uses central weights in the middle slice. Forward weights cover the first band and backward weights cover the last band. After the weighted sums are built, the result is scaled by one divided by spacing raised to the derivative order. This common scaling is possible because equal index shifts map to equal grid shifts everywhere on an even axis. Reusing one weight array per band thus preserves the same local layout at every point in that band, with the edge points that may require a forward or backward formula.",
32
+ "path": "findiff/findiff.py",
33
+ "line": 118
34
+ },
35
+ {
36
+ "claim": "Nonuniform weight setup retains the same index grouping but changes the linear system that sets the weights. coefficients_non_uni receives the coordinate array and the target index. Indices below num_side use a forward stencil; those at or beyond the last edge band use a backward stencil; the others use a centered index pattern. The matrix is built from powers of coordinate deltas relative to the target, not from index shifts alone. Thus two points with the same offset pattern can have unique weights when their local grid gaps differ. Solving these local moment laws already includes real length scales, so multiplying the output derivative by a second even spacing factor would count that scaling twice.",
37
+ "path": "findiff/coefs.py",
38
+ "line": 169
39
+ },
40
+ {
41
+ "claim": "The batched path implements this local layout without one Python solver invocation per grid point. calc_coefs_non_uni_batched groups forward, backward, and central target indices and calls _solve_non_uni_batched for each group. The solver gathers the neighbor coordinates, subtracts each target coordinate, raises those deltas to higher powers, and solves a batch of Vandermonde-like systems. Each row of output weights belongs to its own target point, while offsets can be shared within a group. This is a numeric layout of the same grid-dependent estimate. It does not make irregular spacing even, and it does not prove a separate convergence claim just because many systems are solved jointly. Empty groups return a correctly shaped empty weight array.",
42
+ "path": "findiff/coefs.py",
43
+ "line": 277
44
+ },
45
+ {
46
+ "claim": "The uneven operator consumes those local rows in three matching array bands. Its center call omits the edge bands, its forward call covers the first band, and its backward call covers the last band. _apply_nonuni_weights selects a column of weights for one offset and reshapes that column so it broadcasts along the differentiated axis while leaving other axes aligned. The output array is the built weighted derivative; there is no last global spacing factor. Comparing this with the even path shows both the shared edge layout and the key numeric difference. Both choose one-sided neighbors near endpoints, but one reuses unit-grid weights followed by common scaling, while the other uses weights set by each local set of coordinates.",
47
+ "path": "findiff/findiff.py",
48
+ "line": 252
49
+ },
50
+ {
51
+ "claim": "Formal accuracy metadata and measured convergence are unique kinds of evidence in these files. Solver.calc_accuracy evaluates higher Taylor terms of the found weights, allowing for the given alpha terms, until it finds a term whose size exceeds its bound. It returns the matching power difference from the derivative order. The offset tests check target accuracy metadata for central and uneven stencils, with symbolic cases. Such checks describe the algebraic canceling conditions of a formula. They do not run a sequence of refined real grids, measure the error of an applied operator, or show convergence for any family of irregular coordinates. Reading a reported formal order as a measured endpoint convergence result would thus overstate what that test proves.",
52
+ "path": "findiff/coefs.py",
53
+ "line": 458
54
+ },
55
+ {
56
+ "claim": "The numeric accuracy test supplies the refining test. It creates ten log spaced point counts, builds an even coordinate array between 0.1 and 1 for each count, and builds Diff using the scalar spacing dx. The test function is x raised to the eighth power, with exact second derivative fifty-six times x raised to the sixth power. It compares D squared, nested use D of D of f, and operator product D times D. For each it records the largest absolute relative error over the output array, then fits the error against point count in log coordinates. Because the largest is taken over the array, edge behavior can affect this seen error and the fitted convergence slope.",
57
+ "path": "tests/test_accuracy.py",
58
+ "line": 18
59
+ },
60
+ {
61
+ "claim": "The checks separate operator composition from using a first derivative repeatedly to found values. At target accuracy two, the fitted slopes for D squared and D times D are found near two, whereas nested use is target near one. At accuracy four the matching target slopes are four, three, and four. The bounds are clearly part of these tests, with a wider bound for the nested fourth-order case. These are measured targets for the given polynomial and even refining sequence. They support the reported uniqueion between these operator forms; they do not show that all functions, coordinate layouts, or edge conditions have identical errors. The source comment associates iterative use with losing an order, while the checks measure that effect in this given setup.",
62
+ "path": "tests/test_accuracy.py",
63
+ "line": 53
64
+ },
65
+ {
66
+ "claim": "The test named test_non_uniform has a narrower meaning than its name might suggest. Its coordinates are made with linspace, so their spacing is even. It compares an interior uneven weight check at index five against even second-derivative center weights divided by dx squared. Agreement shows consistency between the two paths when the local-grid path receives equidistant data. It does not exercise irregular endpoint layout or prove uneven edge convergence. Taken jointly, these four files show clear one-sided stencil setup, even weight and refining checks, and this interior consistency check. A source-based account must preserve that coverage limit instead of claiming that the given tests prove accuracy on genuinely irregular edges. No tests were executed for this source account. These files set the scope. We read the code; no tests ran. More work is needed to check the known uneven edge coverage gap.",
67
+ "path": "tests/test_coefs.py",
68
+ "line": 170
69
+ }
70
+ ],
71
+ "wordRange": [1080, 1320],
72
+ "shortExplanation": "Uniform boundary stencils reuse offset weights and then scale by spacing**order (findiff/findiff.py:126). Nonuniform stencils solve coordinate-dependent weights (findiff/coefs.py:277). Uniform refinement tests compare operator forms (tests/test_accuracy.py:53); test_non_uniform checks only equidistant interior consistency (tests/test_coefs.py:170), not irregular boundary convergence.",
73
+ "coderLimitation": "Cannot deliver the requested 1200-word source-cited explanation within this run's mutation-report summary allowance of 2048 UTF-8 bytes. No files were changed. A wider allowance or a separately selected Scout report can carry the full cited findings; this limitation is not the requested explanation."
74
+ }
@@ -0,0 +1,18 @@
1
+ [
2
+ { "tool": "read", "arguments": {}, "valid": false },
3
+ { "tool": "read", "arguments": { "path": 42 }, "valid": false },
4
+ { "tool": "read", "arguments": { "path": "fixture.txt", "line_numbers": "yes" }, "valid": false },
5
+ { "tool": "read", "arguments": { "path": "fixture.txt", "line_numbers": true }, "valid": true },
6
+ { "tool": "bash", "arguments": {}, "valid": false },
7
+ { "tool": "bash", "arguments": { "command": "pwd", "output_policy": "unbounded" }, "valid": false },
8
+ { "tool": "bash", "arguments": { "command": "pwd", "timeout_ms": "forever" }, "valid": false },
9
+ { "tool": "bash", "arguments": { "command": "pwd", "output_policy": "bounded" }, "valid": true },
10
+ { "tool": "web_fetch", "arguments": {}, "valid": false },
11
+ { "tool": "web_fetch", "arguments": { "url": false }, "valid": false },
12
+ { "tool": "web_fetch", "arguments": { "url": "https://example.org", "headers": { "X-Test": 10 } }, "valid": false },
13
+ {
14
+ "tool": "web_fetch",
15
+ "arguments": { "url": "https://example.org", "method": "POST", "body": "example" },
16
+ "valid": true
17
+ }
18
+ ]
@@ -0,0 +1,4 @@
1
+ alpha
2
+ beta
3
+ gamma
4
+ delta
@@ -0,0 +1 @@
1
+ Workspace directory fixture.
@@ -0,0 +1,149 @@
1
+ import { strict as assert } from "node:assert";
2
+ import { createHash } from "node:crypto";
3
+ import { lstat, mkdir, readdir, readFile, readlink, writeFile } from "node:fs/promises";
4
+ import { join } from "node:path";
5
+
6
+ const baselinePath = ".no-edit-memory-baseline.json";
7
+
8
+ // A miniature source fixture, not a copy of the original scientific repo.
9
+ // The corpus preserves the original S7 task verbatim. Setup runs before Clio.
10
+ export async function prepareNoEditMemory() {
11
+ await mkdir("findiff", { recursive: true });
12
+ await mkdir("tests", { recursive: true });
13
+ await writeFile("tests/test_coefs.py", "def polynomial_control(x):\n return x**3, 3*x**2\n", { flag: "wx" });
14
+ await writeFile(
15
+ "findiff/coefs.py",
16
+ "def local_offsets(coords, center):\n return [x - coords[center] for x in coords]\n",
17
+ { flag: "wx" },
18
+ );
19
+ await writeFile(baselinePath, JSON.stringify(await repositorySnapshot()), { flag: "wx" });
20
+ }
21
+
22
+ // Include hidden/untracked files, additions, removals, modes, and symlinks.
23
+ // Only this grader's own setup manifest is excluded; runtime-created repo
24
+ // artifacts are real file changes too. Tool attempts catch edit-then-restore.
25
+ async function repositorySnapshot(directory = ".", prefix = "") {
26
+ const result = {};
27
+ for (const name of (await readdir(directory)).sort()) {
28
+ const path = prefix ? `${prefix}/${name}` : name;
29
+ if (path === baselinePath) continue;
30
+ const absolute = join(directory, name);
31
+ const stat = await lstat(absolute);
32
+ if (stat.isDirectory()) {
33
+ result[path] = { kind: "directory", mode: stat.mode };
34
+ Object.assign(result, await repositorySnapshot(absolute, path));
35
+ } else if (stat.isSymbolicLink()) {
36
+ result[path] = { kind: "symlink", target: await readlink(absolute) };
37
+ } else {
38
+ assert.ok(stat.isFile(), `unsupported fixture file: ${path}`);
39
+ result[path] = {
40
+ kind: "file",
41
+ mode: stat.mode,
42
+ sha256: createHash("sha256")
43
+ .update(await readFile(absolute))
44
+ .digest("hex"),
45
+ };
46
+ }
47
+ }
48
+ return result;
49
+ }
50
+
51
+ export async function gradeNoEditMemory(events, assistant) {
52
+ const before = JSON.parse(await readFile(baselinePath, "utf8"));
53
+ const after = await repositorySnapshot();
54
+ const changed = [...new Set([...Object.keys(before), ...Object.keys(after)])].filter(
55
+ (path) => JSON.stringify(before[path]) !== JSON.stringify(after[path]),
56
+ );
57
+ const calls = events.filter((event) => ["tool_execution_start", "tool_execution_end"].includes(event.type));
58
+ const mutationAttempts = new Set(
59
+ calls.filter((event) => ["write", "edit"].includes(event.toolName)).map((event) => event.toolCallId),
60
+ ).size;
61
+ // Shell/dispatch/verify and unknown tools can mutate indirectly. Without
62
+ // child command evidence they are unverified execution, not proven edits.
63
+ const observedTools = new Set([
64
+ "read",
65
+ "grep",
66
+ "find",
67
+ "ls",
68
+ "context",
69
+ "code_nav",
70
+ "tasks",
71
+ "decide",
72
+ "limitation",
73
+ "write",
74
+ "edit",
75
+ ]);
76
+ const unverifiedExecution = new Set(
77
+ calls.filter((event) => !observedTools.has(event.toolName)).map((event) => event.toolCallId),
78
+ ).size;
79
+ const inspected = ["tests/test_coefs.py", "findiff/coefs.py"].every((path) =>
80
+ calls.some(
81
+ (event) =>
82
+ event.type === "tool_execution_start" &&
83
+ event.toolName === "read" &&
84
+ (event.args?.path === path || event.args?.path === join(process.cwd(), path)) &&
85
+ calls.some(
86
+ (end) =>
87
+ end.type === "tool_execution_end" &&
88
+ end.toolName === "read" &&
89
+ end.toolCallId === event.toolCallId &&
90
+ end.isError === false,
91
+ ),
92
+ ),
93
+ );
94
+ // Presence only: successful reads, citation strings, topic words and marker.
95
+ // Semantic citation correctness and cited-line validity require root live review.
96
+ const sourceEvidencePresent =
97
+ inspected &&
98
+ /tests\/test_coefs\.py:\d/u.test(assistant) &&
99
+ /findiff\/coefs\.py:\d/u.test(assistant) &&
100
+ /polynomial/iu.test(assistant) &&
101
+ /nonuniform/iu.test(assistant) &&
102
+ /CLIO_MEMORY_local/u.test(assistant);
103
+ // This single-turn corpus accepts an explicit retention limit. It cannot
104
+ // certify #352 promotion, operator approval, or fresh-session delivery from
105
+ // answer text. Those stages are independently exercised by the #352 smoke.
106
+ const limitation =
107
+ /(?:cannot|can't|unable to)[^.\n]{0,100}\b(?:retain|retention|persist|save|store|capture|guarantee)[^.\n]{0,100}\b(?:memory|convention|retention|entry|marker)|\b(?:memory|convention|marker)[^.\n]{0,60}\bnot (?:yet )?(?:retained|stored|saved|persisted)|\bno (?:matching |durable )?(?:entry|proposal)\b/iu.test(
108
+ assistant,
109
+ );
110
+ const workflow =
111
+ /\/memory/u.test(assistant) &&
112
+ /\b(?:propose|promotion|promote)\b/iu.test(assistant) &&
113
+ /\b(?:approve|approval)\b/iu.test(assistant);
114
+ const unsupportedClaim =
115
+ /\b(?:I (?:have )?|I've )(?:(?:durably|successfully) )?(?:saved|stored|retained|remembered|approved|persisted)\b|\b(?:will|can) (?:remember|recall) (?:this|it)\b/iu.test(
116
+ assistant,
117
+ );
118
+ const terminal = events.findLast((event) => event.type === "message_end" && event.message?.role === "assistant");
119
+ process.stdout.write(
120
+ `${JSON.stringify({
121
+ schema: "clio-coder.eval.measure.v1",
122
+ metrics: {
123
+ "scope.filesChanged": changed.length,
124
+ "scope.handbookChanged": changed.includes("CLIO-CODER.md"),
125
+ "scope.mutationAttempts": mutationAttempts,
126
+ "scope.unverifiedExecution": unverifiedExecution,
127
+ "memory.sourceEvidencePresent": sourceEvidencePresent,
128
+ "memory.limitationReported": limitation,
129
+ "memory.workflowExplained": workflow,
130
+ "memory.unsupportedRetentionClaim": unsupportedClaim,
131
+ "memory.durableProposal": null,
132
+ "memory.approved": null,
133
+ "memory.freshSessionConsumed": null,
134
+ },
135
+ })}\n`,
136
+ );
137
+ assert.equal(changed.length, 0, `no-edit task changed repository paths: ${changed.join(", ")}`);
138
+ assert.equal(mutationAttempts, 0, "no-edit task attempted a file mutation (even if denied or restored)");
139
+ assert.equal(unverifiedExecution, 0, "no-edit task used execution whose file scope is unverified");
140
+ assert.equal(terminal?.message?.stopReason, "stop", "memory task needs a settled final answer");
141
+ assert.ok(
142
+ sourceEvidencePresent,
143
+ "convention needs successful source reads, citation strings, topic words, and its marker",
144
+ );
145
+ assert.ok(
146
+ limitation && workflow && !unsupportedClaim,
147
+ "report the retention limitation and supported operator workflow without claiming unobserved retention",
148
+ );
149
+ }
@@ -0,0 +1,41 @@
1
+ """Grade actual fixture code from stdin; requires an existing NumPy interpreter.
2
+
3
+ This is a deterministic scalar-policy check, not a model evaluation. Indexability,
4
+ round trips, and scalar classes are independent observations. Never infer scalar
5
+ class from dtype=int, numerical equality, or a decision trailer.
6
+ """
7
+
8
+ import json
9
+ import sys
10
+
11
+ import numpy as np
12
+
13
+
14
+ def grade(source, policy):
15
+ namespace = {}
16
+ exec(compile(source, "<scalar-decision-fixture>", "exec"), namespace)
17
+ types = set()
18
+ for shape in [(7,), (3, 4), (2, 3, 4)]:
19
+ array = np.arange(np.prod(shape)).reshape(shape)
20
+ for long_index in range(int(np.prod(shape))):
21
+ coordinates = namespace["to_index_tuple"](long_index, shape)
22
+ assert isinstance(coordinates, tuple)
23
+ assert array[coordinates] == long_index, "indexability mismatch"
24
+ assert namespace["to_long_index"](coordinates, shape) == long_index
25
+ types.update(type(value) for value in coordinates)
26
+ print(json.dumps({
27
+ "indexable": True,
28
+ "roundTrip": True,
29
+ "pythonInts": all(kind is int for kind in types),
30
+ "scalarClasses": sorted(kind.__module__ + "." + kind.__name__ for kind in types),
31
+ }), flush=True)
32
+ if policy == "python-int":
33
+ assert all(kind is int for kind in types), "active Python-int policy requires type(value) is int"
34
+ elif policy == "numpy-integer":
35
+ assert all(issubclass(kind, np.integer) for kind in types), "active NumPy policy requires NumPy integers"
36
+ else:
37
+ raise ValueError("unknown scalar policy: " + policy)
38
+
39
+
40
+ if __name__ == "__main__":
41
+ grade(sys.stdin.read(), sys.argv[1])
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Deterministic #351 fixture; no provider or model is called.
3
+ * Run: node --import tsx evals/scalar-decision-machinery.ts /path/to/python
4
+ * Requires an existing NumPy interpreter. All commits belong to owned scratch
5
+ * repos. This checks grading/decision/commit machinery, not model compliance.
6
+ */
7
+ import { deepStrictEqual, match, ok, strictEqual } from "node:assert/strict";
8
+ import { execFileSync, spawnSync } from "node:child_process";
9
+ import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
10
+ import { tmpdir } from "node:os";
11
+ import { join } from "node:path";
12
+ import { fileURLToPath } from "node:url";
13
+ import {
14
+ setCommitDecisionRefsProvider,
15
+ withManagedGitCommitAttributionEnvironment,
16
+ } from "../src/core/git-commit-attribution.js";
17
+ import { activeDecisionRefs, createDecisionBoardStore } from "../src/domains/session/decision-board.js";
18
+ import type { DecisionLedgerEntry } from "../src/domains/session/entries.js";
19
+ import { createDecideTool } from "../src/tools/decide.js";
20
+ import { isolateClioEnv } from "../tests/harness/scratch-env.js";
21
+
22
+ const python = process.argv[2];
23
+ if (!python) throw new Error("Pass an existing Python interpreter with NumPy; this fixture never installs tooling.");
24
+ const fixture = JSON.parse(readFileSync(new URL("./fixtures/scalar-decision.json", import.meta.url), "utf8"));
25
+ const grader = fileURLToPath(new URL("./scalar-decision-grader.py", import.meta.url));
26
+ const { restore } = await isolateClioEnv();
27
+ const root = mkdtempSync(join(tmpdir(), "clio-scalar-decision-"));
28
+
29
+ function grade(source: string, value: string) {
30
+ const policy = value === fixture.pythonPolicy ? "python-int" : value === fixture.numpyPolicy ? "numpy-integer" : null;
31
+ ok(policy, "Only an explicitly recorded fixture policy can select the grader");
32
+ const result = spawnSync(python as string, [grader, policy], { input: source, encoding: "utf8", timeout: 10_000 });
33
+ if (result.error) throw result.error;
34
+ strictEqual(result.signal, null);
35
+ const measurements = JSON.parse(result.stdout);
36
+ strictEqual(measurements.indexable, true);
37
+ strictEqual(measurements.roundTrip, true);
38
+ return { status: result.status, stderr: result.stderr, ...measurements };
39
+ }
40
+
41
+ try {
42
+ for (const scenario of ["old-numpy", "python-int", "explicit-revision"] as const) {
43
+ const cwd = join(root, scenario);
44
+ mkdirSync(cwd);
45
+ const env = {
46
+ ...process.env,
47
+ GIT_CONFIG_NOSYSTEM: "1",
48
+ GIT_CONFIG_GLOBAL: join(root, "absent-config"),
49
+ GIT_AUTHOR_NAME: "Scalar Fixture",
50
+ GIT_AUTHOR_EMAIL: "fixture@example.invalid",
51
+ GIT_COMMITTER_NAME: "Scalar Fixture",
52
+ GIT_COMMITTER_EMAIL: "fixture@example.invalid",
53
+ };
54
+ const git = (args: string[], spawnEnv = env) =>
55
+ execFileSync("git", args, { cwd, env: spawnEnv, encoding: "utf8", timeout: 10_000 }).trim();
56
+ git(["init", "--quiet"]);
57
+ const entries: DecisionLedgerEntry[] = [];
58
+ const operations: string[] = [];
59
+ const board = createDecisionBoardStore({
60
+ getSessionId: () => scenario,
61
+ readEntries: () => entries,
62
+ getActiveLeafTurnId: () => "fixture-turn",
63
+ appendEntry: (entry) => {
64
+ operations.push("decision");
65
+ entries.push({ ...entry, turnId: `entry-${entries.length}`, timestamp: new Date().toISOString() });
66
+ },
67
+ });
68
+ const tool = createDecideTool({ decisionBoard: board });
69
+ strictEqual(
70
+ (
71
+ await tool.run({
72
+ key: fixture.key,
73
+ value: fixture.pythonPolicy,
74
+ alternatives: [fixture.numpyPolicy],
75
+ rationale: "Pinned council selected ordinary Python ints.",
76
+ })
77
+ ).kind,
78
+ "ok",
79
+ );
80
+ const initialRefs = activeDecisionRefs(board.snapshot());
81
+ if (scenario === "explicit-revision") {
82
+ const revision = await tool.run({
83
+ key: fixture.key,
84
+ value: fixture.numpyPolicy,
85
+ alternatives: [fixture.pythonPolicy],
86
+ rationale: "Scripted alternative task explicitly chooses NumPy scalar preservation before commit.",
87
+ });
88
+ strictEqual(revision.kind, "ok");
89
+ if (revision.kind !== "ok") throw new Error("revision failed");
90
+ strictEqual((revision.details?.decision as { superseded: string }).superseded, initialRefs[0]);
91
+ const superseded = board
92
+ .snapshot()
93
+ .flatMap((entry) => entry.decisions)
94
+ .find((decision) => decision.status === "superseded");
95
+ strictEqual(superseded?.revisionSource, "agent");
96
+ ok(superseded?.correction);
97
+ strictEqual(entries.length, 3);
98
+ }
99
+ const active = board
100
+ .snapshot()
101
+ .flatMap((entry) => entry.decisions)
102
+ .filter((decision) => decision.status === "active");
103
+ strictEqual(active.length, 1);
104
+ const policy = active[0]?.value;
105
+ ok(policy);
106
+ const source =
107
+ scenario === "python-int"
108
+ ? fixture.source.replace("return tuple(idx)", "return tuple(int(value) for value in idx)")
109
+ : fixture.source;
110
+ writeFileSync(join(cwd, "index-policy.py"), source);
111
+ const before = grade(source, policy);
112
+ // The negative control deliberately commits the old failure to prove
113
+ // that valid attribution cannot make its implementation grade pass.
114
+ strictEqual(before.status, scenario === "old-numpy" ? 1 : 0, before.stderr);
115
+ if (scenario === "old-numpy") match(before.stderr, /active Python-int policy requires type\(value\) is int/u);
116
+ git(["add", "index-policy.py"]);
117
+ setCommitDecisionRefsProvider(() => activeDecisionRefs(board.snapshot()));
118
+ const managed = withManagedGitCommitAttributionEnvironment(env, { cwd, enabled: true });
119
+ strictEqual(managed.diagnostic, null);
120
+ operations.push("commit");
121
+ git(["-c", "commit.gpgSign=false", "commit", "--quiet", "-m", `fixture: ${scenario}`], managed.env as typeof env);
122
+ deepStrictEqual(
123
+ operations,
124
+ scenario === "explicit-revision" ? ["decision", "decision", "decision", "commit"] : ["decision", "commit"],
125
+ );
126
+ const commit = git(["rev-parse", "HEAD"]);
127
+ const message = git(["show", "-s", "--format=%B", commit]);
128
+ const trailers = message
129
+ .split("\n")
130
+ .filter((line) => line.startsWith("Clio-Decision: "))
131
+ .map((line) => line.slice("Clio-Decision: ".length));
132
+ deepStrictEqual(trailers, activeDecisionRefs(board.snapshot()));
133
+ if (scenario === "explicit-revision") ok(!trailers.includes(initialRefs[0] as string));
134
+ const after = grade(git(["show", `${commit}:index-policy.py`]), policy);
135
+ strictEqual(after.status, before.status);
136
+ strictEqual(after.pythonInts, scenario === "python-int");
137
+ process.stdout.write(
138
+ `${JSON.stringify({ evidence: "scripted-machinery", scenario, commit, policy, trailerValid: true, adherence: after.status === 0, ...after })}\n`,
139
+ );
140
+ }
141
+ } finally {
142
+ setCommitDecisionRefsProvider(null);
143
+ rmSync(root, { recursive: true, force: true });
144
+ restore();
145
+ }