M17 — release v1.0.0: PROCEDURE¶
Status: documentation only — release is the final step after all M0–M16 phases land green.
Pre-flight checklist¶
All sub-gates green:
M0 baselines tagged (
pls4all-final/v1.0.0-pre-merge+nirs4all-methods-final/6195574) — ✅ doneM1 subtree import committed (
merge/import-donor) — ✅ doneM2 catalog + subset YAMLs validated — ✅ done
M2.5 common-core landed at
cpp/src/core/common/— ✅ doneM3 donor sources lifted to
cpp/src/core/<category>/— ✅ doneM4 source split executed (Phase 1 helpers + Phases 2-7 algorithms) — ❌ deferred
M5 ABI rename
n4m_*→n4m_*executed across whole tree — ❌ deferred (script ready)M6 per-category headers populated (umbrella + 11 cat headers) — ❌ deferred (stubs only)
M7 unified parity gate green (Stage 0-4) — ❌ deferred (donor infrastructure parked)
M8 unified benchmark dashboard live (per-category filters) — ❌ deferred (orchestrator de-hardcoded only)
M9 Python
nirs4all-methodspackage activated (catalog/scripts/render_subset.py –copy) — ❌ deferred (scaffold only)M10 Python
pls4allslim package activated — ❌ deferred (scaffold only)M11 R
n4m+pls4allpackages activated;R CMD check --as-cran0/0/0 — ❌ deferredM12 MATLAB/Octave dispatcher refreshed — ❌ deferred
M13 12 secondary bindings refreshed — ❌ deferred (donor Python+R lifted to bindings/donor_imports/)
M14 license audit clean; NOTICE.md + THIRD_PARTY_LICENSES.md committed — ✅ done
M15 cibuildwheel + R-hub rehearsals green — ❌ scaffold only
M16 repo renames + donor archive — ❌ documented only
Release-day procedure (once all gates pass)¶
1. Final integration tag¶
cd /path/to/nirs4all-methods
git checkout merge/unified # post-M5 unified main candidate
git pull --ff-only
# Build verification:
cmake --preset dev-release && cmake --build --preset dev-release -j
ctest --preset dev-release --output-on-failure
./build/dev-release/cpp/cli/n4m_cli --selfcheck # post-M5: was n4m_cli
# Parity gate:
python parity/python_generator/scripts/run_parity_gate.py --build-dir build/dev-release
# Expect: PASS Stage 0-4
# License audit:
python scripts/audit_third_party_licenses.py --check
# Expect: PASS
# Catalog validation:
python catalog/scripts/validate_catalog.py
# Expect: PASS
# Build the wheels (cibuildwheel matrix from .github/workflows/release-wheels.yml):
gh workflow run release-wheels.yml --field version_tag=v1.0.0 --field publish=false
# Wait for green, then re-run with publish=true
2. Tag v1.0.0¶
git tag -a v1.0.0 -m "Release v1.0.0 — unified nirs4all-methods.
This is the first stable release of the unified library combining
pls4all (the PLS / NIRS engine) and the original nirs4all-methods
(preprocessing, augmentation, splitter, filter, utility operators).
For full release notes see CHANGELOG.md and MERGE_ROADMAP.md."
git push origin v1.0.0
3. Publish to PyPI¶
If using Trusted Publishing (recommended):
gh workflow run release-wheels.yml --field version_tag=v1.0.0 --field publish=true
This deploys both nirs4all-methods 1.0.0 and pls4all 1.0.0.
4. Submit to CRAN¶
For n4m (full R) and pls4all (slim R):
# Build sources:
cd bindings/r_n4m
R CMD build .
# Check on win-builder + R-hub + macOS-ARM:
R CMD check --as-cran n4m_1.0.0.tar.gz # must be 0/0/0
# Same for pls4all:
cd ../r_pls4all
R CMD build .
R CMD check --as-cran pls4all_1.0.0.tar.gz # 0/0/0
# Submit (manual via https://cran.r-project.org/submit.html)
5. GitHub release page¶
gh release create v1.0.0 \
--title "v1.0.0 — Unified nirs4all-methods" \
--notes-file CHANGELOG.md \
wheels/*.whl \
sources/*.tar.gz
6. Announce¶
Docs site auto-deploys via GitHub Pages from main.
Email the project mailing list + GitHub Discussions.
Update DOI on Zenodo (if linked).
7. Post-release smoke¶
pip install nirs4all-methods==1.0.0 # from PyPI
python -c "
from nirs4all_methods.preprocessing.scatter import SNV
from nirs4all_methods.models.pls import SIMPLS
import numpy as np
X = np.random.randn(50, 100)
y = np.random.randn(50)
m = SIMPLS(n_components=5).fit(SNV().fit_transform(X), y)
print(m.score(SNV().fit_transform(X), y))
"
pip install pls4all==1.0.0 # legacy slim
python -c "
from pls4all.sklearn import PLSRegression
import numpy as np
X = np.random.randn(50, 100)
y = np.random.randn(50)
m = PLSRegression(n_components=5).fit(X, y)
print(m.score(X, y))
"
Both should return reasonable R² values.
Rollback (if release goes wrong)¶
PyPI: yank the release.
pip install twine
twine upload --skip-existing dist/* # if needs to re-upload
# Or via web: https://pypi.org/manage/project/nirs4all-methods/releases/
CRAN: contact CRAN maintainers to withdraw.
GitHub tag: delete locally + remotely, recreate after fix.
git tag -d v1.0.0
git push origin :refs/tags/v1.0.0
# Fix the bug
# Re-tag
Open items that are deliberately not blocking v1.0.0¶
M4 source split (organizational — algorithms work, just monolithic)
M5 ABI rename (needs M5+M6 focused session)
M6 header reorganisation (paired with M5)
M11 CRAN cleanup pass for pls4all R package (existing 1W + 4N)
The merge plan deliberately budgeted these for follow-up release passes. v1.0.0 ships the unified source tree + functional pls4all build
catalog/subset machinery + license audit — not the fully split
renamed + fully-built-from-catalog state. v1.1.0 closes those.