millwright 2.2.0__tar.gz → 2.2.1__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 (94) hide show
  1. millwright-2.2.1/.github/dependabot.yml +59 -0
  2. {millwright-2.2.0 → millwright-2.2.1}/.github/workflows/ci.yml +94 -19
  3. {millwright-2.2.0 → millwright-2.2.1}/.github/workflows/release-crate.yml +1 -1
  4. {millwright-2.2.0 → millwright-2.2.1}/.github/workflows/release-python.yml +13 -13
  5. {millwright-2.2.0 → millwright-2.2.1}/CHANGELOG.md +40 -0
  6. {millwright-2.2.0 → millwright-2.2.1}/CONTRIBUTING.md +2 -1
  7. {millwright-2.2.0 → millwright-2.2.1}/Cargo.lock +1 -1
  8. {millwright-2.2.0 → millwright-2.2.1}/Cargo.toml +1 -1
  9. {millwright-2.2.0 → millwright-2.2.1}/PKG-INFO +1 -1
  10. {millwright-2.2.0 → millwright-2.2.1}/RELEASING.md +10 -5
  11. millwright-2.2.1/deny.toml +34 -0
  12. {millwright-2.2.0 → millwright-2.2.1}/docs/index.html +2 -2
  13. {millwright-2.2.0 → millwright-2.2.1}/guide.html +3 -3
  14. {millwright-2.2.0 → millwright-2.2.1}/index.html +1 -1
  15. {millwright-2.2.0 → millwright-2.2.1}/pyproject.toml +5 -1
  16. millwright-2.2.1/scripts/release.ps1 +64 -0
  17. {millwright-2.2.0 → millwright-2.2.1}/scripts/release.sh +13 -4
  18. millwright-2.2.1/scripts/sync-version.py +80 -0
  19. {millwright-2.2.0 → millwright-2.2.1}/src/ensemble.rs +2 -89
  20. millwright-2.2.1/src/ensemble_tests.rs +87 -0
  21. millwright-2.2.1/src/onnx.rs +349 -0
  22. millwright-2.2.1/src/onnx_native.rs +565 -0
  23. millwright-2.2.1/src/onnx_tests.rs +161 -0
  24. {millwright-2.2.0 → millwright-2.2.1}/src/pipeline.rs +3 -1
  25. {millwright-2.2.0 → millwright-2.2.1}/src/profile.rs +4 -353
  26. millwright-2.2.1/src/profile_render.rs +197 -0
  27. millwright-2.2.1/src/profile_tests.rs +156 -0
  28. {millwright-2.2.0 → millwright-2.2.1}/src/python.rs +3 -161
  29. millwright-2.2.1/src/python_data.rs +163 -0
  30. {millwright-2.2.0 → millwright-2.2.1}/src/table.rs +10 -2
  31. millwright-2.2.1/src/transform.rs +468 -0
  32. millwright-2.2.1/src/transform_advanced.rs +437 -0
  33. millwright-2.2.1/src/transform_tests.rs +196 -0
  34. millwright-2.2.1/tests/python/conftest.py +21 -0
  35. millwright-2.2.1/tests/python/test_frame_and_profile.py +42 -0
  36. millwright-2.2.1/tests/python/test_pipeline.py +46 -0
  37. millwright-2.2.1/tests/python/test_search_and_portability.py +53 -0
  38. millwright-2.2.0/src/onnx.rs +0 -1075
  39. millwright-2.2.0/src/transform.rs +0 -1096
  40. millwright-2.2.0/tests/python_smoke.py +0 -29
  41. {millwright-2.2.0 → millwright-2.2.1}/.cargo/audit.toml +0 -0
  42. {millwright-2.2.0 → millwright-2.2.1}/.gitignore +0 -0
  43. {millwright-2.2.0 → millwright-2.2.1}/CNAME +0 -0
  44. {millwright-2.2.0 → millwright-2.2.1}/GUIDE.md +0 -0
  45. {millwright-2.2.0 → millwright-2.2.1}/LICENSE +0 -0
  46. {millwright-2.2.0 → millwright-2.2.1}/README.md +0 -0
  47. {millwright-2.2.0 → millwright-2.2.1}/benches/throughput.rs +0 -0
  48. {millwright-2.2.0 → millwright-2.2.1}/docs/data.html +0 -0
  49. {millwright-2.2.0 → millwright-2.2.1}/docs/deploy.html +0 -0
  50. {millwright-2.2.0 → millwright-2.2.1}/docs/insight.html +0 -0
  51. {millwright-2.2.0 → millwright-2.2.1}/docs/pipelines.html +0 -0
  52. {millwright-2.2.0 → millwright-2.2.1}/docs/python.html +0 -0
  53. {millwright-2.2.0 → millwright-2.2.1}/docs/site.css +0 -0
  54. {millwright-2.2.0 → millwright-2.2.1}/examples/automl.rs +0 -0
  55. {millwright-2.2.0 → millwright-2.2.1}/examples/backends.rs +0 -0
  56. {millwright-2.2.0 → millwright-2.2.1}/examples/explore.rs +0 -0
  57. {millwright-2.2.0 → millwright-2.2.1}/examples/insight.rs +0 -0
  58. {millwright-2.2.0 → millwright-2.2.1}/examples/operations.rs +0 -0
  59. {millwright-2.2.0 → millwright-2.2.1}/examples/portability.rs +0 -0
  60. {millwright-2.2.0 → millwright-2.2.1}/examples/specialized.rs +0 -0
  61. {millwright-2.2.0 → millwright-2.2.1}/examples/spine.rs +0 -0
  62. {millwright-2.2.0 → millwright-2.2.1}/examples/trust.rs +0 -0
  63. {millwright-2.2.0 → millwright-2.2.1}/examples/workflow.rs +0 -0
  64. {millwright-2.2.0 → millwright-2.2.1}/src/anomaly.rs +0 -0
  65. {millwright-2.2.0 → millwright-2.2.1}/src/automl.rs +0 -0
  66. {millwright-2.2.0 → millwright-2.2.1}/src/backends/chronos.rs +0 -0
  67. {millwright-2.2.0 → millwright-2.2.1}/src/backends/incremental.rs +0 -0
  68. {millwright-2.2.0 → millwright-2.2.1}/src/backends/linfa.rs +0 -0
  69. {millwright-2.2.0 → millwright-2.2.1}/src/backends/mod.rs +0 -0
  70. {millwright-2.2.0 → millwright-2.2.1}/src/backends/smartcore.rs +0 -0
  71. {millwright-2.2.0 → millwright-2.2.1}/src/balance.rs +0 -0
  72. {millwright-2.2.0 → millwright-2.2.1}/src/calibration.rs +0 -0
  73. {millwright-2.2.0 → millwright-2.2.1}/src/diagnostics.rs +0 -0
  74. {millwright-2.2.0 → millwright-2.2.1}/src/error.rs +0 -0
  75. {millwright-2.2.0 → millwright-2.2.1}/src/evaluate.rs +0 -0
  76. {millwright-2.2.0 → millwright-2.2.1}/src/explain.rs +0 -0
  77. {millwright-2.2.0 → millwright-2.2.1}/src/frame.rs +0 -0
  78. {millwright-2.2.0 → millwright-2.2.1}/src/lib.rs +0 -0
  79. {millwright-2.2.0 → millwright-2.2.1}/src/logistic.rs +0 -0
  80. {millwright-2.2.0 → millwright-2.2.1}/src/monitor.rs +0 -0
  81. {millwright-2.2.0 → millwright-2.2.1}/src/registry.rs +0 -0
  82. {millwright-2.2.0 → millwright-2.2.1}/src/rng.rs +0 -0
  83. {millwright-2.2.0 → millwright-2.2.1}/src/selection/cv.rs +0 -0
  84. {millwright-2.2.0 → millwright-2.2.1}/src/selection/mod.rs +0 -0
  85. {millwright-2.2.0 → millwright-2.2.1}/src/selection/scoring.rs +0 -0
  86. {millwright-2.2.0 → millwright-2.2.1}/src/selection/search.rs +0 -0
  87. {millwright-2.2.0 → millwright-2.2.1}/src/serve.rs +0 -0
  88. {millwright-2.2.0 → millwright-2.2.1}/src/traits.rs +0 -0
  89. {millwright-2.2.0 → millwright-2.2.1}/src/viz.rs +0 -0
  90. {millwright-2.2.0 → millwright-2.2.1}/tests/ensemble_zoo.rs +0 -0
  91. {millwright-2.2.0 → millwright-2.2.1}/tests/golden.rs +0 -0
  92. {millwright-2.2.0 → millwright-2.2.1}/tests/hero_snippet.rs +0 -0
  93. {millwright-2.2.0 → millwright-2.2.1}/tests/onnx_export.rs +0 -0
  94. {millwright-2.2.0 → millwright-2.2.1}/tests/real_data.rs +0 -0
