This is the agreed target architecture for the Ziran and Kryon repositories. It is not a claim that every part is implemented. Current gaps are tracked in Implementation status.
Repository ownership
| Repository | Owns | Must not own |
|---|---|---|
| Ziran | Language semantics, parser, checker, laws, standard library, .zir, native backends, .zx linker, verifier, loader, and generic execution runtime |
Widgets, UI trees, styling, DOM policy, renderers, Kryon-specific names or implicit UI startup |
| Kryon | Importable .zi modules for widgets, layout, themes, interaction, accessibility, rendering, and platform adapters |
Ziran syntax, compiler branches for widgets, or an application's terminal or product UI |
The dependency direction is Kryon → Ziran. A CLI, service, or library can use Ziran without Kryon. Importing Kryon is an explicit source dependency. Kryon's maintained implementation, including its widget and runtime logic, is 100% Ziran source. A platform adapter may call operating-system or third-party APIs through declared FFI or host capabilities; those external libraries are dependencies, not a second copy of Kryon's implementation. Generated C or Go is compiler output, not Kryon source.
Language boundary
Modules, records, functions, imports, and procedure values are general
language features. Calls resolve against visible function signatures and
record types. Their semantics do not depend on the callee's spelling.
Button, Text, and Image mean nothing until imported or declared.
Kryon's intended Image(ImageProps) surface is an ordinary library API,
including when used for semantic images; its full rendering implementation
is still being migrated. A record argument uses Function(Props.{value = 42});
result: Result = Function(Props.{value = 42}) binds a non-void return value.
Ziran has no #ui function modifier, app/route syntax, widget fallback,
#style directive, DOM fields in its IR, or renderer-specific type checks.
Kryon defines its own composition, styling, navigation, and lifecycle APIs in
.zi. If a general language feature is needed for those APIs, it must work
for unrelated libraries too and pass the same checker and backend tests.
Language laws constrain semantics, types, evaluation order, IR validity, and backend equivalence. Kryon owns its UI behavior and rendering laws. Language direction sets the additional requirements for law-driven development, LLM tooling, parallel execution, and evolution.
Compilation and execution
.zi modules ──parse/check──> .zir modules
.zir modules ──native backend──> C or native Go output
.zir modules ──link/verify──> .zx ──portable runtime + host capabilities──> process
Inside the compiler, names in that model are interned: an expression's or
statement's name and type, and a function's parameter list, are shared
immutable strings (KeepName, KeepParameters), so equal spellings within a
compilation context are one pointer. Parameter lists are split once into names and types
(ParametersOf). Type and procedure resolution keep entry-scope answers,
including misses and ambiguity, until declarations or imports change
(SymbolLookupsChanged). Lookup file spellings remain part of each key;
recursive import walks retain separate cycle state. make sanitize checks
each kept answer against a fresh lookup.
Record bodies share immutable parsed field snapshots. Field lookup uses an index over that snapshot, and ownership checking can reuse the fact that every field is a built-in value or pointer. This shortcut never assumes facts about named types, arrays, or generic applications: those still resolve in their owning scope. Rewriting a body selects a new snapshot, so copied or relocated record declarations cannot retain stale field names or ownership facts.
Every backend consumes the same checked .zir model. Native output may bind
declared platform libraries. .zx contains portable executable content and
cannot depend on arbitrary target-specific C or Go source fragments.
Native and portable builds of the same supported program must agree on
observable language behavior.
Semantic checking sets ZirFunction.checked only from language validity.
Native symbol planning runs afterward, and body eligibility is a separate
emitter query. An emitter's inability to represent a valid function does not
turn that function into unchecked source. The portable verifier remains the
authority for executable .zx support.
Parameter declarations have one immutable parsed view, including binding names, types, namespace modifiers, and defaults. Record fields likewise use the shared field snapshots. Backends consume these views; source spellings remain available for diagnostics, template rewriting, and serialization.
Compilation contexts own interned text, source paths, symbol answers, declaration snapshots, expression caches, and reusable scratch buffers. Source and artifact readers create a context when the caller has not selected one. Programs and linked copies retain the contexts whose bytes they borrow; closing the original program therefore cannot invalidate a linked copy. Source spans keep their original context independently of the module's lookup context. Context pointers and cache identities are never serialized.
Public source parsing is a recoverable operation. Syntax and source-read
errors return NULL after reporting the ordinary structured diagnostic.
An operation-local allocation transaction releases partial trees, temporary
buffers, and open streams after an error, and restores the enclosing parser
state. Transactions nest across import callbacks and are local to each thread.
Published immutable caches remain owned by their context. See
Compiler embedding for lifetime and concurrency rules.
The linker resolves explicit imports, includes the reachable library code, and reports unresolved symbols or unavailable capabilities. A program with no Kryon import has no Kryon code or graphics requirement. A program importing Kryon links the Kryon modules it uses; graphics, input, audio, filesystem, and other host access must be declared as capabilities when needed. The host supplies those capabilities. A missing required capability is a reported error, never silently ignored.
The portable runtime launches a non-graphical .zx without initializing a
window or display. Kryon decides how to use the host's graphical capabilities
through its imported .zi implementation. The compiler and loader do not
inspect widget names to make that decision.
Product boundary
Kryon is a reusable library. Applications keep their own product logic and UI in their repositories and import Kryon. Kapsule's terminal emulator, for example, belongs to Kapsule; Kryon only gains small reusable primitives when multiple applications need them. See Migration for the single breaking cutover and verification gates.