xarray-spatial 0.9.9__tar.gz → 0.10.0__tar.gz

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 (519) hide show
  1. xarray_spatial-0.10.0/.claude/commands/deep-sweep.md +432 -0
  2. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.claude/commands/release-patch.md +38 -4
  3. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.claude/commands/review-pr.md +65 -2
  4. xarray_spatial-0.10.0/.claude/commands/rockout.md +374 -0
  5. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.claude/commands/sweep-accuracy.md +33 -0
  6. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.claude/commands/sweep-api-consistency.md +29 -0
  7. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.claude/commands/sweep-metadata.md +31 -0
  8. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.claude/commands/sweep-performance.md +33 -0
  9. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.claude/commands/sweep-security.md +34 -0
  10. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.claude/commands/sweep-test-coverage.md +32 -0
  11. xarray_spatial-0.10.0/.claude/sweep-accuracy-state.csv +36 -0
  12. xarray_spatial-0.10.0/.claude/sweep-api-consistency-state.csv +5 -0
  13. xarray_spatial-0.10.0/.claude/sweep-metadata-state.csv +5 -0
  14. xarray_spatial-0.10.0/.claude/sweep-performance-state.csv +47 -0
  15. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.claude/sweep-security-state.csv +4 -6
  16. xarray_spatial-0.10.0/.claude/sweep-style-state.csv +2 -0
  17. xarray_spatial-0.10.0/.claude/sweep-test-coverage-state.csv +7 -0
  18. xarray_spatial-0.10.0/.github/ISSUE_TEMPLATE/new-contributor.md +64 -0
  19. xarray_spatial-0.10.0/.github/workflows/copilot-review.yml +30 -0
  20. xarray_spatial-0.10.0/.github/workflows/test-cog-validator.yml +104 -0
  21. xarray_spatial-0.10.0/.github/workflows/test-geotiff-corpus.yml +84 -0
  22. xarray_spatial-0.10.0/.github/workflows/test.yml +52 -0
  23. xarray_spatial-0.10.0/.github/workflows/welcome-contributor.yml +64 -0
  24. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.gitignore +2 -0
  25. xarray_spatial-0.10.0/AI_POLICY.md +312 -0
  26. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/CHANGELOG.md +70 -0
  27. xarray_spatial-0.10.0/CONTRIBUTING.md +87 -0
  28. {xarray_spatial-0.9.9/xarray_spatial.egg-info → xarray_spatial-0.10.0}/PKG-INFO +210 -234
  29. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/README.md +197 -230
  30. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/setup.cfg +15 -3
  31. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0/xarray_spatial.egg-info}/PKG-INFO +210 -234
  32. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xarray_spatial.egg-info/SOURCES.txt +167 -24
  33. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xarray_spatial.egg-info/requires.txt +15 -3
  34. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/_version.py +3 -3
  35. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/accessor.py +71 -6
  36. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/balanced_allocation.py +1 -1
  37. xarray_spatial-0.10.0/xrspatial/geotiff/__init__.py +903 -0
  38. xarray_spatial-0.10.0/xrspatial/geotiff/_attrs.py +1744 -0
  39. xarray_spatial-0.10.0/xrspatial/geotiff/_backends/__init__.py +8 -0
  40. xarray_spatial-0.10.0/xrspatial/geotiff/_backends/_gpu_helpers.py +333 -0
  41. xarray_spatial-0.10.0/xrspatial/geotiff/_backends/dask.py +759 -0
  42. xarray_spatial-0.10.0/xrspatial/geotiff/_backends/gpu.py +1706 -0
  43. xarray_spatial-0.10.0/xrspatial/geotiff/_backends/vrt.py +1298 -0
  44. xarray_spatial-0.10.0/xrspatial/geotiff/_cog_http.py +1039 -0
  45. xarray_spatial-0.10.0/xrspatial/geotiff/_compression.py +1887 -0
  46. xarray_spatial-0.10.0/xrspatial/geotiff/_coords.py +811 -0
  47. xarray_spatial-0.10.0/xrspatial/geotiff/_crs.py +321 -0
  48. xarray_spatial-0.10.0/xrspatial/geotiff/_decode.py +915 -0
  49. xarray_spatial-0.10.0/xrspatial/geotiff/_dtypes.py +279 -0
  50. xarray_spatial-0.10.0/xrspatial/geotiff/_encode.py +674 -0
  51. xarray_spatial-0.10.0/xrspatial/geotiff/_errors.py +290 -0
  52. xarray_spatial-0.10.0/xrspatial/geotiff/_geotags.py +1704 -0
  53. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/geotiff/_gpu_decode.py +1015 -152
  54. xarray_spatial-0.10.0/xrspatial/geotiff/_header.py +924 -0
  55. xarray_spatial-0.10.0/xrspatial/geotiff/_layout.py +205 -0
  56. xarray_spatial-0.10.0/xrspatial/geotiff/_nodata.py +368 -0
  57. xarray_spatial-0.10.0/xrspatial/geotiff/_overview.py +505 -0
  58. xarray_spatial-0.10.0/xrspatial/geotiff/_overview_kernels.py +268 -0
  59. xarray_spatial-0.10.0/xrspatial/geotiff/_reader.py +429 -0
  60. xarray_spatial-0.10.0/xrspatial/geotiff/_runtime.py +150 -0
  61. xarray_spatial-0.10.0/xrspatial/geotiff/_safe_xml.py +108 -0
  62. xarray_spatial-0.10.0/xrspatial/geotiff/_sidecar.py +436 -0
  63. xarray_spatial-0.10.0/xrspatial/geotiff/_sources.py +1779 -0
  64. xarray_spatial-0.10.0/xrspatial/geotiff/_validation.py +1511 -0
  65. xarray_spatial-0.10.0/xrspatial/geotiff/_vrt.py +2244 -0
  66. xarray_spatial-0.10.0/xrspatial/geotiff/_vrt_validation.py +664 -0
  67. xarray_spatial-0.10.0/xrspatial/geotiff/_write_layout.py +711 -0
  68. xarray_spatial-0.10.0/xrspatial/geotiff/_writer.py +1320 -0
  69. xarray_spatial-0.10.0/xrspatial/geotiff/_writers/__init__.py +7 -0
  70. xarray_spatial-0.10.0/xrspatial/geotiff/_writers/eager.py +1393 -0
  71. xarray_spatial-0.10.0/xrspatial/geotiff/_writers/gpu.py +725 -0
  72. xarray_spatial-0.10.0/xrspatial/geotiff/_writers/vrt.py +227 -0
  73. xarray_spatial-0.10.0/xrspatial/geotiff/tests/_helpers/__init__.py +8 -0
  74. xarray_spatial-0.10.0/xrspatial/geotiff/tests/_helpers/markers.py +67 -0
  75. xarray_spatial-0.9.9/xrspatial/geotiff/tests/conftest.py → xarray_spatial-0.10.0/xrspatial/geotiff/tests/_helpers/tiff_builders.py +7 -36
  76. xarray_spatial-0.10.0/xrspatial/geotiff/tests/_helpers/tiff_surgery.py +75 -0
  77. xarray_spatial-0.10.0/xrspatial/geotiff/tests/attrs/test_contract.py +968 -0
  78. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/geotiff/tests/bench_vs_rioxarray.py +9 -5
  79. xarray_spatial-0.10.0/xrspatial/geotiff/tests/conftest.py +60 -0
  80. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/README.md +85 -0
  81. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/__init__.py +12 -0
  82. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/_marks.py +61 -0
  83. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/_oracle.py +709 -0
  84. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/cog_internal_overview_uint16.tif +0 -0
  85. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/compression_deflate_predictor2_uint16.tif +0 -0
  86. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/compression_deflate_predictor3_float32.tif +0 -0
  87. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/compression_jpeg_uint8_ycbcr.tif +0 -0
  88. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/compression_lerc_float32.tif +0 -0
  89. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/compression_lzw_predictor2_int16.tif +0 -0
  90. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/compression_none_uint8.tif +0 -0
  91. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/crs_citation_only.tif +0 -0
  92. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/crs_epsg_3857.tif +0 -0
  93. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/crs_wkt_utm10n.tif +0 -0
  94. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_float32.tif +0 -0
  95. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_float64.tif +0 -0
  96. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_int16.tif +0 -0
  97. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_int32.tif +0 -0
  98. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_int8.tif +0 -0
  99. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_uint16.tif +0 -0
  100. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_uint32.tif +0 -0
  101. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_uint8.tif +0 -0
  102. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/extra_tags_uint16.tif +0 -0
  103. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/gdal_metadata_namespaced_uint16.tif +0 -0
  104. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/nodata_int_sentinel_uint16.tif +0 -0
  105. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/nodata_miniswhite_uint8.tif +0 -0
  106. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/nodata_nan_float32.tif +0 -0
  107. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/overview_external_ovr_uint16.tif +0 -0
  108. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/overview_external_ovr_uint16.tif.ovr +0 -0
  109. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/overview_internal_uint16.tif +0 -0
  110. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/planar_separate_uint8_rgb.tif +0 -0
  111. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/sparse_tiled_uint16.tif +0 -0
  112. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/stripped_be_uint16.tif +0 -0
  113. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/stripped_le_uint16.tif +0 -0
  114. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/tiled_be_uint16.tif +0 -0
  115. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/fixtures/tiled_le_uint16.tif +0 -0
  116. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/generate.py +880 -0
  117. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/manifest.yaml +740 -0
  118. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/test_compression.py +247 -0
  119. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/test_corpus_determinism.py +419 -0
  120. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/test_dask_gpu.py +242 -0
  121. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/test_dask_numpy.py +233 -0
  122. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/test_dtype_variants.py +187 -0
  123. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/test_eager_numpy.py +204 -0
  124. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/test_fsspec.py +276 -0
  125. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/test_gpu.py +245 -0
  126. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/test_http.py +219 -0
  127. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/test_layout_endian.py +122 -0
  128. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/test_manifest.py +176 -0
  129. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/test_metadata_tags.py +270 -0
  130. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/test_nodata_sentinels.py +192 -0
  131. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/test_oracle.py +1432 -0
  132. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/test_overview_cog.py +281 -0
  133. xarray_spatial-0.10.0/xrspatial/geotiff/tests/golden_corpus/test_vrt.py +149 -0
  134. xarray_spatial-0.10.0/xrspatial/geotiff/tests/gpu/__init__.py +1 -0
  135. xarray_spatial-0.10.0/xrspatial/geotiff/tests/gpu/test_codec.py +1890 -0
  136. xarray_spatial-0.10.0/xrspatial/geotiff/tests/gpu/test_kernels_and_kwargs.py +3131 -0
  137. xarray_spatial-0.10.0/xrspatial/geotiff/tests/gpu/test_reader.py +1551 -0
  138. xarray_spatial-0.10.0/xrspatial/geotiff/tests/gpu/test_writer.py +2122 -0
  139. xarray_spatial-0.10.0/xrspatial/geotiff/tests/integration/test_dask_pipeline.py +1034 -0
  140. xarray_spatial-0.10.0/xrspatial/geotiff/tests/integration/test_gpu_pipeline.py +188 -0
  141. xarray_spatial-0.10.0/xrspatial/geotiff/tests/integration/test_http_sources.py +6311 -0
  142. xarray_spatial-0.10.0/xrspatial/geotiff/tests/integration/test_sidecar.py +1865 -0
  143. xarray_spatial-0.10.0/xrspatial/geotiff/tests/parity/__init__.py +0 -0
  144. xarray_spatial-0.10.0/xrspatial/geotiff/tests/parity/test_backend_matrix.py +2806 -0
  145. xarray_spatial-0.10.0/xrspatial/geotiff/tests/parity/test_finalization.py +1102 -0
  146. xarray_spatial-0.10.0/xrspatial/geotiff/tests/parity/test_pixel_equality.py +660 -0
  147. xarray_spatial-0.10.0/xrspatial/geotiff/tests/parity/test_reference.py +794 -0
  148. xarray_spatial-0.10.0/xrspatial/geotiff/tests/parity/test_signature_contract.py +388 -0
  149. xarray_spatial-0.10.0/xrspatial/geotiff/tests/read/__init__.py +1 -0
  150. xarray_spatial-0.10.0/xrspatial/geotiff/tests/read/test_basic.py +1756 -0
  151. xarray_spatial-0.10.0/xrspatial/geotiff/tests/read/test_compression.py +664 -0
  152. xarray_spatial-0.10.0/xrspatial/geotiff/tests/read/test_coords.py +1475 -0
  153. xarray_spatial-0.10.0/xrspatial/geotiff/tests/read/test_crs.py +625 -0
  154. xarray_spatial-0.10.0/xrspatial/geotiff/tests/read/test_dtypes.py +529 -0
  155. xarray_spatial-0.10.0/xrspatial/geotiff/tests/read/test_endianness.py +120 -0
  156. xarray_spatial-0.10.0/xrspatial/geotiff/tests/read/test_georef.py +2776 -0
  157. xarray_spatial-0.10.0/xrspatial/geotiff/tests/read/test_nodata.py +3380 -0
  158. xarray_spatial-0.10.0/xrspatial/geotiff/tests/read/test_overview.py +1087 -0
  159. xarray_spatial-0.10.0/xrspatial/geotiff/tests/read/test_streaming.py +226 -0
  160. xarray_spatial-0.10.0/xrspatial/geotiff/tests/read/test_tiling.py +1853 -0
  161. xarray_spatial-0.10.0/xrspatial/geotiff/tests/release_gates/__init__.py +8 -0
  162. {xarray_spatial-0.9.9/xrspatial/geotiff/tests → xarray_spatial-0.10.0/xrspatial/geotiff/tests/release_gates}/test_features.py +1278 -104
  163. xarray_spatial-0.10.0/xrspatial/geotiff/tests/release_gates/test_stable_features.py +2590 -0
  164. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/geotiff/tests/test_edge_cases.py +21 -19
  165. xarray_spatial-0.10.0/xrspatial/geotiff/tests/test_fuzz_hypothesis.py +431 -0
  166. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_polish_1488.py → xarray_spatial-0.10.0/xrspatial/geotiff/tests/test_polish.py +160 -21
  167. xarray_spatial-0.10.0/xrspatial/geotiff/tests/test_round_trip.py +1112 -0
  168. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/geotiff/tests/test_security.py +407 -30
  169. xarray_spatial-0.10.0/xrspatial/geotiff/tests/test_shutdown_cleanup_2486.py +163 -0
  170. xarray_spatial-0.10.0/xrspatial/geotiff/tests/unit/__init__.py +7 -0
  171. xarray_spatial-0.10.0/xrspatial/geotiff/tests/unit/test_codec_roundtrip.py +1360 -0
  172. xarray_spatial-0.10.0/xrspatial/geotiff/tests/unit/test_compression.py +336 -0
  173. xarray_spatial-0.10.0/xrspatial/geotiff/tests/unit/test_geotags.py +933 -0
  174. {xarray_spatial-0.9.9/xrspatial/geotiff/tests → xarray_spatial-0.10.0/xrspatial/geotiff/tests/unit}/test_header.py +121 -52
  175. xarray_spatial-0.10.0/xrspatial/geotiff/tests/unit/test_ifd.py +1423 -0
  176. xarray_spatial-0.10.0/xrspatial/geotiff/tests/unit/test_input_validation.py +1772 -0
  177. xarray_spatial-0.10.0/xrspatial/geotiff/tests/unit/test_metadata.py +1820 -0
  178. xarray_spatial-0.10.0/xrspatial/geotiff/tests/unit/test_photometric.py +844 -0
  179. xarray_spatial-0.10.0/xrspatial/geotiff/tests/unit/test_predictor.py +1242 -0
  180. xarray_spatial-0.10.0/xrspatial/geotiff/tests/unit/test_safe_xml.py +350 -0
  181. xarray_spatial-0.10.0/xrspatial/geotiff/tests/unit/test_signatures.py +3252 -0
  182. xarray_spatial-0.10.0/xrspatial/geotiff/tests/vrt/__init__.py +1 -0
  183. xarray_spatial-0.10.0/xrspatial/geotiff/tests/vrt/test_dtype_conversion.py +1354 -0
  184. xarray_spatial-0.10.0/xrspatial/geotiff/tests/vrt/test_metadata.py +1818 -0
  185. xarray_spatial-0.10.0/xrspatial/geotiff/tests/vrt/test_missing_sources.py +888 -0
  186. xarray_spatial-0.10.0/xrspatial/geotiff/tests/vrt/test_parity.py +1147 -0
  187. xarray_spatial-0.10.0/xrspatial/geotiff/tests/vrt/test_validation.py +1894 -0
  188. xarray_spatial-0.10.0/xrspatial/geotiff/tests/vrt/test_window.py +1305 -0
  189. xarray_spatial-0.10.0/xrspatial/geotiff/tests/write/__init__.py +0 -0
  190. xarray_spatial-0.10.0/xrspatial/geotiff/tests/write/test_basic.py +2617 -0
  191. xarray_spatial-0.10.0/xrspatial/geotiff/tests/write/test_bigtiff.py +580 -0
  192. xarray_spatial-0.10.0/xrspatial/geotiff/tests/write/test_cog.py +2273 -0
  193. xarray_spatial-0.10.0/xrspatial/geotiff/tests/write/test_crs.py +1136 -0
  194. xarray_spatial-0.10.0/xrspatial/geotiff/tests/write/test_nodata.py +767 -0
  195. xarray_spatial-0.10.0/xrspatial/geotiff/tests/write/test_overview.py +2679 -0
  196. xarray_spatial-0.10.0/xrspatial/geotiff/tests/write/test_streaming.py +1157 -0
  197. xarray_spatial-0.10.0/xrspatial/hydro/tests/__init__.py +0 -0
  198. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/polygonize.py +384 -92
  199. xarray_spatial-0.10.0/xrspatial/rasterize.py +3338 -0
  200. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/__init__.py +685 -87
  201. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/_crs_utils.py +62 -3
  202. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/_grid.py +95 -7
  203. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/_itrf.py +40 -4
  204. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/_vertical.py +36 -9
  205. xarray_spatial-0.10.0/xrspatial/tests/__init__.py +0 -0
  206. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/bench_reproject_vs_rioxarray.py +2 -2
  207. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_accessor.py +74 -0
  208. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_focal.py +22 -49
  209. xarray_spatial-0.10.0/xrspatial/tests/test_optional_shapely.py +81 -0
  210. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_polygonize.py +416 -0
  211. xarray_spatial-0.10.0/xrspatial/tests/test_polygonize_coverage_2026_05_19.py +713 -0
  212. xarray_spatial-0.10.0/xrspatial/tests/test_polygonize_issue_2172.py +254 -0
  213. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_rasterize.py +937 -0
  214. xarray_spatial-0.10.0/xrspatial/tests/test_rasterize_all_touched_supercover_2169.py +197 -0
  215. xarray_spatial-0.10.0/xrspatial/tests/test_rasterize_coverage_2026_05_17.py +604 -0
  216. xarray_spatial-0.10.0/xrspatial/tests/test_rasterize_coverage_2026_05_21.py +494 -0
  217. xarray_spatial-0.10.0/xrspatial/tests/test_rasterize_gpu_race_2167.py +231 -0
  218. xarray_spatial-0.10.0/xrspatial/tests/test_rasterize_nan_propagation_2255.py +161 -0
  219. xarray_spatial-0.10.0/xrspatial/tests/test_rasterize_signature_annot_2250.py +45 -0
  220. xarray_spatial-0.10.0/xrspatial/tests/test_rasterize_tile_props_slice_2020.py +269 -0
  221. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_reproject.py +2537 -23
  222. xarray_spatial-0.9.9/.claude/commands/rockout.md +0 -103
  223. xarray_spatial-0.9.9/.claude/sweep-accuracy-state.csv +0 -36
  224. xarray_spatial-0.9.9/.claude/sweep-api-consistency-state.csv +0 -1
  225. xarray_spatial-0.9.9/.claude/sweep-metadata-state.csv +0 -1
  226. xarray_spatial-0.9.9/.claude/sweep-performance-state.csv +0 -47
  227. xarray_spatial-0.9.9/.claude/sweep-test-coverage-state.csv +0 -1
  228. xarray_spatial-0.9.9/.github/workflows/test.yml +0 -31
  229. xarray_spatial-0.9.9/CONTRIBUTING.md +0 -48
  230. xarray_spatial-0.9.9/xrspatial/geotiff/__init__.py +0 -1804
  231. xarray_spatial-0.9.9/xrspatial/geotiff/_compression.py +0 -971
  232. xarray_spatial-0.9.9/xrspatial/geotiff/_dtypes.py +0 -136
  233. xarray_spatial-0.9.9/xrspatial/geotiff/_geotags.py +0 -715
  234. xarray_spatial-0.9.9/xrspatial/geotiff/_header.py +0 -456
  235. xarray_spatial-0.9.9/xrspatial/geotiff/_reader.py +0 -941
  236. xarray_spatial-0.9.9/xrspatial/geotiff/_vrt.py +0 -521
  237. xarray_spatial-0.9.9/xrspatial/geotiff/_writer.py +0 -1530
  238. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_accessor_io.py +0 -166
  239. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_accuracy_1081.py +0 -292
  240. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_cog.py +0 -379
  241. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_cog_http_concurrent.py +0 -180
  242. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_compression.py +0 -129
  243. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_compression_level.py +0 -171
  244. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_dtype_read.py +0 -117
  245. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_georef_edges.py +0 -157
  246. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_geotags.py +0 -255
  247. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_jpeg.py +0 -151
  248. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_jpeg2000.py +0 -186
  249. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_lerc.py +0 -160
  250. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_lz4.py +0 -137
  251. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_metadata_round_trip_1484.py +0 -418
  252. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_predictor_fp_write_1313.py +0 -203
  253. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_predictor_multisample.py +0 -448
  254. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_reader.py +0 -185
  255. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_streaming_write.py +0 -334
  256. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_vrt_write.py +0 -111
  257. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_writer.py +0 -104
  258. xarray_spatial-0.9.9/xrspatial/geotiff/tests/test_writer_matrix.py +0 -253
  259. xarray_spatial-0.9.9/xrspatial/rasterize.py +0 -2232
  260. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.claude/commands/backend-parity.md +0 -0
  261. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.claude/commands/bench.md +0 -0
  262. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.claude/commands/dask-notebook.md +0 -0
  263. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.claude/commands/efficiency-audit.md +0 -0
  264. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.claude/commands/new-issues.md +0 -0
  265. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.claude/commands/release-major.md +0 -0
  266. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.claude/commands/release-minor.md +0 -0
  267. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.claude/commands/user-guide-notebook.md +0 -0
  268. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.claude/commands/validate.md +0 -0
  269. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.efficiency-audit-baseline.json +0 -0
  270. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.efficiency-audit-baseline.prev.json +0 -0
  271. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.gitattributes +0 -0
  272. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  273. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.github/ISSUE_TEMPLATE/feature-proposal.md +0 -0
  274. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.github/labeler.yml +0 -0
  275. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.github/pull_request_template.md +0 -0
  276. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.github/workflows/benchmarks.yml +0 -0
  277. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.github/workflows/labeler.yml +0 -0
  278. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.github/workflows/pypi-publish.yml +0 -0
  279. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/.readthedocs.yml +0 -0
  280. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/CODE_OF_CONDUCT.md +0 -0
  281. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/Citation-styles.md +0 -0
  282. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/LICENSE.txt +0 -0
  283. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/MANIFEST.in +0 -0
  284. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/RELEASE.md +0 -0
  285. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/codecov.yml +0 -0
  286. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/pyproject.toml +0 -0
  287. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/setup.py +0 -0
  288. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xarray_spatial.egg-info/dependency_links.txt +0 -0
  289. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xarray_spatial.egg-info/entry_points.txt +0 -0
  290. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xarray_spatial.egg-info/not-zip-safe +0 -0
  291. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xarray_spatial.egg-info/top_level.txt +0 -0
  292. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/__init__.py +0 -0
  293. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/__main__.py +0 -0
  294. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/analytics.py +0 -0
  295. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/aspect.py +0 -0
  296. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/bilateral.py +0 -0
  297. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/bump.py +0 -0
  298. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/classify.py +0 -0
  299. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/contour.py +0 -0
  300. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/convolution.py +0 -0
  301. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/corridor.py +0 -0
  302. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/cost_distance.py +0 -0
  303. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/curvature.py +0 -0
  304. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/dasymetric.py +0 -0
  305. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/dataset_support.py +0 -0
  306. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/datasets/__init__.py +0 -0
  307. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/datasets/sentinel-2/blue_band.nc +0 -0
  308. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/datasets/sentinel-2/green_band.nc +0 -0
  309. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/datasets/sentinel-2/nir_band.nc +0 -0
  310. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/datasets/sentinel-2/red_band.nc +0 -0
  311. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/datasets/sentinel-2/swir1_band.nc +0 -0
  312. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/datasets/sentinel-2/swir2_band.nc +0 -0
  313. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/diagnostics.py +0 -0
  314. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/diffusion.py +0 -0
  315. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/edge_detection.py +0 -0
  316. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/emerging_hotspots.py +0 -0
  317. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/erosion.py +0 -0
  318. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/experimental/__init__.py +0 -0
  319. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/experimental/min_observable_height.py +0 -0
  320. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/fire.py +0 -0
  321. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/flood.py +0 -0
  322. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/focal.py +0 -0
  323. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/geodesic.py +0 -0
  324. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/geotiff/tests/__init__.py +0 -0
  325. {xarray_spatial-0.9.9/xrspatial/hydro/tests → xarray_spatial-0.10.0/xrspatial/geotiff/tests/attrs}/__init__.py +0 -0
  326. {xarray_spatial-0.9.9/xrspatial/tests → xarray_spatial-0.10.0/xrspatial/geotiff/tests/integration}/__init__.py +0 -0
  327. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/glcm.py +0 -0
  328. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/gpu_rtx/__init__.py +0 -0
  329. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/gpu_rtx/_memory.py +0 -0
  330. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/gpu_rtx/cuda_utils.py +0 -0
  331. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/gpu_rtx/hillshade.py +0 -0
  332. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/gpu_rtx/mesh_utils.py +0 -0
  333. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/gpu_rtx/viewshed.py +0 -0
  334. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hillshade.py +0 -0
  335. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/__init__.py +0 -0
  336. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/_boundary_store.py +0 -0
  337. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/basin_d8.py +0 -0
  338. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/fill_d8.py +0 -0
  339. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/flow_accumulation_d8.py +0 -0
  340. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/flow_accumulation_dinf.py +0 -0
  341. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/flow_accumulation_mfd.py +0 -0
  342. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/flow_direction_d8.py +0 -0
  343. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/flow_direction_dinf.py +0 -0
  344. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/flow_direction_mfd.py +0 -0
  345. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/flow_length_d8.py +0 -0
  346. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/flow_length_dinf.py +0 -0
  347. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/flow_length_mfd.py +0 -0
  348. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/flow_path_d8.py +0 -0
  349. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/flow_path_dinf.py +0 -0
  350. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/flow_path_mfd.py +0 -0
  351. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/hand_d8.py +0 -0
  352. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/hand_dinf.py +0 -0
  353. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/hand_mfd.py +0 -0
  354. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/sink_d8.py +0 -0
  355. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/snap_pour_point_d8.py +0 -0
  356. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/stream_link_d8.py +0 -0
  357. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/stream_link_dinf.py +0 -0
  358. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/stream_link_mfd.py +0 -0
  359. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/stream_order_d8.py +0 -0
  360. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/stream_order_dinf.py +0 -0
  361. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/stream_order_mfd.py +0 -0
  362. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/conftest.py +0 -0
  363. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_basin_d8.py +0 -0
  364. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_fill_d8.py +0 -0
  365. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_flow_accumulation_d8.py +0 -0
  366. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_flow_accumulation_dinf.py +0 -0
  367. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_flow_accumulation_mfd.py +0 -0
  368. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_flow_direction_d8.py +0 -0
  369. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_flow_direction_dinf.py +0 -0
  370. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_flow_direction_mfd.py +0 -0
  371. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_flow_length_d8.py +0 -0
  372. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_flow_length_dinf.py +0 -0
  373. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_flow_length_mfd.py +0 -0
  374. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_flow_path_d8.py +0 -0
  375. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_flow_path_dinf.py +0 -0
  376. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_flow_path_mfd.py +0 -0
  377. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_hand_d8.py +0 -0
  378. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_hand_dinf.py +0 -0
  379. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_hand_mfd.py +0 -0
  380. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_sink_d8.py +0 -0
  381. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_snap_pour_point_d8.py +0 -0
  382. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_stream_link_d8.py +0 -0
  383. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_stream_link_dinf.py +0 -0
  384. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_stream_link_mfd.py +0 -0
  385. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_stream_order_d8.py +0 -0
  386. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_stream_order_dinf.py +0 -0
  387. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_stream_order_mfd.py +0 -0
  388. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_twi_d8.py +0 -0
  389. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_validate_cellsize.py +0 -0
  390. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_validate_scalar_params.py +0 -0
  391. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_validate_secondary_args.py +0 -0
  392. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_watershed_d8.py +0 -0
  393. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_watershed_dinf.py +0 -0
  394. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/tests/test_watershed_mfd.py +0 -0
  395. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/twi_d8.py +0 -0
  396. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/watershed_d8.py +0 -0
  397. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/watershed_dinf.py +0 -0
  398. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/hydro/watershed_mfd.py +0 -0
  399. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/interpolate/__init__.py +0 -0
  400. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/interpolate/_idw.py +0 -0
  401. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/interpolate/_kriging.py +0 -0
  402. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/interpolate/_spline.py +0 -0
  403. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/interpolate/_validation.py +0 -0
  404. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/kde.py +0 -0
  405. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/mahalanobis.py +0 -0
  406. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/mcda/__init__.py +0 -0
  407. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/mcda/combine.py +0 -0
  408. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/mcda/constrain.py +0 -0
  409. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/mcda/sensitivity.py +0 -0
  410. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/mcda/standardize.py +0 -0
  411. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/mcda/weights.py +0 -0
  412. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/morphology.py +0 -0
  413. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/multispectral.py +0 -0
  414. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/normalize.py +0 -0
  415. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/pathfinding.py +0 -0
  416. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/perlin.py +0 -0
  417. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/polygon_clip.py +0 -0
  418. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/preview.py +0 -0
  419. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/proximity.py +0 -0
  420. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/_datum_grids.py +0 -0
  421. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/_interpolate.py +0 -0
  422. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/_lite_crs.py +0 -0
  423. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/_merge.py +0 -0
  424. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/_projections.py +0 -0
  425. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/_projections_cuda.py +0 -0
  426. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/_transform.py +0 -0
  427. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/grids/at_bev_AT_GIS_GRID.tif +0 -0
  428. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/grids/au_icsm_A66_National_13_09_01.tif +0 -0
  429. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/grids/be_ign_bd72lb72_etrs89lb08.tif +0 -0
  430. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/grids/ch_swisstopo_CHENyx06_ETRS.tif +0 -0
  431. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/grids/de_adv_BETA2007.tif +0 -0
  432. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/grids/es_ign_SPED2ETV2.tif +0 -0
  433. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/grids/nl_nsgi_rdcorr2018.tif +0 -0
  434. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/grids/pt_dgt_D73_ETRS89_geo.tif +0 -0
  435. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/grids/uk_os_OSTN15_NTv2_OSGBtoETRS.tif +0 -0
  436. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/grids/us_nga_egm96_15.tif +0 -0
  437. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/grids/us_noaa_alaska.tif +0 -0
  438. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/grids/us_noaa_conus.tif +0 -0
  439. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/grids/us_noaa_hawaii.tif +0 -0
  440. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/grids/us_noaa_nadcon5_nad27_nad83_1986_conus.tif +0 -0
  441. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/reproject/grids/us_noaa_prvi.tif +0 -0
  442. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/resample.py +0 -0
  443. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/sieve.py +0 -0
  444. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/sky_view_factor.py +0 -0
  445. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/slope.py +0 -0
  446. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/surface_distance.py +0 -0
  447. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/terrain.py +0 -0
  448. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/terrain_metrics.py +0 -0
  449. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/conftest.py +0 -0
  450. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/general_checks.py +0 -0
  451. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_analytics.py +0 -0
  452. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_aspect.py +0 -0
  453. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_balanced_allocation.py +0 -0
  454. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_bilateral.py +0 -0
  455. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_bump.py +0 -0
  456. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_classify.py +0 -0
  457. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_contour.py +0 -0
  458. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_convolution.py +0 -0
  459. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_corridor.py +0 -0
  460. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_cost_distance.py +0 -0
  461. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_curvature.py +0 -0
  462. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_dask_cupy_gaps.py +0 -0
  463. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_dask_laziness.py +0 -0
  464. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_dasymetric.py +0 -0
  465. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_dataset_support.py +0 -0
  466. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_datasets.py +0 -0
  467. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_diagnostics.py +0 -0
  468. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_diffusion.py +0 -0
  469. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_edge_detection.py +0 -0
  470. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_emerging_hotspots.py +0 -0
  471. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_erosion.py +0 -0
  472. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_fire.py +0 -0
  473. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_flood.py +0 -0
  474. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_fused_overlap.py +0 -0
  475. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_geodesic_aspect.py +0 -0
  476. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_geodesic_slope.py +0 -0
  477. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_glcm.py +0 -0
  478. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_glcm_metric_order.py +0 -0
  479. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_gpu_rtx_memory.py +0 -0
  480. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_gpu_rtx_mesh.py +0 -0
  481. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_hillshade.py +0 -0
  482. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_hypsometric_integral.py +0 -0
  483. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_interpolation.py +0 -0
  484. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_kde.py +0 -0
  485. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_lite_crs.py +0 -0
  486. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_mahalanobis.py +0 -0
  487. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_mcda.py +0 -0
  488. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_min_observable_height.py +0 -0
  489. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_morphology.py +0 -0
  490. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_morphology_derived.py +0 -0
  491. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_multi_overlap.py +0 -0
  492. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_multispectral.py +0 -0
  493. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_normalize.py +0 -0
  494. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_northness_eastness.py +0 -0
  495. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_pathfinding.py +0 -0
  496. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_perlin.py +0 -0
  497. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_polygon_clip.py +0 -0
  498. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_preview.py +0 -0
  499. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_proximity.py +0 -0
  500. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_rasterize_accuracy.py +0 -0
  501. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_rechunk_no_shuffle.py +0 -0
  502. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_resample.py +0 -0
  503. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_sieve.py +0 -0
  504. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_sieve_gdal_parity.py +0 -0
  505. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_sky_view_factor.py +0 -0
  506. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_slope.py +0 -0
  507. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_surface_distance.py +0 -0
  508. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_terrain.py +0 -0
  509. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_terrain_metrics.py +0 -0
  510. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_utils.py +0 -0
  511. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_validation.py +0 -0
  512. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_viewshed.py +0 -0
  513. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_visibility.py +0 -0
  514. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/tests/test_zonal.py +0 -0
  515. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/utils.py +0 -0
  516. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/viewshed.py +0 -0
  517. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/visibility.py +0 -0
  518. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/worley.py +0 -0
  519. {xarray_spatial-0.9.9 → xarray_spatial-0.10.0}/xrspatial/zonal.py +0 -0
