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: 4 additions & 0 deletions .claude/agents/implementer.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ guess. Then build, then test on root `CLAUDE.md`'s tiers before anyone reviews:

## A fork

A fork is for a crate, `rust/` or LLVM. A standalone C program has none: its ToyOS changes are patch
files in a recipe in this repository, against an upstream archive pinned by hash, and only a delta
too large to read as patches moves to a fork repository pinned by commit.

To edit a fork, clone it beside the monorepo and list it in `.cargo/config.toml`. Fork clones are
shared by every worktree: explicit paths, never `stash`, never switch a branch in one. A fork keeps
one branch per upstream base; a fix is a commit appended to it, never a new branch. A fork depends
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
status: open
kind: defect
opened: 2026-10-03
---

# A ToyOS-hosted LLVM is configured as running on the build machine

LLVM takes `LLVM_HOST_TRIPLE` from `config.guess`, run by the CMake that
configures it (`llvm/cmake/modules/GetHostTriple.cmake`,
`llvm/cmake/config-ix.cmake`), unless the configuration names one, and
bootstrap names none: the `rust/` fork's
`src/bootstrap/src/core/build_steps/llvm.rs` defines
`LLVM_DEFAULT_TARGET_TRIPLE` and no `LLVM_HOST_TRIPLE`. So the LLVM that M2
cross-builds to run on ToyOS (`issues/build/toyos-builds-itself.md`) records
the machine that built it as its host. The configure of that build on the
development Mac, the fork at the commit `main` pins (`95960d6c214`), logged
(#682, comment 5968053849)

```
-- LLVM host triple: arm64-apple-darwin27.0.0
-- LLVM default target triple: x86_64-unknown-toyos
```

`config.guess` knows no ToyOS, and `get_host_triple` ends the configure where
it exits non-zero, so a configure run inside ToyOS stops there. That half is
read from `GetHostTriple.cmake`, not run.

Owner: `issues/build/toyos-builds-itself.md`: M2 for the triple the host
build records, M5 for the configure inside ToyOS.

Exit condition: the configure of a ToyOS-hosted LLVM logs `LLVM host triple:
x86_64-unknown-toyos`, and a configure inside ToyOS reaches its end.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ program named is neither. No step here merges one; each stays a crate under
the no-panic track.

Every step lands green on `--ci host` and `--build-only`. Test counts are what
`cargo test -p <package> -- --list` lists today.
`cargo test -p <package> -- --list` lists today. Step 2 lands right after #592
and #631, of which #631 has landed, before the latency work
(`issues/kernel/toyos-beats-linuxs-latency-on-the-t14.md`; owner, 2026-10-03).

1. **Delete `toyos-userpin`.** It models the pin invariant and names nothing
the kernel defines; `munmap_reissues_read_window` holds the kernel to it.
Expand Down
28 changes: 12 additions & 16 deletions issues/build/mio-deregister-fd-leaves-a-pending-poll-live.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,22 +55,18 @@ first (grepped the estate for a submitter — found none, which is true and
remains true) rather than asking whether `deregister_fd`'s behavior was itself
correct.

## Why it matters for pipeline 2
## What a fix has to promise

The completion track makes every kernel wait a cancellable completion, answered
by `Cancelled` rather than by discarding the stack
(`issues/kernel/every-wait-in-this-kernel-is-a-spin.md`). The 2026-08-15
mechanism-consolidation audit called the userland-facing half of that "pipeline
2" and named its cancellation rewrite the highest-risk piece of the whole
track. mio's selector is exactly
the kind of consumer that rewrite has to get right: a `deregister` that cannot
promise "no event after this point" is the userland mirror of the kernel-side
bug pipeline 2 exists to remove. Re-adding a cancel op (or otherwise making
`deregister_fd` synchronous with the kernel's pending state — draining the SQ/CQ
for that fd, or having the kernel answer a targeted query) is in scope for
whoever designs that half; retiring `IORING_OP_POLL_REMOVE` a second time
without addressing this would repeat the same reasoning gap.
A kernel wait a kill ends is answered `Cancelled` (`kernel/src/watch.rs`).
mio's selector is the userland mirror of that, and a `deregister` that cannot
promise "no event after this point" is what it lacks: no ring op withdraws a
watch (`toyos-abi/src/inbox.rs` has `OP_NOP`, `OP_WATCH` and `OP_ACCEPT`).
Re-adding a cancel op (or otherwise making `deregister_fd` synchronous with
the kernel's pending state — draining the SQ/CQ for that fd, or having the
kernel answer a targeted query) is in scope for whoever fixes this; retiring
`IORING_OP_POLL_REMOVE` a second time without addressing this would repeat the
same reasoning gap.

Filed rather than fixed: this is a fork (mio, not this repository) and a
design question (what the cancel primitive should look like once pipeline 2
exists), not a local bug fix.
design question (what the cancel primitive should look like), not a local bug
fix.
26 changes: 26 additions & 0 deletions issues/build/n2-does-not-compile-for-toyos.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
status: open
kind: defect
opened: 2026-10-03
---

# n2 does not compile for ToyOS

n2 is the only Ninja the build runs (`src/n2.rs`), pinned at `b1fead52ccda`.
At that commit its `process::run_command` exists under `cfg(unix)`,
`cfg(windows)` and for `wasm32`, and its `terminal::use_fancy` and `get_cols`
under the same three; its `task.rs`, `run.rs` and `progress_fancy.rs` call
them under no `cfg`. `x86_64-unknown-toyos` is none of the three: its target
names no family (`compiler/rustc_target/src/spec/base/toyos.rs` in the `rust/`
fork). Read from the source, not built.

Its unix arm is `posix_spawn` of `/bin/sh -c <command>` with `/dev/null` as
stdin, a pipe and `waitpid`, so a ToyOS arm waits on what
`issues/build/ninja-runs-every-command-through-a-bin-sh-toyos-does-not-have.md`
and `issues/filesystem/there-is-no-dev-null.md` wait on.

Owner: `issues/build/toyos-builds-itself.md`, whose M5 builds LLVM in the
guest.

Exit condition: n2 builds for `x86_64-unknown-toyos`, and inside ToyOS it
builds a file of two edges, one depending on the other.
21 changes: 21 additions & 0 deletions issues/build/nothing-launches-a-script-by-its-interpreter-line.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
status: open
kind: defect
opened: 2026-10-03
---

# Nothing launches a script by its interpreter line

A file that begins `#!` is not a program on ToyOS. A spawn of one is refused
`InvalidArgument` with every other file that is not an ELF
(`kernel/src/loader/mod.rs`, where `elf::parse_layout` fails), and nothing
above the kernel reads the line: `git grep -n -e '"#!"' -e ENOEXEC -- kernel
userland toyos toyos-abi` finds only `ENOEXEC`'s definition in
`userland/libc/include/errno.h`.

Owner: `issues/build/toyos-builds-itself.md`, whose tools (a POSIX `sh`, Perl,
make, CMake) are the first programs here that start a script by its path.

Exit condition: inside ToyOS, a spawn by path of an executable file whose
first line names an interpreter runs that interpreter on the file, shown by a
test that runs such a script and reads its exit code.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
status: open
kind: tooling
opened: 2026-10-03
---

# One failed request for the crates.io token reds a publish run

`publish.yml`'s `rust-lang/crates-io-auth-action` step trades the job's OIDC
token for a crates.io token in one request, and the job ends where that
request fails. Run 36998451606, `main` at `7c4a648b3`: the step logged
`Requesting token from: https://crates.io/api/v1/trusted_publishing/tokens`
and, 89 ms later, `##[error]fetch failed`; `cargo run -- --ci publish` was
skipped, and the run was over 12 s after it was created. Nothing ran it
again. The next landing's run, 37000495781 at `c1c504835`, was green, and
36998451606 is the one red among the forty `publish` runs on `main` from
36772021165 to 37110586853.

Until the next landing, what that tip changed in the SDK crates is not on
crates.io, and the nightly's `release` refuses such a tip
(`issues/build/a-release-that-decides-before-its-tips-crates-are-up-reds-the-nightly.md`).

Owner: the orchestrator.

**Exit**: a publish run whose first request for the token fails asks again,
within a bound, before it reds.
22 changes: 3 additions & 19 deletions issues/build/parallel-tests-red-under-other-suites.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ changes.
runs were 270/270 on a tree differing from the red one by two doc comments and
one removed `#[track_caller]`; the branch's kernel delta touches no TLB, no
shootdown and no `munmap` path. `ALONE … GREEN` in 145 ms. `screen_early_panic` failed in the same
run and is already this file's and the redlist's, `ALONE … GREEN` there too.
run and is already this file's, `ALONE … GREEN` there too.

The assertion that went red is the test's own disarmed control: `munmap still
took 11740090ns with the delay disarmed, so the numbers above measured
Expand All @@ -245,8 +245,7 @@ changes.
never ran. Exactly this file's typed-on-a-wall-clock class, and the class
fix had already landed when the row was read back: `shell_type_line`
(7a033450, 2026-08-26) bounds each burst by the queue and takes the guest's
own echo of the whole line as the verdict, with three tries. The redlist row
is retired against it.
own echo of the whole line as the verdict, with three tries.

- **`syscall_window_nmi`** — added 2026-08-27, one sighting, dev host, a
288-name `cargo test` run at 92 guests with a second worktree's suite on the
Expand Down Expand Up @@ -452,20 +451,6 @@ mechanism for it.
seconds. The test asserts an ordering of two lines, and the second line never
came.

**It contradicts a retirement rather than joining a class.** All three of the
name's earlier rows in `src/redlist.rs` are retired: the two dev-host
`ALONE: GREEN` rows by the single-word tally in
`kernel/src/arch/x86_64/i8042/tally.rs` (2026-08-17), which made `N interrupts
and 0 bytes` unprintable, and the CI row by "the verdict revises itself once"
(2026-08-28) — a mute line said while a decoder still holds the run is
`HEALTH_MUTE_BLIND`, the first blamed byte moves it to `HEALTH_MUTE_SAID`
with the line that names the bytes, and `i8042-split-burst` stages that
interleaving on every run. Four bytes and not zero puts this sighting on the
CI row's producer — the test's own Pause, reported after the first interrupt
delivered four of its six bytes — which is exactly what the 2026-08-28 clause
says is no longer waited for. Under a loaded host the second line did not
arrive, so the revision that retirement rests on is not unconditional.

Second sighting, the logd branch's fast tier at `eef19bd1`, on a dev host
running two other worktrees' suites: the same words at `[kernel 5.865 cpu0]
... 2 interrupts and 4 bytes, nothing decoded`, the one red of 357, and
Expand All @@ -474,8 +459,7 @@ mechanism for it.

Owner: the i8042 tally. **Exit condition**: the verdict revising itself in a
parallel run — a loaded full suite in which `i8042_undecoded_bytes`'
first mute line names nothing and its second names the sequence, or the
retirement's clause narrowed to the conditions under which it holds.
first mute line names nothing and its second names the sequence.

## Deleted as flaky tests

Expand Down
27 changes: 0 additions & 27 deletions issues/build/the-guest-check-gates-nothing.md

This file was deleted.

27 changes: 27 additions & 0 deletions issues/build/the-guest-job-builds-every-image-on-every-run.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
status: open
kind: tooling
opened: 2026-10-03
---

# The guest job builds every image on every run

`guest.yml`'s `suite` restores one cache entry, the sysroot, and builds the
rest in the job: the build driver, the harness, and each kernel, loader, ROOT
and test binary a guest boots. Job 111020980149 of run 37061831501 (#649's
head `b6635359a`, a pull request run with the sysroot restored from cache)
ran 18 min 11 s (its log's lines: #682, comment 5968053849):

- 2 min 46 s in `deps`, before the checkout;
- 2 min 15 s compiling the driver and the harness (`Finished` in 1m 26s and
in 47.62s);
- 767.5 s in the suite by its own line, of which its 26 `PASS` lines account
for 208 s. The other 559 s is the log's silence, up to 209 s at a time,
between a `cleaning` line or a verdict and the next guest's first line:
three kernel builds by the suite's summary, and the loaders, ROOTs and test
binaries beside them.

Owner: the orchestrator.

**Exit**: what of those builds an entry restored from `main`'s cache scope
would save is measured on a pull request run.
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
status: open
kind: defect
opened: 2026-10-03
---

# The hosted rustc's stage2 carries seventeen proc-macro libraries no image needs

The ToyOS-hosted stage2's `lib/` in release
`toolchain-linux-x86_64-48dd24f826263d6c` holds eighteen shared objects:
`librustc_driver`, 486,137,984 bytes, and seventeen proc-macro libraries the
compiler's own build loaded, 179,575,736 bytes together (the listing: #682,
comment 5968053849). The Linux-hosted
stage2 beside it holds `librustc_driver` alone, 594,483,472 bytes, which
`issues/build/toyos-builds-itself.md` measures at 184.7 MB stripped.

`collect_hosted_rustc` (`src/build.rs`) puts every `lib/*.so` of that
directory, and `bin/rustc`, into ROOT as built. `hosted-rustc` is `false` in
`system.toml` and a config that sets it is refused until the compiler's
licences are read (`build::shipped`), so no image carries them today. #629
deletes the function, the key and the refusal, and this paragraph goes in its
merge.

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

Exit condition: an image that ships the hosted rustc carries `librustc_driver`
stripped and no proc-macro library.
11 changes: 11 additions & 0 deletions issues/build/toyos-builds-itself.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,14 @@ M3's exit then waits on a linker in the guest
(`issues/build/the-hosted-rustc-names-a-linker-toyos-does-not-have.md`), which
toyos-ld is not: it refuses every executable with thread-local storage, so
every std program.

**Also owed, by milestone.**
- M2: the host triple a ToyOS-hosted LLVM records
(`issues/build/a-toyos-hosted-llvm-is-configured-as-running-on-the-build-machine.md`,
whose other half, the configure inside ToyOS, is M5's).
- M3: `issues/build/the-hosted-rustcs-stage2-carries-seventeen-proc-macro-libraries-no-image-needs.md`.
- M4: cargo's file locks,
`issues/design-debt/std-file-lock-answers-ok-and-locks-nothing.md`.
- M5: `issues/build/n2-does-not-compile-for-toyos.md`.
- The tools of "To build", the first programs that start a script by its
path: `issues/build/nothing-launches-a-script-by-its-interpreter-line.md`.
15 changes: 9 additions & 6 deletions issues/design-debt/redesign-the-log-subsystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ opened: 2026-08-08
# Redesign the log subsystem, and re-shape `kernel/src`

**The owner decided on 2026-08-19: go.** Both halves are approved as planned
work. Sequencing, set by the orchestrator with the ruling: the log core waits
until pipeline 2's second pull request (the lock conversions behind
`issues/kernel/every-wait-in-this-kernel-is-a-spin.md`) has landed — the two
touch the same scheduler-adjacent paths and land one at a time. The directory
re-shape is a scheduling matter exactly as priced below: one clean pass in a
window with few worktrees in flight, and never interleaved with a code change.
work. With the ruling the orchestrator sequenced the log core behind the
kernel's lock conversions (`vfs::VFS`, the FAT volumes' lock, `xhci::XHCI` and
`ProcessData` becoming sleep locks), which touch the same scheduler-adjacent
paths. Nothing plans those conversions any more:
`issues/kernel/the-kernel-is-small-interrupts-post-and-threads-wait.md` moves
storage and USB out of the kernel instead (owner, 2026-09-25), so that wait
names nothing that will land. The directory re-shape is a scheduling matter
exactly as priced below: one clean pass in a window with few worktrees in
flight, and never interleaved with a code change.

The target shape stands as reviewed: a log core (ring + context stamping,
once) with serial, file and screen as independent sinks carrying explicit
Expand Down
25 changes: 25 additions & 0 deletions issues/design-debt/std-file-lock-answers-ok-and-locks-nothing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
status: open
kind: defect
opened: 2026-10-03
---

# std's `File::lock` answers `Ok` and locks nothing

The ToyOS file pal in the std fork (`library/std/src/sys/fs/toyos.rs`) answers
`Ok(())` from `File::lock`, `lock_shared`, `try_lock`, `try_lock_shared` and
`unlock` and takes no lock. Two processes that each ask for the exclusive lock
on one file are both told they hold it, and nothing in the kernel ABI or the
file servers' protocol could tell them otherwise: neither has a lock call.

cargo is one such program. Every file lock it takes is one of these calls
(its `src/util/flock.rs` at `7c83d4cc0953`, the cargo the fork pins), so two
cargo processes in one ToyOS are kept apart by nothing.

Owner: `issues/build/toyos-builds-itself.md`, whose M4 runs cargo in the guest;
the locks libc owes for the same milestone are
`issues/build/libc-refuses-what-toyos-cannot-yet-answer.md`'s.

Exit condition: a second process's `try_lock` on a file another holds locked
answers `WouldBlock`, and its `lock` waits for the holder's `unlock` or its
end, shown by a test with two processes.
21 changes: 19 additions & 2 deletions issues/design-debt/the-internet-clients-work-unchanged.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,25 @@ netd, `toyos::net` and std's ToyOS networking in the `rust/` fork.
program on `rustls`; the program and its judge's server installed
`rustls-rustcrypto` 0.0.2-alpha, and #660 cut both. The row comes back on
`ring` and waits for it; `rustls-rustcrypto` does not come back (owner,
2026-10-02). Whether `ring` builds for the ToyOS target is open and
untried: no build for that target compiles it. `rustls-rustcrypto` is
2026-10-02). Published `ring` 0.17.14 does not link for
`x86_64-unknown-toyos`: its `build.rs` picks its assembly by an OS list
that lacks `toyos`, and `src/rand.rs` has an OS list of its own. With
`"toyos"` added to `build.rs`'s `LINUX_ABI` and `target_os = "toyos"` to
`src/rand.rs` it builds for both ToyOS targets. In an x86-64 QEMU guest
it passes known answers (SHA-256,
SHA-512, HMAC, X25519, ChaCha20-Poly1305, AES-GCM, Ed25519, P-256,
`SystemRandom`), and `ureq` 3.4.2 on `rustls` 0.23.45 fetches 320000
bytes over TLS 1.3 from a server on the host and refuses a wrong name and
an untrusted root (#682, comment 5968053596). What stands before it
lands: a git fork's
`build.rs` runs `perl`, an arrival
`issues/build/the-build-runs-host-tools-outside-rust-and-qemu.md` does not
declare, and leaves C asserts on, so `__assert_fail` is undefined unless
ring builds with `debug = false` or `toyos_c` is linked; `src/build.rs`
gives the C compiler's environment (`cc_env`) to userland builds alone, so
a test crate's C is compiled by the host's `cc`; and not run: AArch64, the
T14, a `git =` dependency, the licence gate over ring in an image.
`rustls-rustcrypto` is
still named by doom's build script, which installs it on the host, and by
a line the cut left in `tests/toyos-rust-tests`
(`issues/build/the-guest-test-crate-depends-on-three-crates-no-test-uses.md`).
Expand Down
Loading
Loading