docs/architecture/forward-compat-invariants.md.The 8 patterns
FCI-001 β Kernel traits upfront, implementations deferred
FCI-001 β Kernel traits upfront, implementations deferred
nika-kernel at v0.90 for subsystems that ship later.
Default methods return Err(Unsupported) until real implementations land.MemoryStore, EmbeddingProvider, ToolExecutor,
WasmPluginHost, MetricsExporter + TracerProvider + AuditSink +
EventSink + BillingSink, Sandbox. Stubs in src/plugin/, src/infra/.Impact: v0.95 lights up the memory subsystem by adding nika-memory-oxigraph that implements
MemoryStore. Zero v0.90 code modification.FCI-002 β `#[non_exhaustive]` on every public struct, enum, error variant
FCI-002 β `#[non_exhaustive]` on every public struct, enum, error variant
#[non_exhaustive] so adding a field or variant
is always additive. new() constructors provide ergonomic construction
without exposing struct literal syntax.#[non_exhaustive] struct ships a new() constructor.FCI-003 β Single version marker per on-disk artifact
FCI-003 β Single version marker per on-disk artifact
nika: v1 (a
single version marker Β· the language name as key, the contract version
as value Β· supersedes the older K8s apiVersion: and schema: nika/workflow@X forms). Parsers reject any other value (v1.0 Β· v2 β¦)
with a clear error.v1 is the only value for the lifetime of the v1 contract β minor
additions are additive and never change it. A nika: v2 would be a
deliberate breaking generation (the v1 envelope is frozen Β· effectively never).
Non-workflow artifacts (package manifests, events) carry their own
schema version field.FCI-004 β Extension namespaces (`nika.*` core + `x-*` community)
FCI-004 β Extension namespaces (`nika.*` core + `x-*` community)
nika.* for core additions
(authoritative, versioned) and x-* for community overlays (no
stability guarantee, no collision with core). Scope note Β· in the
workflow language both are RESERVED, not current β unknown top-level
fields are rejected at v0.1, and the tool namespace set is closed at
nika: / mcp: (engine-specific tools route through mcp:). The
live x-* surface today is the pck registry.FCI-005 β Reserved error code ranges
FCI-005 β Reserved error code ranges
NIKA-<NAMESPACE>-<NNN> taxonomy (28 registered v0.1 codes Β·
reference/error-codes) β namespaces own
001-099 ranges, codes are never repurposed. The ENGINE-INTERNAL
registry (nika_error::codes Β· NIKA-1000+ blocks per L1 effect
crate) is diagnostics machinery β reserved per crate, never
reassigned, and never leaked into workflow-visible errors.FCI-006 β Sealed traits for core, open traits for extension
FCI-006 β Sealed traits for core, open traits for extension
Provider, EventSink, Sandbox) are
sealed via a private supertrait β only Nika-owned crates can
implement them. Extension traits (e.g., MemoryStore) are open for
community crates to implement.FCI-007 β Feature flags with stable defaults
FCI-007 β Feature flags with stable defaults
feature flag, OFF by default. After 1-2 minor
cycles of stability, flips to default-ON. Never remove a default feature
(breaking change) β deprecate and redirect.FCI-008 β Public API discipline via CI
FCI-008 β Public API discipline via CI
cargo public-apiβ detects API surface changes per crate.cargo semver-checksβ verifies SemVer compatibility.cargo denyβ enforces license + advisories + layer bans.
.public-api.json
snapshots are checked into the repo per crate.The 5 locked decisions (v0.80)
| ID | Decision | Impact |
|---|---|---|
| FCI-009 | EventKind = scoped sub-enums (Pattern B), ~22 categories | Emit site is compile-time checked; sub-enums evolve independently |
| FCI-010 | InferRequest / InferResponse fields reserved: memory, budget, baggage, trust_level, trace_id | v0.95 adds memory without touching kernel |
| FCI-011 | schema: field mandatory day-1 | Every on-disk artifact versioned from v0.90 forward |
| FCI-012 | Provider trait shape frozen (4 methods, 1 sealed supertrait) | Cross-provider parity testable (shadow zone 2 + 7) |
| FCI-013 | Telemetry = 5 sibling sinks (Event, Metrics, Trace, Audit, Billing) | OTel GenAI semconv bridged via typed GenAiAttrs β Q13 rev.3 |
The 10 rules
cargo public-api +
cargo semver-checks catch violations before merge.- All public types carry
#[non_exhaustive]. - All public structs with
#[non_exhaustive]ship anew()constructor. - All
asynctrait methods usetrait_variant::makefor dynamic dispatch. - All core traits seal via private supertrait.
- All error types expose a
NIKA-XXXcode viaNikaError::code(). - All on-disk schemas carry
schema: "nika/<kind>@<major>". - All DTO fields reserve forward-compat extension slots (see FCI-010).
- All feature flags default to a stable subset β new caps ship OFF.
- All public API changes emit a
cargo public-apidiff in the PR. - All breaking changes require ADR Accepted before merge.