Release Streams, SemVer, and Channels¶
OpenMed uses two release streams with different blast radii.
Stream A: Model Artifacts¶
Model artifacts are data. A bad checkpoint affects one model entry and can be rolled back by repointing the manifest to the last green artifact.
- Versioning: repository suffix or artifact revision plus a reproducibility hash.
- Cadence: maintainer-triggered after local conversion, evaluation, and review.
- Gate owner: release engineering plus the evaluation gate.
- Rollback: manifest pointer flip, regenerated cards, and a tracking issue.
Stream B: Library and SDK¶
The openmed wheel and source distribution are code. A bad library release can break every downstream install, so it follows SemVer and moves more slowly.
- Versioning:
MAJOR.MINOR.PATCH. - Cadence: patch daily-to-weekly, minor monthly, major by milestone.
- Gate owner: release engineering with maintainer sign-off for minor and major changes.
- Rollback: forward-fix with the next patch; yanking remains a manual registry action.
Channels¶
| Channel | Selector | Contents | Cadence | Audience |
|---|---|---|---|---|
| Nightly / edge | pip install openmed --pre | Latest green code and gated model pins | every green merge or daily | early adopters and internal evaluation |
| Stable | pip install openmed | Full golden-suite pass and canary-ready pins | patch daily-to-weekly, minor monthly | default users |
| LTS | pip install "openmed==1.8.*" | Security and recall-backstop fixes only | as needed for 12 months | regulated deployments |
Nightly builds use PEP 440 development releases such as 1.9.0.devN. Release candidates such as 1.9.0rc1 are reserved for pre-stable cuts.
SemVer Rules¶
- PATCH: registry or manifest refresh, new gated model surfaced, bug fix, or documentation sync without API change.
- MINOR: additive public API, new optional argument, new optional extra, or new capability package.
- MAJOR: breaking API change, label-schema break, or migration that requires a downstream code change.
Deprecation Policy¶
Public APIs receive at least one full minor-version warning window before removal. A deprecation introduced in 1.9 remains usable throughout the 1.9 line; its scheduled removal must still respect SemVer, so this notice window is not permission to make a breaking removal in a later 1.x release.
New deprecations use openmed.utils.deprecated, emit DeprecationWarning, name the replacement when one exists, and appear in CHANGELOG.md under Deprecated. The decorator records the introduction and planned-removal versions so the static API-surface differ can classify the symbol as an intentional deprecation:
from openmed.utils import deprecated
@deprecated(since="1.9", remove_in="2.0", replacement="openmed.new_api")
def legacy_api() -> None:
"""Compatibility entry point retained during the warning window."""
Every breaking or deprecated change must also have a before/after entry in the relevant migration guide. Version-scoped tag builds compare the candidate against the release baseline and fail when the guide omits either kind of required change.
Release Gates¶
The release gates, not aggregate F1 alone, decide whether a model artifact is releasable. A candidate must satisfy critical-leakage, recall, quantization delta, device-tier, span-integrity, and regression checks before it can move to stable. Library releases must also pass the repository policy, dependency license policy, and test suite.
Model promotion and Library/SDK publication remain separate release streams. Training, fine-tuning, and publishing new checkpoints are optional model-research work. They have no library-release milestone and are not prerequisites for feature APIs or SDK releases. Existing and caller-supplied local artifacts can satisfy runtime contracts; missing or unqualified artifacts must still produce typed refusal. Deferral never turns a failed model benchmark into passing evidence or bypasses its promotion gates. .github/workflows/release-gates.yml runs only by explicit model-candidate dispatch or the metadata-only rollback dispatch; it has no schedule and never publishes model artifacts. An SDK v* tag does not promote a model. A Library/SDK release that changes a canary, latest, or last_green model pointer must first complete the model gate with real staged golden and SHIELD evidence. When those pointers are unchanged, the SDK tag uses the retained last-green model evidence and the tag-driven package, platform, and repository gates.
SDK readiness evidence¶
For an SDK candidate that retains model targets, use the explicit SDK stream:
python -m openmed.eval.release_readiness --sdk-baseline v2.5.0 \
--migration-guide docs/migration/2.5-to-3.0.md \
--api-compat-report api-surface-diff.json \
--e2e-report e2e-golden-report.json --version 3.0.0 \
--output release-readiness-report.json --json
This mode verifies the baseline is an ancestor stable tag, preserves every model row, artifact pin, license, benchmark and retained baseline entry, and compares every model pointer target across registry schema representations. Only additive language-routing metadata and script verdicts over unchanged tokenizer measurements can change without model promotion. A new summary policy may add strict thresholds; it cannot rewrite existing model evidence. These catalog edits are not clinical model qualification. Changed artifacts, pointers or retained metrics, and missing evidence, still fail closed.
Minor and patch SDK releases must have no breaking APIs. A major release may include intentional breaking APIs only when every reported symbol is covered by its migration guide; the readiness report retains their count and guide hash. Model candidates use --gate-report with signed evaluation evidence; the two CLI modes cannot be combined. Both streams require API, documentation, disclaimer, and golden-suite checks, and emit signed readiness reports.
Manual Model Orchestration¶
OpenMed does not build, convert, evaluate, or publish models on a GitHub Actions schedule. Maintainers may use gates/nightly_release_queue.json as a reviewed local control file on explicitly provisioned hardware. A queue row fixes the source and target repositories, family, tier, format, parameter count, synthetic fixture path, and evaluation suite. Queue identifiers and repository identifiers are validated before any conversion starts.
For each explicitly selected candidate, a maintainer can run scripts/release/orchestrate.py run locally to execute conversion, the shared evaluation harness, the signed ReleaseGate, artifact-backed model-card generation, publication, registry promotion, and a fresh-environment smoke test in that order. A non-RELEASABLE report halts that candidate before model-card generation or publication. The remaining candidates continue, while the run becomes PARTIAL and its PHI-free evidence records identifiers, hashes, the failing stage, the run id, and the git SHA.
The smoke test downloads the just-published repository into a new virtual environment and calls both extract_pii and deidentify on a synthetic probe. It emits only a span count and offsets hash. Failure immediately flips the family's latest registry pointer back to committed last_green evidence.
Every locally executed candidate outcome is appended to gates/release_runs.jsonl. The row binds the gate-report path and hash, artifact digest, decision, final pointer target, smoke state, start/completion timestamps, run status, and git SHA under a provenance hash. Gate reports live under gates/release_reports/<run-id>/.
Release compute budgets use the same explicit local workflow. Review rolling spend before selecting a batch, ask the orchestrator to write deterministic stage timings, then append the linked cost and carbon record:
python scripts/release/budget_report.py status \
--ledger gates/budget_ledger.jsonl \
--output gates/release_reports/budget-status.json
python scripts/release/orchestrate.py run \
--weekday <weekday> \
--run-id <run-id> \
--budget-timings gates/release_reports/<run-id>/budget-stage-timings.json
python scripts/release/budget_report.py record \
--timings gates/release_reports/<run-id>/budget-stage-timings.json \
--ledger gates/budget_ledger.jsonl \
--orchestrator-ledger gates/release_runs.jsonl \
--output gates/release_reports/<run-id>/budget-report.json
An OVER verdict recommends reducing a future batch, for example by passing --max-candidates 1 to an explicitly initiated run. It is advisory and never overrides or skips privacy, recall, provenance, publication, or smoke-test gates. Stage timings and budget rows contain only validated identifiers, aggregate measurements, reviewed factors, hashes, and threshold decisions.
A maintainer reviews and commits the ledger, reports, manifest, and registry state through a normal PR. Reconstruct and validate a run without a live API call with:
Publication is an explicit local operation and follows the manual Hugging Face publication policy.