Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ Vendor firmware a device or CPU verifies by its maker's signature may be shipped
- **A red test is a defect**: it is fixed, or deleted with its issue recording the commit that restores it; a flaky test is deleted at once, never re-run. A red seen only under load is no flake: it is a defect, recorded with the host's load.
- **A high-risk change names its checks.** Security boundaries, the scheduler, the ABI, filesystems, devices, memory management, concurrency primitives: a negative control where a defect would otherwise land unseen — the *whole* change reverted onto the base the green arm was measured on — and an independent oracle where one exists: an external specification, a differential implementation, real hardware, a third-party checker, a formal model, or a recorded real failure. A second agent is not independence.
- **Never truncate command output.** No `| head`, `| tail`, `| grep` to reduce it: long output runs in the background and is read from its file — `[N characters truncated]` means data was lost.
- **Leave the machine as you found it.** The development machine is shared: every agent stops what it started and never another's process, killing only by PID and waiting out a build that holds the global lock, and removes the scratch output it made once it no longer needs it.
- **Leave the machine as you found it.** The development machine is shared: every agent stops what it started and never another's process, killing only by PID and waiting out a build that holds a lock its own needs (a key's in the host's store or its worktree's, `src/buildlock.rs`), and removes the scratch output it made once it no longer needs it.

## Repository layout

Expand All @@ -82,7 +82,7 @@ The root `Cargo.toml`'s `[workspace]` `members` and `exclude` lists account for
- **Never degrade audible or visual quality** — even temporarily, even for a big win elsewhere — without the owner's explicit sign-off.
- **Always be empirical.** Read actual output; run the code; investigate root causes instead of guessing. Every written number comes from a command that was run; an estimate or datasheet bound says so.
- **Never put the owner's email or any other personal data in a network request or its headers**; any `User-Agent` is `toyos-build (https://github.com/ToyOSOrg/ToyOS)`. Nothing that identifies his machines or network goes into the tree, a commit message or anything posted on GitHub, and one that has to be referred to there is named by where it stands and its kind, with no character of it; `src/sourcegate.rs` names the shapes.
- **One agent, one worktree, one branch.** The primary checkout owns `rust/`, the rustup link and `main`, and is no workspace; `.claude/agents/implementer.md` makes a worktree and `orchestrator.md` removes it. Never make one with `git clone`, and never run `git submodule` in one: either fetches the fork's history again, a clone builds a toolchain that takes the rustup link, and `git submodule` writes `core.worktree` into the fork's shared config, which breaks git in the primary's `rust/`.
- **One agent, one worktree, one branch.** The primary checkout owns `rust/` and `main`, and is no workspace; `.claude/agents/implementer.md` makes a worktree and `orchestrator.md` removes it. Never make one with `git clone`, and never run `git submodule` in one: either fetches the fork's history again, and `git submodule` writes `core.worktree` into the fork's shared config, which breaks git in the primary's `rust/`.
- **Commit freely on your branch.** `git commit -F <file>`, never `-m`. An agent does what it wants with the commits it made and has not pushed, in a fork clone too. A remote branch of this repository other than `main` that one implementer owns is that implementer's to amend, rebase and force-push; a fork's branches are append-only.
- **Never touch `main`.** It moves only through a merged pull request, by its required merge queue, and is protected — no push, force-push, deletion or bypass. A pull request's title and body become the merge commit's: write them as `main`'s record. A branch lands after a review against `.claude/agents/reviewer.md`. A modify/delete conflict is resolved by accounting for every hunk of the modified side, never by checking its headings survived. A merge that deletes a document also deletes every citation to it in the same merge, found by searching the bare name as well as the path. An ABI change lands with the work that needs it: every worktree builds the toolchain its own sources name, so branches that change the ABI run side by side. Every merge leaves `main`'s tip compiling.

Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,8 @@ cargo run -- --build-only # build everything, boot nothing
cargo test # boot the OS and run the integration suite
```

The first run initializes submodules and bootstraps the custom Rust toolchain.
The first run initializes submodules and bootstraps the custom Rust toolchain
into `~/.cache/toyos`, where every checkout on the machine finds it.
Later runs rebuild only what changed; a `std`-only change is a few seconds.

## Running it on real hardware
Expand Down
10 changes: 2 additions & 8 deletions examples/imgstat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,9 @@ fn main() {
}
}

/// Which of the four things on ROOT an entry is.
///
/// The order matters: `bin/rustc` is the toolchain's, not userland's.
/// Which of the three things on ROOT an entry is.
fn group_of(name: &str) -> &'static str {
if name.starts_with("lib/") {
"hosted rustc lib/"
} else if name.starts_with("bin/rustc") {
"hosted rustc bin/"
} else if name.starts_with("bin/") {
if name.starts_with("bin/") {
"userland bin/"
} else if name.starts_with("share/") {
"assets share/"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ opened: 2026-09-29

# A compiler fixture's git commit could not create a temporary file

`src/compiler.rs`'s `a_missing_primary_record_is_refused_and_builds_nothing`
went red in 1 of 200 full runs of the toyos-build lib test binary at
`e3a1cdc8`. Those runs went beside a `cargo test --workspace --exclude
`src/compiler.rs`'s `estate` fixture, which
`one_compiler_per_key_whichever_checkout_names_it` and every other compiler
and LLVM test build on, failed under a test since deleted in 1 of 200 full
runs of the toyos-build lib test binary at `e3a1cdc8`. Those runs went beside a `cargo test --workspace --exclude
toyos-build` loop as host load, with the 1-minute load average at 62.82 for
that run. The fixture's own git failed, not the code under test:

Expand All @@ -22,5 +23,5 @@ that repository's object store failed with EINVAL.

## Exit condition

The EINVAL is traced to a cause the test can rule out by construction, and a
loop of 200 loaded runs shows the test green each time.
The EINVAL is traced to a cause the fixture can rule out by construction, and
a loop of 200 loaded runs shows every test that builds on it green each time.
30 changes: 17 additions & 13 deletions issues/a-compiler-key-reads-no-symbolic-link.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,21 @@ opened: 2026-10-01

# A compiler key reads no symbolic link

`compiler::key` reads `compiler/`, `src/tools/`, `src/stage0` and
`Cargo.lock` through `sysroot::tree_identity` with `Links::Skipped`, so a
symbolic link there is in no key: retargeting one, or editing what it names
outside those trees, keeps the old compiler. Refusing a link there, as the
freestanding key does, refuses every compiler build:
`git -C rust ls-files -s compiler src/tools src/stage0 Cargo.lock` at fork
commit `aca5f527f` lists 5 entries of mode `120000`, all under `src/tools`
(clippy's and rust-analyzer's `LICENSE-APACHE` and `LICENSE-MIT`, and
rust-analyzer's `AGENTS.md`). Hashing a link's target text instead moves the
key of every compiler of a worktree's own once.
`compiler::key` reads the paths of `compiler::KEYED` through
`sysroot::tree_identity` with `Links::Skipped`, so a symbolic link there is
in no key: retargeting one, or editing what it names outside those paths,
keeps the old compiler. Refusing a link there, as the freestanding key does,
refuses every compiler build: `git -C rust ls-files -s` over `KEYED`'s eleven
paths at fork commit `6d6ad8c7190` lists 5 entries of mode `120000`, all
under `src/tools` (`rustc_tools_util`'s and `lsp-server`'s `LICENSE-APACHE`
and `LICENSE-MIT`, and rust-analyzer's `AGENTS.md`). Hashing a link's target
text instead moves the key of every compiler once.

**Exit**: `Links::Skipped` is deleted and the compiler key hashes a link's
target text, landed with the next change to `compiler.rs`'s `RECIPE`, which
moves every compiler key anyway.
Owner: the first step of
`issues/the-forks-pin-is-a-file-and-a-worktree-checks-no-fork-out.md` ("The
fork's objects are the store's"), which reads a key's fork parts as git tree
ids, where a link's target text is in the key by construction, and moves
every compiler key anyway; the orchestrator briefs it.

**Exit**: `Links::Skipped` is deleted, and a test in which retargeting a link
under a keyed path moves the compiler's key.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
status: open
kind: tooling
opened: 2026-10-08
---

# A compiler's build reads an environment and a cargo configuration its key does not name

Two inputs of `compiler::build_in_fork` are outside the fork checkout, and
`compiler::key` reads neither:

- **The caller's environment.** `toolchain::x_build_compiler` gives bootstrap
the whole environment of the process that asked, less `GITHUB_ACTIONS` and
`CI`, where the LLVM build gets `PATH` and `TMPDIR` alone (`llvm::clear`).
`RUSTFLAGS`, `CC`, `CXX`, `CARGO_*` and `MACOSX_DEPLOYMENT_TARGET` reach the
compiler's build; the C and C++ compilers a compiler's key names are the
ones its LLVM's key resolved in the cleared environment, which a `CC` in the
caller's makes another.
- **The worktree's cargo configuration.** Bootstrap runs cargo in
`<worktree>/rust`, and cargo reads every `.cargo/config.toml` above its
working directory: the worktree's, and through its `include` the untracked
`.cargo/local.toml` in which `.claude/agents/implementer.md` has a fork clone
under edit listed. The compiler's workspace patches four crates to ToyOS
forks (`libloading`, `memmap2`, `stacker`, `getrandom`); a `local.toml`
redirecting one to a local clone builds a compiler from that clone under the
key of the one the lockfile names. The committed `config.toml` holds only
guest-target tables today, which a host-only build does not read.

A compiler built under either is stored and served to every checkout naming
its key. By reading (`src/toolchain.rs`, cargo's documented configuration
search); no compiler was built under a differing environment or a
`local.toml` to measure it. Both are `main`'s shape since worktrees built
compilers of their own; the host's store widens who is served.

Owner: the step of
`issues/the-forks-pin-is-a-file-and-a-worktree-checks-no-fork-out.md` that
builds from an export ("A pinned build reads an export"), which decides where
a compiler's build runs; the orchestrator briefs it.

**Exit**: a compiler's build runs with the environment `llvm::clear` leaves
and in a directory no worktree's `.cargo` is above, or its key names what of
either it reads; and a host test in which a variable set in the caller's
environment does not reach the command the build runs.
16 changes: 0 additions & 16 deletions issues/a-finder-file-in-a-store-directory-panics-its-sweep.md

This file was deleted.

15 changes: 0 additions & 15 deletions issues/a-killed-keystore-writer-leaves-an-orphan-temp-in-target.md

This file was deleted.

24 changes: 0 additions & 24 deletions issues/a-worktree-cannot-build-a-hosted-rustc-of-its-own.md

This file was deleted.

28 changes: 28 additions & 0 deletions issues/an-llvms-key-names-of-bootstrap-only-src-bootstrap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
status: open
kind: tooling
opened: 2026-10-08
---

# An LLVM's key names, of bootstrap, only `src/bootstrap`

`llvm::key` reads the fork's bootstrap as the committed tree of
`src/bootstrap`. The bootstrap that builds an LLVM is also `src/build_helper`,
its path dependency (`src/bootstrap/Cargo.toml`), and the launchers
`toolchain::x_build_with` runs, `x` and `x.py`; a fork commit that moves only
one of them keeps the stored LLVM. A compiler's key reads all three
(`compiler::KEYED`); the LLVM's was left as it is because naming them moves
every LLVM key, which is one cold LLVM on each host (15:19 on an idle
development host, measured once) and three on CI.

Read in the fork at `6d6ad8c7190`, not measured: no LLVM was built from a
fork whose `src/build_helper` differed.

Owner: the first step of
`issues/the-forks-pin-is-a-file-and-a-worktree-checks-no-fork-out.md` ("The
fork's objects are the store's"), which reads every key's fork parts as git
tree ids and so moves every LLVM key anyway; the orchestrator briefs it.

**Exit**: `llvm::key` names `src/build_helper`, `x` and `x.py` as it names
`src/bootstrap`, refused while one holds what no commit does, and a test in
which a commit moving each alone moves the key.
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,16 @@ opened: 2026-09-29
# Every build still removes an in-tree LLVM that no build makes any more

`llvm::retire_in_tree` removes a bootstrap build directory's own `<host>/llvm`,
`<host>/lld`, `<host>/ci-llvm` and `cache/llvm-*`. It runs at four sites on
every build: the primary's `reassemble`, `compiler::place`, `compiler::choose`
on the way back to the primary's compiler, and the std build
(`sysroot::prepare_std_build`).
`<host>/lld`, `<host>/ci-llvm` and `cache/llvm-*`. It runs at two sites:
`compiler::place`, and the std build (`sysroot::prepare_std_build`) on every
sysroot build.

Since the LLVM store, no build makes any of these. Every compiler build links
the store's `llvm-config`, and the std build sets `download-ci-llvm = false`.
What the four sites remove is what a build directory kept from before the
What the two sites remove is what a build directory kept from before the
store. After a checkout's first build at that code, they remove nothing, but
they keep asking, on every build, a `read_dir` of `cache/` and a `stat` of
each name.
they keep asking, a `read_dir` of `cache/` and a `stat` of each name.

Exit: delete `retire_in_tree`, `in_tree` and the four call sites once no
Exit: delete `retire_in_tree`, `in_tree` and the two call sites once no
checkout that builds holds a build directory made before the store. A host
cannot know that for any other host, so the owner sets the date.
19 changes: 0 additions & 19 deletions issues/no-test-covers-the-pid-in-a-keystore-records-temp-name.md

This file was deleted.

35 changes: 35 additions & 0 deletions issues/nothing-builds-the-toyos-hosted-rustc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
status: open
kind: tooling
opened: 2026-10-08
---

# Nothing builds the ToyOS-hosted rustc

No build makes a rustc that runs on ToyOS, and no config can ask for one. The
primary checkout's in-place build of it, the `hosted-rustc` key of
`system.toml` and the image's collection of its files went with the primary's
in-place compiler: the owner, of the in-place hosted rustc build and the rustup
link, "Drop both for now (Recommended)". No tracked config set the key.

What that build left owed, which the one that replaces it owes too:

- It was the primary's alone, built from the primary's `rust/` under the
primary's configuration, so no branch could put the hosted rustc it changes
into a guest before it landed, and a worktree whose configuration alone
differed shipped the primary's without a word.
- Nothing keyed it on std's sources: an edit to `sdk/std` or to the fork's
`library/` left a built one standing, and an image carried its `libstd-*.so`
beside the rlibs of the build's own sysroot.
- It was unmeasured since std's ToyOS backend left the fork for `sdk/std`: no
hosted rustc was built whose std reaches the backend through the fork's
`#[path]` arms.
- Nothing read its licences: a config that set the key was refused for that.

Owner: `issues/toyos-builds-itself.md`, M3.

**Exit**: a hosted rustc is a product of the host's store (`src/keystore.rs`),
keyed as `src/compiler.rs` keys a compiler and on the sources of the std it
runs on, and built by whichever checkout first names it; an image whose config
asks for it carries that one, with its licences read; and the `libstd-*.so` it
carries holds `sdk/std/sys/` paths and no `sys/pal/toyos`.
32 changes: 0 additions & 32 deletions issues/nothing-keys-the-hosted-rustc-on-stds-sources.md

This file was deleted.

Loading
Loading