mtlearn 1.3.0__tar.gz → 2.0.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 (534) hide show
  1. mtlearn-2.0.0/.github/scripts/repository_promotion.py +599 -0
  2. mtlearn-2.0.0/.github/scripts/test_ci_policy.py +233 -0
  3. mtlearn-2.0.0/.github/scripts/test_repository_promotion.py +1233 -0
  4. {mtlearn-1.3.0 → mtlearn-2.0.0}/.github/workflows/ci.yml +54 -0
  5. {mtlearn-1.3.0 → mtlearn-2.0.0}/.github/workflows/docs.yml +1 -0
  6. {mtlearn-1.3.0 → mtlearn-2.0.0}/.github/workflows/notebooks.yml +1 -0
  7. {mtlearn-1.3.0 → mtlearn-2.0.0}/.github/workflows/package.yml +1 -0
  8. mtlearn-2.0.0/.github/workflows/promote-public.yml +67 -0
  9. {mtlearn-1.3.0 → mtlearn-2.0.0}/.github/workflows/release.yml +28 -1
  10. mtlearn-2.0.0/.github/workflows/sync-private.yml +59 -0
  11. {mtlearn-1.3.0 → mtlearn-2.0.0}/PKG-INFO +2 -2
  12. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/development.md +10 -11
  13. mtlearn-2.0.0/external/mmcfilters/AGENTS.md +10 -0
  14. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/README.md +6 -4
  15. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/CMakeLists.txt +5 -5
  16. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/analyze_tree_construction_comparison.py +2 -6
  17. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/api/AttributeScenarios.cpp +2 -2
  18. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/api/CasfScenarios.cpp +1 -1
  19. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/api/ConstructionScenarios.cpp +2 -8
  20. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/build_tree_construction_report.py +24 -69
  21. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/distance_transform_sensitivity.py +12 -29
  22. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/distance_transform_timing.py +10 -12
  23. mtlearn-2.0.0/external/mmcfilters/benchmarks/extremum_residual_tree_by_cts_benchmark.cpp +121 -0
  24. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/python_api_benchmark.py +7 -7
  25. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/sibgrapi2026/bitquad_benchmark.cpp +20 -14
  26. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/tree_construction_comparison_benchmark.cpp +7 -12
  27. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/tree_validation_benchmark.cpp +1 -23
  28. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/workloads/scientific-api.ini +13 -13
  29. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/cmake/mmcfiltersPublicHeaders.cmake +26 -41
  30. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/AttributeRegistry.hpp +21 -7
  31. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/AttributeTypes.hpp +6 -1
  32. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/AreaComputer.hpp +17 -4
  33. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/BitquadAttributeComputer.hpp +16 -2
  34. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/BoundingBoxComputer.hpp +22 -9
  35. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/ContourSideAttributeComputer.hpp +16 -1
  36. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/FilledShapeAttributeComputer.hpp +25 -10
  37. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/GrayLevelStatsComputer.hpp +17 -4
  38. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/MaxDistComputer.hpp +14 -0
  39. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/MaxDistExactComputer.hpp +14 -0
  40. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/MomentBasedAttributeComputer.hpp +85 -28
  41. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/TreeTopologyComputer.hpp +21 -10
  42. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/VolumeComputer.hpp +17 -4
  43. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/BitquadAttributeProjection.hpp +2 -2
  44. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/BitquadConnectivityPolicy.hpp +2 -2
  45. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/BitquadFiniteWindowComputation.hpp +3 -3
  46. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/ContourSideAttributeMaterialization.hpp +3 -5
  47. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/distance_transform/MorphologicalTreeDistanceTransform.hpp +2 -2
  48. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/distance_transform/NodeContourSchedule.hpp +1 -1
  49. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/distance_transform/NodeSupportBoxIndex.hpp +2 -2
  50. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/distance_transform_approx/MorphologicalTreeApproximateDistanceTransform.hpp +6 -6
  51. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/distance_transform_approx/MorphologicalTreePropagationEdgeIndex.hpp +2 -2
  52. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/distance_transform_approx/MorphologicalTreeTopologicalLevelIndex.hpp +2 -2
  53. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/detail/AttributeCapabilityValidation.hpp +3 -3
  54. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/detail/AttributeFamilyScheduler.hpp +1 -0
  55. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/detail/AttributeKernelSupport.hpp +14 -4
  56. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/detail/AttributePipeline.hpp +2 -1
  57. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/detail/AttributeProjection.hpp +7 -7
  58. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/detail/MorphologicalTreeConstructionContextQueries.hpp → mtlearn-2.0.0/external/mmcfilters/mmcfilters/attributes/detail/BitquadProjectionAdjacencies.hpp +2 -23
  59. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/detail/NodeAttributeSampleMaterialization.hpp +52 -31
  60. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/contours/ContourTraceComputation.hpp +10 -10
  61. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/contours/detail/ContourLifetimeIndex.hpp +3 -3
  62. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/contours/detail/ContourTraversal.hpp +4 -4
  63. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/contours/detail/NodeSupportIndex.hpp +5 -5
  64. mtlearn-2.0.0/external/mmcfilters/mmcfilters/distanceTransform/DistanceTransformComputation.hpp +150 -0
  65. mtlearn-2.0.0/external/mmcfilters/mmcfilters/distanceTransform/DistanceTransformProfiles.hpp +113 -0
  66. mtlearn-2.0.0/external/mmcfilters/mmcfilters/distanceTransform/DistanceTransformTypes.hpp +33 -0
  67. mtlearn-2.0.0/external/mmcfilters/mmcfilters/distanceTransform/NodeDistanceField.hpp +81 -0
  68. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/filters/AttributeFilters.hpp +52 -43
  69. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/filters/AttributeReconstructionFilters.hpp +67 -37
  70. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/filters/DepthStableRegionComputer.hpp +6 -3
  71. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/filters/ExtinctionValues.hpp +12 -13
  72. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/filters/MSERComputer.hpp +11 -5
  73. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/filters/NodeDecisionMasks.hpp +13 -0
  74. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/filters/NodePreservationStability.hpp +10 -8
  75. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/filters/UltimateAttributeOpening.hpp +8 -8
  76. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/filters/detail/ViterbiDecision.hpp +11 -11
  77. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/localAttributes/ConnectedSubsetTreeLocalizer.hpp +5 -5
  78. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/localAttributes/FiniteWindowLocalAttributeComputer.hpp +3 -3
  79. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/localAttributes/FiniteWindowLocalEventCompiler.hpp +7 -7
  80. mtlearn-2.0.0/external/mmcfilters/mmcfilters/trees/ComponentTreeBuilder.hpp +251 -0
  81. mtlearn-2.0.0/external/mmcfilters/mmcfilters/trees/ExtremumResidualTreeByCTsBuilder.hpp +443 -0
  82. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/trees/MorphologicalTree.hpp +68 -43
  83. mtlearn-2.0.0/external/mmcfilters/mmcfilters/trees/MorphologicalTreeFactory.hpp +277 -0
  84. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/trees/MorphologicalTreeSemantics.hpp +4 -18
  85. mtlearn-2.0.0/external/mmcfilters/mmcfilters/trees/NativeHierarchyOwned.hpp +93 -0
  86. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/NativeHierarchy.hpp → mtlearn-2.0.0/external/mmcfilters/mmcfilters/trees/NativeHierarchyView.hpp +5 -5
  87. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/trees/TreeAltitudeAlgorithms.hpp +74 -18
  88. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/trees/TreeEditor.hpp +40 -37
  89. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/TreeOfShapesProducer.hpp → mtlearn-2.0.0/external/mmcfilters/mmcfilters/trees/TreeOfShapesBuilder.hpp +142 -107
  90. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/trees/ValuedMorphologicalTree.hpp +39 -36
  91. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/trees/ValuedMorphologicalTreeView.hpp +21 -5
  92. mtlearn-2.0.0/external/mmcfilters/mmcfilters/trees/detail/DualMinMaxTreeIncrementalFilterLeaf.hpp +658 -0
  93. mtlearn-2.0.0/external/mmcfilters/mmcfilters/trees/detail/HigraHierarchyDetail.hpp +435 -0
  94. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/trees/detail/MorphologicalTreeConstructionTag.hpp +25 -3
  95. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/detail/CommittedTreeAccess.hpp → mtlearn-2.0.0/external/mmcfilters/mmcfilters/trees/detail/TreeKernelAccess.hpp +42 -5
  96. mtlearn-2.0.0/external/mmcfilters/mmcfilters/trees/detail/TreeNeighborhood.hpp +195 -0
  97. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/trees/saliency/HierarchicalWatershedSaliency.hpp +14 -31
  98. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/trees/saliency/HierarchySaliencyMap.hpp +148 -121
  99. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/trees/saliency/HierarchySaliencyMapProjection.hpp +7 -21
  100. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/trees/saliency/HierarchySaliencyMapValidation.hpp +178 -192
  101. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/trees/saliency/ShapeSpaceSaliency.hpp +75 -89
  102. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/utils/CommittedGridAccess.hpp +5 -5
  103. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/utils/CommittedImageAccess.hpp +3 -3
  104. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/utils/Image.hpp +0 -16
  105. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/utils/RegularGridAdjacency2D.hpp +49 -20
  106. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/pybinds/AdjustBindings.cpp +3 -3
  107. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/pybinds/AttributeBindings.cpp +17 -45
  108. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/pybinds/AttributeComputationBindings.hpp +28 -16
  109. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/pybinds/AttributeFiltersPybind.hpp +120 -61
  110. mtlearn-2.0.0/external/mmcfilters/pybinds/ContourMapPybind.hpp +130 -0
  111. mtlearn-2.0.0/external/mmcfilters/pybinds/DistanceTransformBindings.cpp +129 -0
  112. mtlearn-2.0.0/external/mmcfilters/pybinds/EdgeMapPybind.hpp +149 -0
  113. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/pybinds/ExtinctionValuesPybind.hpp +14 -31
  114. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/pybinds/FilterBindings.cpp +52 -145
  115. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/pybinds/ModuleBindings.hpp +6 -0
  116. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/pybinds/PybindConversions.hpp +25 -0
  117. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/pybinds/PythonValuedMorphologicalTree.hpp +1 -1
  118. mtlearn-2.0.0/external/mmcfilters/pybinds/ShapeSpaceResultsPybind.hpp +124 -0
  119. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/pybinds/TreeBindings.cpp +94 -437
  120. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/pybinds/UltimateAttributeOpeningPybind.hpp +11 -11
  121. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/pybinds/UtilityBindings.cpp +2 -2
  122. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/scripts/validate_notebooks.py +46 -10
  123. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/bindings/morphology/AttributeBinding.hpp +79 -22
  124. mtlearn-2.0.0/mtlearn/bindings/morphology/AttributeFiltersBinding.hpp +285 -0
  125. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/bindings/morphology/BindingSupport.hpp +11 -2
  126. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/bindings/morphology/WeightedTreeBinding.hpp +4 -8
  127. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/include/mtlearn/detail/morphology_backend.hpp +6 -7
  128. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/include/mtlearn/morphology.hpp +3 -1
  129. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/_backends/_mtlearn.py +8 -24
  130. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/_version.py +3 -3
  131. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/cfp_preprocessor.py +1 -1
  132. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/serialization/config_deserializer.py +2 -0
  133. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/morphology.py +16 -69
  134. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/CMakeLists.txt +2 -3
  135. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/cpp/public_morphology.cpp +6 -0
  136. mtlearn-2.0.0/mtlearn/tests/python/fixtures/mmcfilters_v8/v1.3.0-float32-cache.pt.gz +0 -0
  137. mtlearn-2.0.0/mtlearn/tests/python/fixtures/mmcfilters_v8/v1.3.0-float64-cache.pt.gz +0 -0
  138. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_bindings.py +9 -8
  139. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_deterministic.py +1 -1
  140. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_gradchecks.py +1 -1
  141. mtlearn-2.0.0/mtlearn/tests/python/test_mmcfilters_v8.py +208 -0
  142. mtlearn-2.0.0/mtlearn/tests/python/test_mmcfilters_v8_cache.py +107 -0
  143. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_morphology_api.py +47 -51
  144. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_morphology_attribute_groups.py +9 -8
  145. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_morphology_bounding_box_width.py +21 -10
  146. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_morphology_gray_level.py +5 -5
  147. mtlearn-2.0.0/mtlearn/tests/python/test_notebook_mmcfilters_v8.py +93 -0
  148. {mtlearn-1.3.0 → mtlearn-2.0.0}/pyproject.toml +1 -1
  149. {mtlearn-1.3.0 → mtlearn-2.0.0}/scripts/benchmarks/cfp_cache_p0.py +3 -3
  150. {mtlearn-1.3.0 → mtlearn-2.0.0}/scripts/smoke_test_release.py +1 -1
  151. {mtlearn-1.3.0 → mtlearn-2.0.0}/scripts/validate_notebooks.py +2 -2
  152. mtlearn-1.3.0/external/mmcfilters/benchmarks/README.md +0 -323
  153. mtlearn-1.3.0/external/mmcfilters/benchmarks/min_max_residual_tree_benchmark.cpp +0 -190
  154. mtlearn-1.3.0/external/mmcfilters/benchmarks/validation-sensitive.md +0 -71
  155. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/MorphologicalTreeFactory.hpp +0 -472
  156. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/adjust/DualMinMaxTreeIncrementalFilterLeaf.hpp +0 -1417
  157. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/detail/ComponentTreeProducerDetail.hpp +0 -125
  158. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/detail/ComponentTreeUnionFind.hpp +0 -155
  159. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/detail/HierarchyCapabilityValidation.hpp +0 -49
  160. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/detail/HigraExportLayoutDetail.hpp +0 -138
  161. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/detail/HigraHierarchyAdapterDetail.hpp +0 -130
  162. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/detail/HigraImportLayoutDetail.hpp +0 -103
  163. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/detail/NativeHierarchyValidationDetail.hpp +0 -631
  164. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/detail/TreeAttributeSamplingNeighborhood.hpp +0 -227
  165. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/detail/TreeStabilityNeighborhood.hpp +0 -273
  166. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/detail/TreeTraversalDetail.hpp +0 -66
  167. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/sdrt/ResidualEvolution.hpp +0 -274
  168. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/sdrt/ResidualTreeBuildStatistics.hpp +0 -24
  169. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/sdrt/ResidualTreePolicies.hpp +0 -37
  170. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/sdrt/SaturatedResidualTreeBuilder.hpp +0 -90
  171. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/sdrt/UnrestrictedResidualTreeBuilder.hpp +0 -82
  172. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/sdrt/detail/FlatZonePartition.hpp +0 -397
  173. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/sdrt/detail/ResidualTreeCandidateAgenda.hpp +0 -191
  174. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/sdrt/detail/ResidualTreeCandidateContext.hpp +0 -59
  175. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/sdrt/detail/ResidualTreeCandidatePreparation.hpp +0 -117
  176. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/sdrt/detail/ResidualTreeCandidateTypes.hpp +0 -21
  177. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/sdrt/detail/ResidualTreeEventAssembler.hpp +0 -294
  178. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/sdrt/detail/ResidualTreeMaterialization.hpp +0 -59
  179. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/sdrt/detail/ResidualTreeRegionTypes.hpp +0 -13
  180. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/sdrt/detail/SaturatedDynamicLca.hpp +0 -722
  181. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/sdrt/detail/SaturatedResidualEligibility.hpp +0 -338
  182. mtlearn-1.3.0/external/mmcfilters/mmcfilters/trees/sdrt/detail/SynchronizedResidualTreeEvolution.hpp +0 -607
  183. mtlearn-1.3.0/external/mmcfilters/pybinds/AttributeReconstructionFiltersPybind.hpp +0 -152
  184. mtlearn-1.3.0/mtlearn/bindings/morphology/AttributeFiltersBinding.hpp +0 -303
  185. {mtlearn-1.3.0 → mtlearn-2.0.0}/CMakeLists.txt +0 -0
  186. {mtlearn-1.3.0 → mtlearn-2.0.0}/LICENSE +0 -0
  187. {mtlearn-1.3.0 → mtlearn-2.0.0}/Pipfile +0 -0
  188. {mtlearn-1.3.0 → mtlearn-2.0.0}/README.md +0 -0
  189. {mtlearn-1.3.0 → mtlearn-2.0.0}/cmake/mtlearnConfig.cmake.in +0 -0
  190. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/assets/cfp-class-architecture.svg +0 -0
  191. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/cfp-architecture.md +0 -0
  192. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/cfp-loss-design.md +0 -0
  193. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/cfp-regularization-design.md +0 -0
  194. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/cfp-score-constraint-design.md +0 -0
  195. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/cfp-scoring-design.md +0 -0
  196. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/installation.md +0 -0
  197. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/source/_static/.gitkeep +0 -0
  198. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/source/_templates/.gitkeep +0 -0
  199. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/source/api/python/cfp_preparation.rst +0 -0
  200. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/source/api/python/data.rst +0 -0
  201. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/source/api/python/datasets.rst +0 -0
  202. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/source/api/python/index.rst +0 -0
  203. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/source/api/python/layers.rst +0 -0
  204. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/source/api/python/morphology.rst +0 -0
  205. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/source/api/python/native.rst +0 -0
  206. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/source/concepts/attributes.md +0 -0
  207. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/source/concepts/morphology.md +0 -0
  208. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/source/conf.py +0 -0
  209. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/source/guides/custom-attributes-filter-specs.md +0 -0
  210. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/source/guides/datasets.md +0 -0
  211. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/source/guides/getting-started.md +0 -0
  212. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/source/guides/index.md +0 -0
  213. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/source/guides/morphology.md +0 -0
  214. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/source/guides/patch-training-cache.md +0 -0
  215. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/source/guides/pytorch-integration.md +0 -0
  216. {mtlearn-1.3.0 → mtlearn-2.0.0}/docs/source/index.md +0 -0
  217. {mtlearn-1.3.0 → mtlearn-2.0.0}/environment.yml +0 -0
  218. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/.clang-format +0 -0
  219. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/.editorconfig +0 -0
  220. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/.gitattributes +0 -0
  221. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/CMakeLists.txt +0 -0
  222. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/LICENSE +0 -0
  223. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/adjacency_iteration_benchmark.cpp +0 -0
  224. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/analyze_scientific_experiment.py +0 -0
  225. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/api/ApiBenchmark.hpp +0 -0
  226. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/api/EditingScenarios.cpp +0 -0
  227. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/api/FilterScenarios.cpp +0 -0
  228. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/api/InteroperabilityScenarios.cpp +0 -0
  229. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/api/PipelineScenarios.cpp +0 -0
  230. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/api/WorkloadManifest.cpp +0 -0
  231. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/api/api_benchmark.cpp +0 -0
  232. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/compare_validation_modes.py +0 -0
  233. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/scientific_pipeline_benchmark.cpp +0 -0
  234. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/sibgrapi2026/analyze_results.py +0 -0
  235. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/sibgrapi2026/bitquad_exactness_validation.cpp +0 -0
  236. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/sibgrapi2026/reference-results/correctness.csv +0 -0
  237. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/sibgrapi2026/reference-results/dataset-manifest.csv +0 -0
  238. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/sibgrapi2026/reference-results/experiment.json +0 -0
  239. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/sibgrapi2026/reference-results/raw-1080p.csv +0 -0
  240. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/sibgrapi2026/reference-results/raw-480p.csv +0 -0
  241. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/sibgrapi2026/reference-results/raw-720p.csv +0 -0
  242. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/sibgrapi2026/reference-results/run-1080p.log +0 -0
  243. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/sibgrapi2026/reference-results/run-480p.log +0 -0
  244. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/sibgrapi2026/reference-results/run-720p.log +0 -0
  245. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/sibgrapi2026/reference-results/speedups.csv +0 -0
  246. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/sibgrapi2026/reference-results/summary.csv +0 -0
  247. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/sibgrapi2026/reference-results/table.tex +0 -0
  248. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/sibgrapi2026/run_experiment.py +0 -0
  249. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/summarize_scientific_campaign.py +0 -0
  250. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/support/ScientificBenchmark.hpp +0 -0
  251. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/support/stb_image_read.cpp +0 -0
  252. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/validation_sensitive_algorithms_benchmark.cpp +0 -0
  253. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/benchmarks/workloads/distance-transform-contract.ini +0 -0
  254. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/cmake/mmcfiltersConfig.cmake.in +0 -0
  255. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/CMakeLists.txt +0 -0
  256. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/AttributeComputation.hpp +0 -0
  257. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/AttributeNames.hpp +0 -0
  258. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/AttributeResultTypes.hpp +0 -0
  259. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/Attributes.hpp +0 -0
  260. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/AttributeComputerDomain.hpp +0 -0
  261. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/AttributeComputerFamily.hpp +0 -0
  262. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/AttributeComputerRegistry.hpp +0 -0
  263. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/BitquadAttributeData.hpp +0 -0
  264. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/ContourSideAttributeData.hpp +0 -0
  265. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/ContourSideFiniteWindowComputation.hpp +0 -0
  266. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/distance_transform/DistanceFieldHistogram.hpp +0 -0
  267. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/distance_transform/DistanceFieldMoments.hpp +0 -0
  268. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/distance_transform/DistanceWeightedSpatialMoments.hpp +0 -0
  269. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/distance_transform/ExactSquaredEuclideanDistanceTransform2D.hpp +0 -0
  270. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/distance_transform/NodeDistanceFieldProvider.hpp +0 -0
  271. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/distance_transform_approx/AdaptiveSquaredEuclideanDIFT2D.hpp +0 -0
  272. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/distance_transform_approx/DynamicDistanceFieldMoments2D.hpp +0 -0
  273. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/distance_transform_approx/DynamicDistanceFieldStatistics2D.hpp +0 -0
  274. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/computers/detail/distance_transform_approx/SquaredDistanceBucketQueue.hpp +0 -0
  275. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/detail/AttributeDependencyCache.hpp +0 -0
  276. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/detail/AttributeNumericPolicy.hpp +0 -0
  277. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/detail/AttributeRequestUtils.hpp +0 -0
  278. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/attributes/detail/TopologyAttributeBackend.hpp +0 -0
  279. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/contours/ContourComputation.hpp +0 -0
  280. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/contours/ContourTrace.hpp +0 -0
  281. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/contours/detail/ContourBoundaryTracer.hpp +0 -0
  282. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/contours/detail/ContourEdgeDeltaStore.hpp +0 -0
  283. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/contours/detail/ContourTraceTraversal.hpp +0 -0
  284. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/dataStructure/FastQueue.hpp +0 -0
  285. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/dataStructure/FastStack.hpp +0 -0
  286. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/filters/detail/VariationMeasure.hpp +0 -0
  287. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/localAttributes/LocalEventModel.hpp +0 -0
  288. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/trees/ProperPartDomain.hpp +0 -0
  289. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/trees/adjust/CasfComponentTrees.hpp +0 -0
  290. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/trees/adjust/DualMinMaxTreeIncrementalFilter.hpp +0 -0
  291. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/trees/adjust/DynamicTreeAttributeComputer.hpp +0 -0
  292. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/utils/Altitude.hpp +0 -0
  293. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/utils/Assert.hpp +0 -0
  294. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/utils/Common.hpp +0 -0
  295. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/utils/Contract.hpp +0 -0
  296. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/mmcfilters/utils/GenerationStampSet.hpp +0 -0
  297. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/pybinds/ContourBindings.cpp +0 -0
  298. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/pybinds/ContourTraceBindings.cpp +0 -0
  299. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/pybinds/DepthStableRegionComputerPybind.hpp +0 -0
  300. {mtlearn-1.3.0 → mtlearn-2.0.0}/external/mmcfilters/scripts/execute_notebooks.py +0 -0
  301. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/bindings/CMakeLists.txt +0 -0
  302. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/bindings/MtlearnModule.cpp +0 -0
  303. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/bindings/cfp/TreeTensorsBinding.hpp +0 -0
  304. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/bindings/cfp/TreeTraversalBinding.hpp +0 -0
  305. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/__init__.py +0 -0
  306. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/_backends/__init__.py +0 -0
  307. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/_datasets/__init__.py +0 -0
  308. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/_datasets/_dataset_contracts.py +0 -0
  309. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/_datasets/_explicit_pairs.py +0 -0
  310. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/_datasets/_generated_target.py +0 -0
  311. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/_datasets/_image_ops.py +0 -0
  312. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/_datasets/_manifest_dataset.py +0 -0
  313. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/_datasets/_pair_audit.py +0 -0
  314. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/_datasets/_paired_image.py +0 -0
  315. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/_datasets/_sample_ids.py +0 -0
  316. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/_datasets/_split.py +0 -0
  317. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/_datasets/_split_ids.py +0 -0
  318. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/_datasets/_split_manifest.py +0 -0
  319. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/_datasets/_suffix_pairs.py +0 -0
  320. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/_native.py +0 -0
  321. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/data.py +0 -0
  322. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/datasets.py +0 -0
  323. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/__init__.py +0 -0
  324. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/_helpers.py +0 -0
  325. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/__init__.py +0 -0
  326. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/component_registries.py +0 -0
  327. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/connected_filter_preprocessing_layer.py +0 -0
  328. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/constraints/__init__.py +0 -0
  329. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/constraints/base.py +0 -0
  330. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/constraints/preserve_root.py +0 -0
  331. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/normalization/__init__.py +0 -0
  332. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/normalization/attribute_normalizer.py +0 -0
  333. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/normalization/attribute_statistics.py +0 -0
  334. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/normalization/statistics_snapshot.py +0 -0
  335. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/normalization/stats_serializer.py +0 -0
  336. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/__init__.py +0 -0
  337. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/_calibration_measurement.py +0 -0
  338. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/_disk_preparation.py +0 -0
  339. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/_identity.py +0 -0
  340. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/_loader_memory.py +0 -0
  341. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/_parallel_preparation.py +0 -0
  342. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/_persistent_preparation.py +0 -0
  343. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/_preparation_progress.py +0 -0
  344. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/_prepared_reader.py +0 -0
  345. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/_process_reader.py +0 -0
  346. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/_read_diagnostics.py +0 -0
  347. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/_reader_process.py +0 -0
  348. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/_shared_batch.py +0 -0
  349. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/_statistics_fitter.py +0 -0
  350. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/_threaded_reader.py +0 -0
  351. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/calibration.py +0 -0
  352. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/dataset_cache.py +0 -0
  353. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/dataset_diagnostics.py +0 -0
  354. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/dataset_source.py +0 -0
  355. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/preparation_result.py +0 -0
  356. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/prepared_batch.py +0 -0
  357. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/prepared_dataloader.py +0 -0
  358. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/prepared_dataset.py +0 -0
  359. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/preparation/prepared_morphology.py +0 -0
  360. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/regularization/__init__.py +0 -0
  361. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/regularization/_tree_info.py +0 -0
  362. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/regularization/attribute_order_score_monotonicity.py +0 -0
  363. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/regularization/base.py +0 -0
  364. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/regularization/edge_score_monotonicity.py +0 -0
  365. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/regularization/path_score_monotonicity.py +0 -0
  366. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/runtime/__init__.py +0 -0
  367. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/runtime/_prepared_lifetime.py +0 -0
  368. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/runtime/batch_input.py +0 -0
  369. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/runtime/cache_input_contract.py +0 -0
  370. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/runtime/cached_dataloader_builder.py +0 -0
  371. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/runtime/context.py +0 -0
  372. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/runtime/forward_executor.py +0 -0
  373. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/runtime/implicit_jacobian_function.py +0 -0
  374. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/runtime/training_sample_inspector.py +0 -0
  375. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/runtime/tree_payload_cache.py +0 -0
  376. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/runtime/tree_payload_provider.py +0 -0
  377. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/runtime/tree_reconstructor.py +0 -0
  378. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/scoring/__init__.py +0 -0
  379. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/scoring/_layer_owned_linear_parameter_initializer.py +0 -0
  380. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/scoring/base.py +0 -0
  381. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/scoring/linear_sigmoid.py +0 -0
  382. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/scoring/mlp.py +0 -0
  383. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/serialization/__init__.py +0 -0
  384. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/serialization/config_serializer.py +0 -0
  385. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/serialization/persistent_state_manager.py +0 -0
  386. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/specs/__init__.py +0 -0
  387. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/specs/feature_spec.py +0 -0
  388. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/specs/filter_spec.py +0 -0
  389. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/specs/filter_spec_normalizer.py +0 -0
  390. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/specs/normalized_filter_spec.py +0 -0
  391. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/specs/spec_registry.py +0 -0
  392. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/specs/tree_spec.py +0 -0
  393. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/storage/__init__.py +0 -0
  394. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/storage/_disk_format.py +0 -0
  395. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/storage/_manifest.py +0 -0
  396. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/storage/_manifest_inspection.py +0 -0
  397. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/storage/_read_validation.py +0 -0
  398. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/storage/_storages.py +0 -0
  399. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/storage/_writer_lock.py +0 -0
  400. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/storage/disk_store.py +0 -0
  401. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/storage/memory_store.py +0 -0
  402. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/cfp/storage/null_store.py +0 -0
  403. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/layers/checkpoint.py +0 -0
  404. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/patches/__init__.py +0 -0
  405. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/patches/_geometry.py +0 -0
  406. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/patches/_reconstruction.py +0 -0
  407. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/training/__init__.py +0 -0
  408. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/training/_patch_backward.py +0 -0
  409. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/python/mtlearn/training/_patch_diagnostics.py +0 -0
  410. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/src/CMakeLists.txt +0 -0
  411. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/src/mtlearn/cfp/tree_tensors.hpp +0 -0
  412. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/src/mtlearn/cfp/tree_traversal.hpp +0 -0
  413. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/src/mtlearn/morphology.cpp +0 -0
  414. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/cmake/installed_consumer_test.cmake +0 -0
  415. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/cpp/test_interpreter.cpp +0 -0
  416. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/_paired_dataset_reference.py +0 -0
  417. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/cfp_reference_names.py +0 -0
  418. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/README.md +0 -0
  419. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/baseline.pt +0 -0
  420. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/manifest.json +0 -0
  421. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/max-tree_linear_dataset_clipped_zscore01.pt +0 -0
  422. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/max-tree_linear_dataset_clipped_zscore01.stats.pt +0 -0
  423. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/max-tree_linear_dataset_minmax01.pt +0 -0
  424. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/max-tree_linear_dataset_minmax01.stats.pt +0 -0
  425. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/max-tree_linear_dataset_zscore.pt +0 -0
  426. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/max-tree_linear_dataset_zscore.stats.pt +0 -0
  427. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/max-tree_linear_none.pt +0 -0
  428. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/max-tree_linear_none.stats.pt +0 -0
  429. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/max-tree_mlp_dataset_clipped_zscore01.pt +0 -0
  430. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/max-tree_mlp_dataset_clipped_zscore01.stats.pt +0 -0
  431. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/max-tree_mlp_dataset_minmax01.pt +0 -0
  432. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/max-tree_mlp_dataset_minmax01.stats.pt +0 -0
  433. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/max-tree_mlp_dataset_zscore.pt +0 -0
  434. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/max-tree_mlp_dataset_zscore.stats.pt +0 -0
  435. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/max-tree_mlp_none.pt +0 -0
  436. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/max-tree_mlp_none.stats.pt +0 -0
  437. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/min-tree_linear_dataset_clipped_zscore01.pt +0 -0
  438. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/min-tree_linear_dataset_clipped_zscore01.stats.pt +0 -0
  439. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/min-tree_mlp_dataset_clipped_zscore01.pt +0 -0
  440. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/min-tree_mlp_dataset_clipped_zscore01.stats.pt +0 -0
  441. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/tree-of-shapes_linear_dataset_clipped_zscore01.pt +0 -0
  442. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/tree-of-shapes_linear_dataset_clipped_zscore01.stats.pt +0 -0
  443. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/tree-of-shapes_mlp_dataset_clipped_zscore01.pt +0 -0
  444. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0/tree-of-shapes_mlp_dataset_clipped_zscore01.stats.pt +0 -0
  445. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/baseline.pt +0 -0
  446. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/manifest.json +0 -0
  447. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/max-tree_linear_dataset_clipped_zscore01.pt +0 -0
  448. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/max-tree_linear_dataset_clipped_zscore01.stats.pt +0 -0
  449. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/max-tree_linear_dataset_minmax01.pt +0 -0
  450. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/max-tree_linear_dataset_minmax01.stats.pt +0 -0
  451. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/max-tree_linear_dataset_zscore.pt +0 -0
  452. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/max-tree_linear_dataset_zscore.stats.pt +0 -0
  453. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/max-tree_linear_none.pt +0 -0
  454. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/max-tree_linear_none.stats.pt +0 -0
  455. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/max-tree_mlp_dataset_clipped_zscore01.pt +0 -0
  456. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/max-tree_mlp_dataset_clipped_zscore01.stats.pt +0 -0
  457. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/max-tree_mlp_dataset_minmax01.pt +0 -0
  458. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/max-tree_mlp_dataset_minmax01.stats.pt +0 -0
  459. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/max-tree_mlp_dataset_zscore.pt +0 -0
  460. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/max-tree_mlp_dataset_zscore.stats.pt +0 -0
  461. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/max-tree_mlp_none.pt +0 -0
  462. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/max-tree_mlp_none.stats.pt +0 -0
  463. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/min-tree_linear_dataset_clipped_zscore01.pt +0 -0
  464. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/min-tree_linear_dataset_clipped_zscore01.stats.pt +0 -0
  465. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/min-tree_mlp_dataset_clipped_zscore01.pt +0 -0
  466. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/min-tree_mlp_dataset_clipped_zscore01.stats.pt +0 -0
  467. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/tree-of-shapes_linear_dataset_clipped_zscore01.pt +0 -0
  468. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/tree-of-shapes_linear_dataset_clipped_zscore01.stats.pt +0 -0
  469. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/tree-of-shapes_mlp_dataset_clipped_zscore01.pt +0 -0
  470. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p0_mmcfilters_v5_2_0/tree-of-shapes_mlp_dataset_clipped_zscore01.stats.pt +0 -0
  471. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p1/statistics.json +0 -0
  472. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_cache_p5/notebook_before_p5.json +0 -0
  473. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_disk_cache_e0/legacy_linear_sigmoid_max-tree.pt +0 -0
  474. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_disk_cache_e0/legacy_linear_sigmoid_min-tree.pt +0 -0
  475. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_disk_cache_e0/legacy_linear_sigmoid_tree-of-shapes.pt +0 -0
  476. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_disk_cache_e0/legacy_mlp_max-tree.pt +0 -0
  477. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_disk_cache_e0/legacy_mlp_min-tree.pt +0 -0
  478. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_disk_cache_e0/legacy_mlp_tree-of-shapes.pt +0 -0
  479. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_disk_cache_e0/manifest.json +0 -0
  480. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_disk_cache_e0/memory_linear_sigmoid_max-tree.pt +0 -0
  481. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_disk_cache_e0/memory_linear_sigmoid_min-tree.pt +0 -0
  482. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_disk_cache_e0/memory_linear_sigmoid_tree-of-shapes.pt +0 -0
  483. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_disk_cache_e0/memory_mlp_max-tree.pt +0 -0
  484. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_disk_cache_e0/memory_mlp_min-tree.pt +0 -0
  485. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/fixtures/cfp_disk_cache_e0/memory_mlp_tree-of-shapes.pt +0 -0
  486. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_cache.py +0 -0
  487. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_cache_baseline.py +0 -0
  488. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_cache_calibration.py +0 -0
  489. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_cache_compatibility.py +0 -0
  490. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_checkpoint_independence.py +0 -0
  491. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_components.py +0 -0
  492. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_dataset_cache.py +0 -0
  493. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_dataset_diagnostics.py +0 -0
  494. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_dataset_source.py +0 -0
  495. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_disk_cache.py +0 -0
  496. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_disk_cache_e0.py +0 -0
  497. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_disk_cache_validation.py +0 -0
  498. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_disk_preparation_flow.py +0 -0
  499. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_jacobian_intervals.py +0 -0
  500. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_mps_reconstruction.py +0 -0
  501. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_notebook_cache_budget.py +0 -0
  502. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_notebook_streaming.py +0 -0
  503. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_parallel_preparation.py +0 -0
  504. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_preparation.py +0 -0
  505. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_prepared_dataloader.py +0 -0
  506. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_prepared_runtime.py +0 -0
  507. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_process_dataloader.py +0 -0
  508. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_uint32_pixel_map.py +0 -0
  509. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_cfp_validation.py +0 -0
  510. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_data.py +0 -0
  511. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_dataset_pair_audit.py +0 -0
  512. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_dataset_split_ids.py +0 -0
  513. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_dataset_split_manifest.py +0 -0
  514. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_paired_dataset_characterization.py +0 -0
  515. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_patch_backward.py +0 -0
  516. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_patch_cfp_integration.py +0 -0
  517. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_patch_geometry.py +0 -0
  518. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_patch_reconstruction.py +0 -0
  519. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_reusable_paired_dataset.py +0 -0
  520. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_suffix_paired_dataset.py +0 -0
  521. {mtlearn-1.3.0 → mtlearn-2.0.0}/mtlearn/tests/python/test_version.py +0 -0
  522. {mtlearn-1.3.0 → mtlearn-2.0.0}/requirements.txt +0 -0
  523. {mtlearn-1.3.0 → mtlearn-2.0.0}/scripts/benchmarks/cfp_cache_p1.py +0 -0
  524. {mtlearn-1.3.0 → mtlearn-2.0.0}/scripts/benchmarks/cfp_cache_p2.py +0 -0
  525. {mtlearn-1.3.0 → mtlearn-2.0.0}/scripts/benchmarks/cfp_cache_p3.py +0 -0
  526. {mtlearn-1.3.0 → mtlearn-2.0.0}/scripts/benchmarks/cfp_cache_p4.py +0 -0
  527. {mtlearn-1.3.0 → mtlearn-2.0.0}/scripts/benchmarks/cfp_cache_p5.py +0 -0
  528. {mtlearn-1.3.0 → mtlearn-2.0.0}/scripts/benchmarks/cfp_cache_p6.py +0 -0
  529. {mtlearn-1.3.0 → mtlearn-2.0.0}/scripts/benchmarks/cfp_cache_p6_finalize.py +0 -0
  530. {mtlearn-1.3.0 → mtlearn-2.0.0}/scripts/benchmarks/cfp_jacobian_intervals.py +0 -0
  531. {mtlearn-1.3.0 → mtlearn-2.0.0}/scripts/benchmarks/patch_backward.py +0 -0
  532. {mtlearn-1.3.0 → mtlearn-2.0.0}/scripts/download_data.py +0 -0
  533. {mtlearn-1.3.0 → mtlearn-2.0.0}/scripts/install_release_dependencies.py +0 -0
  534. {mtlearn-1.3.0 → mtlearn-2.0.0}/scripts/resolve_package_version.py +0 -0
