hea-bench 2.6.2__tar.gz → 2.7.2__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 (182) hide show
  1. {hea_bench-2.6.2 → hea_bench-2.7.2}/CHANGELOG.md +156 -0
  2. {hea_bench-2.6.2 → hea_bench-2.7.2}/CITATION.cff +1 -1
  3. {hea_bench-2.6.2 → hea_bench-2.7.2}/PKG-INFO +75 -40
  4. {hea_bench-2.6.2 → hea_bench-2.7.2}/README.md +66 -38
  5. {hea_bench-2.6.2 → hea_bench-2.7.2}/data/raw/README.md +1 -1
  6. hea_bench-2.7.2/data/raw/borg2020/MPEA_dataset.csv +1546 -0
  7. hea_bench-2.7.2/data/raw/chizhevskiy2026/UPSTREAM_README.md +66 -0
  8. hea_bench-2.7.2/data/raw/chizhevskiy2026/database_of_HEAs.csv +12428 -0
  9. hea_bench-2.7.2/data/raw/pei2020/pei2020_alloys_phases.csv +1253 -0
  10. hea_bench-2.7.2/data/raw/peivaste/fetch.py +80 -0
  11. hea_bench-2.7.2/docs/benchmark-baselines.json +1137 -0
  12. {hea_bench-2.6.2 → hea_bench-2.7.2}/llms.txt +43 -26
  13. {hea_bench-2.6.2 → hea_bench-2.7.2}/pyproject.toml +51 -9
  14. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/__init__.py +5 -2
  15. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/_json.py +15 -0
  16. hea_bench-2.7.2/src/hea_bench/_model_cache.py +46 -0
  17. hea_bench-2.7.2/src/hea_bench/_overrides.py +24 -0
  18. hea_bench-2.7.2/src/hea_bench/_paths.py +66 -0
  19. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/consolidate.py +24 -16
  20. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/corpus.py +5 -1
  21. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/loaders/chizhevskiy2026.py +6 -0
  22. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/composition.py +84 -21
  23. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/corpus/__init__.py +121 -21
  24. hea_bench-2.7.2/src/hea_bench/custom.py +136 -0
  25. hea_bench-2.7.2/src/hea_bench/descriptors/_tables.py +28 -0
  26. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/backend.py +2 -1
  27. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/data/pair_enthalpies.py +5 -1
  28. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/elastic.py +2 -1
  29. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/electronegativity.py +10 -5
  30. hea_bench-2.7.2/src/hea_bench/descriptors/elements.py +132 -0
  31. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/entropy.py +2 -0
  32. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/gamma.py +4 -3
  33. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/lam.py +2 -1
  34. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/melting.py +4 -3
  35. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/miedema.py +14 -3
  36. hea_bench-2.7.2/src/hea_bench/descriptors/miedema_decomposition.py +303 -0
  37. hea_bench-2.7.2/src/hea_bench/descriptors/omega.py +168 -0
  38. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/phi.py +9 -3
  39. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/size.py +5 -4
  40. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/vec.py +4 -3
  41. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/design/search.py +31 -3
  42. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/mcp_server.py +602 -179
  43. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/properties/__init__.py +2 -1
  44. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/properties/borg.py +2 -2
  45. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/properties/hardness.py +9 -2
  46. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/properties/tier_a.py +4 -1
  47. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/rules/guo_vec.py +32 -1
  48. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/rules/king_phi.py +2 -1
  49. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/rules/senkov_kappa.py +38 -2
  50. hea_bench-2.7.2/src/hea_bench/rules/sheikh_ductility.py +58 -0
  51. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/rules/tsai_sigma.py +2 -1
  52. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/rules/yang_omega.py +2 -1
  53. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/rules/ye_phi.py +2 -1
  54. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/rules/yeh_smix.py +2 -1
  55. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/rules/zhang_delta.py +2 -1
  56. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/uncertainty/applicability.py +4 -2
  57. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/uncertainty/coverage.py +10 -0
  58. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/uncertainty/phase.py +31 -6
  59. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/webapp.py +82 -49
  60. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/app_smoke.cjs +91 -9
  61. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/data/_sync_js_provenance.py +4 -1
  62. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/data/_sync_js_tables.py +5 -45
  63. hea_bench-2.7.2/tests/data/feature_parity.json +544 -0
  64. hea_bench-2.7.2/tests/data/formula_parity_cases.json +40 -0
  65. hea_bench-2.7.2/tests/package_smoke.py +165 -0
  66. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_app_smoke.py +6 -1
  67. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_applicability.py +2 -2
  68. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_benchmark_corpus.py +1 -2
  69. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_chizhevskiy_loader.py +4 -3
  70. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_composition.py +61 -1
  71. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_conformal.py +26 -0
  72. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_corpus.py +38 -2
  73. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_design_search.py +21 -0
  74. hea_bench-2.7.2/tests/test_desktop_smoke.py +79 -0
  75. hea_bench-2.6.2/tests/test_app_parity.py → hea_bench-2.7.2/tests/test_feature_parity.py +58 -19
  76. hea_bench-2.7.2/tests/test_installed_package.py +88 -0
  77. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_kappa_sigma_ductility.py +27 -0
  78. hea_bench-2.7.2/tests/test_mcp_app_features.py +227 -0
  79. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_mcp_expansion.py +1 -1
  80. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_mcp_server.py +12 -9
  81. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_provenance_data.py +15 -0
  82. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_web_miedema.py +43 -0
  83. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_web_parity.py +53 -6
  84. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_webapp.py +48 -1
  85. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/web_engine_snapshot.cjs +6 -2
  86. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/web_parity_snapshot.cjs +15 -2
  87. {hea_bench-2.6.2 → hea_bench-2.7.2}/web/README.md +27 -18
  88. hea_bench-2.6.2/src/hea_bench/descriptors/omega.py +0 -77
  89. hea_bench-2.6.2/src/hea_bench/rules/sheikh_ductility.py +0 -42
  90. hea_bench-2.6.2/tests/data/app_parity.json +0 -251
  91. {hea_bench-2.6.2 → hea_bench-2.7.2}/.gitignore +0 -0
  92. {hea_bench-2.6.2 → hea_bench-2.7.2}/LICENSE +0 -0
  93. {hea_bench-2.6.2 → hea_bench-2.7.2}/data/raw/borg2020/README.md +0 -0
  94. {hea_bench-2.6.2 → hea_bench-2.7.2}/data/raw/chizhevskiy2026/README.md +0 -0
  95. {hea_bench-2.6.2 → hea_bench-2.7.2}/data/raw/pei2020/README.md +0 -0
  96. {hea_bench-2.6.2 → hea_bench-2.7.2}/data/raw/peivaste/README.md +0 -0
  97. {hea_bench-2.6.2 → hea_bench-2.7.2}/examples/README.md +0 -0
  98. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/__init__.py +0 -0
  99. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/baselines.py +0 -0
  100. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/evaluate.py +0 -0
  101. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/frozen.py +0 -0
  102. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/loaders/__init__.py +0 -0
  103. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/loaders/borg2020.py +0 -0
  104. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/loaders/pei2020.py +0 -0
  105. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/loaders/peivaste.py +0 -0
  106. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/metrics.py +0 -0
  107. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/splits.py +0 -0
  108. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/taxonomy.py +0 -0
  109. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/ceramics/__init__.py +0 -0
  110. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/cli.py +0 -0
  111. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/constants.py +0 -0
  112. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/__init__.py +0 -0
  113. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/data/LICENSE.matminer.txt +0 -0
  114. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/data/README.md +0 -0
  115. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/data/__init__.py +0 -0
  116. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/data/elemental.py +0 -0
  117. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/data/mechanics.py +0 -0
  118. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/data/miedema_parameters.csv +0 -0
  119. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/data/pair_enthalpies.tsv +0 -0
  120. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/data/provenance.py +0 -0
  121. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/design/__init__.py +0 -0
  122. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/design/campaign.py +0 -0
  123. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/design/constraints.py +0 -0
  124. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/oxides/__init__.py +0 -0
  125. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/oxides/_data.py +0 -0
  126. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/oxides/data/LICENSE.pymatgen.txt +0 -0
  127. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/oxides/data/README.md +0 -0
  128. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/oxides/data/oxide_elements.json +0 -0
  129. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/oxides/descriptors.py +0 -0
  130. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/oxides/families.py +0 -0
  131. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/oxides/radii.py +0 -0
  132. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/oxides/states.py +0 -0
  133. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/properties/data/__init__.py +0 -0
  134. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/properties/data/atomic_masses.py +0 -0
  135. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/properties/data/element_prices.py +0 -0
  136. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/rules/__init__.py +0 -0
  137. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/uncertainty/__init__.py +0 -0
  138. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/uncertainty/conformal.py +0 -0
  139. {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/uncertainty/splitting.py +0 -0
  140. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/__init__.py +0 -0
  141. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/conftest.py +0 -0
  142. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/data/_build_parity_cases.py +0 -0
  143. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/data/_sync_js_oxide_tables.py +0 -0
  144. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/data/_vendor_oxide_data.py +0 -0
  145. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/data/web_engine_calls.json +0 -0
  146. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/data/web_oxide_parity_cases.json +0 -0
  147. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/data/web_parity_cases.json +0 -0
  148. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/data/web_properties_parity_cases.json +0 -0
  149. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_benchmark_evaluate.py +0 -0
  150. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_benchmark_metrics.py +0 -0
  151. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_benchmark_splits.py +0 -0
  152. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_campaign.py +0 -0
  153. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_ceramics.py +0 -0
  154. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_cli.py +0 -0
  155. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_consolidate_errors.py +0 -0
  156. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_descriptor_backend.py +0 -0
  157. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_descriptors_simple.py +0 -0
  158. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_elastic.py +0 -0
  159. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_element_expansion.py +0 -0
  160. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_entropy.py +0 -0
  161. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_lambda_gamma.py +0 -0
  162. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_mechanics_data.py +0 -0
  163. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_miedema_and_omega.py +0 -0
  164. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_oxides.py +0 -0
  165. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_pair_enthalpies.py +0 -0
  166. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_phi.py +0 -0
  167. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_phi_rules.py +0 -0
  168. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_properties_borg.py +0 -0
  169. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_properties_cost.py +0 -0
  170. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_properties_hardness.py +0 -0
  171. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_properties_tier_a.py +0 -0
  172. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_rules.py +0 -0
  173. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_smoke.py +0 -0
  174. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_version_sync.py +0 -0
  175. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_web_engine.py +0 -0
  176. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_web_oxides_parity.py +0 -0
  177. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_web_properties_parity.py +0 -0
  178. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_yang_zhang_anchors.py +0 -0
  179. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/web_miedema_snapshot.cjs +0 -0
  180. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/web_oxides_snapshot.cjs +0 -0
  181. {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/web_properties_snapshot.cjs +0 -0
  182. {hea_bench-2.6.2 → hea_bench-2.7.2}/web/mathjax/LICENSE +0 -0
@@ -10,6 +10,162 @@ The format is loosely based on
10
10
 
11
11
  ## [Unreleased]
12
12
 
13
+ ## [2.7.2] — 2026-10-06
14
+
15
+ ### Fixed
16
+
17
+ - The landing page said the Dataset tab holds 7,783 alloys, the size of
18
+ corpus v0.1.0. The tab has opened on v0.2.0, 10,290 alloys, since
19
+ 2.7.0. A test now ties that number to the corpus the tab opens.
20
+ - Documentation that still called corpus v0.2.0 opt-in, or called the
21
+ Chizhevskiy rows in group notation unparseable, now matches 2.7.1.
22
+ Those rows parse, and the loader keeps them out because v0.2.0 is
23
+ frozen.
24
+
25
+ ## [2.7.1] — 2026-10-06
26
+
27
+ 2.7.1 is the first published 2.7 release. GitHub refused the v2.7.0 tag
28
+ push, so 2.7.0 reached only the web site. 2.7.1 contains everything
29
+ listed under 2.7.0 plus the changes below, which answer an outside
30
+ review of the app and the library.
31
+
32
+ ### Added
33
+
34
+ - **Every function that takes a composition also takes a formula
35
+ string.** `hb.smix("CoCrFeMnNi")` raised `AttributeError` before and
36
+ now equals `hb.smix(hb.parse_formula("CoCrFeMnNi"))`. A test fails for
37
+ any public composition function that does not accept a formula.
38
+ - **Group notation**, in all four parts. `(CoCrFeNi)95Al5` is 95 parts
39
+ equimolar CoCrFeNi plus 5 parts Al, the usual HEA convention, and
40
+ groups nest. Repeated elements add up, so `CoCrFeNiNi` is Ni at
41
+ 40 at.%. The app now uses the library's parser, and a shared case list
42
+ keeps the Python and browser parsers identical.
43
+ - **Rule notes.** Guo VEC flags a VEC within 0.2 of its 8.0 or 6.87
44
+ cutoff (`guo_vec.boundary_note`), where the published data scatter.
45
+ The verdict itself is unchanged, because the benchmark measures it.
46
+ Senkov κ names the pair it takes ΔH_IM from (`im_pair`) and adds a
47
+ note when that pair has an element under 10 at.%, because κ does not
48
+ weight the pair by amount.
49
+ - **Composition search shows each candidate's predicted phase**, the
50
+ four-class prediction set, in the library, the MCP `design_search`
51
+ tool and the app. The app's example search now caps Al at 20 at.% and
52
+ uses 4 or 5 elements, so it no longer opens on alloys of 40 to 70%
53
+ Al.
54
+ - `predict_phase_set` reports the coverage the coverage study measured
55
+ for corpus v0.1.0 at the chosen confidence, inside and outside the
56
+ dataset's range (`measured_coverage`).
57
+
58
+ ### Changed
59
+
60
+ - **Sheikh ductility returns `not_applicable` for any alloy with an
61
+ element outside Ti, Zr, Hf, V, Nb, Ta, Cr, Mo and W**, the refractory
62
+ alloys the screen was built on. It used to give a verdict for alloys
63
+ such as CoCrFeMnNi.
64
+ - The domain flag reads "Inside the dataset's range?" instead of
65
+ "Resembles the dataset?". Inside the range it gives the measured
66
+ coverage of the 90% sets on unseen alloy systems (87.5% for single
67
+ versus multi-phase, 82.9% for the structure), so a yes is not read as
68
+ a promise of accuracy.
69
+ - **The desktop app starts its engine by itself.** The engine has always
70
+ been inside the exe. The app now also fetches the Peivaste source file
71
+ by itself the first time it is online, checks it and keeps it, so the
72
+ whole app works offline after that. That file cannot ship inside the
73
+ exe until its authors license it for redistribution. Until the app
74
+ has been online once, the hardness prediction still works, because it
75
+ needs only data inside the app, and the phase and dataset cards say
76
+ what they are waiting for. The website's Start button behaves the
77
+ same way.
78
+ - The Benchmark tab leads with each model's two scores and the gap.
79
+ - The app's footer says "Runs on this device" instead of "Offline",
80
+ which read like a warning.
81
+
82
+ ### Fixed
83
+
84
+ - A permalink always opens in alloy mode, even when the page was last
85
+ in Oxides mode.
86
+ - A formula that fails to parse clears the previous results instead of
87
+ leaving them up beside the error.
88
+ - The app merges repeated elements (`CoCrFeNiNi`) instead of rejecting
89
+ them as duplicates.
90
+ - Amounts with more than two decimals reach the result, its result ID
91
+ and the permalink unrounded. The table's 0.01 at.% display rounding
92
+ used to change them.
93
+ - The calculator shows one melting-temperature card, in K and °C,
94
+ instead of two.
95
+ - The release bot retries the tag push, which GitHub refused once for
96
+ v2.7.0.
97
+
98
+ The experimental corpus is unchanged. The Chizhevskiy loader keeps rows
99
+ written in group notation out, so corpus v0.2.0 stays byte-identical,
100
+ and adding them is left for a future corpus version.
101
+
102
+ ## [2.7.0] — 2026-10-06
103
+
104
+ ### Added
105
+
106
+ - **Every feature is now in all four parts**: the Python package, the
107
+ MCP server, the website and the desktop app. A person only needs to
108
+ pick one of them. This is a standing project rule from now on, and CI
109
+ enforces it (see the last item below).
110
+ - **The MCP server has every feature of the package: 24 tools, up from
111
+ 13.** New tools: `ceramic_report`, `element_data`, `corpus_build`,
112
+ `corpus_export`, `measured_properties`, `predict_phase_set`,
113
+ `benchmark_summary`, `benchmark_run`, `benchmark_folds`,
114
+ `benchmark_score` and `coverage_study`. `alloy_descriptors` now
115
+ returns the Miedema formation enthalpies, and `alloy_descriptors`,
116
+ `alloy_rules` and `omega_sensitivity` accept custom elements and pair
117
+ enthalpies. `campaign_suggest` also accepts a campaign inline. The
118
+ server moves to the official MCP Python SDK 2.x (`mcp>=2.3,<3`), and
119
+ the `mcp` extra now includes scikit-learn, so hardness, phase sets and
120
+ campaigns work from a registry install.
121
+ - **The dataset works from a plain pip install.** The wheel ships the
122
+ openly licensed source datasets, and `hea_bench.corpus.build_corpus()`
123
+ downloads the one file that declares no license (Peivaste), checks its
124
+ SHA-256 and builds every corpus version in a per-user folder. The MCP
125
+ `corpus_build` tool does the same.
126
+ - **Library functions for what only the apps had:**
127
+ `hea_bench.custom_data()` (your own elements and pair enthalpies, for
128
+ any descriptor or rule), `hea_bench.omega_sensitivity()`,
129
+ `hea_bench.descriptors.miedema_decomposition` and
130
+ `hea_bench.descriptors.elements.element_data()`.
131
+ - `pip install "hea-bench[all]"` installs everything. Python 3.13 and
132
+ 3.14 are now tested and declared.
133
+ - New checks that keep the four parts equal.
134
+ `tests/test_feature_parity.py` (formerly `test_app_parity.py`) fails CI
135
+ unless every feature has its library function, its MCP tool, a working
136
+ app surface and tests. The CI `package` job builds the wheel, installs
137
+ it fresh and calls every MCP tool over stdio
138
+ (`tests/test_installed_package.py`, also run by the pre-push
139
+ preflight). The release `desktop-build` job uses every tab inside the
140
+ built exe before attaching it (`tests/test_desktop_smoke.py`). The
141
+ preflight also checks that the MCP container image receives every file
142
+ the wheel bundles.
143
+
144
+ ### Changed
145
+
146
+ - **The app is much smoother.** It keeps its fitted models (hardness,
147
+ phase sets, the dataset check) in the browser between visits, so a
148
+ returning visitor gets predictions about a second after the engine
149
+ starts instead of waiting about 18 seconds for refits. The engine
150
+ prepares models in the background while the page is idle, starts by
151
+ itself for returning visitors, and long tables no longer stall tab
152
+ switches.
153
+ - **The dataset opens on corpus v0.2.0, the largest (10,290 alloys)**,
154
+ in `load_corpus()`, the app's Dataset tab and the MCP corpus tools.
155
+ The benchmark, the phase predictions and the domain flag stay on the
156
+ reference corpus v0.1.0, so every published number is unchanged.
157
+ - The in-app engine runs Pyodide 0.29.5 (was 0.29.3), the desktop app
158
+ uses Tauri 2.12.1 (was 2.11.2) without the unused logging plugin, the
159
+ MCP container image uses Python 3.13, and every GitHub Action is on
160
+ its current major version.
161
+
162
+ ### Fixed
163
+
164
+ - The data-file fingerprints the app shows now match the ones the
165
+ library reports on every platform. They were computed from a Windows
166
+ checkout's line endings; they now use the bytes git stores. The data
167
+ itself is unchanged.
168
+
13
169
  ## [2.6.2] — 2026-10-06
14
170
 
15
171
  ### Added
@@ -50,7 +50,7 @@ keywords:
50
50
  - alloy design
51
51
  license: MIT
52
52
  repository-code: 'https://github.com/dfieser/hea-bench'
53
- version: 2.6.2
53
+ version: 2.7.2
54
54
  date-released: '2026-10-06'
55
55
  doi: 10.5281/zenodo.20346287
56
56
  identifiers:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: hea-bench
3
- Version: 2.6.2
3
+ Version: 2.7.2
4
4
  Summary: An open, interpretable calculator of high-entropy-alloy and high-entropy-oxide thermodynamic and geometric descriptors plus the canonical empirical phase-prediction rules.
5
5
  Project-URL: Homepage, https://dfieser.github.io/hea-bench/
6
6
  Project-URL: Repository, https://github.com/dfieser/hea-bench
@@ -19,19 +19,26 @@ Classifier: Programming Language :: Python :: 3
19
19
  Classifier: Programming Language :: Python :: 3.10
20
20
  Classifier: Programming Language :: Python :: 3.11
21
21
  Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
22
24
  Classifier: Topic :: Scientific/Engineering :: Chemistry
23
25
  Classifier: Topic :: Scientific/Engineering :: Physics
24
26
  Requires-Python: >=3.10
27
+ Provides-Extra: all
28
+ Requires-Dist: mcp<3,>=2.3; extra == 'all'
29
+ Requires-Dist: scikit-learn~=1.7.2; extra == 'all'
25
30
  Provides-Extra: benchmark
26
31
  Requires-Dist: scikit-learn~=1.7.2; extra == 'benchmark'
27
32
  Provides-Extra: dev
33
+ Requires-Dist: build>=1.2; extra == 'dev'
28
34
  Requires-Dist: pytest-cov>=4.0; extra == 'dev'
29
35
  Requires-Dist: pytest>=7.0; extra == 'dev'
30
36
  Requires-Dist: ruff~=0.15.0; extra == 'dev'
31
37
  Provides-Extra: interop
32
38
  Requires-Dist: heacalculator~=2.0.1; extra == 'interop'
33
39
  Provides-Extra: mcp
34
- Requires-Dist: mcp<2,>=1.9.4; extra == 'mcp'
40
+ Requires-Dist: mcp<3,>=2.3; extra == 'mcp'
41
+ Requires-Dist: scikit-learn~=1.7.2; extra == 'mcp'
35
42
  Provides-Extra: properties
36
43
  Requires-Dist: scikit-learn~=1.7.2; extra == 'properties'
37
44
  Description-Content-Type: text/markdown
@@ -90,10 +97,13 @@ For any composition it reports:
90
97
  Yang–Zhang Ω, Pauling electronegativity mismatch Δχ, Mansoori excess
91
98
  entropy S<sub>E</sub>, ΔG<sub>ss</sub>, ΔG<sub>max</sub>, King Φ, Ye φ.
92
99
  - **Phase-prediction rules:** Yeh entropy, Zhang δ, Guo–Liu VEC,
93
- Yang–Zhang Ω, King Φ, Ye φ.
94
- - **Miedema formation enthalpies** (browser/desktop apps): compound /
95
- solid-solution / amorphous, decomposed into chemical, elastic,
96
- structural, and topological terms.
100
+ Yang–Zhang Ω, King Φ, Ye φ, Senkov–Miracle κ, the Tsai σ-phase
101
+ window and Sheikh ductility.
102
+ - **Miedema formation enthalpies:** compound / solid-solution /
103
+ amorphous, decomposed into chemical, elastic, structural, and
104
+ topological terms.
105
+ - **Your own elements and pair values:** any descriptor or rule, for a
106
+ composition with an element or pair enthalpy that is not tabulated.
97
107
  - **High-entropy oxides** (`hea_bench.oxides` + the apps' Oxides mode):
98
108
  rock-salt, perovskite, fluorite, and pyrochlore formability
99
109
  descriptors over Shannon ionic radii with automatic charge-balance
@@ -125,16 +135,27 @@ flowchart LR
125
135
  D --> E
126
136
  ```
127
137
 
128
- ## Four ways to run it
138
+ ## Four ways to run it, each with every feature
129
139
 
130
- | Surface | Where | Status |
140
+ | Part | Where | Best for |
131
141
  |---|---|---|
132
- | **Python library + CLI** | `pip install hea-bench` | done, tested |
133
- | **Zero-install browser app** | <https://dfieser.github.io/hea-bench/> · `web/index.html` | done, Python-parity-tested |
134
- | **Native desktop app** | a single portable `.exe`, [download (no install)](https://github.com/dfieser/hea-bench/releases/latest/download/HEA-Bench.exe) (Tauri wrapper of the same page) | done, built from the same parity-tested core |
135
- | **MCP server for AI agents** | `pip install "hea-bench[mcp]"`, then `hea-bench-mcp` | done, thirteen tools over the same core |
136
-
137
- The three surfaces share **one calculation core**. The browser/desktop
142
+ | **Web app** | <https://dfieser.github.io/hea-bench/> | anyone, no install |
143
+ | **Desktop app** | one portable `.exe`, [download (no install)](https://github.com/dfieser/hea-bench/releases/latest/download/HEA-Bench.exe), the same app in its own window, engine inside, works offline | Windows users who want it local |
144
+ | **Python library + CLI** | `pip install "hea-bench[all]"` | scripts and notebooks |
145
+ | **MCP server for AI agents** | `pip install "hea-bench[mcp]"`, then `hea-bench-mcp` | Claude, Cursor and other MCP clients, as 24 tools |
146
+
147
+ Every feature is in all four parts, so pick whichever suits you and you
148
+ lose nothing. That is a standing project rule, and CI enforces it:
149
+ `tests/test_feature_parity.py` fails whenever a public feature lacks
150
+ its library function, its MCP tool or a working app surface, a headless
151
+ browser uses every tab of the built site, the built desktop exe goes
152
+ through the same steps before it is attached to a release, and a
153
+ freshly installed wheel answers every MCP tool. `pip install
154
+ hea-bench` alone has no dependencies and covers everything except the
155
+ fitted models and the MCP server; the `[all]` extra adds scikit-learn
156
+ and the MCP SDK for those.
157
+
158
+ All four share **one calculation core**. The browser/desktop
138
159
  core (`web/hea-calculator-core.js`) is a pure-JS port of the Python
139
160
  library, and `tests/test_web_parity.py` guarantees the two match on all
140
161
  1484 binary pairs and the canonical multi-element fixtures, while
@@ -143,10 +164,7 @@ down to identical warning messages. The app's Dataset, Design and
143
164
  Benchmark tabs and its predictions panel run the Python package itself,
144
165
  unchanged, inside the page (Pyodide, `web/hea-engine-worker.js`), and
145
166
  `tests/test_web_engine.py` checks that it returns exactly what CPython
146
- returns. `tests/test_app_parity.py` fails CI whenever a public library
147
- feature has no working app surface, so the app never falls behind the
148
- library, and before every release a headless browser uses every tab of
149
- the built site the way a person would.
167
+ returns.
150
168
 
151
169
  ## Quick start (Python)
152
170
 
@@ -260,18 +278,22 @@ ceramics datasets: [docs/ceramics.md](docs/ceramics.md).
260
278
  ## Quick start (AI agents, MCP)
261
279
 
262
280
  LLM agents hallucinate descriptor values; this server grounds them.
263
- `hea_bench.mcp_server` exposes the whole workflow over the
264
- [Model Context Protocol](https://modelcontextprotocol.io/) as thirteen
265
- deterministic tools: the original calculator seven
266
- (`parse_composition`, batch `alloy_descriptors` and `alloy_rules`,
267
- `omega_sensitivity`, `oxide_report`, `element_coverage`, `about`) plus
268
- the capability layers (`corpus_query` and `corpus_describe` over the
269
- provenance-tracked experimental corpus, `predict_properties` with
270
- intervals and domain flags at the top level of every payload,
271
- `check_applicability` for the novelty components, `design_search` with
272
- hard caps on palette, step, and candidate count, and
273
- `campaign_suggest` operating on a campaign file the user supplies).
274
- Every response carries units or uncertainty fields, citation keys
281
+ `hea_bench.mcp_server` exposes every feature of the package over the
282
+ [Model Context Protocol](https://modelcontextprotocol.io/) as 24
283
+ deterministic tools. The calculator: `parse_composition`, batch
284
+ `alloy_descriptors` (with the Miedema enthalpies) and `alloy_rules`,
285
+ both taking custom elements and pair values, `omega_sensitivity`,
286
+ `oxide_report`, `ceramic_report`, `element_data` and
287
+ `element_coverage`. The dataset: `corpus_build` (once, to build the
288
+ corpus locally), `corpus_query`, `corpus_describe`, `corpus_export` and
289
+ `measured_properties`. Predictions: `predict_properties` with
290
+ intervals and `predict_phase_set` with prediction sets, both carrying
291
+ the domain flag, and `check_applicability`. Design:
292
+ `design_search`, with hard caps on palette, step and candidate count,
293
+ and `campaign_suggest`, on a campaign file or an inline campaign. The
294
+ benchmark: `benchmark_summary`, `benchmark_run`, `benchmark_folds`,
295
+ `benchmark_score` and `coverage_study`. And `about`. Every response
296
+ carries units or uncertainty fields, citation keys
275
297
  where a parametrization is involved, and the library version, so an
276
298
  agent's reasoning trace contains auditable receipts rather than bare
277
299
  floats; `about()` reports which capabilities are available in the
@@ -358,10 +380,13 @@ Li et al., *Commun. Mater.* **6**:9 (2025),
358
380
  Baselines, split digests, and full provenance:
359
381
  [`docs/benchmark-baselines.md`](./docs/benchmark-baselines.md).
360
382
 
361
- This surface currently works from a repository checkout only: the
362
- corpus's largest source dataset declares no license, so the corpus is
363
- rebuilt locally from a fetch script and pinned hashes rather than
364
- redistributed (see [`data/raw/README.md`](./data/raw/README.md)).
383
+ The corpus is built on your machine, once, because its largest source
384
+ dataset declares no license and is never redistributed (see
385
+ [`data/raw/README.md`](./data/raw/README.md)).
386
+ `hea_bench.corpus.build_corpus()` downloads that file from its authors'
387
+ repository, accepts it only if its pinned SHA-256 matches, and builds
388
+ every corpus version. The apps and the MCP server's `corpus_build` tool
389
+ do the same.
365
390
 
366
391
  ## The corpus as a standalone product
367
392
 
@@ -371,7 +396,7 @@ addressable directly, with no task or split machinery involved:
371
396
  ```python
372
397
  from hea_bench.corpus import load_corpus
373
398
 
374
- corpus = load_corpus() # v0.1.0, every row, full provenance
399
+ corpus = load_corpus() # v0.2.0 (10,290 alloys), every row, full provenance
375
400
  corpus.describe() # counts, families, agreement rate
376
401
  al_bcc = corpus.query(contains=["Al"], phase="BCC", descriptor_ready=True)
377
402
  al_bcc.rows[0].raw_labels # each source's verbatim reported phase
@@ -383,8 +408,11 @@ processing route and primary-literature DOI where available, and
383
408
  upstream record identifiers, so a label can be audited without leaving
384
409
  the package. Provenance chains, per-source license status,
385
410
  harmonization rules, and known limitations are documented in the
386
- [corpus card](docs/corpus-card.md). The corpus data is still built
387
- locally from the recipe above, for the same licensing reason.
411
+ [corpus card](docs/corpus-card.md). `load_corpus()` opens the largest
412
+ version, v0.2.0, which adds the LLM-extracted Chizhevskiy database.
413
+ `load_corpus(version="0.1.0")` is the hand-curated reference (7,783
414
+ alloys) that the benchmark, the phase predictions and the domain flag
415
+ always use, so every published number stays put.
388
416
 
389
417
  ## Uncertainty and domain of applicability
390
418
 
@@ -398,7 +426,7 @@ guarantee's exchangeability assumption plausibly holds for your query:
398
426
  from hea_bench.corpus import load_corpus
399
427
  from hea_bench.uncertainty import ConformalClassifier, fit_domain
400
428
 
401
- domain = fit_domain(load_corpus())
429
+ domain = fit_domain(load_corpus(version="0.1.0"))
402
430
  domain.novelty({"Hf": 0.2, "Nb": 0.2, "Ta": 0.2, "Ti": 0.2, "Zr": 0.2})
403
431
  # {'element_set_seen': True, 'family_count': ..., 'nearest_family_distance': 0.0,
404
432
  # 'descriptor_distance': ..., 'element_coverage': True, 'in_domain': True, ...}
@@ -517,11 +545,18 @@ the number does not, so read Ω qualitatively in that regime.
517
545
  hea-bench/
518
546
  ├── src/hea_bench/
519
547
  │ ├── descriptors/ ΔS_mix, δ, VEC, T_m, ΔH_mix, Ω, S_E, φ + data tables
520
- │ ├── rules/ the six empirical phase-prediction rules
548
+ │ ├── rules/ the nine empirical phase-prediction rules
521
549
  │ ├── oxides/ HEO module: families, oxidation-state solver,
522
550
  │ │ Shannon radii (94 elements, vendored from pymatgen)
551
+ │ ├── ceramics/ carbides, nitrides, diborides
552
+ │ ├── corpus/ the experimental corpus: build_corpus, load_corpus
523
553
  │ ├── benchmark/ frozen family-grouped + random paired splits and evaluation
524
- │ │ (repo-only; corpus is built locally, see data/raw/)
554
+ │ ├── properties/ density, melting point, cost, hardness
555
+ │ ├── uncertainty/ conformal sets and intervals, phase sets, domain flag
556
+ │ ├── design/ composition search and campaigns
557
+ │ ├── mcp_server.py the MCP server (hea-bench-mcp)
558
+ │ ├── webapp.py the bridge the in-page engine calls
559
+ │ ├── custom.py custom elements and pair values
525
560
  │ ├── composition.py formula parser, normalizer
526
561
  │ ├── constants.py R = 8.314
527
562
  │ └── cli.py command-line entry point
@@ -52,10 +52,13 @@ For any composition it reports:
52
52
  Yang–Zhang Ω, Pauling electronegativity mismatch Δχ, Mansoori excess
53
53
  entropy S<sub>E</sub>, ΔG<sub>ss</sub>, ΔG<sub>max</sub>, King Φ, Ye φ.
54
54
  - **Phase-prediction rules:** Yeh entropy, Zhang δ, Guo–Liu VEC,
55
- Yang–Zhang Ω, King Φ, Ye φ.
56
- - **Miedema formation enthalpies** (browser/desktop apps): compound /
57
- solid-solution / amorphous, decomposed into chemical, elastic,
58
- structural, and topological terms.
55
+ Yang–Zhang Ω, King Φ, Ye φ, Senkov–Miracle κ, the Tsai σ-phase
56
+ window and Sheikh ductility.
57
+ - **Miedema formation enthalpies:** compound / solid-solution /
58
+ amorphous, decomposed into chemical, elastic, structural, and
59
+ topological terms.
60
+ - **Your own elements and pair values:** any descriptor or rule, for a
61
+ composition with an element or pair enthalpy that is not tabulated.
59
62
  - **High-entropy oxides** (`hea_bench.oxides` + the apps' Oxides mode):
60
63
  rock-salt, perovskite, fluorite, and pyrochlore formability
61
64
  descriptors over Shannon ionic radii with automatic charge-balance
@@ -87,16 +90,27 @@ flowchart LR
87
90
  D --> E
88
91
  ```
89
92
 
90
- ## Four ways to run it
93
+ ## Four ways to run it, each with every feature
91
94
 
92
- | Surface | Where | Status |
95
+ | Part | Where | Best for |
93
96
  |---|---|---|
94
- | **Python library + CLI** | `pip install hea-bench` | done, tested |
95
- | **Zero-install browser app** | <https://dfieser.github.io/hea-bench/> · `web/index.html` | done, Python-parity-tested |
96
- | **Native desktop app** | a single portable `.exe`, [download (no install)](https://github.com/dfieser/hea-bench/releases/latest/download/HEA-Bench.exe) (Tauri wrapper of the same page) | done, built from the same parity-tested core |
97
- | **MCP server for AI agents** | `pip install "hea-bench[mcp]"`, then `hea-bench-mcp` | done, thirteen tools over the same core |
98
-
99
- The three surfaces share **one calculation core**. The browser/desktop
97
+ | **Web app** | <https://dfieser.github.io/hea-bench/> | anyone, no install |
98
+ | **Desktop app** | one portable `.exe`, [download (no install)](https://github.com/dfieser/hea-bench/releases/latest/download/HEA-Bench.exe), the same app in its own window, engine inside, works offline | Windows users who want it local |
99
+ | **Python library + CLI** | `pip install "hea-bench[all]"` | scripts and notebooks |
100
+ | **MCP server for AI agents** | `pip install "hea-bench[mcp]"`, then `hea-bench-mcp` | Claude, Cursor and other MCP clients, as 24 tools |
101
+
102
+ Every feature is in all four parts, so pick whichever suits you and you
103
+ lose nothing. That is a standing project rule, and CI enforces it:
104
+ `tests/test_feature_parity.py` fails whenever a public feature lacks
105
+ its library function, its MCP tool or a working app surface, a headless
106
+ browser uses every tab of the built site, the built desktop exe goes
107
+ through the same steps before it is attached to a release, and a
108
+ freshly installed wheel answers every MCP tool. `pip install
109
+ hea-bench` alone has no dependencies and covers everything except the
110
+ fitted models and the MCP server; the `[all]` extra adds scikit-learn
111
+ and the MCP SDK for those.
112
+
113
+ All four share **one calculation core**. The browser/desktop
100
114
  core (`web/hea-calculator-core.js`) is a pure-JS port of the Python
101
115
  library, and `tests/test_web_parity.py` guarantees the two match on all
102
116
  1484 binary pairs and the canonical multi-element fixtures, while
@@ -105,10 +119,7 @@ down to identical warning messages. The app's Dataset, Design and
105
119
  Benchmark tabs and its predictions panel run the Python package itself,
106
120
  unchanged, inside the page (Pyodide, `web/hea-engine-worker.js`), and
107
121
  `tests/test_web_engine.py` checks that it returns exactly what CPython
108
- returns. `tests/test_app_parity.py` fails CI whenever a public library
109
- feature has no working app surface, so the app never falls behind the
110
- library, and before every release a headless browser uses every tab of
111
- the built site the way a person would.
122
+ returns.
112
123
 
113
124
  ## Quick start (Python)
114
125
 
@@ -222,18 +233,22 @@ ceramics datasets: [docs/ceramics.md](docs/ceramics.md).
222
233
  ## Quick start (AI agents, MCP)
223
234
 
224
235
  LLM agents hallucinate descriptor values; this server grounds them.
225
- `hea_bench.mcp_server` exposes the whole workflow over the
226
- [Model Context Protocol](https://modelcontextprotocol.io/) as thirteen
227
- deterministic tools: the original calculator seven
228
- (`parse_composition`, batch `alloy_descriptors` and `alloy_rules`,
229
- `omega_sensitivity`, `oxide_report`, `element_coverage`, `about`) plus
230
- the capability layers (`corpus_query` and `corpus_describe` over the
231
- provenance-tracked experimental corpus, `predict_properties` with
232
- intervals and domain flags at the top level of every payload,
233
- `check_applicability` for the novelty components, `design_search` with
234
- hard caps on palette, step, and candidate count, and
235
- `campaign_suggest` operating on a campaign file the user supplies).
236
- Every response carries units or uncertainty fields, citation keys
236
+ `hea_bench.mcp_server` exposes every feature of the package over the
237
+ [Model Context Protocol](https://modelcontextprotocol.io/) as 24
238
+ deterministic tools. The calculator: `parse_composition`, batch
239
+ `alloy_descriptors` (with the Miedema enthalpies) and `alloy_rules`,
240
+ both taking custom elements and pair values, `omega_sensitivity`,
241
+ `oxide_report`, `ceramic_report`, `element_data` and
242
+ `element_coverage`. The dataset: `corpus_build` (once, to build the
243
+ corpus locally), `corpus_query`, `corpus_describe`, `corpus_export` and
244
+ `measured_properties`. Predictions: `predict_properties` with
245
+ intervals and `predict_phase_set` with prediction sets, both carrying
246
+ the domain flag, and `check_applicability`. Design:
247
+ `design_search`, with hard caps on palette, step and candidate count,
248
+ and `campaign_suggest`, on a campaign file or an inline campaign. The
249
+ benchmark: `benchmark_summary`, `benchmark_run`, `benchmark_folds`,
250
+ `benchmark_score` and `coverage_study`. And `about`. Every response
251
+ carries units or uncertainty fields, citation keys
237
252
  where a parametrization is involved, and the library version, so an
238
253
  agent's reasoning trace contains auditable receipts rather than bare
239
254
  floats; `about()` reports which capabilities are available in the
@@ -320,10 +335,13 @@ Li et al., *Commun. Mater.* **6**:9 (2025),
320
335
  Baselines, split digests, and full provenance:
321
336
  [`docs/benchmark-baselines.md`](./docs/benchmark-baselines.md).
322
337
 
323
- This surface currently works from a repository checkout only: the
324
- corpus's largest source dataset declares no license, so the corpus is
325
- rebuilt locally from a fetch script and pinned hashes rather than
326
- redistributed (see [`data/raw/README.md`](./data/raw/README.md)).
338
+ The corpus is built on your machine, once, because its largest source
339
+ dataset declares no license and is never redistributed (see
340
+ [`data/raw/README.md`](./data/raw/README.md)).
341
+ `hea_bench.corpus.build_corpus()` downloads that file from its authors'
342
+ repository, accepts it only if its pinned SHA-256 matches, and builds
343
+ every corpus version. The apps and the MCP server's `corpus_build` tool
344
+ do the same.
327
345
 
328
346
  ## The corpus as a standalone product
329
347
 
@@ -333,7 +351,7 @@ addressable directly, with no task or split machinery involved:
333
351
  ```python
334
352
  from hea_bench.corpus import load_corpus
335
353
 
336
- corpus = load_corpus() # v0.1.0, every row, full provenance
354
+ corpus = load_corpus() # v0.2.0 (10,290 alloys), every row, full provenance
337
355
  corpus.describe() # counts, families, agreement rate
338
356
  al_bcc = corpus.query(contains=["Al"], phase="BCC", descriptor_ready=True)
339
357
  al_bcc.rows[0].raw_labels # each source's verbatim reported phase
@@ -345,8 +363,11 @@ processing route and primary-literature DOI where available, and
345
363
  upstream record identifiers, so a label can be audited without leaving
346
364
  the package. Provenance chains, per-source license status,
347
365
  harmonization rules, and known limitations are documented in the
348
- [corpus card](docs/corpus-card.md). The corpus data is still built
349
- locally from the recipe above, for the same licensing reason.
366
+ [corpus card](docs/corpus-card.md). `load_corpus()` opens the largest
367
+ version, v0.2.0, which adds the LLM-extracted Chizhevskiy database.
368
+ `load_corpus(version="0.1.0")` is the hand-curated reference (7,783
369
+ alloys) that the benchmark, the phase predictions and the domain flag
370
+ always use, so every published number stays put.
350
371
 
351
372
  ## Uncertainty and domain of applicability
352
373
 
@@ -360,7 +381,7 @@ guarantee's exchangeability assumption plausibly holds for your query:
360
381
  from hea_bench.corpus import load_corpus
361
382
  from hea_bench.uncertainty import ConformalClassifier, fit_domain
362
383
 
363
- domain = fit_domain(load_corpus())
384
+ domain = fit_domain(load_corpus(version="0.1.0"))
364
385
  domain.novelty({"Hf": 0.2, "Nb": 0.2, "Ta": 0.2, "Ti": 0.2, "Zr": 0.2})
365
386
  # {'element_set_seen': True, 'family_count': ..., 'nearest_family_distance': 0.0,
366
387
  # 'descriptor_distance': ..., 'element_coverage': True, 'in_domain': True, ...}
@@ -479,11 +500,18 @@ the number does not, so read Ω qualitatively in that regime.
479
500
  hea-bench/
480
501
  ├── src/hea_bench/
481
502
  │ ├── descriptors/ ΔS_mix, δ, VEC, T_m, ΔH_mix, Ω, S_E, φ + data tables
482
- │ ├── rules/ the six empirical phase-prediction rules
503
+ │ ├── rules/ the nine empirical phase-prediction rules
483
504
  │ ├── oxides/ HEO module: families, oxidation-state solver,
484
505
  │ │ Shannon radii (94 elements, vendored from pymatgen)
506
+ │ ├── ceramics/ carbides, nitrides, diborides
507
+ │ ├── corpus/ the experimental corpus: build_corpus, load_corpus
485
508
  │ ├── benchmark/ frozen family-grouped + random paired splits and evaluation
486
- │ │ (repo-only; corpus is built locally, see data/raw/)
509
+ │ ├── properties/ density, melting point, cost, hardness
510
+ │ ├── uncertainty/ conformal sets and intervals, phase sets, domain flag
511
+ │ ├── design/ composition search and campaigns
512
+ │ ├── mcp_server.py the MCP server (hea-bench-mcp)
513
+ │ ├── webapp.py the bridge the in-page engine calls
514
+ │ ├── custom.py custom elements and pair values
487
515
  │ ├── composition.py formula parser, normalizer
488
516
  │ ├── constants.py R = 8.314
489
517
  │ └── cli.py command-line entry point
@@ -36,7 +36,7 @@ date and neither repository declared a license.
36
36
  | [`borg2020/`](borg2020/) | Borg *et al.* 2020 (*Sci. Data* 7, 430) | **CC-BY-4.0** (figshare deposit explicitly licensed) | ✓ **Mirrored 2026-05-20.** 1,545 measurement rows / 740 unique (formula, processing) alloys / 23 columns including phase, processing, mechanical properties, and per-row source DOI. The canonical backbone of the benchmark. |
37
37
  | [`pei2020/`](pei2020/) | Pei *et al.* 2020 (*npj Comput. Mater.* 6, 50) | **CC-BY-4.0** (Crossref-confirmed, `tdm` and `vor`, zero delay) | ✓ **Mirrored 2026-05-20.** 1,252 rows, 2 columns (Alloy, Phase), four phase labels (bcc/fcc/hcp/multi-phase). 1,208 unique formulas load after deduplicating 43 repeated formulas and rejecting the malformed `Ta_Th` entry at row 1251. |
38
38
  | [`peivaste/`](peivaste/) | Iman-Peivaste/ML_HEAs_Phase_Dataset (GitHub) + companion Sci. Rep. 13, 22556 (2023) by same authors | **None.** No LICENSE file on the data repository, re-confirmed 2026-08-10. The *Sci. Rep.* article is CC-BY, the GitHub dataset is not covered by it. | **Pointer-only.** `fetch.py` provided, CSV gitignored. Largest single contributor to the corpus, which is why the corpus as a whole cannot be redistributed. |
39
- | [`chizhevskiy2026/`](chizhevskiy2026/) | Chizhevskiy *et al.* 2026 (*Sci. Data* 13, 612), repo Vladimirchizh/hea_database | **CC-BY-4.0**, resolved 2026-08-10: the maintainer merged [hea_database#2](https://github.com/Vladimirchizh/hea_database/pull/2) adding a LICENSE file (GitHub license detection confirms CC-BY-4.0). | ✓ **Mirrored 2026-08-10**, byte-identical to upstream at the pinned SHA-256. 12,427 LLM-extracted records, 2,974 unique parseable alloys. Feeds corpus **v0.2.0 only**; v0.1.0 is frozen without it. Its labels agree with the v0.1.0 consensus on only ~70% of overlapping alloys, so disagreements are quarantined as conflicts and corpus v0.2.0 is opt-in by design; v0.1.0 stays the reference corpus. |
39
+ | [`chizhevskiy2026/`](chizhevskiy2026/) | Chizhevskiy *et al.* 2026 (*Sci. Data* 13, 612), repo Vladimirchizh/hea_database | **CC-BY-4.0**, resolved 2026-08-10: the maintainer merged [hea_database#2](https://github.com/Vladimirchizh/hea_database/pull/2) adding a LICENSE file (GitHub license detection confirms CC-BY-4.0). | ✓ **Mirrored 2026-08-10**, byte-identical to upstream at the pinned SHA-256. 12,427 LLM-extracted records, 2,974 unique alloys in plain formulas (rows in group notation stay out, because v0.2.0 is frozen). Feeds corpus **v0.2.0 only**; v0.1.0 is frozen without it. Its labels agree with the v0.1.0 consensus on only ~70% of overlapping alloys, so disagreements are quarantined as conflicts. Browsing opens on v0.2.0 since 2.7.0, and v0.1.0 stays the reference corpus for the benchmark, the phase predictions and the domain flag. |
40
40
  | [`couzinie2018/`](couzinie2018/) | Couzinié *et al.* 2018 (*Data in Brief* 21, 1622) | CC-BY-4.0 | Acquisition stalled. Elsevier CDN supplementary files are mis-attributed, and the content is mostly subsumed by Borg anyway. **Deprioritized.** See README for log. |
41
41
  | (planned) `miracle_senkov2017/` | Miracle & Senkov 2017 (*Acta Mater.* 122, 448) | Elsevier, to be determined | Not yet attempted |
42
42
  | (planned) `witman/` | mwitman1/HEAphaseML (GitHub) | To be determined | Not yet attempted |