Versioning¶
sci-rag-kit follows Semantic Versioning with the 0.x rules spelled out, because "semver" alone promises nothing before 1.0 and users deserve to know what actually holds.
While we are 0.x¶
- Minor releases (0.2 -> 0.3) may break APIs, and the CHANGELOG says so explicitly under a "Breaking" heading with a migration note. We break deliberately and loudly, never silently.
- Patch releases (0.2.0 -> 0.2.1) do not break anything: fixes, docs, and additive features only.
- The database schema is versioned by Alembic migrations
(
migrations/versions/), and every release's migrations run forward from any prior release's schema. Skipping releases is fine; downgrades are best-effort. - Eval report JSON is additive: new keys may appear in
report.json/calibration.json; existing keys do not change meaning or type within 0.x. External tooling (the UW SSEC evaluation platform seam) can rely on that. - Domain profiles are forward-compatible. A
domain/directory written for an older 0.x keeps working. New capabilities arrive as optional keys with safe defaults; the reranker block is the model, where absent means off.
What is public API¶
The compatibility promise covers:
- The
sci_ragPython package's documented top-level exports (docs/api.md) - The CLI command surface (
sci-rag ...) - The REST contract under
/v1and the MCP tool names/schemas - The
domain/directory format - Eval report JSON keys
Internal module paths (anything not in docs/api.md) may move in any
minor release.
Deprecation¶
Within 0.x: deprecated surface keeps working for one minor release with a visible warning, then goes. The CHANGELOG lists every deprecation the release it starts and the release it lands.
Criteria for 1.0¶
1.0 is a promise, so it waits for evidence the promise can be kept:
- At least two production deployments outside the maintainers' own (ADOPTERS.md is the register; BioCirV is the flagship candidate)
- One full minor-release cycle with no breaking change needed to the five public surfaces above
- The benchmark page reproducible by an outside party from a clean
clone (
make benchmark) - Judge calibration against domain-expert labels (not the shipped non-expert seed set) published for at least one real corpus
- Security review of the serving layer since the last surface change
After 1.0: breaking changes only in major releases, with migration guides.
Release mechanics¶
Releases are tagged vX.Y.Z from main with CI green, a CHANGELOG
entry, and (once the maintainer enables it; see the launch-gated list in
ROADMAP.md) an archival DOI per release.
Pushing the tag runs .github/workflows/release.yml,
which verifies, publishes to TestPyPI, then publishes to PyPI:
verifyruns four checks. It confirms theciworkflow already passed for the tagged commit, confirms the tag matchesproject.versioninpyproject.toml, runsuv build, and installs the built wheel into a throwaway environment to check that bothsci-ragandsci-rag-neware on the path.testpypipublishes to TestPyPI. It runs first on every release because PyPI does not allow re-uploading a version, even a broken one, so a packaging mistake found on PyPI costs a version number.pypipublishes to PyPI.
The tag is the source of truth for the version, and the verify job enforces
that. sci-rag-new fetches the template at the tag matching its own
installed version, so a release whose tag and packaged version disagree
would generate projects from the wrong commit.
One-time setup, by a maintainer¶
The workflow uses Trusted Publishing (OIDC), so the repository stores no API token to leak or rotate. You establish that trust once per index, by hand. CI cannot do it for you:
- Reserve
sci-rag-kiton PyPI and on TestPyPI. They are separate accounts and separate namespaces. - On each index, add a pending publisher for the project:
- Owner:
sustainability-software-lab - Repository:
sci-rag-kit - Workflow:
release.yml - Environment:
pypion PyPI,testpypion TestPyPI - Create the matching GitHub environments (
pypi,testpypi) in the repository settings. Put a required reviewer onpypifor the first release; that turns the final publish into a decision you make rather than one a tag push makes for you. - Verify end to end before announcing anything, from a clean directory:
pipx install --index-url https://test.pypi.org/simple/ \
--pip-args="--extra-index-url https://pypi.org/simple/" sci-rag-kit
sci-rag-new --defaults
TestPyPI does not mirror the runtime dependencies, which is what the extra index is for.
Skip step 2 on an index and that index's job fails with a missing-publisher error. It publishes nothing and costs nothing; configure it and re-run the workflow.