@@ -0,0 +1,599 @@
1
+ #!/usr/bin/env python3
2
+ """Publish approved private PRs and reconcile the two repository histories.
3
+
4
+ Operational limits:
5
+ - Until scheduled executions are verified, start an idle publication queue after
6
+ merging private work with:
7
+ gh workflow run promote-public.yml --repo wonderalexandre/MTLearn
8
+ A successful private synchronization resumes the remaining queue automatically.
9
+ - Closing a publication PR without merging blocks later publications. Reopen it
10
+ to continue; closing it does not cancel the change already in private main.
11
+ - Development PRs require squash merges; synchronization PRs require merge commits.
12
+ - If conflict resolution leaves a public PR with no content changes, completion
13
+ requires manual review. Do not assume GitHub can squash an empty PR or silently
14
+ treat the original private change as published. Cancellation is not automated.
15
+ - A conflicting expected tree can use the original promotion tree only when both
16
+ sides agree on every path changed by already-integrated public commits. Other
17
+ cases require manual synchronization; an unguarded historical base can lose fixes.
18
+ - Public main supplies the running controller. The PR introducing a new version
19
+ still uses the previous controller until merged. A blocked rollout can require
20
+ a separate public maintenance PR, with public CI and normal review.
21
+ """
22
+
23
+ import argparse
24
+ import json
25
+ import os
26
+ from pathlib import Path
27
+ import re
28
+ import subprocess
29
+ from urllib.parse import urlencode
30
+
31
+
32
+ PUBLIC = "wonderalexandre/MTLearn"
33
+ PRIVATE = "wonderalexandre/MTLearn-dev"
34
+ SYNC_BRANCH = "sync/public-main"
35
+ PROMOTION_PREFIX = "promotion/private-pr-"
36
+ MARKER = re.compile(r"<!-- mtlearn-promotion: (\{[^\n]+\}) -->")
37
+ PUBLISHED_MARKER = re.compile(r"<!-- mtlearn-already-published: (\{[^\n]+\}) -->")
38
+ APPROVED_MERGE_RECOVERIES = {
39
+ "5fa238708ab0a903d1c4e8a9e80520ba1a91ade6": (
40
+ 8,
41
+ "47e9d95b98e84034c3cda2dc34ea297144a01b7b",
42
+ "fa09ef45af13afee38c07512441d72d372ba3c28",
43
+ ),
44
+ }
45
+
46
+
47
+ class PromotionError(RuntimeError):
48
+ pass
49
+
50
+
51
+ class MergeConflict(PromotionError):
52
+ pass
53
+
54
+
55
+ def command(args, *, cwd=None, data=None, check=True):
56
+ result = subprocess.run(args, cwd=cwd, input=data, text=True, capture_output=True)
57
+ if check and result.returncode:
58
+ raise PromotionError(result.stderr.strip() or result.stdout.strip())
59
+ return result
60
+
61
+
62
+ class GitHub:
63
+ def api(self, path, method="GET", data=None):
64
+ args = ["gh", "api", "--method", method, path]
65
+ if data is not None:
66
+ args += ["--input", "-"]
67
+ result = command(args, data=json.dumps(data) if data is not None else None)
68
+ return json.loads(result.stdout) if result.stdout.strip() else None
69
+
70
+ def pages(self, path, **query):
71
+ rows = []
72
+ for page in range(1, 10001):
73
+ batch = self.api(path + "?" + urlencode(dict(query, per_page=100, page=page)))
74
+ rows.extend(batch)
75
+ if len(batch) < 100:
76
+ return rows
77
+ raise PromotionError("Pagination limit exceeded.")
78
+
79
+ def pull(self, repo, number):
80
+ return self.api(f"repos/{repo}/pulls/{number}")
81
+
82
+ def find_pull(self, repo, branch, state="all"):
83
+ rows = self.pages(
84
+ f"repos/{repo}/pulls", state=state, base="main",
85
+ head=f"{repo.split('/')[0]}:{branch}",
86
+ )
87
+ if len(rows) > 1:
88
+ raise PromotionError(f"Multiple PRs use {repo}:{branch}; resolve them first.")
89
+ return rows[0] if rows else None
90
+
91
+ def auto_merge(self, repo, pull, method):
92
+ args = ["gh", "pr", "merge", str(pull["number"]), "--repo", repo,
93
+ "--" + method, "--match-head-commit", pull["head"]["sha"]]
94
+ if repo == PUBLIC:
95
+ if pull.get("auto_merge"):
96
+ return
97
+ args.append("--auto")
98
+ elif repo != PRIVATE or pull["head"]["ref"] != SYNC_BRANCH or method != "merge":
99
+ raise PromotionError("Only the reserved private synchronization PR can merge directly.")
100
+ # Private returns have no required CI; GitHub rejects --auto when already clean.
101
+ command(args)
102
+
103
+ def request_sync(self):
104
+ self.api(f"repos/{PUBLIC}/dispatches", "POST", {"event_type": "sync-private"})
105
+
106
+ def resume_queue(self):
107
+ self.api(f"repos/{PUBLIC}/dispatches", "POST", {"event_type": "resume-promotion"})
108
+
109
+
110
+ class Git:
111
+ def __init__(self, root="."):
112
+ self.root = root
113
+
114
+ def run(self, *args, check=True):
115
+ return command(["git", *args], cwd=self.root, check=check)
116
+
117
+ def text(self, *args):
118
+ return self.run(*args).stdout.strip()
119
+
120
+ def url(self, repo):
121
+ return f"https://github.com/{repo}.git"
122
+
123
+ def fetch_main(self, repo, name):
124
+ self.run("fetch", "--no-tags", self.url(repo),
125
+ f"+refs/heads/main:refs/remotes/{name}/main")
126
+ return self.text("rev-parse", f"refs/remotes/{name}/main")
127
+
128
+ def ancestor(self, older, newer):
129
+ result = self.run("merge-base", "--is-ancestor", older, newer, check=False)
130
+ if result.returncode not in (0, 1):
131
+ raise PromotionError(result.stderr.strip())
132
+ return result.returncode == 0
133
+
134
+ def tree(self, commit):
135
+ return self.text("rev-parse", commit + "^{tree}")
136
+
137
+ def changed_paths(self, left, right):
138
+ result = self.run("diff", "--name-only", "-z", "--no-renames", left, right, "--")
139
+ return {path for path in result.stdout.split("\0") if path}
140
+
141
+ def parents(self, commit):
142
+ return self.text("show", "-s", "--format=%P", commit).split()
143
+
144
+ def remote_branch(self, repo, branch):
145
+ result = self.run("ls-remote", "--exit-code", "--heads",
146
+ self.url(repo), "refs/heads/" + branch,
147
+ check=False)
148
+ if result.returncode == 2:
149
+ return None
150
+ if result.returncode:
151
+ raise PromotionError(result.stderr.strip())
152
+ self.run("fetch", "--no-tags", self.url(repo),
153
+ "refs/heads/" + branch)
154
+ return self.text("rev-parse", "FETCH_HEAD")
155
+
156
+ def pull_head(self, repo, number):
157
+ # GitHub retains this ref after deleting the merged publication branch.
158
+ self.run("fetch", "--no-tags", self.url(repo), f"refs/pull/{number}/head")
159
+ return self.text("rev-parse", "FETCH_HEAD")
160
+
161
+ def merge_tree(self, left, right, *, base=None, context="Merge"):
162
+ args = ["merge-tree", "--write-tree"]
163
+ if base is not None:
164
+ args.append("--merge-base=" + base)
165
+ result = self.run(*args, left, right, check=False)
166
+ details = "\n".join(part.strip() for part in (result.stdout, result.stderr) if part.strip())
167
+ if result.returncode == 1:
168
+ raise MergeConflict(f"{context} has conflicts; resolve them manually.\n{details}")
169
+ if result.returncode:
170
+ raise PromotionError(f"Git merge-tree failed during {context.lower()} "
171
+ f"(exit {result.returncode}).\n{details}")
172
+ return result.stdout.splitlines()[0]
173
+
174
+ def commit_merge(self, left, right, tree, message):
175
+ return self.text("commit-tree", tree, "-p", left, "-p", right, "-m", message)
176
+
177
+ def checkout(self, branch, base):
178
+ self.run("checkout", "-B", branch, base)
179
+
180
+ def replay(self, source, base, *, mainline=None):
181
+ self.checkout("automation-replay", base)
182
+ args = ["cherry-pick", "-x"]
183
+ if mainline is not None:
184
+ args += ["--mainline", str(mainline)]
185
+ result = self.run(*args, source, check=False)
186
+ if result.returncode:
187
+ self.run("cherry-pick", "--abort", check=False)
188
+ raise PromotionError(
189
+ "The approved change cannot be applied to public main. "
190
+ "Resolve the conflict or an already-applied change before retrying.\n"
191
+ + result.stderr.strip()
192
+ )
193
+ return self.text("rev-parse", "HEAD")
194
+
195
+ def push(self, repo, branch, commit, previous=None):
196
+ args = ["-c", "push.followTags=false", "push"]
197
+ # A lease also prevents overwriting a branch created after the initial read.
198
+ args += [f"--force-with-lease=refs/heads/{branch}:{previous or ''}"]
199
+ args += [self.url(repo), f"{commit}:refs/heads/{branch}"]
200
+ self.run(*args)
201
+
202
+
203
+ def read_record(pull, marker, required, optional=()):
204
+ matches = marker.findall(pull.get("body") or "")
205
+ if len(matches) != 1:
206
+ raise PromotionError("Missing or ambiguous promotion metadata.")
207
+ try:
208
+ result = json.loads(matches[0])
209
+ except json.JSONDecodeError as error:
210
+ raise PromotionError("Invalid promotion metadata.") from error
211
+ if (not isinstance(result, dict) or not set(required) <= set(result)
212
+ or not set(result) <= set(required) | set(optional)):
213
+ raise PromotionError("Invalid promotion metadata.")
214
+ if type(result["private_pr"]) is not int or result["private_pr"] <= 0:
215
+ raise PromotionError("Invalid private PR number.")
216
+ for key in set(result) - {"private_pr"}:
217
+ if not isinstance(result[key], str) or not re.fullmatch(r"[0-9a-f]{40}", result[key]):
218
+ raise PromotionError("Invalid promotion object ID.")
219
+ return result
220
+
221
+
222
+ def metadata(pull):
223
+ return read_record(pull, MARKER, {"private_pr", "source", "public_base", "tree"},
224
+ {"promotion_commit"})
225
+
226
+
227
+ def promotion_body(record):
228
+ return (
229
+ "Publish changes approved in the private development repository.\n\n"
230
+ "The public checks must pass before this PR can merge.\n\n"
231
+ "Resolve conflicts with public main in this branch, preserving the original "
232
+ "promotion commit. Closing this PR without merging blocks later publications.\n\n"
233
+ "<!-- mtlearn-promotion: " + json.dumps(record, sort_keys=True) + " -->\n"
234
+ )
235
+
236
+
237
+ def merged(pull):
238
+ return bool(pull.get("merged_at"))
239
+
240
+
241
+ def approved_source_base(git, source, number):
242
+ parents = git.parents(source)
243
+ if len(parents) == 1:
244
+ return parents[0]
245
+ recovery = APPROVED_MERGE_RECOVERIES.get(source)
246
+ if len(parents) != 2 or recovery != (number, *parents):
247
+ return None
248
+ expected = git.merge_tree(parents[0], parents[1], context="Approved merge recovery")
249
+ return parents[0] if expected == git.tree(source) else None
250
+
251
+
252
+ def promotion_origin(git, head, source, number, public_tip, record=None):
253
+ """Validate or recover the original cherry-pick, including interrupted runs."""
254
+ if record and (record["source"] != source or record["private_pr"] != number):
255
+ raise PromotionError("The public PR refers to another private change.")
256
+ source_base = approved_source_base(git, source, number)
257
+ if source_base is None:
258
+ raise PromotionError("The publication source is not an approved private change.")
259
+ public_history = set(git.text("rev-list", "--first-parent", public_tip).splitlines())
260
+ candidates = ([record["promotion_commit"]] if record and "promotion_commit" in record
261
+ else git.text("rev-list", head, "--not", public_tip).splitlines())
262
+ origins = []
263
+ for candidate in candidates:
264
+ parents = git.parents(candidate)
265
+ trailer = f"(cherry picked from commit {source})"
266
+ if (len(parents) != 1 or parents[0] not in public_history
267
+ or not git.ancestor(candidate, head)
268
+ or trailer not in git.text("show", "-s", "--format=%B", candidate).splitlines()):
269
+ continue
270
+ if record and (parents[0] != record["public_base"]
271
+ or git.tree(candidate) != record["tree"]):
272
+ continue
273
+ expected = git.merge_tree(parents[0], source, base=source_base,
274
+ context="Promotion origin reconstruction")
275
+ if git.tree(candidate) == expected:
276
+ origins.append(dict(private_pr=number, source=source, public_base=parents[0],
277
+ tree=expected, promotion_commit=candidate))
278
+ if len(origins) != 1:
279
+ raise PromotionError("The publication history has no unique valid promotion origin; "
280
+ "preserve and review the branch.")
281
+ return origins[0]
282
+
283
+
284
+ def already_published(git, source_pr, public_tip):
285
+ """A durable receipt is accepted only with its original content proof."""
286
+ if "<!-- mtlearn-already-published:" not in (source_pr.get("body") or ""):
287
+ return False
288
+ record = read_record(source_pr, PUBLISHED_MARKER,
289
+ {"private_pr", "source", "public_commit", "tree"})
290
+ source = source_pr["merge_commit_sha"]
291
+ public = record["public_commit"]
292
+ source_base = approved_source_base(git, source, source_pr["number"])
293
+ if (record["private_pr"] != source_pr["number"] or record["source"] != source
294
+ or public not in git.text("rev-list", "--first-parent", public_tip).splitlines()
295
+ or source_base is None
296
+ or record["tree"] != git.tree(public)
297
+ or git.merge_tree(public, source, base=source_base,
298
+ context="Already-published verification") != record["tree"]):
299
+ raise PromotionError("Invalid already-published record on the private PR.")
300
+ return True
301
+
302
+
303
+ def record_already_published(git, github, source_pr, public_tip):
304
+ number, source = source_pr["number"], source_pr["merge_commit_sha"]
305
+ current = github.pull(PRIVATE, number)
306
+ if not merged(current) or current["merge_commit_sha"] != source:
307
+ raise PromotionError("The private PR changed while recording publication; retry.")
308
+ if already_published(git, current, public_tip):
309
+ return
310
+ record = dict(private_pr=number, source=source, public_commit=public_tip,
311
+ tree=git.tree(public_tip))
312
+ body = (current.get("body") or "").rstrip()
313
+ body += "\n\n<!-- mtlearn-already-published: " + json.dumps(record, sort_keys=True) + " -->\n"
314
+ github.api(f"repos/{PRIVATE}/pulls/{number}", "PATCH", {"body": body})
315
+
316
+
317
+ def publication_base(git, source, private_tip, public_history):
318
+ """Find an integrated base on which the original change can still be reviewed.
319
+
320
+ The caller limits history to bases containing every earlier publication.
321
+ A later manual synchronization may have resolved away the original change;
322
+ that is not proof that the change was published and must not skip its review.
323
+ """
324
+ for base in public_history:
325
+ if not git.ancestor(base, private_tip):
326
+ continue
327
+ try:
328
+ tree = git.merge_tree(base, source, base=git.parents(source)[0],
329
+ context="Approved change publication")
330
+ except MergeConflict:
331
+ continue
332
+ if tree != git.tree(base):
333
+ return base
334
+ raise PromotionError("The approved change has no usable integrated public base "
335
+ "containing all earlier publications; review its history manually.")
336
+
337
+
338
+ def promote(git, github, private_tip, public_tip):
339
+ pulls = github.pages(f"repos/{PRIVATE}/pulls", state="closed", base="main")
340
+ pulls = [p for p in pulls if merged(p) and p["head"]["ref"] != SYNC_BRANCH]
341
+ order = git.text("rev-list", "--first-parent", "--reverse", private_tip).splitlines()
342
+ positions = {sha: i for i, sha in enumerate(order)}
343
+ if any(p["merge_commit_sha"] not in positions for p in pulls):
344
+ raise PromotionError("A merged private PR is outside the main history.")
345
+ pulls.sort(key=lambda p: positions[p["merge_commit_sha"]])
346
+ public_history = git.text("rev-list", "--first-parent", public_tip).splitlines()
347
+ public_positions = {sha: i for i, sha in enumerate(public_history)}
348
+ earlier_publications = set()
349
+
350
+ for source_pr in pulls:
351
+ number = source_pr["number"]
352
+ source = source_pr["merge_commit_sha"]
353
+ if already_published(git, source_pr, public_tip):
354
+ earlier_publications.add(read_record(
355
+ source_pr, PUBLISHED_MARKER,
356
+ {"private_pr", "source", "public_commit", "tree"})["public_commit"])
357
+ continue
358
+ branch = PROMOTION_PREFIX + str(number)
359
+ public_pr = github.find_pull(PUBLIC, branch)
360
+ old_record = None
361
+ if public_pr:
362
+ old_record = metadata(public_pr)
363
+ if old_record["source"] != source or old_record["private_pr"] != number:
364
+ raise PromotionError("The public PR refers to another private change.")
365
+ if merged(public_pr):
366
+ published = public_pr["merge_commit_sha"]
367
+ if published not in public_positions:
368
+ raise PromotionError("An earlier publication is outside public main history.")
369
+ earlier_publications.add(published)
370
+ continue
371
+ if public_pr["state"] != "open":
372
+ raise PromotionError(f"Public PR #{public_pr['number']} was closed without merging. "
373
+ "Reopen it to continue; publication cancellation is not supported.")
374
+ if approved_source_base(git, source, number) is None:
375
+ raise PromotionError(f"Private PR #{number} must use squash merge.")
376
+ if any(not git.ancestor(commit, private_tip) for commit in earlier_publications):
377
+ github.request_sync()
378
+ return "Waiting for earlier public promotions to be reconciled into private main."
379
+ previous = git.remote_branch(PUBLIC, branch)
380
+ if public_pr and previous != public_pr["head"]["sha"]:
381
+ raise PromotionError("The publication branch changed or disappeared; retry with a fresh PR head.")
382
+ if previous:
383
+ record = promotion_origin(git, previous, source, number, public_tip, old_record)
384
+ candidate = previous
385
+ else:
386
+ try:
387
+ expected = git.merge_tree(public_tip, source, base=git.parents(source)[0],
388
+ context="Already-published comparison")
389
+ except MergeConflict:
390
+ # A conflict is not an already-published proof. Open a reviewable
391
+ # promotion on a compatible historical base instead.
392
+ expected = None
393
+ if expected == git.tree(public_tip):
394
+ record_already_published(git, github, source_pr, public_tip)
395
+ earlier_publications.add(public_tip)
396
+ continue
397
+ latest_publication_index = min((public_positions[c] for c in earlier_publications),
398
+ default=len(public_history) - 1)
399
+ base = publication_base(git, source, private_tip,
400
+ public_history[:latest_publication_index + 1])
401
+ if len(git.parents(source)) == 1:
402
+ candidate = git.replay(source, base)
403
+ else:
404
+ candidate = git.replay(source, base, mainline=1)
405
+ record = dict(private_pr=number, source=source, public_base=base,
406
+ tree=git.tree(candidate), promotion_commit=candidate)
407
+ if candidate != previous:
408
+ git.push(PUBLIC, branch, candidate, previous)
409
+ if public_pr:
410
+ if old_record != record:
411
+ body = MARKER.sub(lambda _: MARKER.search(promotion_body(record))[0],
412
+ public_pr["body"])
413
+ github.api(f"repos/{PUBLIC}/pulls/{public_pr['number']}", "PATCH", {"body": body})
414
+ public_pr = github.pull(PUBLIC, public_pr["number"])
415
+ else:
416
+ public_pr = github.api(f"repos/{PUBLIC}/pulls", "POST", {
417
+ "head": branch, "base": "main", "title": source_pr["title"],
418
+ "body": promotion_body(record),
419
+ })
420
+ # Keep the original branch and PR available even when updating conflicts.
421
+ # Waiting for all public changes to enter private first would deadlock.
422
+ if not git.ancestor(public_tip, candidate):
423
+ try:
424
+ tree = git.merge_tree(candidate, public_tip, context="Publication branch update")
425
+ except MergeConflict as error:
426
+ raise MergeConflict(
427
+ f"Public PR #{public_pr['number']} needs conflict resolution: "
428
+ f"{public_pr['html_url']}\n{error}"
429
+ ) from error
430
+ updated = git.commit_merge(candidate, public_tip, tree, "Merge public main into promotion")
431
+ if not git.ancestor(candidate, updated):
432
+ raise PromotionError("A publication update must preserve the existing branch history.")
433
+ git.push(PUBLIC, branch, updated, candidate)
434
+ candidate = updated
435
+ public_pr = github.pull(PUBLIC, public_pr["number"])
436
+ if git.tree(candidate) == git.tree(public_tip):
437
+ raise PromotionError(
438
+ f"Public PR #{public_pr['number']} has no remaining content changes: "
439
+ f"{public_pr['html_url']}\nEmpty promotion completion requires manual review; "
440
+ "it is not automatically marked as published or cancelled."
441
+ )
442
+ github.auto_merge(PUBLIC, public_pr, "squash")
443
+ return f"Publication pending: {public_pr['html_url']}"
444
+ return "All merged private PRs have been published."
445
+
446
+
447
+ def verify_published_change(git, github, commit, private_tip, pull, integrated_public):
448
+ """Return the expected tree at the last integrated public main commit.
449
+
450
+ The original marker remains immutable. The integration base can be newer,
451
+ or precede the squash parent when the squash resolves a blocked public change.
452
+ """
453
+ record = metadata(pull)
454
+ source_pr = github.pull(PRIVATE, record["private_pr"])
455
+ source = record["source"]
456
+ source_base = approved_source_base(git, source, record["private_pr"])
457
+ if (not merged(source_pr) or source_pr["base"]["ref"] != "main"
458
+ or source_pr["head"]["ref"] == SYNC_BRANCH
459
+ or source_pr["merge_commit_sha"] != source
460
+ or pull["head"]["ref"] != PROMOTION_PREFIX + str(record["private_pr"])
461
+ or len(git.parents(commit)) != 1
462
+ or source_base is None
463
+ or not git.ancestor(source, private_tip)
464
+ or not git.ancestor(record["public_base"], integrated_public)
465
+ or not git.ancestor(integrated_public, private_tip)
466
+ or not git.ancestor(integrated_public, git.parents(commit)[0])):
467
+ raise PromotionError("The public squash does not match approved private history.")
468
+ head = git.pull_head(PUBLIC, pull["number"])
469
+ if head != pull["head"]["sha"]:
470
+ raise PromotionError("The retained public PR head does not match the merged PR.")
471
+ promotion_origin(git, head, source, record["private_pr"], git.parents(commit)[0], record)
472
+ published = git.merge_tree(git.parents(commit)[0], head, context="Public squash verification")
473
+ if published != git.tree(commit):
474
+ raise PromotionError("The public squash content does not match the merged PR head.")
475
+ try:
476
+ return git.merge_tree(integrated_public, source, base=source_base,
477
+ context="Expected promotion reconstruction")
478
+ except MergeConflict as error:
479
+ # Manual private synchronization can resolve the same conflict later
480
+ # resolved in the public PR. The old base is safe only on paths where
481
+ # these already-integrated public changes now agree on both sides.
482
+ integrated_paths = git.changed_paths(record["public_base"], integrated_public)
483
+ differing_paths = integrated_paths & git.changed_paths(private_tip, commit)
484
+ if differing_paths:
485
+ paths = ", ".join(repr(path) for path in sorted(differing_paths))
486
+ raise MergeConflict(
487
+ "Expected promotion reconstruction has conflicts and the prior public "
488
+ f"changes still differ on: {paths}. Resolve synchronization manually."
489
+ ) from error
490
+ return record["tree"]
491
+
492
+
493
+ def synchronize(git, github, private_tip, public_tip):
494
+ if git.ancestor(public_tip, private_tip):
495
+ github.resume_queue()
496
+ return "Private main already includes public main."
497
+ git.checkout("automation-sync", private_tip)
498
+ commits = git.text("rev-list", "--first-parent", "--reverse",
499
+ private_tip + ".." + public_tip).splitlines()
500
+ history = git.text("rev-list", "--first-parent", public_tip).splitlines()
501
+ integrated_public = next((c for c in history if git.ancestor(c, private_tip)), None)
502
+ if integrated_public is None:
503
+ raise PromotionError("Private main has no integrated public main history.")
504
+ publications = {}
505
+ for commit in commits:
506
+ associated = github.pages(f"repos/{PUBLIC}/commits/{commit}/pulls")
507
+ promotions = [p for p in associated if merged(p)
508
+ and p["merge_commit_sha"] == commit and p["base"]["ref"] == "main"
509
+ and p["head"]["ref"].startswith(PROMOTION_PREFIX)]
510
+ if len(promotions) > 1:
511
+ raise PromotionError("Ambiguous public promotion history.")
512
+ if promotions:
513
+ publications[commit] = promotions[0]
514
+ index = 0
515
+ while index < len(commits):
516
+ # Integrate through the next verified promotion as one unit. Its squash
517
+ # includes preceding public commits and any reviewed conflict resolution.
518
+ # Splitting that unit can conflict before reaching the resolution, or make
519
+ # the original feature impossible to reconstruct on an intermediate base.
520
+ following = next((i for i in range(index, len(commits))
521
+ if commits[i] in publications), None)
522
+ if following is not None:
523
+ index = following
524
+ commit = commits[index]
525
+ current = git.text("rev-parse", "HEAD")
526
+ equivalent = False
527
+ if commit in publications:
528
+ expected = verify_published_change(git, github, commit, current,
529
+ publications[commit], integrated_public)
530
+ equivalent = expected == git.tree(commit)
531
+ if not equivalent:
532
+ tree = git.merge_tree(current, commit, base=expected,
533
+ context="Public corrections and private work")
534
+ else:
535
+ tree = git.merge_tree(current, commit, context="Public synchronization")
536
+ message = "Sync public main: " + commit
537
+ if equivalent:
538
+ git.run("merge", "--strategy=ours", "--no-ff", "-m", message, commit)
539
+ else:
540
+ candidate = git.commit_merge(current, commit, tree, message)
541
+ git.checkout("automation-sync", candidate)
542
+ integrated_public = commit
543
+ index += 1
544
+ candidate = git.text("rev-parse", "HEAD")
545
+ previous = git.remote_branch(PRIVATE, SYNC_BRANCH)
546
+ if (previous and git.ancestor(private_tip, previous) and git.ancestor(public_tip, previous)
547
+ and git.tree(previous) == git.tree(candidate)):
548
+ candidate = previous
549
+ if candidate != previous:
550
+ git.push(PRIVATE, SYNC_BRANCH, candidate, previous)
551
+ sync_pr = github.find_pull(PRIVATE, SYNC_BRANCH, state="open")
552
+ if not sync_pr:
553
+ sync_pr = github.api(f"repos/{PRIVATE}/pulls", "POST", {
554
+ "head": SYNC_BRANCH, "base": "main", "title": "chore: sync public main",
555
+ "body": "Reconcile public main into private main.\n\n"
556
+ "Use a merge commit to retain the public ancestry. "
557
+ "This reserved branch is excluded from publication.\n",
558
+ })
559
+ else:
560
+ sync_pr = github.pull(PRIVATE, sync_pr["number"])
561
+ github.auto_merge(PRIVATE, sync_pr, "merge")
562
+ # The reserved private PR merges directly, without --auto. Dispatch only
563
+ # after that operation succeeds; private Actions cannot wake the public queue.
564
+ github.resume_queue()
565
+ return f"Synchronization completed; publication queue resumed: {sync_pr['html_url']}"
566
+
567
+
568
+ def write_summary(message):
569
+ if os.environ.get("GITHUB_STEP_SUMMARY"):
570
+ with Path(os.environ["GITHUB_STEP_SUMMARY"]).open("a", encoding="utf-8") as stream:
571
+ stream.write(message + "\n")
572
+
573
+
574
+ def main():
575
+ parser = argparse.ArgumentParser(description=__doc__)
576
+ parser.add_argument("mode", choices=("promote", "sync"))
577
+ args = parser.parse_args()
578
+ if os.environ.get("GITHUB_REPOSITORY") != PUBLIC:
579
+ raise PromotionError("Repository automation must run in the public repository.")
580
+ git, github = Git(), GitHub()
581
+ if git.text("status", "--porcelain", "--untracked-files=no"):
582
+ raise PromotionError("The automation checkout must be clean.")
583
+ private_tip = git.fetch_main(PRIVATE, "private")
584
+ public_tip = git.fetch_main(PUBLIC, "public")
585
+ try:
586
+ message = (promote if args.mode == "promote" else synchronize)(
587
+ git, github, private_tip, public_tip)
588
+ except PromotionError as error:
589
+ write_summary(str(error))
590
+ raise
591
+ print(message)
592
+ write_summary(message)
593
+
594
+
595
+ if __name__ == "__main__":
596
+ try:
597
+ main()
598
+ except PromotionError as error:
599
+ raise SystemExit(str(error))