@@ -0,0 +1,59 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: cargo
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ open-pull-requests-limit: 5
8
+ groups:
9
+ rust-infrastructure:
10
+ patterns: ["*"]
11
+ exclude-patterns:
12
+ # These crates form type/serialization boundaries with the exact-pinned
13
+ # ML engines. Upgrade them deliberately, with the full feature matrix.
14
+ - "ndarray"
15
+ - "prost"
16
+ - "sha2"
17
+ - "criterion"
18
+ ignore:
19
+ # Engine versions are exact by design. Dependabot PRs cannot safely infer
20
+ # coordinated upgrades across their ndarray and ONNX type boundaries.
21
+ - dependency-name: "ndarray"
22
+ - dependency-name: "prost"
23
+ - dependency-name: "sha2"
24
+ - dependency-name: "criterion"
25
+ - dependency-name: "smartcore"
26
+ - dependency-name: "imbalance-rs"
27
+ - dependency-name: "model-selection-rs"
28
+ - dependency-name: "linfa*"
29
+ - dependency-name: "hyperopt-rs"
30
+ - dependency-name: "regression-diagnostics"
31
+ - dependency-name: "shap-rs"
32
+ - dependency-name: "plotters-statistical"
33
+ - dependency-name: "onnx-export-rs"
34
+ - dependency-name: "driftwatch"
35
+ - dependency-name: "chronos-ts"
36
+ - dependency-name: "incremental-rs"
37
+ - dependency-name: "polars"
38
+ labels: ["dependencies", "rust"]
39
+
40
+ - package-ecosystem: github-actions
41
+ directory: /
42
+ schedule:
43
+ interval: weekly
44
+ groups:
45
+ actions:
46
+ patterns: ["*"]
47
+ exclude-patterns: ["dtolnay/rust-toolchain"]
48
+ ignore:
49
+ # @1.95 is a Rust toolchain selector, not an action release. It is also
50
+ # expressed as an input in CI, but keep this guard against regressions.
51
+ - dependency-name: "dtolnay/rust-toolchain"
52
+ labels: ["dependencies", "github-actions"]
53
+
54
+ - package-ecosystem: pip
55
+ directory: /
56
+ schedule:
57
+ interval: weekly
58
+ open-pull-requests-limit: 3
59
+ labels: ["dependencies", "python"]
@@ -20,11 +20,31 @@ env:
20
20
  RUSTFLAGS: "-D warnings"
