ChainWeaver follows SemVer 2.0.0. This document defines what counts as the public API, what kinds of changes warrant each version bump, and how deprecations are communicated.
| Bump | Examples |
|---|---|
MAJOR (1.0.0 → 2.0.0) |
Removing or renaming a public symbol; changing the type of a public field; raising a different exception class for an existing failure mode; removing a CLI subcommand. |
MINOR (1.0.0 → 1.1.0) |
Adding a new public symbol; adding optional parameters with safe defaults; adding a new CLI subcommand or flag; widening (never narrowing) what an existing function accepts. |
PATCH (1.0.0 → 1.0.1) |
Bug fixes that do not change the public API; documentation corrections; performance improvements; internal refactors. |
Pre-1.0 releases (0.x.y) follow the same shape, but MINOR bumps
may include breaking changes. Pre-1.0 callers should pin a specific
version or accept that minor releases can break them.
The public API is everything exported from chainweaver/__init__.py
__all__. This includes:
- Data models —
Tool,Flow,FlowStep,DAGFlow,DAGFlowStep,FlowStatus,ExecutionPlan,ExecutionResult,StepRecord,StepPlan,StepDiff,RetryPolicy,RedactionPolicy,DriftInfo,CostProfile,CostReport. - Runtime entry points —
FlowExecutor,FlowRegistry,FlowBuilder,TraceRecorder,ObservedStep,ObservedTrace. - Compilation and compatibility —
compile_flow,CompilationResult,CompilationError,CompilationWarning,schema_fingerprint,check_flow_compatibility,CompatibilityIssue,validate_dag_topology. - Serialization —
flow_to_dict,flow_from_dict,flow_to_json,flow_from_json,flow_to_yaml,flow_from_yaml. - Storage —
RegistryStore,InMemoryStore,FileStore. - Visualization —
flow_to_ascii,flow_to_dot,flow_to_mermaid,result_to_mermaid. - Decorators —
tool. - The CLI module —
cli(and itsmainentry point exposed as thechainweaverconsole script). - All exception classes inheriting from
ChainWeaverError.
- Anything prefixed with
_(module-level helpers, leading-underscore attributes). - Log message text, log levels, and structured log field names. These are observability conveniences, not contracts.
- Test utilities under
tests/. - The exact contents of
ExecutionResult.execution_logfor an intermediate failure path — the shape ofStepRecordis public, the number of records produced by a given error path is not. - Internal Pydantic field validators (e.g.
_validate_on_error,_validate_retryable_errors). They will be renamed or replaced freely as long as the externally observable validation contract (which inputs are accepted vs rejected) does not change.
- Announce. Mark the deprecated API in a
DeprecationWarningraised at first use viawarnings.warn(..., DeprecationWarning, stacklevel=2)and document the replacement in its docstring. - List. Add an entry to the relevant
## [x.y.z] - YYYY-MM-DDsection of CHANGELOG.md under### Deprecated. - Retain. Keep the deprecated API functional for at least one minor release before removal. For pre-1.0 releases this window may shrink to one minor release; for post-1.0 the window is at least one major version.
- Remove. Drop the deprecated API in the appropriate MAJOR (or
MINOR, pre-1.0) release; document the removal under
### Removedin the changelog.
Some properties are not just "the public API" but core invariants (documented in docs/agent-context/invariants.md):
- The executor has no LLM calls, no network I/O, no randomness.
- Tool functions have the signature
fn(BaseModel) -> dict[str, Any]. - All exceptions inherit from
ChainWeaverError. from __future__ import annotationsat the top of every module.
Changing any of these is always a MAJOR bump, regardless of how small the surface change appears.
Flow.input_schema_ref / output_schema_ref and
RetryPolicy.retryable_errors store class references as
"module:qualname" strings rather than live class objects. This makes
flow definitions fully JSON/YAML-serializable but introduces an
import-time dependency: a flow file referencing "myapp.schemas:Order"
only loads if myapp.schemas is importable in the destination process.
The qualified-name resolver (chainweaver.flow.resolve_class_ref)
uses importlib.import_module + getattr, so classes defined inside
function bodies (<locals>) cannot be referenced. Schemas referenced
by serialized flows must live at module top level.
Every release adds a section to CHANGELOG.md following
the Keep a Changelog convention.
PRs that introduce user-visible changes are expected to add an
Unreleased entry in the same commit; release tagging promotes the
entry into a versioned heading.
tests/test_public_api_snapshot.py compares the live chainweaver
surface against the checked-in golden file tests/fixtures/public_api.json.
CI fails if any of these change without an accompanying regen:
- a symbol added to or removed from
__all__, - a class's public attribute or method shape (annotations, defaults, parameter kinds),
- a public function's signature or return annotation,
- a Pydantic model's field set or field types.
After an intentional API change, regenerate the fixture in the same PR:
python tests/scripts/regen_public_api.pyThe fixture diff is the receipt — reviewers can read it as the explicit surface delta and map it to the SemVer bump table above.