06 — Ontology evolution, branching & versioning.
The Ontology is a long-lived contract that must evolve without breaking active runs, active
queues, active integrations, or the audit chain. This section specifies how it evolves —
semver rules, deprecation windows, branching for parallel evolution, version pinning at the
agent and tool level, schema-compatibility tests, and replay against historic versions.
6.1 Versioning model
Each ontology object is independently versioned under a strict semver discipline, and the
ontology as a whole has a release version that pins a coherent set of object versions.
| Change kind | Bump | Examples | Migration |
|---|
| Additive optional | minor | New optional property; new enum variant; new link with cardinality 0..N | None required; consumers transparently see new fields. |
| Additive required (with default) | minor | New required property with a derivable or default value | Backfill via mapping; default applied at projection time. |
| Required with no default | major | New required property that cannot be defaulted | Dual-write window; both versions live concurrently. |
| Type narrowing | major | String → enum; nullable → non-nullable | Validation pass over historic records; quarantine rejects. |
| Removal | major | Property dropped; link cardinality changed downward | Deprecation period of at least one minor; readers updated first. |
| Rename | major | Property renamed | Aliasing: old name continues to read for one major; writes go to new name. |
| Marking change | major | Default marking elevated | Re-classification batch; access caches invalidated. |
6.2 Deprecation discipline
- Deprecated fields must remain readable for two minor versions after the deprecation announcement.
- Deprecation is itself a typed AuditEvent on the ontology version chain.
- Tools and agents pinned to a deprecated version produce an Exception (kind
ontology.deprecated_pin) at run start; runs continue but operators see a warning.
- Removal across a major bump is gated by a release-gate check that no production agent or tool still pins the removed field.
6.3 Branching
The ontology supports branches for parallel evolution: a tenant may need to
stage a major change against a subset of agents and tools without affecting production.
Branches are first-class; a branch is named, owned, and has a lifecycle.
Fig. 6.1 — Ontology branching state diagram. A branch may be promoted to shadow, where it dual-writes against trunk and is exercised by a candidate model/prompt set, before merging.
6.4 Pinning
Every agent definition, tool signature, mapping definition, and prompt revision pins to an
ontology version. The pin is a tuple (release, branch?). Pins are recorded in
the run’s model lineage (§4.3) and in every Decision’s
metadata. A run executed against a pinned version sees a frozen contract regardless
of subsequent ontology changes on trunk.
A pinned object is read with the resolver ontology.read(ref, asOf=pin). The
substrate retains historic schemas; readers are version-aware.
6.5 Schema-compatibility tests
Every ontology change passes through a compatibility test pack before it can be promoted.
The pack runs three classes of test:
- Structural: JSON Schema diff classifies the change (additive optional / additive required / narrowing / removal / rename) and validates the bump matches §6.1.
- Replay: A sample of recent runs is replayed against the candidate version; deviations in Decision verdict beyond the noise band are flagged.
- Consumer: Every active tool, mapping, and agent declaring a pin to the changed object is re-validated; pins that no longer satisfy contract block promotion.
6.6 Replay against historic versions
Replay (§4.7) of an old run resolves the ontology version captured in
the run’s model lineage; it does not “upgrade” the run to current trunk. This guarantees
that a regulator-driven re-execution of a Decision produces the exact ontology contract that
was in force at decision time.
6.7 Reconciliation merge algorithm
When a shadow branch merges into trunk, conflicts are resolved per a fixed algebra:
- Disjoint additive changes always merge cleanly.
- Same-property concurrent additions: the one with the higher pin-count wins; the other becomes a deprecation candidate.
- Type changes from both branches: hard conflict; merge fails; resolution is by an explicit Decision tagged
ontology.merge.resolution.
- Marking changes always escalate to the security plane (§15) before merge.
- Every merge produces a typed AuditEvent on the ontology chain with the diff, the algorithm path taken, and the resolver principal.
6.8 Cross-tenant boundary
Each tenant has its own ontology release line. Ontology assets are not shared across
tenants; convergence on a common base happens only via the platform’s reference release,
which a tenant chooses to consume on its own schedule. There is no automatic propagation of
tenant-specific objects, properties, or markings.