Release Notes — v1.18¶
Release date: May 2026
This release ships the most significant structural change since v1.0:
weevr is now distributed as two PyPI wheels sharing a single
weevr namespace. pip install weevr continues to install the
complete Spark engine; a new pip install weevr-core makes the
pure-Python validation, planner, and telemetry-contract surface
available without PySpark. Both wheels publish to PyPI in lockstep at
the same version on every release. Existing users see no behavior
change.
Two wheels, one namespace¶
Source now lives under packages/, declared as a uv workspace at the
repository root. Two wheels build from that workspace:
| Wheel | Concern | Depends on |
|---|---|---|
weevr-core |
Pure-Python validation, planner, telemetry contracts. Installable without PySpark. | pydantic, pyyaml |
weevr |
Spark engine, runtime helpers, OneLake/Fabric integration. | weevr-core (same version) |
The split is physical, not semantic. No public API renames, no
signature changes, no behavior tweaks. Every existing import path
that worked under pip install weevr keeps working unchanged. The
work that landed under v1.17 (PEP 562 lazy Context, pure-helper
extractions, the no-PySpark lock test) was the prerequisite that made
this split safe.
What moved to weevr-core¶
Pure-Python modules whose concern could sensibly exist outside an
engine run — schemas, config resolvers, the planner graph, telemetry
contract types — now ship from weevr-core:
weevr.model.*— every Pydantic model.weevr.errors.*— the full exception hierarchy.- The pure half of
weevr.config:parser,resolver,validation,inheritance,locations,macros,warp,audit_templates,duration. - The contract types in
weevr.telemetry:results,span,trace,events. weevr.engine.plannerandweevr.engine.formatting(DAG construction and pure-Python formatters used by result rendering).- Root-level
weevr.result,weevr.duration,weevr.reserved_words.
What stayed in weevr¶
Anything that orchestrates execution, touches Spark, talks to the
Fabric runtime, or coordinates state — weevr.context,
weevr.engine.executor/runner/cache_manager/display/hooks/
lookups/conditions/column_sets/resources/result/variables,
weevr.operations.*, weevr.state.*, weevr.telemetry.collector/
logging, and the two Spark-bound config helpers
weevr.config.fabric / weevr.config.paths.
Federated namespaces¶
Three sub-packages now ship files from both wheels: weevr.config
(core ships __init__.py + pure helpers; engine adds fabric.py and
paths.py), weevr.engine (engine ships __init__.py + Spark-bound
modules; core adds planner.py and formatting.py), and
weevr.telemetry (engine ships __init__.py + runtime helpers; core
adds the contract types). The top-level weevr.__init__.py stays in
the engine wheel.
In a normal pip install both wheels' files merge into one
site-packages/weevr/ directory and Python's import machinery
resolves through the single owning __init__.py. In editable
workspace installs each wheel's src/ is a separate sys.path
entry, so federated __init__.py files extend __path__ to pull the
sibling wheel's contributions back into the namespace.
Two new install personas¶
pip install weevr (existing users)¶
Behavior is unchanged. The engine wheel declares weevr-core as a
same-version runtime dependency, so the resolver always installs both
wheels in one shot. Every existing import resolves identically:
from weevr import Context
from weevr.config import load_config
from weevr.model.thread import Thread
from weevr.engine.planner import build_plan
pip install weevr-core (new in 1.18)¶
Installs only the pure-Python distribution. The validation API,
Pydantic models, planner graph, and telemetry contracts all import
without PySpark on sys.path:
from weevr.config import load_config # works
from weevr.model.thread import Thread # works
from weevr.engine.planner import build_plan # works (pure-Python)
from weevr import Context # ImportError — engine wheel not installed
This is the persona that unblocks weevr-cli, native docs
generation, stored-run summary rendering, and any other tool that
needs to read or validate .weevr/ projects without paying for
Spark.
Restricted-network Fabric installs that upload wheels manually now need to upload both files; see the Fabric runtime guide for the updated example.
CI and tooling¶
- Both wheels build from the workspace root via
uv build --all-packagesand publish through onepypa/gh-action-pypi-publishstep. release-please bumps the version line in bothpyproject.tomlfiles (and bothuv.lockentries) atomically on every release PR. The first lockstep release (this one) is the empirical confirmation. - A new integration suite at
tests/integration/test_dual_install_modes.py(gated by theinstall_smokemarker) builds both wheels, installs them into isolated venvs, and asserts that the documented import paths resolve in core-only and full modes — wired into the release workflow as a pre-publish gate via theWEEVR_SMOKE_DISTenv var, so the smoke test exercises the same artifacts the publish step uploads. tests/weevr/test_lazy_init_consistency.pykeeps the PEP 562 lazy modules'_LAZY_ATTRSmap in sync with their__all__.- mkdocstrings reads from a deep-merged tree at
.docs-merged/(assembled byscripts/mkdocs_merge_weevr.pyat config time) so reference pages span both src roots. pyrightconfig downgradesreportMissingImportsandreportAttributeAccessIssuefor the federated cross-wheel imports it cannot merge; runtime resolution remains locked by the full pytest suite.
Backwards compatibility¶
pip install weevrbehavior is identical for existing users — the install pulls both wheels, every import path resolves unchanged, no behavior or signature changes.git log --followis preserved on every relocated file (Phase B was puregit mv— no content edits on moves).- No new credentials, no new session-state mutation, no new YAML
fields. The 1.17 lazy-Context contract is preserved exactly; the
four PEP 562 lazy attributes (
Context,RunResult,ExecutionMode,LoadedConfig) still resolve to the same underlying objects.
1.18.1 patch (2026-05-27)¶
A defect surfaced in v1.18.0 affecting the new core-only install
persona: ReservedWordConfig(strategy="rename", ...) raised
ImportError when the engine wheel was absent. The
ReservedWordConfig validator performed a function-local import
through the engine-wheel back-compat shim
weevr.operations.reserved_words instead of the canonical core
module weevr.reserved_words. Both modules export the same
resolve_effective_words symbol, so installs that had both wheels
were unaffected — the failure mode was silent until a
weevr-core-only caller exercised the rename strategy.
v1.18.1 swaps the import to the canonical core path, restoring the
core/engine layer-direction invariant that the workspace split was
designed to enforce. A regression test lock now exercises the
rename-strategy validator under an in-process weevr.operations
import blocker so the violation cannot silently return. No API
change; no behavior change for installs with both wheels.
What's next¶
The new core-only persona is the foundation; consumer adoption is the follow-on work:
weevr-climigrates from hand-written JSON Schemas tofrom weevr.config import load_config(separate topic, not part of v1.18). Validation will widen to include cross-field validators, filename-stem matching, and the full inheritance cascade that the CLI's schemas could not previously express.- Native project documentation generation (per-weave DAG, thread
lineage, target contracts) becomes possible without Spark — the
planner and warp-discovery surfaces that this feature needs all
ship from
weevr-core. - Stored-run summary rendering (reading serialized telemetry
outside the originating notebook) becomes possible on the
weevr.telemetry.results/span/trace/eventscontract types shipped from core.
None of these features ship in 1.18; the wheel split simply removes the install-time blocker that prevented them.