What is contract versioning in Traverse?
Every capability registration includes a semver version string. Multiple versions of the same capability can live in the registry at once. Callers can pin to a specific version or request the latest version that satisfies a given constraint. Old versions keep working until you explicitly remove them.
Why versioning matters
Business logic changes. A pricing rule that worked last quarter might need new inputs next quarter. Without versioning, you have two choices: update all callers at once (risky), or freeze the logic forever (costly). With versioning, you register a new version and migrate callers incrementally. Nothing breaks until you choose to retire the old version.
How version selection works
When a caller requests calculate_price without pinning a version, the runtime queries the registry for all registered versions of that capability and picks the latest one that satisfies the caller's placement constraints. If the caller pins to 1.0.0, the runtime resolves only that entry.
Breaking vs. non-breaking changes
- Adding an optional input field — non-breaking, patch or minor bump
- Removing a required input field — non-breaking for callers, minor bump
- Adding a required input field — breaking for existing callers, major bump
- Changing output field types — breaking, major bump
- Tightening preconditions — breaking for callers that relied on the looser constraint
Retiring old versions
Remove a version with traverse registry remove calculate_price --version 1.0.0. Callers pinned to that version will fail with a registry error at discovery time. Plan migrations before removing versions that have active callers.
See also what is the contract lifecycle for the full picture from creation to retirement.