@@ -0,0 +1,432 @@
1
+ # Deep Sweep: Run every sweep-* command focused on a single module
2
+
3
+ Pick one xrspatial module and dispatch every `/sweep-*` command at it in
4
+ parallel. Each sub-sweep follows the audit template embedded in its own
5
+ `.claude/commands/sweep-*.md` file, runs `/rockout` for HIGH/MEDIUM findings
6
+ when the sweep specifies it, and updates its own
7
+ `.claude/sweep-{type}-state.csv` row for the target module.
8
+
9
+ New sweeps are picked up automatically. Drop a
10
+ `.claude/commands/sweep-XYZ.md` into the commands directory and the next
11
+ `/deep-sweep` run will dispatch it alongside the others.
12
+
13
+ Required first argument: the module name (e.g. `geotiff`, `slope`, `hydro`).
14
+ Optional flags: $ARGUMENTS
15
+ (e.g. `geotiff --only-sweep security,performance`,
16
+ `viewshed --exclude-sweep test-coverage`,
17
+ `slope --no-fix`,
18
+ `reproject --reset-state`)
19
+
20
+ ---
21
+
22
+ ## Step 0 -- Parse arguments and snapshot main-checkout state
23
+
24
+ The first positional token in `$ARGUMENTS` is the module name. It is
25
+ required. If `$ARGUMENTS` is empty or starts with a flag, stop and ask the
26
+ user which module to deep-sweep.
27
+
28
+ Capture the main checkout's branch as `DEEP_SWEEP_START_BRANCH` so Step
29
+ 5.5 can verify the sweeps left it untouched:
30
+
31
+ ```bash
32
+ DEEP_SWEEP_START_BRANCH="$(git -C $(git rev-parse --show-toplevel) branch --show-current)"
33
+ ```
34
+
35
+ If the main checkout has uncommitted changes when /deep-sweep starts,
36
+ note them. Step 5.5 will diff against this snapshot, not the empty
37
+ state, so existing dirtiness is not mistaken for a sweep breach.
38
+
39
+ Then parse flags (multiple may combine):
40
+
41
+ | Flag | Effect |
42
+ |------|--------|
43
+ | `--only-sweep s1,s2` | Only dispatch the named sweeps. Names are the suffix after `sweep-` (e.g. `security`, `performance`, `api-consistency`). |
44
+ | `--exclude-sweep s1,s2` | Skip the named sweeps. |
45
+ | `--no-fix` | Pass `--no-fix` semantics to every dispatched sweep: subagent audits only, no `/rockout`, no PR. State CSV is still updated. |
46
+ | `--reset-state` | Before dispatching, delete the target module's row from every `.claude/sweep-*-state.csv` so the audit is treated as never-inspected. Do NOT delete other modules' rows. |
47
+
48
+ ## Step 1 -- Validate the module
49
+
50
+ Determine the module's files under `xrspatial/`:
51
+
52
+ - If `xrspatial/{module}.py` exists, the module is a single file at that path.
53
+ - Else if `xrspatial/{module}/` is a directory, the module is a subpackage.
54
+ List all `.py` files under it (excluding `__init__.py`).
55
+ - Otherwise, stop and report that `{module}` was not found, listing the
56
+ available top-level `.py` files and subpackage directories under
57
+ `xrspatial/` so the user can correct the name.
58
+
59
+ Skip names that the individual sweeps already exclude from their discovery:
60
+ `__init__`, `_version`, `__main__`, `utils`, `accessor`, `preview`,
61
+ `dataset_support`, `diagnostics`, `analytics`. If the user passes one of
62
+ these, stop and explain that these modules are not in scope for the
63
+ per-module sweeps.
64
+
65
+ ## Step 2 -- Discover sweep commands
66
+
67
+ List all files matching `.claude/commands/sweep-*.md`. For each, the sweep
68
+ name is the basename without `sweep-` prefix and `.md` suffix
69
+ (e.g. `.claude/commands/sweep-security.md` → `security`). Build the list
70
+ in sorted order so the dispatch table is deterministic.
71
+
72
+ Apply `--only-sweep` / `--exclude-sweep` filters. If the resulting list is
73
+ empty, stop and report which filters eliminated everything.
74
+
75
+ For each remaining sweep, record:
76
+ - `sweep_name` (e.g. `security`)
77
+ - `sweep_file` (path to the `.md`)
78
+ - `state_file` (`.claude/sweep-{sweep_name}-state.csv`)
79
+
80
+ ## Step 3 -- Gather shared module metadata
81
+
82
+ Collect once and pass to every subagent (each sweep file lists the metadata
83
+ it needs; the union below covers all current sweeps):
84
+
85
+ | Field | How |
86
+ |-------|-----|
87
+ | **module_files** | from Step 1 |
88
+ | **last_modified** | `git log -1 --format=%aI -- <path>` (for subpackages, most recent file) |
89
+ | **total_commits** | `git log --oneline -- <path> \| wc -l` |
90
+ | **loc** | `wc -l < <path>` (for subpackages, sum all files) |
91
+ | **has_cuda_kernels** | grep file(s) for `@cuda.jit` |
92
+ | **has_file_io** | grep file(s) for `open(`, `mkstemp`, `os.path`, `pathlib` |
93
+ | **has_numba_jit** | grep file(s) for `@ngjit`, `@njit`, `@jit`, `numba.jit` |
94
+ | **allocates_from_dims** | grep file(s) for `np.empty(height`, `np.zeros(height`, `np.empty(H`, `cp.empty(`, and width variants |
95
+ | **has_shared_memory** | grep file(s) for `cuda.shared.array` |
96
+ | **has_dask_backend** | grep file(s) for `_run_dask`, `map_overlap`, `map_blocks` |
97
+ | **has_cuda_backend** | grep file(s) for `@cuda.jit`, `import cupy` |
98
+
99
+ Also detect CUDA availability once:
100
+
101
+ ```bash
102
+ python -c "from numba import cuda; print(cuda.is_available())" 2>/dev/null
103
+ ```
104
+
105
+ Capture as `CUDA_AVAILABLE` (`true` / `false`).
106
+
107
+ ## Step 4 -- Handle `--reset-state`
108
+
109
+ If `--reset-state` was passed, for each state file in scope:
110
+
111
+ ```python
112
+ import csv
113
+ from pathlib import Path
114
+
115
+ path = Path("{state_file}")
116
+ if not path.exists():
117
+ continue
118
+ with path.open() as f:
119
+ reader = csv.DictReader(f)
120
+ header = reader.fieldnames
121
+ rows = [r for r in reader if r["module"] != "{module}"]
122
+ with path.open("w", newline="") as f:
123
+ w = csv.DictWriter(f, fieldnames=header, quoting=csv.QUOTE_MINIMAL)
124
+ w.writeheader()
125
+ for r in rows:
126
+ w.writerow(r)
127
+ ```
128
+
129
+ This removes only the target module's row from each state file, leaving
130
+ other modules' history intact. Do this before dispatching the subagents so
131
+ they each see a clean slate for this module.
132
+
133
+ ## Step 5 -- Dispatch one subagent per sweep, in parallel
134
+
135
+ Print a short dispatch table:
136
+
137
+ ```
138
+ Deep-sweeping module "{module}" across {N} sweeps:
139
+ - security → .claude/sweep-security-state.csv
140
+ - performance → .claude/sweep-performance-state.csv
141
+ - accuracy → .claude/sweep-accuracy-state.csv
142
+ ...
143
+ ```
144
+
145
+ Then in a **single message**, launch one Agent per sweep with
146
+ `isolation: "worktree"` and `mode: "auto"` so they run concurrently in
147
+ separate worktrees. Use the prompt template below for every agent,
148
+ substituting `{sweep_name}`, `{sweep_file}`, `{state_file}`, `{module}`,
149
+ `{module_files}`, `{loc}`, `{commits}`, `{cuda_available}`, `{today}`, and
150
+ the boolean metadata flags. The `{today}` value is critical: it's woven
151
+ into the deterministic branch name `deep-sweep-{sweep_name}-{module}-{today}`
152
+ that each sibling rebases its worktree onto, and the parent later checks
153
+ those names for uniqueness.
154
+
155
+ ### Subagent prompt template
156
+
157
+ ```
158
+ You are running ONE specific sweep -- "{sweep_name}" -- against a single
159
+ xrspatial module: "{module}".
160
+
161
+ The parent command (/deep-sweep) has already chosen this module and is
162
+ dispatching every sweep against it in parallel. Your job is to behave
163
+ exactly as the embedded subagent prompt in
164
+ .claude/commands/sweep-{sweep_name}.md would, but skip module discovery
165
+ and scoring -- the module is already chosen.
166
+
167
+ ## WORKTREE ISOLATION CONTRACT (read first, enforce throughout)
168
+
169
+ You were dispatched with `isolation: "worktree"`. That means a dedicated
170
+ git worktree was created for you, and your CWD at launch IS that
171
+ worktree directory. Several parallel siblings are running the other
172
+ sweeps against the same module right now. If you operate outside your
173
+ worktree, you will collide with them and your commits will land on the
174
+ wrong branch.
175
+
176
+ **Step ISO-1 (run BEFORE anything else, before reading any sweep file):**
177
+
178
+ ```bash
179
+ DEEP_SWEEP_WT="$(pwd)"
180
+ DEEP_SWEEP_TOP="$(git rev-parse --show-toplevel)"
181
+ DEEP_SWEEP_BRANCH="$(git branch --show-current)"
182
+ echo "wt=$DEEP_SWEEP_WT top=$DEEP_SWEEP_TOP branch=$DEEP_SWEEP_BRANCH"
183
+ ```
184
+
185
+ Assert ALL of the following. If any fails, STOP immediately, do NOT
186
+ make any commits, and report exactly `WORKTREE_ISOLATION_FAILED:
187
+ <reason>` back to the parent:
188
+
189
+ - `$DEEP_SWEEP_WT` equals `$DEEP_SWEEP_TOP` (you are at the worktree
190
+ root, not in a subdirectory of some other checkout).
191
+ - `$DEEP_SWEEP_TOP` contains the segment `.claude/worktrees/agent-`
192
+ (you are inside an isolated worktree, not the user's main checkout).
193
+ - `$DEEP_SWEEP_BRANCH` is NOT `main` and NOT `master`.
194
+ - `$DEEP_SWEEP_BRANCH` does NOT already match a branch created by
195
+ another deep-sweep sibling. Specifically, reject branches matching
196
+ `deep-sweep-*-{module}-*` whose `{sweep_name}` segment is NOT
197
+ "{sweep_name}". (If you find yourself on a sibling's branch, the
198
+ Agent harness has handed you the wrong worktree -- bail out.)
199
+
200
+ **Step ISO-2 (immediately after ISO-1, before any audit work):**
201
+
202
+ Rename your branch to a deterministic, sweep-specific name so /rockout
203
+ calls and state-CSV commits cannot collide with siblings:
204
+
205
+ ```bash
206
+ DEEP_SWEEP_TARGET_BRANCH="deep-sweep-{sweep_name}-{module}-{today}"
207
+ if [ "$DEEP_SWEEP_BRANCH" != "$DEEP_SWEEP_TARGET_BRANCH" ]; then
208
+ git branch -m "$DEEP_SWEEP_TARGET_BRANCH"
209
+ DEEP_SWEEP_BRANCH="$DEEP_SWEEP_TARGET_BRANCH"
210
+ fi
211
+ ```
212
+
213
+ From this point on, every git operation (add, commit, push,
214
+ checkout, rebase) MUST be executed from `$DEEP_SWEEP_WT`. Do NOT use
215
+ absolute paths into the user's main checkout. Do NOT `cd` away from
216
+ `$DEEP_SWEEP_WT`. If a tool resolves an absolute path back to the
217
+ main checkout (e.g. `/home/.../xarray-spatial-contrib/...`), pass the
218
+ worktree-relative path instead.
219
+
220
+ **Step ISO-3 (before EVERY commit you make, parent or /rockout-driven):**
221
+
222
+ Re-check that you are still on the right branch in the right
223
+ directory. /rockout in particular may switch branches; if so, it
224
+ must do so from within `$DEEP_SWEEP_WT` and the new branch name
225
+ must start with `deep-sweep-{sweep_name}-{module}-` (use
226
+ `--branch-prefix` or equivalent if /rockout exposes one; otherwise
227
+ create your /rockout branches manually from
228
+ `$DEEP_SWEEP_TARGET_BRANCH` rather than letting /rockout pick a
229
+ plain `issue-NNNN` name that could collide):
230
+
231
+ ```bash
232
+ [ "$(pwd)" = "$DEEP_SWEEP_WT" ] || { echo "CWD drift"; exit 1; }
233
+ case "$(git branch --show-current)" in
234
+ deep-sweep-{sweep_name}-{module}-*) : ;;
235
+ *) echo "branch drift: $(git branch --show-current)"; exit 1 ;;
236
+ esac
237
+ ```
238
+
239
+ A failed re-check is an isolation breach. Stop, do not commit, and
240
+ report back.
241
+
242
+ **Step ISO-4 (when filing PRs):**
243
+
244
+ If /rockout produces one or more PRs, every PR must be pushed from a
245
+ branch matching `deep-sweep-{sweep_name}-{module}-*`. Do NOT push to
246
+ `main`. Do NOT push to a sibling's branch name. If the sweep template
247
+ mandates one PR per finding (e.g. security: one fix per PR), use
248
+ suffixes like `deep-sweep-{sweep_name}-{module}-{today}-01`,
249
+ `-02`, etc., all branched off `$DEEP_SWEEP_TARGET_BRANCH`.
250
+
251
+ ## Bootstrapping steps (after ISO-1 / ISO-2 pass)
252
+
253
+ 1. Read the sweep definition: {sweep_file}
254
+
255
+ Inside it, locate the "subagent prompt template" (a fenced block under
256
+ a heading like "Step 5b" or "Step 3b" titled "Launch subagents"). That
257
+ block is what an individual sweep dispatches to its own audit workers.
258
+ You are going to act as that worker for module "{module}".
259
+
260
+ 2. Pre-collected metadata for "{module}":
261
+
262
+ - module_files : {module_files}
263
+ - loc : {loc}
264
+ - total_commits : {commits}
265
+ - last_modified : {last_modified}
266
+ - has_cuda_kernels : {has_cuda_kernels}
267
+ - has_file_io : {has_file_io}
268
+ - has_numba_jit : {has_numba_jit}
269
+ - allocates_from_dims: {allocates_from_dims}
270
+ - has_shared_memory : {has_shared_memory}
271
+ - has_dask_backend : {has_dask_backend}
272
+ - has_cuda_backend : {has_cuda_backend}
273
+ - CUDA_AVAILABLE : {cuda_available}
274
+
275
+ Use only the fields the sweep's template actually references. Ignore
276
+ ones it does not mention.
277
+
278
+ 3. Follow the sweep's embedded subagent prompt verbatim against this
279
+ module. That means:
280
+
281
+ - Read every file the template tells you to read (module files, utils,
282
+ tests, general_checks.py, etc.).
283
+ - Run every audit category the template lists. Only flag issues
284
+ ACTUALLY present in the code -- false positives are worse than
285
+ missed issues.
286
+ - If the template instructs the worker to run /rockout for
287
+ HIGH/MEDIUM findings, do so {fix_mode_note}, observing the
288
+ worktree-isolation contract above (ISO-3 / ISO-4).
289
+ - Update the sweep's state CSV ({state_file}) using the read-update-
290
+ write Python pattern the template specifies. Key by module name;
291
+ last write wins on duplicates. Use today's ISO date
292
+ ({today}) for last_inspected. Use empty strings (not "null") for
293
+ missing fields.
294
+ - `git add {state_file}` and commit it on YOUR worktree branch
295
+ (`$DEEP_SWEEP_TARGET_BRANCH`) so the state update lands in any
296
+ resulting PR. Run ISO-3's re-check immediately before the commit.
297
+ If you did not file a PR, still commit the state update on the
298
+ worktree branch -- the parent will surface the branch path in its
299
+ summary.
300
+
301
+ 4. The sweep file may have its own CUDA-availability conditional (run
302
+ GPU paths vs. static review only). Honour it using CUDA_AVAILABLE
303
+ above. If CUDA is unavailable and the sweep specifies adding a
304
+ "cuda-unavailable" token to notes, do so.
305
+
306
+ **Hard rules (override any conflicting hint in the template):**
307
+
308
+ - Operate ONLY on module "{module}". Do not score, rank, or audit any
309
+ other module. Do not re-discover the module list.
310
+ - Do not modify other modules' rows in {state_file}. Only your own
311
+ module's row is touched.
312
+ - Do not call `.compute()` in any dask graph-construction probe.
313
+ - If the sweep template would normally launch its own sub-subagents,
314
+ do NOT recurse -- you ARE the worker. Inline the work it would
315
+ delegate.
316
+ - All commits and pushes happen from `$DEEP_SWEEP_WT` on a branch
317
+ starting with `deep-sweep-{sweep_name}-{module}-`. Never on `main`,
318
+ never in the user's main checkout, never on a sibling sweep's branch.
319
+ - {fix_mode_rule}
320
+
321
+ **Final report (mandatory):**
322
+
323
+ When you finish, report a short summary including, in addition to the
324
+ audit content, an isolation footer with the literal values of
325
+ `$DEEP_SWEEP_WT`, `$DEEP_SWEEP_TARGET_BRANCH`, and the SHA of the
326
+ state-CSV commit. The parent uses these to verify the contract held:
327
+
328
+ ```
329
+ Findings: <N CRITICAL>, <N HIGH>, <N MEDIUM>, <N LOW>
330
+ /rockout: <not-run | PRs: #NNNN, #NNNN>
331
+ Isolation:
332
+ worktree: <$DEEP_SWEEP_WT>
333
+ branch: <$DEEP_SWEEP_TARGET_BRANCH>
334
+ state-commit: <SHA>
335
+ ```
336
+ ```
337
+
338
+ Where `{fix_mode_note}` and `{fix_mode_rule}` are:
339
+
340
+ - If `--no-fix` was NOT passed:
341
+ - `{fix_mode_note}` = `end-to-end (GitHub issue, worktree branch, fix, tests, PR)`
342
+ - `{fix_mode_rule}` = `Run /rockout for HIGH/MEDIUM/CRITICAL findings as the sweep template specifies. LOW findings: document, do not fix.`
343
+ - If `--no-fix` WAS passed:
344
+ - `{fix_mode_note}` = `-- skipped, --no-fix is set`
345
+ - `{fix_mode_rule}` = `Do NOT run /rockout. Document findings in the state CSV's notes field and your summary. This run is audit-only.`
346
+
347
+ And `{today}` is the current date in ISO 8601 (use the `currentDate`
348
+ context value if available; otherwise `date +%Y-%m-%d`).
349
+
350
+ ## Step 5.5 -- Verify the worktree-isolation contract held
351
+
352
+ Before printing the user-facing results table, parse each agent's
353
+ returned summary for its "Isolation" footer (worktree path, branch
354
+ name, state-commit SHA). Then verify:
355
+
356
+ 1. **No `WORKTREE_ISOLATION_FAILED` markers.** If any agent returned
357
+ that token, mark its row `ISOLATION FAILED` in the results table
358
+ and surface the agent's full final message verbatim. Do not treat
359
+ its findings as merged-ready.
360
+ 2. **Branch uniqueness.** Every agent must be on a distinct branch.
361
+ Expected pattern: `deep-sweep-{sweep_name}-{module}-{today}`
362
+ (with optional `-NN` suffix for /rockout fan-out). Reject any
363
+ duplicates and any branch equal to `main` / `master`.
364
+ 3. **Worktree distinctness.** Every agent's reported worktree path
365
+ must be unique and must contain `.claude/worktrees/agent-`.
366
+ 4. **Main checkout untouched.** Run:
367
+
368
+ ```bash
369
+ git -C $(git rev-parse --show-toplevel) rev-parse --abbrev-ref HEAD
370
+ git -C $(git rev-parse --show-toplevel) status --porcelain
371
+ ```
372
+
373
+ The main checkout's HEAD branch must be unchanged from what it was
374
+ before /deep-sweep started (capture it in Step 0 as
375
+ `DEEP_SWEEP_START_BRANCH`). The porcelain output should contain no
376
+ commits or modifications introduced by sweep agents (a still-untracked
377
+ `.claude/commands/*.md` from the current session is fine; new commits
378
+ on the current branch from a sweep agent are NOT).
379
+
380
+ If any of (1)-(4) fails, print a clearly-labeled
381
+ `### Isolation contract breached` section ABOVE the results table,
382
+ listing every breach and which agent caused it, so the user can decide
383
+ whether to keep the produced PRs or unwind them. Do not silently
384
+ proceed.
385
+
386
+ ## Step 6 -- Wait, collect, and print the summary
387
+
388
+ All Agent calls run in the foreground in parallel. Once they return, print
389
+ a single results table:
390
+
391
+ ```
392
+ | Sweep | Findings | /rockout PR | State row written |
393
+ |-----------------|-----------------|-------------|-------------------|
394
+ | security | 0 HIGH, 1 MED | #1567 | yes |
395
+ | performance | 2 HIGH | #1568 | yes |
396
+ | accuracy | clean | -- | yes |
397
+ | api-consistency | 1 HIGH | #1569 | yes |
398
+ | metadata | 0 | -- | yes |
399
+ | test-coverage | 3 MED | #1570 | yes |
400
+ ```
401
+
402
+ Pull the values from each agent's returned summary. If an agent failed,
403
+ mark that row with `ERROR` in the findings column and surface the agent's
404
+ final message verbatim below the table so the user can decide whether to
405
+ re-run that single sweep manually (`/sweep-{sweep_name}`).
406
+
407
+ Finally, list the worktree branches each agent left behind so the user can
408
+ inspect or push them.
409
+
410
+ ---
411
+
412
+ ## General rules
413
+
414
+ - Never modify source files from the parent. All edits happen inside
415
+ per-sweep worktrees via the subagents.
416
+ - The deliverable from the parent is: validated module, dispatch table,
417
+ parallel agents, results table. Keep parent output concise.
418
+ - Each sweep's state CSV is registered with `merge=union` in
419
+ `.gitattributes`, so the N concurrent state updates auto-merge cleanly
420
+ even though they all touch the same module's row in different worktrees
421
+ -- the last write per row wins, which is the read-update-write semantics
422
+ the sweep templates already use.
423
+ - If a sweep template later changes its state-file schema or its audit
424
+ categories, deep-sweep picks up the change automatically the next time
425
+ it runs, because each subagent re-reads its sweep file on dispatch.
426
+ - If $ARGUMENTS provides a module that has no entry in any state file
427
+ (never inspected before), that is fine -- the subagents will create the
428
+ first row.
429
+ - /deep-sweep is not for triaging the whole codebase. For that, run the
430
+ individual `/sweep-*` commands; they score and pick the highest-priority
431
+ modules. Use /deep-sweep when you already know which module needs a
432
+ full-spectrum audit.
@@ -13,13 +13,36 @@ $ARGUMENTS
13
13
  3. Increment the **patch** component: `X.Y.Z` -> `X.Y.(Z+1)`.
