Skip to content

Release management

How a reactifact version is cut, built, verified, and published.

Versioning

  • SemVer; pre-releases carry an rc mark (e.g. 0.5.0rc1), dropped for the stable cut (0.5.0).
  • The version lives in two places and must stay in sync:
  • pyproject.toml[project] version;
  • reactifact/__init__.py__version__.

Changelog rule

Every user-visible change lands in CHANGELOG.md (Keep a Changelog). Cut the entry when the version is bumped:

  1. move unreleased items under a new ## [X.Y.Z] — <date> heading;
  2. group them as Added / Changed / Removed (deprecations too);
  3. mark breaking changes explicitly, even in rcs.

Upgrading

There's no separate migration doc — CHANGELOG.md is the source of truth for what changed between versions, and breaking entries are marked per the rule above. A few changes worth knowing if you're crossing them (see also migrating.md for porting from other frameworks):

  • 0.10.0 — behavior-visible (non-breaking) changes to know about:
  • PromptTemplate.render now substitutes only identifier-shaped {field} placeholders and leaves other braces verbatim, so a literal JSON example in a prompt needs no {{/}} escaping. Templates that relied on str.format treating a stray {...} as an error/format-spec now pass it through.
  • reactifact.chat.ChatEvent.kind is a closed Literal["session","status","message"]; constructing one with an arbitrary kind now fails validation.
  • Provider/WebSource/OTLP/Langfuse HTTP clients are created lazily per event loop (no more RuntimeError: Event loop is closed across loops); an injected client= is still used as-is.
  • Runtime.arun/astream gained a keyword-only request=; Runtime.run/ run_once likewise. Existing positional calls are unaffected.
  • 0.7.0Context.merge_from now preserves the id of an artifact that exists in other but not in target (it previously minted a fresh one). If you relied on the old id-regenerating behavior — unlikely, since it silently detached the merged artifact from any relation pointing at its original id — pass the artifact through create(data, id=new_id()) yourself before merging to keep the old effect.
  • 0.5.0reactifact/__init__.py re-exports only the core surface (~40 names, down from ~150); eval, tracing, checkpoint/branch backends, the chat/web layer, the adaptive scheduler, replay, structured-LLM helpers, viz, and prompt templates moved to their own submodule imports. Nothing renamed — see the ### Breaking entry in CHANGELOG.md for the full before/after import list.
  • 0.4.0-rc1LLMRequest.temperature changed from a hard-coded 0.7 to float | None; None now means "omit → provider default" instead of "use 0.7". Same call shape, different generation behavior, no error raised — pass temperature=0.7 explicitly (per-call or on the provider) if your code relied on the old implicit default.
  • 0.1.0-rc1Produce no longer returns a Patch; it writes self.effects.create/update/link/ask/resume and returns None (see effects). InterruptPatch, Patch.merge_existing_patch and Patch.to_dict were removed.

The release loop

# 1) sanity
.venv/bin/python -m pytest
.venv/bin/python -m mypy
.venv/bin/python -m ruff check
.venv/bin/python -m ruff format --check

# 2) version + changelog (see above)

# 3) build artifacts
uv build                     # dist/reactifact-0.5.0-py3-none-any.whl + sdist

# 4) verify the wheel in a scratch venv (not the workspace, so no PYTHONPATH)
uv venv /tmp/reactifact-rc
/tmp/reactifact-rc/bin/python -m pip install --quiet dist/reactifact-0.5.0-py3-none-any.whl
/tmp/reactifact-rc/bin/python -c "import reactifact; print(reactifact.__version__)"
/tmp/reactifact-rc/bin/python -m reactifact graph examples.knowledge.agents 2>/dev/null \
    || /tmp/reactifact-rc/bin/reactifact --help >/dev/null   # console script present
# confirm the wheel contains reactifact + tracing templates and NOT examples/tests:
unzip -l dist/reactifact-0.5.0-py3-none-any.whl | grep -E "examples/|tests/|tracing/templates" 

# 5) tag
git tag v0.5.0
git push origin v0.5.0

# 6) publish (PyPI token in env)
uv publish --publish-url https://upload.pypi.org/legacy/

What ships

uv build packages only the reactifact package (setuptools packages.find excludes examples/tests) plus the trace dashboard templates (reactifact/tracing/templates/*.html). Examples, tests and docs stay in the repository and are the documentation-by-example.

Rollback

A broken rc is fixed in the next rc/release — never rewrite history of a tagged version. Keep patch releases strictly backwards-compatible (§61: the framework is stable at the stated surface).