Skip to content

Architecture Decisions — Register ​

2026-10-22: every proposal below was ACCEPTED by the project owner and recorded in ADR 0002. The exceptions are KQ-2, 3, 5, 6 and 7, which need CosmoOS changes or rulings; Nova uses the conservative defaults listed in ADR 0002. Add new open questions below with the next free ID (OD-22+).

Original status: Milestone 0 (master prompt §23.K). Each item lists the proposed (now accepted) answer.

Language and compiler (owner: Nova) ​

IDQuestionProposedAlternativesSafety impactPerf impactBlocks
OD-1Compiler implementation languageC# / .NET 10, NativeAOT for distribution (ADR 0001)Rust, C++20none directlycompile speed onlyM1
OD-2Memory architectureHybrid (C): ownership + regions-as-loans + optimisation-only escape analysis (memory-model.md)A (pure ownership), B (regions)defines the safety argument—M1 (shapes IR)
OD-3Lifetime-parameterised structs (references in user aggregates)Not in v0 (E3). Designed in M6f (od3-design.md); accepted (ADR 0006) and implemented in M6x (2026-10-23; milestone-6x.md): region parameters on structs, enums and functions (struct Parser<region src>), one loan set per value, call-site propagation by regions, drop check (type-system.md §25, ownership.md E3/E4)Rust-style 'a nowlarger checker surfaceenables zero-copy— (done in M6x)
OD-4class keywordReserved; future sugar for always-boxed non-Copy typesClasses now; drop the keywordnone if sugar—M6
OD-5Panic strategyAbort, no unwinding; destructors do not run on panicUnwinding via C setjmp (no setjmp in CosmoOS libc, and costly)simpler cleanup proofssmaller codeM1
OD-6Integer overflowPanic in all builds; explicit wrapping*/checked*/saturating*Rust-like wrap in releaselogic safetysmall check cost (BCE/range analysis M9)M1
OD-7Copyability of structsImplicitly Copy iff all fields Copy and no drop; @noncopy to opt outExplicit copy struct opt-in (Rust-like)none (both sound)—M2
OD-8Arena with destructorsv0: arena contents must have no drop (R2); later a drop listAllow drops nowresource leaks if done wrong—M4
OD-9ClosuresNone in v0. Non-capturing fn pointers only. Scoped capturing closures in M6+. M11 G8: ADR 0012 accepted 2026-10-25 (function values fn(…) -> R, scoped closures borrow fn(…) -> R with arrow literals, inferred captures, effects on function types)—closures carry borrows—M6
OD-9aMonomorphised closures (each literal its own type, F: Fn(T) -> R bounds; inlinable calls, owning captures through generics)Deferred by ADR 0012: decide when a performance need appears, with a benchmark. ADR 0019 accepted and implemented 2026-10-28: specialisation in the compiler (optimisations.md §5), no language change; benchmarks/sort is 34% (clang) and 28% (gcc) faster. Closure types and Fn bounds stay open as a language question. Re-examined 2026-10-29 and kept deferred (owner): specialisation met the measured need and Box<dyn fn> stores closures; take it up when a real program needs a closure stored without an allocation, or lazy iterator adapters—none beyond ADR 0012removes the indirect call—
OD-9bOwning, heap-allocated closures (returnable, storable, sendable)Deferred by ADR 0012: only together with dyn (OD-10). M13 G3: ADR 0015 accepted 2026-10-28: move literals boxed as Box<dyn fn(…) -> R, A>, an explicit and fallible allocation (so the kernel profile may use them with KernelHeap); implemented 2026-10-28 (type-system §36.5)—needs dyn and allocationan allocation per closureOD-27
OD-28Global and per-CPU state: static items whose mutable state is reached only through Share types (lock guards, atomics), statically initialised C state, @percpu statics accessed where the CPU cannot changeProposed by M14 K1 for CosmoOS's roadmap 2.0 (SA2, SA3). ADR 0024 accepted 2026-10-29: static of Share types and static mut (every use unsafe), built by @constant constructors and C constant macros; per-CPU data a kernel-library typestate only in C, as todaya static is shared by every thread: it must be SharenoneSA2
OD-29Nova-to-Nova calls with Nova's types across compilation units: C in several translation units (K2a), then separate compilation per package with interface files (ADR 0013 D4 deferred it until build times were measured)Proposed by M14 K2: a whole-program build of 202,000 lines takes 13.1 s in novac plus 33.8 s in clang, one translation unit, on every change. K2a accepted (ADR 0022, 2026-10-29): --split, one C file per Nova file; separate compilation stays openstay whole-programnone (the checks are the same)build timeSA6
OD-30Where the kernel library (KernelHeap, KRef<T>, the lock guards, Quiesce, and a new ObjectCache<T>) lives and who owns itProposed by M14 K3. ADR 0025 accepted 2026-10-29: in Nova's repository, lib/kernel, selected by kernel = "cosmoos"; trusted = true packages may declare @threadSafein Nova's repositoryunsafe at the floor, argued oncenoneSA2
OD-31How a self-hosted CosmoOS builds its kernel when the generated C is no longer committed (its roadmap 2.0's rule 7), since novac does not run on CosmoOSProposed by M14 K4. ADR 0023 accepted 2026-10-29: source releases carry the generated Cnovac on CosmoOS; a compiler written in NovanonenoneSA1
OD-32novac running on CosmoOS (a .NET runtime port, or .NET through the Linux personality)Recorded by ADR 0023: not needed while source releases carry the generated C—nonenone—
OD-33A Nova compiler written in Nova, for a self-hosting toolchainRecorded by ADR 0023 as the long-term direction—nonenone—
OD-34Self-pointing C state in statics (a static Mutex, wait queues, list heads) and moves of non-Copy values through raw pointers (ObjectCache<T>)Left open by ADR 0025 §7. ADR 0027 accepted 2026-10-29: here in static initialisers, MUTEX_INIT_AT in CosmoOS; unsafe read/write for any T, Layout.of<T>(), a static-only ObjectCache<T>a lazily initialised StaticMutex<T>; stateful Box allocatorsread/write can duplicate or leak ownership (unsafe)none (here); two pointers per cache boxSA2, SA3
OD-10
OD-9cEffect-polymorphic functions: a function whose effects are its own plus those of a closure argument's type (so sortBy could run in an atomic context with an @effects() comparator)Deferred by G8c (type-system.md §36.4): the library methods have the effects of a closure without an effect list. ADR 0020 accepted 2026-10-29: @effectsOf(p), Swift's rethrows for sleep and alloc; effect variables stay open—nonenoneADR 0012 §3.7
OD-23Floating-point types (f32/f64): arithmetic semantics, formatting for Console, casts, and the kernel-profile banDeferred by ADR 0005. Schedule as a separate increment (after M6). M11 G7: ADR 0011 accepted 2026-10-25 (IEEE, no contraction, never-panicking arithmetic, checked float→int, shortest round-trip printing (Schubfach), --no-float; then sqrt/abs/floor/ceil/min/max)Add in M6float formatting costEx2/Ex13 run with integers until thenpost-M6
OD-24Weaker atomic orderings (acquire, release, relaxed) for userland atomicsDeferred by ADR 0016: sequentially consistent only in v1, until a benchmark needs more. ADR 0021 accepted 2026-10-29 after benchmarks/atomics (a ring 5–9× faster on x86-64 with acquire/release): ordered …With methods in lib/std—ordering bugs are not data races, but are logic bugsfences on weakly ordered CPUs—
OD-25Scoped threads (Thread.scope) that borrow the spawner's localsDeferred by ADR 0016: needs a rule for borrows that outlive one closure call. ADR 0018 accepted and implemented 2026-10-28: fork-join, Thread.both(a, b) (type-system §38.6, ownership T4), which needs no new borrow rule. Handles and loops of spawns (Rust-style scopes) stay open—borrows across threadsnone—
OD-26Several versions of one package in one buildDeferred by ADR 0017: one version per package name, as today; several would need per-version C names (c-backend.md §2.1). Re-examined 2026-10-29 and kept deferred (owner): the index has no packages yet, so no build can meet a conflict; take it up when published packages' requirements conflict—nonecode size—
OD-10Dynamic dispatch (dyn Interface)Future. Static generics only in v0. M13 G2: ADR 0015 accepted 2026-10-28: fat pointers behind borrow/borrow mut/Box, dyn-compatible interfaces, no scoped T and no downcasting in v1 (OD-10a dyn(r) I, OD-10b downcasting stay open)vtables now—code sizeM6
OD-11Package / manifest formatnova.toml with name, version, profile, dependencies. M10: ADR 0013 accepted 2026-10-26 (path and git dependencies with a lock file, as the owner chose; package-level names, import; whole-program builds). M13 G6: ADR 0017 accepted 2026-10-28: a git index, caret requirements, a solver———M10 (T5–T6)
OD-12Growable scratch arrays (Goose "one growable on top")Not in v0adoptcomplex shrink rulesfaster temporariesM5
OD-13Rc<T>/Weak<T> library typePost-M6, explicit and opt-in, single-threadednevercycles leakRC trafficpost-M6
OD-14@flat inline variable-size layoutsPost-M9 research————
OD-17Call-site borrow syntaxImplicit shared borrow, mut x for exclusive, borrow x/borrow mut x elsewhereRust &x/&mut xnone—M2
OD-18Surface syntax for references in typesborrow T / borrow mut T (as the prompt proposes)&T/ref Tnone—M2

CosmoOS integration (owner: CosmoOS project owner) ​

IDQuestionProposedBlocks
OD-15Is the Nova runtime "library" under libc invariant L1 (may it use raw cosmo_* syscall wrappers)?No: public libc functions only, until the owner says otherwiseC1 (confirms the approach)
OD-16May Profile A also target the musl/Linux personality?Later, as an opt-in profile; native is the defaultC3
OD-19Is checked-in generated C acceptable (port route S1)? Or must generation run in the build (.NET in CI)?S1: checked-in, deterministic, with a header naming the novac version and source hashC1→C3 in-tree
OD-20Will the owner schedule a Nova unit (AGENTS.md restricts work to the owner-chosen 1.2 unit)?Propose after C1 succeeds out of tree (S0)in-tree work
OD-21Missing libc pieces (aligned_alloc, math.h, poll, strtod, exec*): add to CosmoOS libc, or implement in the Nova runtime?Add to libc as owner-chosen units (they benefit C too); Nova works around them meanwhileC3
KQ-1…KQ-8Kernel questionsSee cosmoos/kernel-memory-and-lifetimes.md §8C5–C8

Also to report to the owner (no decision needed from Nova): CosmoOS's limits.h CHAR_MIN/MAX are wrong on AArch64. About 18 doc/code disagreements are listed in the two audit reports.

Pre-1.0: the language and its tools are still changing.