# How to Manage LoopX Project Versions: A Complete Guide to Contract-First Versioning

> Master LoopX project versions with our guide to contract-first versioning. Learn about schema versions, Git tags, and automated releases for seamless backward compatibility.

- Repository: [huangruiteng/loopx](https://github.com/huangruiteng/loopx)
- Tags: how-to-guide
- Published: 2026-08-15

---

**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`](https://github.com/huangruiteng/loopx/blob/main/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`](https://github.com/huangruiteng/loopx/blob/main/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.

```python

# 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`](https://github.com/huangruiteng/loopx/blob/main/packages/loopx-finance-value-discovery/README.md) (line 196), it exposes versioned entry points that downstream projects can pin in their dependency files:

```toml

# 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:

```bash

# 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_version` updates
- Migration notes for breaking changes

## Automated Release Notes via GitHub Actions

The workflow in [`.github/workflows/update-notes.yml`](https://github.com/huangruiteng/loopx/blob/main/.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:

```yaml

# 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`](https://github.com/huangruiteng/loopx/blob/main/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_version` fields 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.yml`](https://github.com/huangruiteng/loopx/blob/main/.github/workflows/update-notes.yml) generate 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`](https://github.com/huangruiteng/loopx/blob/main/docs/reference/protocols/README.md) file for the current contract definitions. The dashboard README at [`apps/presentation/dashboard/README.md`](https://github.com/huangruiteng/loopx/blob/main/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`](https://github.com/huangruiteng/loopx/blob/main/.github/workflows/update-notes.yml) assembles release notes from `schema_version` changes. For manual additions, update the package README or root [`README.md`](https://github.com/huangruiteng/loopx/blob/main/README.md) (line 451) before tagging the release.