Compatibility policy
OpenSIP CLI has multiple public surfaces. They do not all version the same way,
so the CLI records them as named compatibility contract classes in
COMPATIBILITY_POLICIES.
| Contract class | Current marker | Owner | Compatibility rule |
|---|---:|---|---|
| cli-command-surface | 1 | opensip-cli | Command removals or semantic flag changes require a command-surface snapshot update and release note. |
| project-config | 1 | @opensip-cli/config | Schema bumps require opensip config migrate support before the strict loader can require the new shape. |
| public-json | 2 | @opensip-cli/contracts | SignalEnvelope.schemaVersion is the inner run-output version; optional fields are additive. |
| tool-plugin-api | current PLUGIN_API_VERSION | @opensip-cli/core | Tool manifests are admitted through the plugin API compatibility range. |
| cloud-wire | 1 | @opensip-cli/core | SignalBatch.schemaVersion is the OpenSIP Cloud egress wire version. |
| release-artifact | 1 | root release scripts | Release manifest/SBOM/attestation shape changes require verifier updates. |
| datastore-payload | 1 | @opensip-cli/datastore | Generic session rows stay host-owned; payload additions must be optional or migrated. |
| platform-support | 1 | root release scripts | Support rows are additive; changing a supported tuple restarts burn-in before re-promotion. A PLATFORM_SUPPORT_CONTRACT_VERSION bump requires qualification-evidence, acceptance-profile, and supported-platforms docs review. |
The registry lives in
packages/core/src/lib/compatibility-policy.ts
and is re-exported from @opensip-cli/contracts for public consumers.
Project config migration
Use:
opensip config migrate
opensip config migrate --dry-run
opensip config migrate --check
--check is the CI form. It does not write and exits 2 if the config would be
changed. The current migration normalizes legacy files to schemaVersion: 1;
future schema bumps add deterministic transforms here before the strict
dispatcher loader requires the new version.
Compatibility matrix gate
CI runs:
pnpm compat:matrix:ci -- --out compatibility-matrix-report.json
The matrix checks:
- every registered contract class has a policy row;
- policy versions match exported code constants;
- public JSON fixtures match
SIGNAL_ENVELOPE_SCHEMA_VERSIONand
COMMAND_OUTCOME_CONTRACT_VERSION;
- cloud wire fixtures match
SIGNAL_BATCH_SCHEMA_VERSION; - project-config fixtures migrate deterministically.
The checked-in matrix is .config/compatibility-matrix.json; public fixtures
live under scripts/compat/fixtures/.
Platform support
The platform-support class governs the native-host support claim — the exact
OS/kernel/arch/Node-ABI/npm/filesystem tuple a release is qualified against,
plus the status (supported / preview / unqualified / unsupported) that
separates a measured tuple from an unmeasured one. It is a distinct contract
class because engines.node cannot encode any of those dimensions, and because
supported is an evidence claim, never an engine-compatibility inference.
The registry lives in
packages/core/src/lib/platform-support.ts
and is rendered into the authoritative
pnpm docs:platform-support (CI enforces sync via
pnpm docs:platform-support:check). A supported row requires a bound
acceptance profile, a published release-evidence link, and burn-in
qualification metadata; a preview row requires an acceptance profile.
Bumping PLATFORM_SUPPORT_CONTRACT_VERSION is gated on evidence, profile, and
docs review together — the same lockstep rule as every other contract class.
Contributor rule
If a change touches any public contract surface, update the policy, fixture,
documentation, and tests in the same PR. Do not weaken a guardrail just to make a
breaking change pass quietly.