Versioning
Version: 2.0.0
This document specifies how Calor semantics are versioned and how version compatibility is managed.
Why Versioning Matters for Agents
Agents will be trained and prompted against specific rules.
When an agent generates Calor code, it relies on specific semantic behaviors:
- "Overflow traps" (not wraps)
- "Left-to-right evaluation" (not unspecified)
- "
&&short-circuits" (not eager)
If these rules change between versions without clear versioning:
- Agents trained on v1 rules will generate incorrect code on v2 compilers
- Prompts that describe v1 behavior will mislead agents on v2
- Code that "worked before" will silently break
Stable versioning ensures that agents know exactly which rules apply.
Version Format
Calor semantics versions follow Semantic Versioning 2.0.0:
MAJOR.MINOR.PATCH
- MAJOR: Breaking semantic changes (agents must be retrained)
- MINOR: Backward-compatible semantic additions (old code still works)
- PATCH: Clarifications, bug fixes in semantics (no behavior change)
Current Version
Semantics Version: 2.0.0
Bumped from 1.0.0 for the v0.14 nullability work. This changed the severity of binder diagnostics, not their production CLI routing.
Diagnostic routing correction (2026-09-11)
Error severity in the binder is not the same as production CLI rejection.
Historical routing through Calor 0.21: at checked main revision 080ed5a7,
Program.Compile used BindingDiagnosticPolicy, which excluded
Calor0272 (binding initialization),
Calor0273 (return), and Calor0274 (argument). The language server's
DocumentState bound directly, so editor diagnostics could differ. Other
compiler passes may independently reject the same program.
This historical behavior was not a newly introduced regression. The routing policy and its
Program.Compile call were introduced in
cc62c4ac,
an ancestor of all three release commits below. Each tagged source has the
same exclusion and calls the policy from Program.Compile.
| Release tag | Commit | Tagged policy / compilation path |
|---|---|---|
| v0.14.0 | 0e327664 | Policy / Compile |
| v0.14.1 | 473cb5e3 | Policy / Compile |
| v0.14.2 | 1246d8d9 | Policy / Compile |
These are scoped source-history findings, not a claim that every possibly-null program compiles or that every published binary has been independently tested. Calor 0.22's bounded checks (#1082) now activate production Errors at specified initialization, native-return, and resolved method-input boundaries. They cover scalar strings, supported arrays, one-level whitelisted string generic payloads, and identity-proven nominal references. The historical exclusion above is not the current routing policy for those shapes. See the nullability guide for complete examples and mode behavior.
General mutation, member writes, constructor inputs, and outer generic-container enforcement remain excluded; array annotations do not prove every slot initialized. These checks do not establish whole-program non-nullness. The D3/D12/D14 safeguards that demote conditional proofs and retain their runtime guards remain in place. #875 remains open.
Version Declaration
A module declares the semantics version it was written for with a §SEMVER
directive, usually the first line of the module body:
§M{m001:MyModule}
§SEMVER{2.0.0}
§F{f001:Main:pub} () -> void
§E{}
§R
Syntax
Exactly one spelling is accepted: §SEMVER{MAJOR.MINOR.PATCH} with three
numeric parts and nothing else between the braces, for example
§SEMVER{2.0.0}. Caret (^2.0.0), range (>=2.0.0 <3.0.0), and shortened
(2, 2.0) forms are rejected with Calor0702; so are a leading sign or any
whitespace (+2.0.0, { 2.0.0 }), the bracket form §SEMVER[2.0.0], a {
not closed on its line, and a second §SEMVER in the same module.
Modules That Declare Nothing
A module without §SEMVER takes the compiler's own version (currently 2.0.0)
and gets no diagnostic. The calor hook write-time reminder suggests adding
§SEMVER{2.0.0}.
Compatibility Rules
Patch Version Changes (x.y.Z)
Fully compatible. Changes include:
- Documentation clarifications
- Specification bug fixes
- Test additions
Example: 2.0.0 to 2.0.1 is safe.
Minor Version Changes (x.Y.z)
Backward compatible. Changes include:
- New constructs added
- New operators added
- New optional behaviors
- Extended standard library
Example: Code written for 2.0.0 will compile and run correctly under 2.1.0.
Major Version Changes (X.y.z)
Incompatible by definition. Changes may include:
- Evaluation order changes
- Operator precedence changes
- Type system changes (the 2.0.0 bump changed binder nullability severity, not production CLI routing; see the correction above)
- Default behavior changes
- Removed constructs
Example: Code written for 1.x is refused by a 2.x compiler.
Compiler Behavior
The major must match exactly. A module that declares an older major (for
example §SEMVER{1.0.0} on the 2.0.0 compiler) is refused rather than quietly
read under the newer rules. The error calls for manual review and migration
to current semantics before declaring §SEMVER{2.0.0}. Changing the declaration
alone is not a migration. There is no legacy Info compilation mode, and
Calor0272/0273/0274 are binder/editor diagnostics rather than production
CLI rejection gates. See
#1084.
Diagnostic Codes
| Code | Severity | Condition |
|---|---|---|
| Calor0700 | Warning | Same major, declared minor newer than the compiler's (might work) |
| Calor0701 | Error | Declared major differs from the compiler's — older or newer |
| Calor0702 | Error | §SEMVER is not MAJOR.MINOR.PATCH, or appears more than once |
Compatibility Matrix (2.0.0 compiler)
| Module declares | Result |
|---|---|
| (nothing) | Compatible — takes 2.0.0, no diagnostic |
| 2.0.0, 2.0.5 | Compatible |
| 2.1.0 | Warning (Calor0700), compiles |
| 1.0.0, 1.9.9, 0.9.0 | Error (Calor0701) with migration pointer to #1084 |
| 3.0.0 | Error (Calor0701), "upgrade the compiler" |
^1.0.0, 2, 2.0, second §SEMVER | Error (Calor0702) |
Version History
Version 2.0.0 (Current)
The v0.14 bump changed binder diagnostic severity. The v0.14.0 promise of
legacy Info severity was a future plan, not a shipped mode. The severity
helper's lower-major branch does not make older modules compatible.
The §SEMVER parser and fail-closed refusal arrived in
#1087:
that commit is not an ancestor of v0.14.0-v0.14.2, but is an ancestor of
v0.15.0 (3bb2601e).
Modules declaring 1.x or 0.x are now refused with Calor0701, not compiled
in an Info mode. This correction adds no automated semantics migration tool.
Version 1.0.0
Initial formal semantics specification including:
Evaluation Order
- Left-to-right function argument evaluation
- Left-to-right binary operator evaluation
- Short-circuit
&&and||
Scoping
- Lexical scoping with parent chain lookup
- Inner scope shadows outer
- Return from nested scope
Numeric Semantics
- Integer overflow traps by default
- INT to FLOAT implicit
- FLOAT to INT explicit
Contracts
- REQUIRES evaluated before body
- ENSURES evaluated after body with
resultbinding - ContractViolationException with FunctionId
When to Bump Versions
Bump MAJOR When
- Changing evaluation order of existing constructs
- Changing default overflow behavior
- Removing constructs
- Changing type coercion rules
- Changing contract semantics
Bump MINOR When
- Adding new syntax constructs
- Adding new operators
- Adding new built-in types
- Extending pattern matching
- Adding optional compiler flags
Bump PATCH When
- Fixing ambiguities in specification
- Adding test cases
- Improving documentation
- Fixing compiler bugs that didn't match spec
Migration Guidance
Upgrading Modules
When upgrading a module to a new semantics version:
- Review changelog for breaking changes
- Run tests with new compiler version
- Update
§SEMVERdeclaration - Test edge cases related to changed semantics
For 1.x to 2.0.0, manually review the current semantics and the module's
null-handling choices before changing the declaration to §SEMVER{2.0.0}.
Test the migrated code; a version edit or successful compile alone does not
establish null safety. Calor0272/0273/0274 can appear in binder/editor
diagnostics but do not establish production CLI rejection. Other passes may
reject independently. An older-major declaration still produces Calor0701.
Mixed-Version Projects
There is no dual-semantics mode. Every module in a compilation must declare
the compiler's major (or declare nothing); a §SEMVER{1.0.0} module is
refused until it is migrated.