- Status: Accepted (partially implemented — see per-item status)
- Tier: varies (see individual items)
- Author: David Porkka
- Created: 2026-07-19
- Resolved: 2026-07-19 (Accepted)
- Language-version at effect: 1.0.0-frozen (items 5, 6, 10, 11 took effect)
- Supersedes: none
- Superseded by: Per-item RFCs TBD
Documents the remaining items from the Nulang 200-Year Longevity Roadmap that were scoped but not implemented in the initial execution pass. Each item below is a distinct, self-contained RFC-to-be with concrete file targets and the change to make. This RFC serves as the scoping artifact so the remaining work is tracked, not forgotten.
Target: spec/formal/ — new top-level directory (language artifact).
Change:
spec/formal/types.lean— formalizeType,Scheme,Substitution,mguwith occurs check,generalize/instantiate. State and prove Theorem type_soundness:∅ ⊢ e : τ ∧ e ↦ v ⇒ ∅ ⊢ v : τ.spec/formal/capabilities.lean— formalize the capability lattice,join,is_subtype_of,is_sendable, LinearIso at-most-once consumption. Prove Theorem cap_sendable: aval/tagvalue can cross actor boundaries without violating isolation.spec/formal/effects.lean— formalizeEffectRow(Closed/Open + Region), handler dispatch,Perform/Resume/Unwind. Prove Theorem effect_safety: a program with closed effect row{}cannot perform an unhandled effect.spec/formal/Makefileand CI job runninglake buildon every PR touchingsrc/typechecker.rs,src/effect_checker.rs,src/types.rs.
Why: The combined type/effect/capability system has no machine-checked model. Prose is insufficient for a language that wants to survive 200 years.
Contingency: If the full combined system is too hard, formalize the components separately (HM, capabilities follow Pony, row effects follow Koka) and state the combination as a conjecture with a documented proof plan. Do not skip the artifact entirely.
Target: bootstrap/ — new top-level directory. SPEC2.md §"Core".
Change:
- Write a Nulang→Nulang compiler in Nulang Core targeting the
.nbcformat (RFC 0001). Stage 1 compiles Core programs only. Stage 2 compiles itself. bootstrap/host.nula— thin shim running the bootstrap compiler under the current Rust implementation until stage 2.- CI job:
nulang bootstrap/bootstrap_compiler.nula --eval bootstrap/self_test.nulaproduces identical output tocargo run -- bootstrap/self_test.nula.
Why: Self-hosting decouples the language from its host's survival. Every 50+ year-old language either self-hosts or has multiple independent implementations.
Item 5: Decouple LLM (and All Transient Tech) from the Language Vocabulary (Stable) — NON-BREAKING PHASE IMPLEMENTED 2026-07-19
Target: src/bytecode.rs, src/mir.rs, src/effect_checker.rs,
src/hir_lower.rs, src/lsp/mod.rs, src/ai/.
Change (non-breaking first phase — this RFC):
- Add a
Providereffect mechanism: a runtime-registered effect handler that the language dispatches to via the existingActorVmCallbackstrait. Users writeperform Provider.ask("llm", prompt); the core language has no knowledge of "LLM". - Mark
Effect::LLMandOpCode::LlmAskas deprecated inCHANGELOG.md. They remain functional for the deprecation cycle.
Change (breaking second phase — separate RFC in 2 major versions):
- Remove
OpCode::LlmAskfromsrc/bytecode.rs; removeRValue::LlmAskfromsrc/mir.rs; removeEffect::LLMfromsrc/effect_checker.rs. - Remove
PipelineNew,PipelineStage,PipelineRunopcodes likewise. - Bytecode v1→v2 migration in
src/format/migrate.rsrewritesLlmAskopcodes toPerform+ aProviderhandler registration.
Why: The language's stable vocabulary must reference eternal concepts (actor, message, type, effect, capability) not transient ones (LLM, pipeline, debate).
Target: New traits in src/backends/ directory. Existing impls in
src/jit/, src/mir_wasm.rs, src/wasm_runtime.rs, src/python/,
src/runtime/persistence.rs.
Change:
- Define
trait JitBackend,trait WasmBackend,trait StorageBackend(generalizePersistenceStore),trait Transport,trait CryptoProvider,trait HttpProvider. src/jit/becomes aJitBackendimpl for Cranelift, swappable.src/mir_wasm.rs+src/wasm_runtime.rsbecome aWasmBackendimpl.src/python/becomes aForeignInteropimpl for PyO3.- Core language never imports
cranelift,wasmtime,pyo3,libsql,quinn,rustls, orreqwestdirectly.
Why: Dependencies are transient; the language is not. Trait boundaries let a 2125 runtime swap Cranelift for whatever codegen exists then.
Contingency: If this breaks JIT tiering (concrete access to VM fields),
keep a JitView struct exposed by VM — the boundary is "JIT sees a
stable view", not "JIT sees only traits".
Target: src/runtime/mod.rs (5911 lines).
Change:
- Extract
Scheduler,GcCoordinator,SupervisorTree,PersistenceLayer,Clusterinto separate structs owned byRuntimeas fields, each behind its own trait. Partial factoring already exists (distributed_context.rs).
Why: Unblocks independent evolution of each subsystem on a 200-year horizon.
Target: src/package/ — extend resolver.rs and lockfile.rs.
Change:
Nulang.lockpins{module_name → blake3(deps + source)}.- A module pinned in 2026 is bit-identically resolvable in 2226 if any conforming registry mirrors it.
Why: URLs and git repos are not durable artifact identifiers; content
hashes are. blake3 is already a dep.
Target: src/runtime/network.rs, src/runtime/quic_transport.rs.
Change:
- Route through Item 6's
trait Transport/trait HttpProvider. - Default impl uses quinn/rustls/reqwest today; a 2125 impl uses whatever then. The language never knows.
Accepted 2026-07-19. Items 5 (non-breaking phase), 6 (traits), 10
(supervisor teams), and 11 (content-addressed modules) are implemented and
verified — 1358 tests pass. Items 2 (formal semantics) and 3 (self-hosting
bootstrap) are multi-week research efforts that remain as scoped follow-ups;
they are the highest-leverage remaining items. Item 5's breaking phase
(removing LlmAsk/Effect::LLM) follows the deprecation cycle (≥2 major
versions). Item 6's full wiring (routing existing impls behind the new
traits) and item 14 (deprecating direct quinn/rustls/reqwest use) are
incremental follow-ups.
- Item 5 (non-breaking):
perform Provider.ask("llm", prompt)is the new, eternal-vocabulary replacement forperform LLM.ask(prompt). TheProvidereffect dispatches through the existingPerformopcode; the"llm"provider reuses the existing LLM client via MIR-level special-case lowering toLlmAsk.Effect::LLMandOpCode::LlmAskare deprecated inCHANGELOG.md. 2 new tests pass. - Item 6 (traits):
src/backends/mod.rsdefinesStorageBackend,JitBackend,WasmBackend, andTransporttraits.StorageBackendandTransportare blanket-impl'd over the existingPersistenceStoreandNetworkTransport. 2 new tests pass. - Item 10 (extraction):
src/runtime/supervisor_registry.rsextracts the AI-runtime supervisor-team state (supervisor_teams,next_supervisor_id) into aSupervisorTeamRegistrystruct.Runtimeholds it as a field; methods delegate. 2 new tests pass; 401 runtime tests pass. - Item 11 (content-addressed):
Nulang.locknow carries a BLAKE3content_hashper pinned package, computed from.nulasource files. 2 new tests pass.
- Item 2 (formal semantics): Multi-week Lean formalization of the
type/effect/capability system. Starter artifact: the formalization target
is
spec/formal/(to be created). The Rust impl insrc/typechecker.rs,src/effect_checker.rs,src/types.rsis the oracle to formalize against. - Item 3 (self-hosting): Multi-week Nulang→Nulang bootstrap compiler
targeting Core (RFC 0002) and
.nbc(RFC 0001). Starter artifact: the bootstrap compiler lives inbootstrap/(to be created). Core is defined in RFC 0002; the.nbcformat is defined in RFC 0001. - Item 5 (breaking phase): Remove
OpCode::LlmAsk,RValue::LlmAsk,Effect::LLMafter the deprecation cycle. Requires bytecode v1→v2 migration insrc/format/migrate.rs. - Item 6 (full wiring): Route
src/jit/,src/mir_wasm.rs,src/wasm_runtime.rs,src/python/behind the new traits. The trait definitions are in place; the concrete impls need to be moved. - Item 14: Route
quinn/rustls/reqwestthroughtrait Transport/trait HttpProvider(to be defined). Depends on item 6 full wiring.