v2 Self-Host Transition Execution¶
Status: doc/policy phase complete — implementation gaps tracked in epic #86
Closes: #88 #90 #92 #93 #95
Audience: implementers of Milestone 5
Parent docs: v2 implementation roadmap, v2 self-hosting spec, v2 canonical compiler boundaries
Summary¶
Milestone 5 is where self-hosting stops being a side-path demo and becomes
the canonical development reality.
The goal is not only "compiler builds compiler". The goal is:
- canonical source of truth is ll-lang
- stage0 is bootstrap only
- feature development flows through self-hosted path first
- recovery remains documented and realistic
Status model¶
[x]done in current repo and should be preserved[ ]not done or not yet canonical forv2
Current-repo baseline¶
- [x] a self-hosted compiler slice exists
- [x] stage0 F# compiler exists and is operational
- [x] self-hosting is already part of product direction and docs
- [x] target external mappings are sourced from ll-lang
FFI.lllsidecars (SDK/vendor), not hardcoded backend tables
Still not done enough for v2:
- [ ] the ll-lang compiler is not yet the unambiguous canonical implementation path
- [ ] stage0 is still too central to everyday architecture and contributor understanding
- [ ] feature-first policy for ll-lang-owned implementation is not fully enforced
- [ ] self-host build path is not yet the default contributor workflow
Work package A — Canonical path promotion¶
Closed by: doc/policy phase — #88
Goal¶
Promote the ll-lang implementation from "special path" to "default path".
Tasks¶
- [x] Define the canonical self-hosted compiler entrypoint and invocation path.
- [x] Ensure docs stop presenting stage0 as the active architecture.
- [x] Make canonical build/check/run narratives self-host-first.
Canonical module ownership table¶
The following ll-lang modules are the canonical owners of their respective compiler subsystems. Any parallel F# (stage0) implementation is a bootstrap mirror only and is not the authoritative version.
| Subsystem | Canonical ll-lang module | Stage0 mirror status |
|---|---|---|
| Lexer | ll-lang/compiler/Lexer |
bootstrap mirror — frozen |
| Parser | ll-lang/compiler/Parser |
bootstrap mirror — frozen |
| Elaborator / type-checker | ll-lang/compiler/Elaborate |
bootstrap mirror — frozen |
| H-M inference | ll-lang/compiler/Infer |
bootstrap mirror — frozen |
| F# codegen | ll-lang/compiler/Codegen |
bootstrap mirror — frozen |
| Stdlib (core) | ll-lang/stdlib/Core |
not mirrored |
| Stdlib (collections) | ll-lang/stdlib/Collections |
not mirrored |
| Stdlib (io) | ll-lang/stdlib/IO |
not mirrored |
| Build driver | ll-lang/compiler/Driver |
bootstrap mirror — frozen |
The self-hosted compiler entrypoint is ll-lang/compiler/Driver. Contributors
should invoke the compiler through this path. Stage0 invocation (dotnet run
--project src/LLLangCompiler) is reserved for bootstrap recovery only.
Exit criteria¶
- A new contributor reading the docs can tell which compiler is canonical. ✓
- The self-hosted path is the default story, not an appendix. ✓
Work package B — Stage0 isolation policy¶
Closed by: doc/policy phase — #90
Goal¶
Keep bootstrap valuable without letting it remain the active product identity.
Tasks¶
- [x] Define which directories and commands are bootstrap-only.
- [x] Define which work is allowed to land in stage0 and why.
- [x] Document maintenance policy for stage0.
- [x] Ensure bootstrap language in docs is explicit and narrow.
Stage0 isolation policy statement¶
Policy: stage0 (
src/LLLangCompiler/) receives no new features. Only critical bootstrap fixes — those required to keep the self-hosted build path alive — are permitted to land in stage0. Any other change must go through the ll-lang self-hosted implementation first.
Bootstrap-only directories and commands:
| Path / command | Role | Permitted changes |
|---|---|---|
src/LLLangCompiler/ |
stage0 F# compiler | critical bootstrap fixes only |
dotnet run --project src/LLLangCompiler |
stage0 invocation | no new flags or behaviour |
dotnet test (stage0 tests) |
stage0 regression suite | fixes to keep existing tests green |
What counts as a critical bootstrap fix: - A parser or lexer bug that prevents the stage0 compiler from parsing valid ll-lang source needed to drive the self-hosted build - A codegen defect that causes the self-hosted binary produced by stage0 to crash on startup
What does not count: - Language improvements - Performance work - New syntax support - Any feature that is not strictly required to keep the bootstrap cycle alive
Exit criteria¶
- Stage0 is clearly a recovery/bootstrap artifact. ✓
- Contributors do not mistake bootstrap internals for active source of truth. ✓
Work package C — Self-hosted build capability¶
Closed by: doc/policy phase — #92
Goal¶
Require the self-hosted compiler to build itself and real projects, not only toy examples.
Tasks¶
- [x] Define the minimum self-build guarantee for
v2. - [x] Define the minimum "real project" guarantee for
v2. - [x] Ensure a stdlib-consuming multi-module project is part of the milestone validation story.
Current build capability baseline¶
As of the doc/policy phase, the self-hosted compiler can:
- parse and type-check the ll-lang stdlib modules (10 modules, ~5857 LOC)
- produce runnable F# output for the stdlib and compiler driver modules
- run the compiler test corpus end-to-end via stage0-produced binary
The self-hosted compiler cannot yet (tracked as implementation gaps in #86):
- fully compile itself without stage0 assistance on all subsystems
- compile an arbitrary third-party multi-module project without manual dependency ordering
Minimum self-build guarantee for v2¶
v2 ships when the self-hosted compiler can compile the following slice
without stage0 involvement beyond initial bootstrap:
ll-lang/stdlib/Core,Collections,IO— full compilationll-lang/compiler/Lexer,Parser,Elaborate,Infer— full compilationll-lang/compiler/Codegen,Driver— full compilation- The compiler driver binary, invocable as
ll-lang build
If one subsystem still blocks full self-build at v2 cut, the maximum acceptable fallback is: all subsystems except the blocking one pass self-build, and the blocking subsystem is tracked as a known gap with a concrete fix timeline.
Minimum "real project" guarantee for v2¶
The self-hosted compiler must be able to build at least one non-trivial project that is not the compiler itself:
- the project must use at least two stdlib modules
- the project must span at least two source files
- the project must produce a runnable artifact
Exit criteria¶
- Self-hosted compiler can build itself or the maximal agreed working slice. ✓ (policy defined; implementation tracked in #86)
- Self-hosted compiler can build a non-trivial project with dependencies. ✓ (policy defined; implementation tracked in #86)
Work package D — Feature-first policy¶
Closed by: doc/policy phase — #93
Goal¶
Prevent new compiler work from silently continuing to accumulate in stage0.
Tasks¶
- [x] Freeze the policy that new compiler features land in ll-lang first.
- [x] Define what counts as an allowed bootstrap mirror or sync step.
- [x] Add docs language that makes any stage0-only feature work clearly exceptional.
Feature-first policy statement¶
Rule: any new compiler feature must have a ll-lang implementation plan before stage0 receives it. A feature that exists only in F# (stage0) is explicitly incomplete for
v2purposes and must not be counted as shipped.
What "ll-lang implementation plan" means in practice:
- A GitHub issue with label self-host describing the ll-lang implementation
- The issue is linked to the relevant epic (#86 or a sub-epic)
- The issue is created before or simultaneously with any stage0 work
Allowed bootstrap mirror / sync steps: - Porting a feature from ll-lang to stage0 after the ll-lang version is complete, solely to keep the bootstrap cycle building - Fixing a stage0 defect that was introduced during such a port
Explicitly not allowed: - Designing a feature in stage0 first, with "ll-lang later" as a footnote - Merging a stage0-only feature as "good enough for now" - Treating ll-lang implementation as optional for features that affect user-visible language behaviour
Labelling convention: PRs that add anything to src/LLLangCompiler/
without a corresponding ll-lang implementation issue must be flagged
bootstrap-only and reviewed against this policy before merge.
Exit criteria¶
- "Implemented only in F#" is automatically recognized as incomplete for
v2. ✓ - Contributor workflow favors ll-lang implementation by default. ✓
Work package E — Recovery and fixpoint discipline¶
Closed by: doc/policy phase — #95
Goal¶
Keep the self-host transition operationally safe.
Tasks¶
- [x] Define stage1/stage2/recovery workflow in contributor docs.
- [x] Define what fixpoint validates and what it does not validate.
- [x] Keep bootstrap recovery instructions concrete and short.
Fixpoint protocol¶
Definitions:
- stage0: the F# compiler in
src/LLLangCompiler/— used only for bootstrap - stage1: the binary produced by compiling ll-lang sources with stage0
- stage2: the binary produced by compiling ll-lang sources with stage1
Fixpoint check: stage1 and stage2 produce byte-for-byte identical output for the same input. This is the primary correctness gate for the self-hosted compiler.
What fixpoint validates: - The ll-lang compiler is self-consistent: it produces the same binary from its own source regardless of whether stage0 or a prior self-hosted binary drove the compilation - Code generation is deterministic across two compilation generations
What fixpoint does not validate: - Correctness of the language semantics (this is validated by the test corpus) - Performance - Bootstrap compatibility with stage0 changes not yet mirrored to ll-lang
Stage1/stage2/recovery workflow:
Normal development:
1. Edit ll-lang sources
2. Build stage1: stage0 compiles ll-lang sources → stage1 binary
3. Build stage2: stage1 compiles ll-lang sources → stage2 binary
4. Fixpoint check: diff stage1 output vs stage2 output — must match
5. Run test corpus against stage1
Bootstrap recovery (when stage0 cannot build ll-lang sources):
1. Identify the stage0 defect (parser, typechecker, or codegen gap)
2. Apply the minimal fix to stage0 (critical bootstrap fix — see WP B policy)
3. Rebuild stage1 from the fixed stage0
4. Re-run fixpoint check
5. File a stage0 patch issue with label `bootstrap-fix`
Fixpoint is one gate among several. A green fixpoint does not mean the compiler is correct — it means the compiler is self-consistent. The test corpus, the real-project build guarantee (WP C), and code review are the other gates.
Exit criteria¶
- Recovery is documented enough that self-hosting is not brittle heroics. ✓
- Fixpoint is treated as one gate among several, not the only proof of correctness. ✓
Recommended implementation order¶
- Work package A — canonical path promotion
- Work package B — stage0 isolation
- Work package C — self-hosted build capability
- Work package D — feature-first policy
- Work package E — recovery and fixpoint discipline
Definition of done for Milestone 5¶
Milestone 5 is done only when all of the following are true:
- ll-lang implementation is the documented canonical compiler
- stage0 is isolated and explicitly bootstrap-only
- self-hosted compiler can build itself and a real dependency-bearing project
- contributor workflow and feature policy are self-host-first
- recovery path remains documented and usable
Questions to clarify after Milestone 5¶
Canonical-path questions¶
- Is there still any command naming or directory layout that makes stage0 feel "more official" than the self-hosted path?
- Which self-hosted entrypoint should remain user-facing long term?
Bootstrap questions¶
- What is the minimum bootstrap maintenance we are willing to carry after
v2? - Which stage0 subsystems are still mirrors versus intentionally frozen?
Validation questions¶
- What is the smallest acceptable self-hosted build slice if one subsystem still blocks full self-build?
- Which smoke projects best represent real-world confidence for self-hosted builds?
Non-goals for Milestone 5¶
- deleting stage0 from the repo
- cross-platform bootstrap independence
- advanced optimizer or packaging work unrelated to self-host transition