14
14
  4. Store the new version string (without `v` prefix) for later steps.
15
15
 
16
- ## Step 2 -- Create a release branch
16
+ ## Step 2 -- Create a release branch in a worktree
17
+
18
+ The main checkout MUST stay on `main` -- the release branch lives in a
19
+ dedicated worktree. All remaining steps (changelog edits, commit,
20
+ push, PR) run from that worktree.
17
21
 
18
22
  ```bash
19
- git checkout main && git pull
20
- git checkout -b release/vX.Y.Z
23
+ RELEASE_MAIN="$(git rev-parse --show-toplevel)"
24
+ git -C "$RELEASE_MAIN" fetch origin main
25
+ RELEASE_MAIN_BRANCH="$(git -C "$RELEASE_MAIN" branch --show-current)"
26
+ if [ "$RELEASE_MAIN_BRANCH" = "main" ]; then
27
+ git -C "$RELEASE_MAIN" pull --ff-only origin main
28
+ fi
29
+ git -C "$RELEASE_MAIN" worktree add \
30
+ ".claude/worktrees/release-vX.Y.Z" -b "release/vX.Y.Z" origin/main
31
+ RELEASE_WT="$RELEASE_MAIN/.claude/worktrees/release-vX.Y.Z"
32
+ cd "$RELEASE_WT"
21
33
  ```
