Skip to main content
Version: 0.2.10

Compatibility contract

This page is the single source of truth for what “compatibility” means in the X07 ecosystem.

The goal is to make it safe and measurable to evolve the toolchain without repeatedly breaking real projects and dependencies.

Definitions

X07 has multiple versioned surfaces:

  • Toolchain: x07 / x07c SemVer releases.
  • Project manifests: x07.json (x07.project@…) and lockfiles (x07.lock@…).
  • Programs/modules: *.x07.json (x07.x07ast@…).
  • Contracts/schemas: JSON schemas under spec/ (for example x07diag, x07patch, x07test).
  • Stable function contracts: _v1 suffixes and other explicitly versioned ABIs/encodings.

Compat Selection (project.compat, --compat, X07_COMPAT)

x07.project@0.5.0 introduces an optional project.compat field that pins language/toolchain compatibility semantics for a project.

Example:

{
"schema_version": "x07.project@0.5.0",
"compat": "0.5",
"world": "run-os",
"entry": "src/main.x07.json",
"module_roots": ["src"]
}

Resolution order (highest priority first):

  • CLI: --compat ...
  • Environment: X07_COMPAT=...
  • Project: x07.json compat
  • Default: current

When a behavior change is mechanically migratable, prefer x07 migrate --check/--write to explicitize required rewrites.

What Must Stay Compatible

The following are treated as “compat-critical” surfaces:

  • Older x07.project@… manifests should remain readable and runnable for as long as we claim support in docs/packages/index.md.
  • Older x07.lock@… lockfiles should remain readable, or fail with a deterministic error that tells the user what to do next.
  • Older x07.x07ast@… programs and modules used by official packages should continue to compile.
  • Call-argument compatibility: in call-argument position, bytes (and in some APIs, vec_u8) is accepted where a parameter expects bytes_view and is treated as an implicit view for that call. This is a call-site-only rule (bytes is not a general subtype of bytes_view).
  • Diagnostic codes are stable identifiers. New codes are additive; existing code meanings should not be silently repurposed.
  • Versioned contracts (*_v1, MAGIC+VERSION envelopes, spec/ schemas) do not change in-place.

What Is Allowed To Change

Some surfaces are intentionally allowed to evolve:

  • Non-versioned CLI text output (use --json/reports for machine stability).
  • Performance characteristics (as long as determinism and resource bounds remain intact).
  • Internal implementation details that are not part of a documented public contract.

Deprecations (policy)

When a compat-critical behavior or surface is deprecated, the deprecation must be:

  • Documented in this file (including the migration story and the diagnostic code(s)).
  • Backed by a regression surface (compat corpus and/or fixability cases).
  • Surfaced to users as structured diagnostics with actionable notes.

Timeline:

  • Deprecations must not be removed while they are still inside the supported window (current stable and N-1).
  • If removal is planned, the toolchain should first emit warnings for at least one supported release cycle before turning the deprecation into an error, unless security or correctness requires immediate failure.

How warnings are emitted:

  • Warnings are emitted as x07diag diagnostics with severity="warning" and stable code identifiers.
  • x07 check and x07 run continue to succeed (exit code 0) when only warnings are present, but they still include the warnings in the JSON report so agents can repair/migrate proactively.

Guardrails

Compatibility is enforced by CI guardrails:

  • Compat corpus: a curated set of projects and fixability cases that must keep working across toolchain changes.
    • Config: tests/compat_corpus/corpus.json
    • Harness: scripts/ci/check_compat_corpus.sh
  • Docs examples compile: all docs/examples/**/x07.json projects must typecheck against the current toolchain.
    • Harness: scripts/ci/check_doc_examples_compile.py
  • Diagnostics catalog coverage: every emitted diagnostic code must be documented and discoverable. (See x07 diag coverage and the CI gate described in this section.)

How To Introduce A Behavior Change

Any behavior change that can affect downstream packages/projects must:

  1. Be documented here first (including the motivation and the migration story).
  2. Have a regression surface in the compat corpus (a project or a fixability case).
  3. Either:
    • be behind a compatibility switch, or
    • be mechanically migratable (via x07 fix and x07 migrate).

Change → Migration Mapping (Appendix)

When a breaking or near-breaking change is introduced, add an entry here with:

  • the exact behavior change
  • what breaks (and how to detect it)
  • the mechanical rewrite (when possible)
  • the compatibility switch (when applicable)
  • links to the relevant diagnostic codes

Control Flow: while (compat 0.5)

Behavior:

  • Adds the core form ["while", cond, body] (returns i32 0) to reduce recursion-as-loop pressure.

Migration:

  • No migration required (additive).

Recursion: Termination Evidence (compat 0.5)

Behavior:

  • Direct self-recursive defn targets require decreases[] only when the function declares any contract clauses (requires/ensures/invariant/decreases).
  • Functions with no contract clauses may recurse without decreases[] boilerplate.
  • decreases[] is allowed as the only contract clause.

Detection:

  • X07-CONTRACT-0011 indicates a recursive self-call is missing decreases[] on a contract-bearing function.

Mechanical rewrite:

  • Add decreases[] to the recursive defn.
  • When the recursive call matches a common pattern (for example n -> n-1), x07 fix --write / x07 migrate --write --to 0.5 can insert an inferred decreases[] clause.