Review topic: Backward compatibility, public contracts & version companions
When this applies
Trigger on the CONTENT of the diff, not one directory. Load when a PR:
- Adds/removes/renames an HTTP route or changes a request/response entity under
inference/core/entities/** or inference/core/interfaces/http/http_api.py.
- Changes a Workflow block manifest under
inference/core/workflows/core_steps/** — its type Literal, I/O fields, kinds, defaults, or get_execution_engine_compatibility.
- Changes Workflow compile/run behavior under
inference/core/workflows/execution_engine/**.
- Changes a public
inference_models API (AutoModel, auto_loaders, weights_providers, response/entity shapes, backend selection).
- Changes a persisted or cache format (model cache, weights layout, compiled-workflow serialization) older code or on-disk artifacts must still read.
- Is release-bound: touches
requirements/*.txt, inference_models/pyproject.toml, uv.lock, dockerfiles, or .release/pypi/*.
- Deprecates or removes a model/block/CLI command users depend on.
Review checklist
Severity tags: BLOCK = fix before merge; FLAG = raise it; NIT = optional.
- BLOCK — Existing-caller break with no version gate: an existing
@vN block's I/O/kinds/type mutated in place, a persisted/cache format changed so older builds can't read it, or a live HTTP/SDK contract broken. (see Standards §1, §2)
- BLOCK — EE compile/run behavior changed but no user-facing entry was added under
## Unreleased in the EE changelog in the roboflow/docs repo (workflows/developer-guide/execution-engine-changelog.md). (§3)
- BLOCK —
inference-models pin bumped in some requirements/*.txt but not all four, producing divergent installs. (§6)
- BLOCK — A functional
inference_models change has no entry under ## Unreleased in inference_models/docs/changelog.md. (§5)
- FLAG — Correct additive block version but
get_execution_engine_compatibility range not set, or the floor left at the copy-pasted default while the block relies on a capability introduced later (verify against the EE changelog in the roboflow/docs repo (workflows/developer-guide/execution-engine-changelog.md)). Maintainers, not contributors, choose release bump granularity. (§2, §3)
- FLAG — Deprecation by deletion: model/block/command ripped from code without the coordinated dockerfile/CI/docs/packaging sweep (#2334). (§7)
- FLAG — HTTP error-on-failure/status semantics changed without confirming it's deliberate + tested (#2528/#2529). (§8)
Not blocking
Pure internal refactor / types / comments / formatting under a public surface with no observable contract or behavior change requires NO companion. Say so explicitly so the contributor isn't asked to over-version. Types-only/comment changes under execution_engine/** do NOT require an EE bump.
Never require an inference/core/version.py, inference_models/pyproject.toml, or EXECUTION_ENGINE_V1_VERSION bump from a contributor. Maintainers handle version changes in release PRs. This does not relax the contributor-owned Unreleased changelog rules (§3, §5), and it has one EE exception: a Workflow block gating on unreleased EE capabilities forces the version to be placed and bumped early (§3).
Standards
One canonical statement per rule. The checklist references these by number.
Existing callers keep working. A live workflow JSON, a pinned SDK call, an HTTP client, or an on-disk cache written by an older build must not break silently after upgrade. Removing/renaming a field on an existing surface, or changing a persisted format older code must read, is a break.
Block schemas are additive, versioned side-by-side. If a block's I/O, kinds, or type changes, it lands as a NEW vN+1.py sibling with a new type Literal (e.g. roboflow_core/roboflow_instance_segmentation_model@v4), not an in-place edit of an existing @vN. Each version sets get_execution_engine_compatibility returning a version range (e.g. ">=1.3.0,<2.0.0") whose floor is derived from the EE changelog — the version that introduced the newest capability the block uses — not copy-pasted. A block relying on a capability still under ## Unreleased has no released floor to declare; that forces the EE version to be placed and bumped early (§3's exception) before the block ships. Canonical set: inference/core/workflows/core_steps/models/roboflow/instance_segmentation/{v1,v2,v3,v4}.py.
EE behavior change → Unreleased changelog entry. A compile/run change adds a user-facing entry under ## Unreleased in the EE changelog in the roboflow/docs repo (workflows/developer-guide/execution-engine-changelog.md). The contributor does not change EXECUTION_ENGINE_V1_VERSION. At release time maintainers choose the bump, update the constant and mirrored assertions, move the entries under ## Execution Engine \vX.Y.Z` | inference `vA.B.C`, and leave a fresh ## Unreleasedsection. Contract codified in.cursor/rules/execution-engine-version-changelog.mdc— treat as the spec.get_execution_engine_compatibilitygates against the released constant. Exception: when a Workflow block must gate on a capability still under## Unreleased`, the version is placed and bumped early (final heading + constant + mirrored assertions, maintainer-coordinated) so the block can declare its floor.
Release-time mirrored assertions. When maintainers bump the EE/inference version, they update the hardcoded version tests: tests/inference/integration_tests/test_workflow_endpoints.py::test_get_versions_of_execution_engine and tests/inference/hosted_platform_tests/test_workflows.py::test_get_versions_of_execution_engine. Grep EXECUTION_ENGINE_V1_VERSION, execution_engine_version.
inference_models public API/entity change → Unreleased changelog entry. Add an entry under ## Unreleased in inference_models/docs/changelog.md (Added/Changed/Fixed/Removed). The contributor does not change inference_models/pyproject.toml; maintainers choose and apply that package version during release.
Release-bound pins stay in lock-step. In a maintainer release PR, any inference-models~=X change is identical across requirements/requirements.{cpu,gpu,jetson,vino}.txt (they carry a "keep in sync" comment), with uv.lock regenerated and the ## Unreleased changelog section amended to its final version heading. Do not demand these changes from a feature/fix contributor.
Deprecation done right. Removing a model/block/command raises the agreed error (FeatureDeprecatedError from inference/core/exceptions.py for deprecation-scoped surfaces), keeps the symbol resolvable, and sweeps dockerfiles/CI/docs/packaging together — not a bare code delete.
HTTP behavior change is intentional and gated. Changing error-on-failure / status semantics (e.g. serverless auth failure) is a client-visible contract; confirm it's deliberate, tested, and not an accidental regression.
Release notices
When the PR changes inference-models functionality, include the non-blocking
maintainer notice inference-models requires a version bump for release. When
it changes Execution Engine compile/run behavior, include Execution Engine
requires a version bump for release. Include both notices for cross-system
changes. Missing Unreleased entries are contributor-actionable findings;
version bumps are not.
Key files & Reference PRs
inference/core/version.py — single source of truth for the inference package version; release PRs touch it (never demand a bump on feature/bugfix PRs).
inference/core/workflows/execution_engine/v1/core.py — EXECUTION_ENGINE_V1_VERSION constant that get_execution_engine_compatibility gates against.
- the EE changelog in the roboflow/docs repo (
workflows/developer-guide/execution-engine-changelog.md) — canonical EE changelog format.
.cursor/rules/execution-engine-version-changelog.mdc — the repo's written contract for when/how to bump EE + changelog + version tests.
inference/core/workflows/core_steps/models/roboflow/instance_segmentation/{v1,v2,v3,v4}.py — canonical additive block versioning; distinct type Literal + version-range compat per file.
inference_models/pyproject.toml + inference_models/docs/changelog.md — the standalone package's version + changelog companion pair.
requirements/requirements.{cpu,gpu,jetson,vino}.txt — the four inference-models~=0.29.7 pins carrying the "keep in sync" comment.
Reference PRs that shipped a contract change WITH its companions: #2383 (EE version + changelog + tests), #2475 (EE perf change keeping parity), #2384 (block schema shipped additively with defaults), #2510 / #2341 / #2175 / #2102 (release: version + changelog + all four pins + lock), #2334 (mediapipe gaze deprecation across dockerfiles/CI/docs/packaging), #2395 (removing deprecated Gemini block versions), #2528/#2529 (serverless auth-failure status change then revert), #2115 / #2267 (stale mirrored version assertions fixed).
1---2name: review-topic-backward-compat-and-versioning3description: Load when a PR changes a user/dev-visible contract or is release-bound. Triggers on diffs to `inference/core/version.py`, `EXECUTION_ENGINE_V1_VERSION`, `inference/core/interfaces/http/http_api.py` or `inference/core/entities/**`, a Workflow block manifest under `inference/core/workflows/core_steps/**` (`type` Literal, `kinds`, `get_execution_engine_compatibility`), a public `inference_models` API, `inference_models/pyproject.toml`, a persisted/cache format, or `requirements/*.txt` / `uv.lock`.4---56# Review topic: Backward compatibility, public contracts & version companions78## When this applies9Trigger on the CONTENT of the diff, not one directory. Load when a PR:10- Adds/removes/renames an HTTP route or changes a request/response entity under `inference/core/entities/**` or `inference/core/interfaces/http/http_api.py`.11- Changes a Workflow **block** manifest under `inference/core/workflows/core_steps/**` — its `type` Literal, I/O fields, `kinds`, defaults, or `get_execution_engine_compatibility`.12- Changes Workflow **compile/run behavior** under `inference/core/workflows/execution_engine/**`.13- Changes a **public** `inference_models` API (AutoModel, auto_loaders, weights_providers, response/entity shapes, backend selection).14- Changes a **persisted or cache format** (model cache, weights layout, compiled-workflow serialization) older code or on-disk artifacts must still read.15- Is **release-bound**: touches `requirements/*.txt`, `inference_models/pyproject.toml`, `uv.lock`, dockerfiles, or `.release/pypi/*`.16- Deprecates or removes a model/block/CLI command users depend on.1718## Review checklist19Severity tags: **BLOCK** = fix before merge; **FLAG** = raise it; **NIT** = optional.2021- **BLOCK** — Existing-caller break with no version gate: an existing `@vN` block's I/O/`kinds`/`type` mutated in place, a persisted/cache format changed so older builds can't read it, or a live HTTP/SDK contract broken. (see Standards §1, §2)22- **BLOCK** — EE compile/run behavior changed but no user-facing entry was added under `## Unreleased` in the EE changelog in the roboflow/docs repo (`workflows/developer-guide/execution-engine-changelog.md`). (§3)23- **BLOCK** — `inference-models` pin bumped in some `requirements/*.txt` but not all four, producing divergent installs. (§6)24- **BLOCK** — A functional `inference_models` change has no entry under `## Unreleased` in `inference_models/docs/changelog.md`. (§5)25- **FLAG** — Correct additive block version but `get_execution_engine_compatibility` range not set, or the floor left at the copy-pasted default while the block relies on a capability introduced later (verify against the EE changelog in the roboflow/docs repo (`workflows/developer-guide/execution-engine-changelog.md`)). Maintainers, not contributors, choose release bump granularity. (§2, §3)26- **FLAG** — Deprecation by deletion: model/block/command ripped from code without the coordinated dockerfile/CI/docs/packaging sweep (#2334). (§7)27- **FLAG** — HTTP error-on-failure/status semantics changed without confirming it's deliberate + tested (#2528/#2529). (§8)2829### Not blocking30Pure internal refactor / types / comments / formatting under a public surface with **no** observable contract or behavior change requires NO companion. Say so explicitly so the contributor isn't asked to over-version. Types-only/comment changes under `execution_engine/**` do NOT require an EE bump.3132Never require an `inference/core/version.py`, `inference_models/pyproject.toml`, or `EXECUTION_ENGINE_V1_VERSION` bump from a contributor. Maintainers handle version changes in release PRs. This does not relax the contributor-owned `Unreleased` changelog rules (§3, §5), and it has one EE exception: a Workflow block gating on unreleased EE capabilities forces the version to be placed and bumped early (§3).3334## Standards35One canonical statement per rule. The checklist references these by number.36371. **Existing callers keep working.** A live workflow JSON, a pinned SDK call, an HTTP client, or an on-disk cache written by an older build must not break silently after upgrade. Removing/renaming a field on an existing surface, or changing a persisted format older code must read, is a break.38392. **Block schemas are additive, versioned side-by-side.** If a block's I/O, `kinds`, or `type` changes, it lands as a NEW `vN+1.py` sibling with a new `type` Literal (e.g. `roboflow_core/roboflow_instance_segmentation_model@v4`), not an in-place edit of an existing `@vN`. Each version sets `get_execution_engine_compatibility` returning a version range (e.g. `">=1.3.0,<2.0.0"`) whose floor is derived from the EE changelog — the version that introduced the newest capability the block uses — not copy-pasted. A block relying on a capability still under `## Unreleased` has no released floor to declare; that forces the EE version to be placed and bumped early (§3's exception) before the block ships. Canonical set: `inference/core/workflows/core_steps/models/roboflow/instance_segmentation/{v1,v2,v3,v4}.py`.40413. **EE behavior change → Unreleased changelog entry.** A compile/run change adds a user-facing entry under `## Unreleased` in the EE changelog in the roboflow/docs repo (`workflows/developer-guide/execution-engine-changelog.md`). The contributor does not change `EXECUTION_ENGINE_V1_VERSION`. At release time maintainers choose the bump, update the constant and mirrored assertions, move the entries under `## Execution Engine \`vX.Y.Z\` | inference \`vA.B.C\``, and leave a fresh `## Unreleased` section. Contract codified in `.cursor/rules/execution-engine-version-changelog.mdc` — treat as the spec. `get_execution_engine_compatibility` gates against the released constant. Exception: when a Workflow block must gate on a capability still under `## Unreleased`, the version is placed and bumped early (final heading + constant + mirrored assertions, maintainer-coordinated) so the block can declare its floor.42434. **Release-time mirrored assertions.** When maintainers bump the EE/inference version, they update the hardcoded version tests: `tests/inference/integration_tests/test_workflow_endpoints.py::test_get_versions_of_execution_engine` and `tests/inference/hosted_platform_tests/test_workflows.py::test_get_versions_of_execution_engine`. Grep `EXECUTION_ENGINE_V1_VERSION`, `execution_engine_version`.44455. **inference_models public API/entity change → Unreleased changelog entry.** Add an entry under `## Unreleased` in `inference_models/docs/changelog.md` (`Added`/`Changed`/`Fixed`/`Removed`). The contributor does not change `inference_models/pyproject.toml`; maintainers choose and apply that package version during release.46476. **Release-bound pins stay in lock-step.** In a maintainer release PR, any `inference-models~=X` change is identical across `requirements/requirements.{cpu,gpu,jetson,vino}.txt` (they carry a "keep in sync" comment), with `uv.lock` regenerated and the `## Unreleased` changelog section amended to its final version heading. Do not demand these changes from a feature/fix contributor.48497. **Deprecation done right.** Removing a model/block/command raises the agreed error (`FeatureDeprecatedError` from `inference/core/exceptions.py` for deprecation-scoped surfaces), keeps the symbol resolvable, and sweeps dockerfiles/CI/docs/packaging together — not a bare code delete.50518. **HTTP behavior change is intentional and gated.** Changing error-on-failure / status semantics (e.g. serverless auth failure) is a client-visible contract; confirm it's deliberate, tested, and not an accidental regression.5253## Release notices5455When the PR changes inference-models functionality, include the non-blocking56maintainer notice **inference-models requires a version bump for release**. When57it changes Execution Engine compile/run behavior, include **Execution Engine58requires a version bump for release**. Include both notices for cross-system59changes. Missing `Unreleased` entries are contributor-actionable findings;60version bumps are not.6162## Key files & Reference PRs63- `inference/core/version.py` — single source of truth for the inference package version; release PRs touch it (never demand a bump on feature/bugfix PRs).64- `inference/core/workflows/execution_engine/v1/core.py` — `EXECUTION_ENGINE_V1_VERSION` constant that `get_execution_engine_compatibility` gates against.65- the EE changelog in the roboflow/docs repo (`workflows/developer-guide/execution-engine-changelog.md`) — canonical EE changelog format.66- `.cursor/rules/execution-engine-version-changelog.mdc` — the repo's written contract for when/how to bump EE + changelog + version tests.67- `inference/core/workflows/core_steps/models/roboflow/instance_segmentation/{v1,v2,v3,v4}.py` — canonical additive block versioning; distinct `type` Literal + version-range compat per file.68- `inference_models/pyproject.toml` + `inference_models/docs/changelog.md` — the standalone package's version + changelog companion pair.69- `requirements/requirements.{cpu,gpu,jetson,vino}.txt` — the four `inference-models~=0.29.7` pins carrying the "keep in sync" comment.7071Reference PRs that shipped a contract change WITH its companions: **#2383** (EE version + changelog + tests), **#2475** (EE perf change keeping parity), **#2384** (block schema shipped additively with defaults), **#2510 / #2341 / #2175 / #2102** (release: version + changelog + all four pins + lock), **#2334** (mediapipe gaze deprecation across dockerfiles/CI/docs/packaging), **#2395** (removing deprecated Gemini block versions), **#2528/#2529** (serverless auth-failure status change then revert), **#2115 / #2267** (stale mirrored version assertions fixed).