21
21
 
22
22
  jobs:
23
+ consistency:
24
+ name: version & links
25
+ runs-on: ubuntu-latest
26
+ steps:
27
+ - uses: actions/checkout@v7
28
+ - uses: actions/setup-python@v7
29
+ with:
30
+ python-version: "3.x"
31
+ - name: verify every public version marker
32
+ run: python scripts/sync-version.py --check
33
+ - name: check local and external HTML links
34
+ uses: lycheeverse/lychee-action@v2
35
+ with:
36
+ args: >-
37
+ --no-progress
38
+ --accept 200,204,206,429
39
+ --retry-wait-time 2
40
+ index.html guide.html docs/*.html README.md CONTRIBUTING.md RELEASING.md
41
+ fail: true
42
+
23
43
  fmt:
24
44
  name: rustfmt
25
45
  runs-on: ubuntu-latest
26
46
  steps:
27
- - uses: actions/checkout@v5
47
+ - uses: actions/checkout@v7
28
48
  - uses: dtolnay/rust-toolchain@stable
29
49
  with:
30
50
  components: rustfmt
@@ -41,7 +61,7 @@ jobs:
41
61
  - features: "" # default features
42
62
  - features: "--features full"
43
63
  steps:
44
- - uses: actions/checkout@v5
64
+ - uses: actions/checkout@v7
45
65
  - uses: dtolnay/rust-toolchain@stable
46
66
  with:
47
67
  components: clippy
@@ -54,7 +74,7 @@ jobs:
54
74
  env:
55
75
  RUSTDOCFLAGS: "-D warnings"
56
76
  steps:
57
- - uses: actions/checkout@v5
77
+ - uses: actions/checkout@v7
58
78
  - uses: dtolnay/rust-toolchain@stable
59
79
  - uses: Swatinem/rust-cache@v2
60
80
  # `full` is every Rust-facing feature (python is a cdylib, doc'd separately
@@ -93,7 +113,7 @@ jobs:
93
113
  # Everything at once — the superset build, including both ndarray worlds.
94
114
  - { name: "full", features: "--features full" }
95
115
  steps:
96
- - uses: actions/checkout@v5
116
+ - uses: actions/checkout@v7
97
117
  - uses: dtolnay/rust-toolchain@stable
98
118
  - uses: Swatinem/rust-cache@v2
99
119
  with:
@@ -110,7 +130,7 @@ jobs:
110
130
  matrix:
111
131
  os: [windows-latest, macos-latest]
112
132
  steps:
113
- - uses: actions/checkout@v5
133
+ - uses: actions/checkout@v7
114
134
  - uses: dtolnay/rust-toolchain@stable
115
135
  - uses: Swatinem/rust-cache@v2
116
136
  - run: cargo test --locked
@@ -119,8 +139,10 @@ jobs:
119
139
  name: minimum Rust 1.95
120
140
  runs-on: ubuntu-latest
121
141
  steps:
122
- - uses: actions/checkout@v5
123
- - uses: dtolnay/rust-toolchain@1.95
142
+ - uses: actions/checkout@v7
143
+ - uses: dtolnay/rust-toolchain@stable
144
+ with:
145
+ toolchain: "1.95"
124
146
  - uses: Swatinem/rust-cache@v2
125
147
  - run: cargo check --locked --all-targets --features full
126
148
 
@@ -128,30 +150,83 @@ jobs:
128
150
  name: advisories
129
151
  runs-on: ubuntu-latest
130
152
  steps:
131
- - uses: actions/checkout@v5
153
+ - uses: actions/checkout@v7
132
154
  - uses: dtolnay/rust-toolchain@stable
133
155
  - run: cargo install cargo-audit --locked
134
156
  - run: cargo audit
135
157
 
158
+ dependency-policy:
159
+ name: dependency policy
160
+ runs-on: ubuntu-latest
161
+ steps:
162
+ - uses: actions/checkout@v7
163
+ - uses: taiki-e/install-action@cargo-deny
164
+ - run: cargo deny check
165
+
166
+ coverage:
167
+ name: coverage
168
+ runs-on: ubuntu-latest
169
+ steps:
170
+ - uses: actions/checkout@v7
171
+ - uses: dtolnay/rust-toolchain@stable
172
+ with:
173
+ components: llvm-tools-preview
174
+ - uses: taiki-e/install-action@cargo-llvm-cov
175
+ - uses: Swatinem/rust-cache@v2
176
+ - name: measure full-feature Rust coverage
177
+ run: cargo llvm-cov --locked --features full --workspace --lcov --output-path lcov.info
178
+ - name: enforce coverage floor
179
+ run: >-
180
+ cargo llvm-cov report --summary-only
181
+ --fail-under-lines 82
182
+ --fail-under-functions 75
183
+ --fail-under-regions 84
184
+ - uses: actions/upload-artifact@v7
185
+ with:
186
+ name: rust-coverage
187
+ path: lcov.info
188
+ if-no-files-found: error
189
+
190
+ branch-coverage:
191
+ name: branch coverage
192
+ runs-on: ubuntu-latest
193
+ steps:
194
+ - uses: actions/checkout@v7
195
+ # LLVM branch instrumentation remains a nightly-only cargo-llvm-cov mode.
196
+ - uses: dtolnay/rust-toolchain@nightly
197
+ with:
198
+ components: llvm-tools-preview
199
+ - uses: taiki-e/install-action@cargo-llvm-cov
200
+ - uses: Swatinem/rust-cache@v2
201
+ with:
202
+ key: branch-coverage
203
+ - name: measure decision coverage
204
+ run: >-
205
+ cargo +nightly llvm-cov --locked --features full --workspace --branch
206
+ --cobertura --output-path branch-coverage.xml
207
+ - uses: actions/upload-artifact@v7
208
+ with:
209
+ name: rust-branch-coverage
210
+ path: branch-coverage.xml
211
+ if-no-files-found: error
212
+
136
213
  semver:
137
214
  name: public API compatibility
138
215
  runs-on: ubuntu-latest
139
216
  steps:
140
- - uses: actions/checkout@v5
217
+ - uses: actions/checkout@v7
141
218
  - uses: dtolnay/rust-toolchain@stable
142
219
  - run: cargo install cargo-semver-checks --locked
143
220
  - run: cargo semver-checks check-release
144
221
 
145
222
  # Compile and *run* the examples (the `test` jobs only build the library and
146
- # its tests), plus a compile-check of the benchmarks. The declared MSRV
147
- # (`rust-version` in Cargo.toml) is enforced by cargo for consumers; we do not
148
- # run a dedicated old-toolchain job, since the floor is dictated entirely by
149
- # transitive engine deps and would otherwise break on every one of their bumps.
223
+ # its tests), plus a compile-check of the benchmarks. The dedicated `msrv`
224
+ # job above proves the declared Rust 1.95 floor independently.
150
225
  examples:
151
226
  name: examples & benches
152
227
  runs-on: ubuntu-latest
153
228
  steps:
154
- - uses: actions/checkout@v5
229
+ - uses: actions/checkout@v7
155
230
  - uses: dtolnay/rust-toolchain@stable
156
231
  - uses: Swatinem/rust-cache@v2
157
232
  - name: run every example
@@ -168,7 +243,7 @@ jobs:
168
243
  name: package (publish dry-run)
169
244
  runs-on: ubuntu-latest
170
245
  steps:
171
- - uses: actions/checkout@v5
246
+ - uses: actions/checkout@v7
172
247
  - uses: dtolnay/rust-toolchain@stable
173
248
  # No rust-cache here: `cargo publish` builds a copy under target/package,
174
249
  # which the cache action's post-step chokes on.
@@ -180,16 +255,16 @@ jobs:
180
255
  name: python wheel
181
256
  runs-on: ubuntu-latest
182
257
  steps:
183
- - uses: actions/checkout@v5
258
+ - uses: actions/checkout@v7
184
259
  - uses: dtolnay/rust-toolchain@stable
185
- - uses: actions/setup-python@v5
260
+ - uses: actions/setup-python@v7
186
261
  with:
187
262
  python-version: "3.9"
188
263
  - uses: Swatinem/rust-cache@v2
189
264
  # The `python` feature can't be linked by `cargo test` (pyo3's
190
265
  # extension-module defers libpython), so it is built the way it ships:
191
266
  # as an abi3 wheel via maturin, then smoke-imported.
192
- - run: pip install maturin
267
+ - run: pip install maturin pytest
193
268
  - run: maturin build --locked --release
194
269
  - run: pip install --find-links target/wheels millwright
195
- - run: python tests/python_smoke.py
270
+ - run: pytest -q tests/python
@@ -19,7 +19,7 @@ jobs:
19
19
  contents: read
20
20
  id-token: write # required for crates.io Trusted Publishing (OIDC)
21
21
  steps:
22
- - uses: actions/checkout@v5
22
+ - uses: actions/checkout@v7
23
23
  - uses: dtolnay/rust-toolchain@stable
24
24
  - uses: Swatinem/rust-cache@v2
25
25
 
@@ -15,7 +15,7 @@ jobs:
15
15
  verify-version:
16
16
  runs-on: ubuntu-latest
17
17
  steps:
18
- - uses: actions/checkout@v5
18
+ - uses: actions/checkout@v7
19
19
  - uses: dtolnay/rust-toolchain@stable
20
20
  - name: check Cargo, Python, and tag versions agree
21
21
  shell: bash
@@ -36,8 +36,8 @@ jobs:
36
36
  matrix:
37
37
  target: [x86_64, aarch64]
38
38
  steps:
39
- - uses: actions/checkout@v5
40
- - uses: actions/setup-python@v5
39
+ - uses: actions/checkout@v7
40
+ - uses: actions/setup-python@v7
41
41
  with:
42
42
  python-version: "3.x"
43
43
  - name: build wheel (${{ matrix.target }})
@@ -48,7 +48,7 @@ jobs:
48
48
  # `[tool.maturin] features = ["python"]` in pyproject.toml selects the
49
49
  # feature; abi3-py39 means one wheel covers Python 3.9+.
50
50
  args: --release --locked --out dist
51
- - uses: actions/upload-artifact@v4
51
+ - uses: actions/upload-artifact@v7
52
52
  with:
53
53
  name: wheels-linux-${{ matrix.target }}
54
54
  path: dist
@@ -61,8 +61,8 @@ jobs:
61
61
  matrix:
62
62
  target: [x64]
63
63
  steps:
64
- - uses: actions/checkout@v5
65
- - uses: actions/setup-python@v5
64
+ - uses: actions/checkout@v7
65
+ - uses: actions/setup-python@v7
66
66
  with:
67
67
  python-version: "3.x"
68
68
  architecture: ${{ matrix.target }}
@@ -71,7 +71,7 @@ jobs:
71
71
  with:
72
72
  target: ${{ matrix.target }}
73
73
  args: --release --locked --out dist
74
- - uses: actions/upload-artifact@v4
74
+ - uses: actions/upload-artifact@v7
75
75
  with:
76
76
  name: wheels-windows-${{ matrix.target }}
77
77
  path: dist
@@ -84,8 +84,8 @@ jobs:
84
84
  matrix:
85
85
  target: [x86_64, aarch64]
86
86
  steps:
87
- - uses: actions/checkout@v5
88
- - uses: actions/setup-python@v5
87
+ - uses: actions/checkout@v7
88
+ - uses: actions/setup-python@v7
89
89
  with:
90
90
  python-version: "3.x"
91
91
  - name: build wheel (${{ matrix.target }})
@@ -93,7 +93,7 @@ jobs:
93
93
  with:
94
94
  target: ${{ matrix.target }}
95
95
  args: --release --locked --out dist
96
- - uses: actions/upload-artifact@v4
96
+ - uses: actions/upload-artifact@v7
97
97
  with:
98
98
  name: wheels-macos-${{ matrix.target }}
99
99
  path: dist
@@ -102,13 +102,13 @@ jobs:
102
102
  needs: verify-version
103
103
  runs-on: ubuntu-latest
104
104
  steps:
105
- - uses: actions/checkout@v5
105
+ - uses: actions/checkout@v7
106
106
  - name: build sdist
107
107
  uses: PyO3/maturin-action@v1
108
108
  with:
109
109
  command: sdist
110
110
  args: --out dist
111
- - uses: actions/upload-artifact@v4
111
+ - uses: actions/upload-artifact@v7
112
112
  with:
113
113
  name: wheels-sdist
114
114
  path: dist
@@ -122,7 +122,7 @@ jobs:
122
122
  permissions:
123
123
  id-token: write # PyPI Trusted Publishing (OIDC) — no stored token
124
124
  steps:
125
- - uses: actions/download-artifact@v4
125
+ - uses: actions/download-artifact@v8
126
126
  with:
127
127
  pattern: wheels-*
128
128
  merge-multiple: true
@@ -6,8 +6,48 @@ All notable changes to Millwright are recorded here. The format follows
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [2.2.1] - 2026-08-24
10
+
11
+ ### Added
12
+ - Enforced line, function, and region coverage floors, plus nightly LLVM branch
13
+ coverage artifacts.
14
+ - Expanded the installed-wheel Python suite to cover validation, classification,
15
+ regression, search, explainability, profiling, and ONNX round trips.
16
+ - Added protected MSRV, branch-coverage, Windows, and macOS checks on `main`.
17
+
18
+ ### Changed
19
+ - Isolated ONNX native execution, profile rendering, advanced transforms, and
20
+ Python data/EDA bindings into focused production modules.
21
+ - Hardened Dependabot so compatibility-boundary and exact-pinned engine upgrades
22
+ remain deliberate, while safe GitHub Actions updates stay automated.
23
+ - Updated GitHub Actions and kept release publishing on trusted OIDC workflows.
24
+
25
+ ### Fixed
26
+ - Version synchronization now includes the root `Cargo.lock` package entry and
27
+ the maintained Python version assertion.
28
+ - Removed the obsolete standalone Python smoke script after migrating CI to the
29
+ pytest behavioral suite.
30
+ - Corrected the MSRV workflow selector so dependency automation cannot rewrite
31
+ Rust 1.95 as an action version.
32
+
9
33
  ## [2.2.0] - 2026-08-24
10
34
 
35
+ ### Added
36
+ - Complete Rust and Python ML lifecycle: typed ingest and EDA, preprocessing,
37
+ model selection and HPO, ensembles, diagnostics and explainability, ONNX
38
+ portability, serving, registry, drift monitoring, specialized estimators, and
39
+ AutoML.
40
+ - Cross-platform Python abi3 wheels and synchronized crates.io/PyPI releases.
41
+
42
+ ### Changed
43
+ - Hardened feature isolation, packaging, MSRV, SemVer, advisory, example, and
44
+ benchmark checks across the full CI matrix.
45
+ - Updated the Python extension to PyO3 0.29 and documented the stable 2.2 API.
46
+
47
+ ### Security
48
+ - Added explicit dependency advisory handling and removed vulnerable PyO3
49
+ releases from the resolved graph.
50
+
11
51
  ## [0.2.1] - 2026-08-23
12
52
 
13
53
  ### Added
@@ -45,7 +45,8 @@ cargo doc --no-deps --features full # with RUSTDOCFLAGS="-D warnings"
45
45
 
46
46
  Maintainers: bump `Cargo.toml` + `pyproject.toml`, roll `CHANGELOG.md`, and tag
47
47
  `vX.Y.Z` — the workflows publish to crates.io and PyPI via OIDC. The helper
48
- `scripts/release.sh X.Y.Z` does the mechanical steps. See
48
+ `scripts/release.sh X.Y.Z` (Linux/macOS) or `scripts/release.ps1 X.Y.Z`
49
+ (Windows) does the mechanical steps. See
49
50
  [`RELEASING.md`](RELEASING.md).
50
51
 
51
52
  ## Scope & conduct
@@ -1975,7 +1975,7 @@ checksum = "38d1115007560874e373613744c6fba374c17688327a71c1476d1a5954cc857b"
1975
1975
 
1976
1976
  [[package]]
1977
1977
  name = "millwright"
1978
- version = "2.2.0"
1978
+ version = "2.2.1"
1979
1979
  dependencies = [
1980
1980
  "axum",
1981
1981
  "chronos-ts",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "millwright"
3
- version = "2.2.0"
3
+ version = "2.2.1"
4
4
  edition = "2021"
5
5
  rust-version = "1.95"
6
6
  description = "A unified ML framework for Rust — proven Rust crates, assembled into one machine."
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: millwright
3
- Version: 2.2.0
3
+ Version: 2.2.1
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: 3
6
6
  Classifier: Intended Audience :: Science/Research
@@ -8,18 +8,23 @@ the same source.
8
8
  With `main` green and `CHANGELOG.md`'s `[Unreleased]` section filled in, run:
9
9
 
10
10
  ```bash
11
- bash scripts/release.sh 0.1.2
11
+ # Linux/macOS
12
+ bash scripts/release.sh 2.2.1
13
+
14
+ # Windows PowerShell
15
+ powershell -File scripts/release.ps1 2.2.1
12
16
  ```
13
17
 
14
- It bumps both manifests, rolls the changelog, syncs `Cargo.lock`, verifies the
15
- package, commits, tags `v0.1.2`, and (after a prompt) pushes — which triggers the
18
+ It synchronizes both manifests and every public HTML version marker, rolls the
19
+ changelog, syncs `Cargo.lock`, verifies the package, commits, tags `v2.2.1`, and
20
+ (after a prompt) pushes — which triggers the
16
21
  publish workflows below. The rest of this file is the manual equivalent.
17
22
 
18
23
  ## Preflight (manual)
19
24
 
20
25
  1. `main` is green in CI and `CHANGELOG.md`'s `[Unreleased]` section is current.
21
- 2. Bump the version in **both** `Cargo.toml` and `pyproject.toml`, move the
22
- changelog's `[Unreleased]` entries under the new version, and commit.
26
+ 2. Run `python scripts/sync-version.py X.Y.Z`, move the changelog's
27
+ `[Unreleased]` entries under the new version, and commit.
23
28
  3. Prove the packaged crate builds exactly as crates.io will build it:
24
29
 
25
30
  ```bash
@@ -0,0 +1,34 @@
1
+ [advisories]
2
+ # Retained only by an inactive optional dependency; absent from every resolved
3
+ # target/feature graph. Keep aligned with .cargo/audit.toml until upstream drops it.
4
+ ignore = ["RUSTSEC-2026-0194", "RUSTSEC-2026-0195"]
5
+ yanked = "deny"
6
+ unused-ignored-advisory = "allow"
7
+
8
+ [licenses]
9
+ confidence-threshold = 0.8
10
+ unused-allowed-license = "allow"
11
+ allow = [
12
+ "Apache-2.0",
13
+ "Apache-2.0 WITH LLVM-exception",
14
+ "BSD-2-Clause",
15
+ "BSD-3-Clause",
16
+ "BSL-1.0",
17
+ "CC0-1.0",
18
+ "ISC",
19
+ "MIT",
20
+ "MPL-2.0",
21
+ "OpenSSL",
22
+ "Unicode-3.0",
23
+ "Zlib",
24
+ ]
25
+
26
+ [bans]
27
+ multiple-versions = "warn"
28
+ wildcards = "deny"
29
+ highlight = "simplest-path"
30
+
31
+ [sources]
32
+ unknown-registry = "deny"
33
+ unknown-git = "deny"
34
+ allow-registry = ["https://github.com/rust-lang/crates.io-index"]
@@ -104,10 +104,10 @@ pipe.fit(&train)?;
104
104
  <p class="muted">Every capability is a feature over one crate. A serving binary never compiles SHAP; a notebook never compiles <code class="inl">axum</code>. <code class="inl">full</code> lights up everything Rust-facing.</p>
105
105
  </div>
106
106
  <pre><span class="c"># just the spine</span>
107
- millwright = { version = <span class="s">"0.1"</span>, default-features = <span class="k">false</span>, features = [<span class="s">"smartcore-backend"</span>] }
107
+ millwright = { version = <span class="s">"2.2.1"</span>, default-features = <span class="k">false</span>, features = [<span class="s">"smartcore-backend"</span>] }
108
108
 
109
109
  <span class="c"># the whole lifecycle</span>
110
- millwright = { version = <span class="s">"0.1"</span>, features = [<span class="s">"full"</span>] }</pre>
110
+ millwright = { version = <span class="s">"2.2.1"</span>, features = [<span class="s">"full"</span>] }</pre>
111
111
  <div class="tablewrap">
112
112
  <table>
113
113
  <thead><tr><th>Feature</th><th>Adds</th></tr></thead>
@@ -1,10 +1,10 @@
1
1
  <!doctype html><html><head><meta charset="utf-8">
2
- <title>Millwright v2.2.0 · Guide</title>
3
- <meta name="millwright-version" content="2.2.0">
2
+ <title>Millwright v2.2.1 · Guide</title>
3
+ <meta name="millwright-version" content="2.2.1">
4
4
  <meta name="viewport" content="width=device-width, initial-scale=1">
5
5
  <meta http-equiv="refresh" content="0; url=docs/index.html">
6
6
  <link rel="canonical" href="docs/index.html">
7
7
  <style>body{margin:0;background:#EEF1F3;color:#556069;font:16px/1.6 system-ui,sans-serif;display:grid;place-items:center;height:100vh}a{color:#94380F}</style>
8
8
  </head><body>
9
- <p>Millwright v2.2.0 guide has moved to <a href="docs/index.html">the docs</a>…</p>
9
+ <p>Millwright v2.2.1 guide has moved to <a href="docs/index.html">the docs</a>…</p>
10
10
  </body></html>
@@ -216,7 +216,7 @@
216
216
 
217
217
  </head><body><header class="top">
218
218
  <div class="wrap">
219
- <div class="brand"><span class="mark">⚙</span>millwright<span class="ver">v2.2.0</span></div>
219
+ <div class="brand"><span class="mark">⚙</span>millwright<span class="ver">v2.2.1</span></div>
220
220
  <nav>
221
221
  <a href="#arch">arch</a>
222
222
  <a href="#api">api</a>
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "millwright"
7
- version = "2.2.0"
7
+ version = "2.2.1"
8
8
  description = "A unified ML framework for Rust — Python bindings over the Rust core."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -24,3 +24,7 @@ Repository = "https://github.com/mi7plus/millwright"
24
24
  # Build the pyo3 extension behind the `python` feature; the module is `millwright`.
25
25
  features = ["python"]
26
26
  module-name = "millwright"
27
+
28
+ [tool.pytest.ini_options]
29
+ testpaths = ["tests/python"]
30
+ addopts = "--strict-markers --strict-config"
@@ -0,0 +1,64 @@
1
+ param(
2
+ [Parameter(Mandatory = $true, Position = 0)]
3
+ [ValidatePattern('^\d+\.\d+\.\d+$')]
4
+ [string]$Version
5
+ )
6
+
7
+ $ErrorActionPreference = 'Stop'
8
+ $root = (git rev-parse --show-toplevel).Trim()
9
+ Set-Location -LiteralPath $root
10
+
11
+ # Codex, Git Bash, and other Unix-flavoured Windows shells can put GNU
12
+ # `link.exe` ahead of Microsoft's linker. Import the official developer-shell
13
+ # environment before invoking Cargo so both link.exe and cl.exe are correct.
14
+ $vswhere = Join-Path ${env:ProgramFiles(x86)} 'Microsoft Visual Studio\Installer\vswhere.exe'
15
+ if (Test-Path -LiteralPath $vswhere) {
16
+ $installation = (& $vswhere -latest -products * -property installationPath).Trim()
17
+ if ($installation) {
18
+ $vsDevCmd = Join-Path $installation 'Common7\Tools\VsDevCmd.bat'
19
+ if (Test-Path -LiteralPath $vsDevCmd) {
20
+ & cmd.exe /d /s /c "`"$vsDevCmd`" -no_logo -arch=x64 && set" |
21
+ ForEach-Object {
22
+ if ($_ -match '^([^=]+)=(.*)$') {
23
+ [Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process')
24
+ }
25
+ }
26
+ }
27
+ }
28
+ }
29
+
30
+ if (git status --porcelain) { throw 'working tree is not clean' }
31
+ if ((git branch --show-current).Trim() -ne 'main') { throw 'not on main' }
32
+ $tag = "v$Version"
33
+ git rev-parse --verify --quiet "refs/tags/$tag" 2>$null
34
+ if ($LASTEXITCODE -eq 0) { throw "tag $tag already exists" }
35
+
36
+ $releaseFiles = @('Cargo.toml', 'Cargo.lock', 'pyproject.toml', 'CHANGELOG.md', 'index.html', 'guide.html', 'docs/index.html', 'tests/python_smoke.py')
37
+ $committed = $false
38
+ try {
39
+ python scripts/sync-version.py $Version
40
+ $date = Get-Date -Format 'yyyy-MM-dd'
41
+ $changelog = Get-Content -Raw CHANGELOG.md
42
+ $changelog = $changelog -replace '## \[Unreleased\]', "## [Unreleased]`n`n## [$Version] - $date"
43
+ [IO.File]::WriteAllText((Join-Path $root 'CHANGELOG.md'), $changelog.Replace("`r`n", "`n"))
44
+
45
+ cargo build --locked
46
+ if ($LASTEXITCODE) { throw 'cargo build failed' }
47
+ cargo publish --dry-run --locked --allow-dirty
48
+ if ($LASTEXITCODE) { throw 'cargo publish dry-run failed' }
49
+
50
+ git add -- $releaseFiles
51
+ git commit -m "Release $Version"
52
+ $committed = $true
53
+ git tag $tag
54
+
55
+ $reply = Read-Host "Push main + $tag now? This publishes to crates.io and PyPI. [y/N]"
56
+ if ($reply -in @('y', 'Y')) {
57
+ git push origin main $tag
58
+ } else {
59
+ Write-Host "Not pushed. When ready: git push origin main $tag"
60
+ }
61
+ } catch {
62
+ if (-not $committed) { git restore --staged --worktree -- $releaseFiles 2>$null }
63
+ throw
64
+ }