22
34
 
35
+ Verify isolation -- assert ALL of the following before continuing:
36
+ - `$(pwd)` equals `$RELEASE_WT`.
37
+ - `git branch --show-current` is `release/vX.Y.Z`.
38
+ - `git -C "$RELEASE_MAIN" branch --show-current` is still `main`
39
+ (the main checkout's branch did NOT change).
40
+
41
+ For every remaining step, use paths anchored at `$RELEASE_WT` for
42
+ Edit / Read / Write tool calls -- do NOT edit files under
43
+ `$RELEASE_MAIN`. Re-check `pwd` and the current branch before
44
+ every `git commit`.
45
+
23
46
  ## Step 3 -- Update CHANGELOG.md
24
47
 
25
48
  1. Run `git log --pretty=format:"- %s" <latest_tag>..HEAD` to collect
@@ -61,14 +84,25 @@ gh pr merge <PR_NUMBER> --merge --delete-branch
61
84
 
62
85
  ## Step 7 -- Tag the release
63
86
 
87
+ Tagging happens from the main checkout (NOT the release worktree),
88
+ because the merged commit lives on `main`:
89
+
64
90
  ```bash
65
- git checkout main && git pull
91
+ cd "$RELEASE_MAIN"
92
+ git checkout main
93
+ git pull --ff-only origin main
66
94
  git tag -a vX.Y.Z -m "Version X.Y.Z"
67
95
  git push origin vX.Y.Z
68
96
  ```
69
97
 
70
98
  Do **not** sign the tag (`-s` flag omitted).
71
99
 
100
+ After tagging, remove the release worktree -- the branch was already
101
+ deleted by `gh pr merge --delete-branch`:
102
+ ```bash
103
+ git -C "$RELEASE_MAIN" worktree remove "$RELEASE_WT" --force
104
+ ```
105
+
72
106
  ## Step 8 -- Create a GitHub release
73
107
 
74
108
  ```bash
@@ -20,8 +20,71 @@ NumPy, Dask, CuPy, and Numba. The prompt is: $ARGUMENTS
20
20
  ```bash
21
21
  gh pr diff <number>
22
22
  ```
23
- 5. Read every changed file in full (not just the diff) to understand surrounding
24
- context.
23
+
24
+ ## Step 1.5 -- Materialize the PR in a worktree
25
+
26
+ The user's main checkout MUST stay on `main`. Read the PR's files
27
+ from a worktree on the PR's head branch so the review sees the
28
+ actual PR state, not whatever happens to be checked out in the
29
+ main directory.
30
+
31
+ First, detect whether we are already inside a worktree on the PR's
32
+ head branch (this is the common case when `/review-pr` is invoked
33
+ from `/rockout` Step 9):
34
+
35
+ ```bash
36
+ REVIEW_PR_NUM=<number>
37
+ REVIEW_HEAD_BRANCH="$(gh pr view "$REVIEW_PR_NUM" --json headRefName -q .headRefName)"
38
+ REVIEW_CUR_BRANCH="$(git branch --show-current)"
39
+ REVIEW_CUR_TOP="$(git rev-parse --show-toplevel)"
40
+ ```
41
+
42
+ - If `$REVIEW_CUR_BRANCH` equals `$REVIEW_HEAD_BRANCH` AND
43
+ `$REVIEW_CUR_TOP` contains the segment `.claude/worktrees/`,
44
+ we are already in the right worktree. Set
45
+ `REVIEW_WT="$REVIEW_CUR_TOP"` and skip to step 4 below. Do NOT
46
+ create another worktree -- a second `git worktree add` on the
47
+ same branch will fail.
48
+
49
+ - Otherwise, create a dedicated review worktree:
50
+
51
+ 1. From any path, resolve the main checkout (use `--git-common-dir`
52
+ to find the shared repo even if we are inside another worktree):
53
+ ```bash
54
+ REVIEW_MAIN="$(git rev-parse --path-format=absolute --git-common-dir)"
55
+ REVIEW_MAIN="${REVIEW_MAIN%/.git}"
56
+ git -C "$REVIEW_MAIN" fetch origin "pull/$REVIEW_PR_NUM/head:pr-$REVIEW_PR_NUM-review"
57
+ git -C "$REVIEW_MAIN" worktree add \
58
+ ".claude/worktrees/pr-$REVIEW_PR_NUM-review" "pr-$REVIEW_PR_NUM-review"
59
+ REVIEW_WT="$REVIEW_MAIN/.claude/worktrees/pr-$REVIEW_PR_NUM-review"
60
+ REVIEW_WT_CREATED=1
61
+ ```
62
+
63
+ 2. Verify isolation -- assert ALL of the following. If any fails,
64
+ STOP and report it:
65
+ - `$REVIEW_WT` exists and is NOT equal to `$REVIEW_MAIN`.
66
+ - `git -C "$REVIEW_WT" branch --show-current` is
67
+ `pr-$REVIEW_PR_NUM-review`.
68
+ - `git -C "$REVIEW_MAIN" branch --show-current` is still
69
+ `main` (or `master`).
70
+
71
+ 3. `cd "$REVIEW_WT"` so subsequent reads happen inside the worktree.
72
+
73
+ 4. Read every changed file in full (not just the diff) from
74
+ `$REVIEW_WT`. Use paths anchored at `$REVIEW_WT` for all Read
75
+ tool calls -- never read the same file from the main checkout;
76
+ that path reflects `main` and will mislead the review.
77
+
78
+ 5. The review is read-only -- do NOT make commits in this worktree.
79
+ When the review is done (after Step 8), clean up only if Step
80
+ 1.5 created the worktree:
81
+ ```bash
82
+ if [ "${REVIEW_WT_CREATED:-0}" = "1" ]; then
83
+ cd "$REVIEW_MAIN"
84
+ git worktree remove ".claude/worktrees/pr-$REVIEW_PR_NUM-review"
85
+ git branch -D "pr-$REVIEW_PR_NUM-review"
86
+ fi
87
+ ```
25
88
 
26
89
  ## Step 2 -- Correctness review
27
90