Can a programming language remain stable enough for real engineering while still evolving its syntax, features, and ergonomics in response to actual usage?
The Living Compiler is an answer to that question. Instead of freezing a language at version 1.0 and compensating with macros, wrappers, and conventions, KernRift separates the language into two layers: a stable semantic core (type rules, IR, safety model, ABI) that changes slowly, and an adaptive surface layer (syntax sugar, annotations, diagnostics, common patterns) that evolves with observed usage. Multiple surface versions can coexist as long as they lower into the same canonical IR, so old code keeps compiling forever while new code gets modern ergonomics.
krc lc is the current entry point to the system. It walks your source, collects telemetry, detects patterns, and reports them in two sections: semantic-core issues (correctness/safety concerns) and adaptive-surface suggestions (ergonomic migrations that lower to the same IR). Patterns tagged auto-fix available are candidates for the migration engine.
Telemetry Collection
The compiler walks your AST and call graph, counting functions, call sites, unsafe operations, total ops, and more. This data feeds every downstream pass.
Two-Layer Pattern Detection
Each pattern is classified as semantic core (correctness/structure) or adaptive surface (ergonomic migration). Core issues weigh more in the fitness score — the cost of a safety bug is strictly greater than the cost of verbose syntax.
Layer-Weighted Fitness
Each source file receives a score from 0 to 100. Core patterns deduct up to fitness/4; surface patterns deduct up to fitness/8. Use krc lc --ci --min-fitness 60 to fail builds that fall below a threshold.
Auto-Fix Candidates
Patterns tagged (auto-fix available) describe a mechanical rewrite to the new form — same generated code, cleaner source. Today the tag is advisory; the migration engine that applies them is the next stage of the blueprint.
The Blueprint Pipeline
Telemetry → Proposals → Fitness → Governance → Migration. Each stage is independent. You can run just the telemetry and proposal passes today; governance and migration are future work.
| Stage | Purpose | Status |
|---|---|---|
| Telemetry | Observe usage patterns: call graph, unsafe density, call chain depth | ✓ Implemented |
| Pattern detection | Identify friction points (semantic-core and adaptive-surface) | ✓ Implemented |
| Fitness scoring | Layer-weighted 0-100 score; CI gating | ✓ Implemented |
| Auto-fix tagging | Mark patterns whose rewrite is identity-preserving | ✓ Implemented (advisory) |
| Migration engine | Apply auto-fixes in place, batch-rewriting old forms | Planned |
| Proposal engine | Generate new candidate syntax forms from observed friction | Planned |
| Governance layer | Approve / reject / stabilize / deprecate proposals over time | Planned |
| Versioned profiles | #lang stable, #lang experimental, domain dialects | Planned |
The Living Compiler in Action
Evaluate code fitness mathematically and enforce it in CI.
$ krc lc driver.kr
=== KernRift Living Compiler Report ===
stable semantic core + adaptive surface layer
Telemetry
Functions: 13
Calls: 21
Unsafe ops: 22
Total ops: 205
Patterns: 2
Fitness: 73/100
--- Semantic Core (1) ---
[1] unchecked_call fitness: 43
title: Unchecked call results
signal: 95 occurrence(s)
suggestion: Check return values of calls, especially for file I/O and allocation.
--- Adaptive Surface (1) ---
[1] legacy_ptr_ops fitness: 60 (auto-fix available)
title: Legacy unsafe{} pointer syntax
signal: 22 occurrence(s)
suggestion: Migrate `unsafe { *(addr as T) -> dest }` to `dest = loadN(addr)` and `unsafe { *(addr as T) = val }` to `storeN(addr, val)`. Same codegen, much cleaner.
# Fail CI if any pattern with fitness ≥ 60 is present
$ krc lc --ci --min-fitness 60 driver.kr
# Fast semantic pass: undeclared identifiers, wrong arg counts, missing returns
$ krc check driver.kr
# Combine with living compiler for a full structural report
$ krc check driver.kr && krc lc driver.kr
Bug Reports & Discussions