How to Manage LoopX Project Versions: A Complete Guide to Contract-First Versioning
LoopX uses a disciplined, contract-first versioning strategy based on schema_version fields in JSON contracts, package-level semantic versioning, annotated Git tags, and automated release-note generation to ensure backward compatibility across all components.
Managing versions in a multi-component AI system requires more than bumping a number in pyproject.toml. The LoopX codebase demonstrates how to coordinate versioning across data contracts, Python packages, and deployment artifacts. This guide walks through the five core mechanisms that keep LoopX releases stable and predictable.
Versioned JSON Contracts with schema_version Fields
Almost every JSON contract in LoopX carries a schema_version field. This field acts as a runtime compatibility gate, allowing services to validate data before processing.
Contract definitions live in docs/reference/protocols/README.md. When you modify a contract's structure—adding fields, changing types, or removing deprecated keys—you must increment its version string.
# Example: bumping a contract's schema_version
contract = {
"schema_version": "goal_vision_replan_contract_v0",
"goal_id": "...",
# ... other fields ...
}
# After a breaking change, update the version:
contract["schema_version"] = "goal_vision_replan_contract_v1"
The versioning convention follows a {contract_name}_v{N} pattern. Runtime validation logic in downstream services checks this field and either processes the contract or triggers a migration path.
Package-Level Versioning for Reusable Components
Optional capabilities ship as independent packages under packages/. Each follows standard Python packaging conventions with its own version number.
The loopx-finance-value-discovery package demonstrates this pattern. Located at packages/loopx-finance-value-discovery/README.md (line 196), it exposes versioned entry points that downstream projects can pin in their dependency files:
# Example dependency pin
loopx-finance-value-discovery = ">=0.3.0,<0.4.0"
This isolation lets teams evolve components at different speeds without forcing monolithic upgrades.
Git-Tagged Releases as Canonical Source of Truth
LoopX treats annotated Git tags as the single source of truth for releases. A typical release workflow:
# Example: creating a new release tag
git checkout main
git pull origin main
# Bump the version in pyproject.toml or setup.cfg if needed
# (manual edit – see package docs for exact file)
git commit -am "chore: bump version to 1.2.0"
git tag -a v1.2.0 -m "Release 1.2.0 – updated contract schemas"
git push origin main --tags
Tagging automatically generates a GitHub Release page containing:
- A changelog compiled from commit history
- Corresponding
schema_versionupdates - Migration notes for breaking changes
Automated Release Notes via GitHub Actions
The workflow in .github/workflows/update-notes.yml (line 26) eliminates manual release-note drift. Triggered on version tag pushes, it scans the repository for schema_version changes and assembles a markdown file:
# Example snippet from .github/workflows/update-notes.yml
name: Update Release Notes
on:
push:
tags:
- 'v*.*.*'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Generate notes
run: |
./scripts/generate_release_notes.py > RELEASE_NOTES.md
This automation guarantees that every version bump is documented and that consumers receive explicit upgrade instructions.
Dashboard Version Checks in the Presentation Layer
The LoopX dashboard UI validates incoming contracts against expected schema_version values. Implementation details appear in apps/presentation/dashboard/README.md (line 92).
When the UI receives a contract whose version is below its minimum supported version, it surfaces a clear error or migration prompt rather than failing silently. This prevents subtle runtime bugs from version skew between backend services and frontend components.
Summary
Managing LoopX project versions requires coordination across five layers:
- Contract versioning – Increment
schema_versionfields for any JSON schema change - Package versioning – Ship optional features as independently versioned Python packages
- Git tags – Use annotated tags as the canonical release marker
- Automated documentation – Let
.github/workflows/update-notes.ymlgenerate release notes - Runtime validation – Enforce version contracts at the dashboard UI layer
Together, these mechanisms provide a backward-compatible upgrade path: modify a contract, bump its version, run CI to document changes, tag the repository, and let downstream services adapt automatically.
Frequently Asked Questions
What happens if I forget to bump a contract's schema_version?
Downstream services may fail to validate the contract or process it incorrectly. The dashboard UI will detect the mismatch and prompt for a restart or migration, but unversioned changes risk silent data corruption in automated pipelines.
Can I use semantic versioning for LoopX contracts?
LoopX uses explicit schema_version strings rather than SemVer for contracts. This avoids ambiguity about what constitutes a "minor" versus "major" change in data schemas. Package-level code still follows standard Python semantic versioning conventions.
How do I know which schema_version my service supports?
Check the docs/reference/protocols/README.md file for the current contract definitions. The dashboard README at apps/presentation/dashboard/README.md documents the minimum supported versions for UI components. Runtime code should expose this through a health check or version endpoint.
Where should I document breaking changes for consumers?
The automated workflow in .github/workflows/update-notes.yml assembles release notes from schema_version changes. For manual additions, update the package README or root README.md (line 451) before tagging the release.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →