Skip to content

Five reviewed branches land together: rubato without its FFT (#811), the build tool's own FAT32, GPT and wallpaper (#813), build-time icons (#814), the loader's own UEFI bindings (#815), and static clang and ld.lld for ToyOS (#809) - #829

Open
Japabu wants to merge 32 commits into
mainfrom
wt/toyos-batch1

Conversation

@Japabu

@Japabu Japabu commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator

Five reviewed branches landed together, so their shared Cargo.lock conflicts are resolved once and CI runs once. Each was approved (LAND) by its own review, with its own CI and T14 record, on its own pull request; those five pull requests are superseded by this one, and the orchestrator closes them once it lands.

PR branch what it brings
#811 wt/toyos-rubato-r0 soundserver takes rubato without its default features: rustfft, realfft and their dependencies leave the lockfile, the resampling code unchanged
#813 wt/toyos-builddeps the build tool drops image, gix, fatfs, gpt and uuid: the wallpaper ships as src/wallpaper.rs draws it, os-release reads git, and the build writes its own FAT32 volumes (src/fatformat.rs) and partition tables (src/gptwrite.rs), with fatfs and gpt kept only as dev-dependency oracles
#814 wt/toyos-icons the desktop's eight icons are rasterized at build time by src/icons.rs, and resvg leaves the shipped programs
#815 wt/toyos-uefi the loader calls UEFI through its own bindings (bootloader/src/efi/), and uefi and uefi-services go
#809 wt/toyos-selfhost-s1 the toolchain builds clang and ld.lld for x86_64-unknown-toyos, statically linked (src/hostedclang.rs, cargo run -- --hosted-clang), and libc gains what they link; its LLVM recipe moves every toolchain key, so CI rebuilds the toolchain cold once

How it was put together

One merge commit per branch, git merge --no-ff origin/<branch> in the order above, so main's history keeps each branch's own commits, then one merge of main at a1eb2c0b9 (#816, #817, #821, #805 landed while the batch was being built). Each merge commit's message names its resolutions; they are all mechanical:

Each branch's diff survives

Each branch's own diff, git diff -U0 origin/main...origin/<branch> without Cargo.lock, reverse-applied (git apply --cached -R --check --unidiff-zero) to the batch head's tree, which succeeds only if every changed line the branch made is there:

branch exit
wt/toyos-rubato-r0 0
wt/toyos-builddeps 0
wt/toyos-icons 0
wt/toyos-uefi 0
wt/toyos-selfhost-s1 1: only issues/the-build-runs-host-tools-outside-rust-and-qemu.md; without that file, 0. Of the 5 lines the branch adds there, 4 are present verbatim, and the fifth, the cc row, is the branch's row with #810's doom insertion and nothing else (cmp of the row with that insertion cut out against the branch's row: equal)

Gates at 50d3c8e86

Logs are under the orchestrator's scratchpad, orch/batch1/logs/.

gate exit
cargo run -- --ci host 0 (78 sections, the last "nothing left in $TMPDIR or /tmp")
cargo run -- --build-only 0
cargo run -- --build-only --arch aarch64 0
cargo test, the whole guest suite 0: tests/toyos.rs 50 passed, 50 total; uptime load averages 51.37 69.51 70.05 at the start, 52.57 63.71 67.59 at the end
cargo run -- --hosted-clang (#809) 0: clang 147532080 bytes, ld.lld 85566504 bytes
cargo test --test toyos-build -- --metal --metal-readback <dir> boot:testcases loader_watchdog_arms blackbox_unclaimed_page blackbox_done_chain blackbox_foreign_record boot_deadline_ends_a_wedge 2, the staging exit by design: five images staged, the machine untouched

The same gates were green at the batch's first head, 17fbad76e, before main's a1eb2c0b9 was merged (guest suite 44 of 44 at load averages 64.91 55.51 53.53); every number above is from 50d3c8e86.

T14

The five branches' T14 readings were each taken at their own heads. The batch changes what the loader (#815), the image layout (#813) and the compositor (#814) build together, so boot:testcases and the loader rows #815 used are staged at 50d3c8e86 in five images whose sha256 are in the staging's request.txt:

image rows sha256
testcases boot:testcases, blackbox_unclaimed_page, and loader_watchdog_arms's control 9b17d123eecc0ef11a5ad724baec77531519bd321ae97dd08faea5ee6c0a683c
testcases-watchdog loader_watchdog_arms 8010cd4c813d65edfdac6d6aa48c4ba937122dceed348207bd7fbd96583da38e
metalcase blackbox_done_chain b69f3c8935f9273aa8532f9c1237048f630db692022c3676ff61c145f28991f4
foreignrecord blackbox_foreign_record 8d4fcb8b614ab829e02f84b3c4684acd38f17aad57b367e6bed303b8bbdea4be
deadlinewedge boot_deadline_ends_a_wedge 8819ccce23eadbb5e06e91a199b3716b60e9e3eedf5b04994f9620573b94500b

The T14 run is not yet taken: this pull request's hardware claims rest on it.

What I am unsure of

🤖 Generated with Claude Code

https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C

Japabu and others added 30 commits October 9, 2026 17:42
…inked

`cargo run -- --hosted-clang` builds clang and LLD for x86_64-unknown-toyos
(src/hostedclang.rs) from the LLVM commit the host's LLVM is, with the
toolchain's clang against its C sysroot, into the host store under a key of
their own: the host LLVM's key, the sysroot's, the recipe and the CMake
options. The sources are the commit's, written from the fork's LLVM
repository through an index of their own, never a checkout's files. The
binaries say the version, revision and repository the host's clang says,
`22.1.8-rust-dev` with bootstrap's suffix among them, since every object a
clang compiles carries that in its `.comment`. Each is refused unless it is
an x86-64 ELF naming no library it needs. Made only when asked for: its
build is LLVM's, and its key moves with every sysroot's. On this host it
took 23 minutes and gave a 147,533,968-byte clang and an 85,568,488-byte
ld.lld, static PIEs; stripped, 121,926,824 and 70,926,168.

What the build for a ToyOS host stopped on, measured with the tree's own
toolchain on the clang and lld targets alone: Support's `alarm`, `wait` and
`wait4` (Watchdog.inc, Program.inc), and clang's `std::ifstream`, which
libc++ has only with `std::filesystem`; at the link, clangBasic's `lround`.
No archive of either tool names ORC's `shm_open`, the interpreter's `scanf`
or llvm-objdump's `ctime`, so libc gains none of them. Neither tool starts a
child for `clang -c` or `ld.lld`: clang runs cc1 in its own process
(`CLANG_SPAWN_CC1` off), and LLD starts one only for
`--error-handling-script`.

libc gains:
- `wait` and `wait4`, answering ECHILD as `waitpid` does: libc starts no
  child.
- `alarm`, kept by a thread of libc's that ends the process with SIGALRM's
  default action, exit 142, once it is due. A handler never runs, since
  `sigaction` keeps none: that is stage 3 of the child-process track. The
  seconds left, rounded up, are `alarmreq.rs`'s rule, held on the host.
- `lround`, and `round` on the same rule, a half away from zero, held to the
  host's C library. `round` was `floor(x + 0.5)`, which answered -2 for -2.5
  and 1 for 0.49999999999999994.
- what libc++'s `src/filesystem` and `<fstream>` call: `setbuf`, `fseeko`,
  `ftello`, `truncate`, `pathconf`'s `_PC_PATH_MAX`, and `utimes`, refused
  ENOSYS: no call sets a file's times.

libc++ is built with `std::filesystem`. `open` refuses every directory, so no
descriptor names one for `openat`: `remove_all` walks a directory iterator,
as libc++'s Windows does.

`issues/bootstrap-cannot-build-llvm-clang-and-lld-for-a-toyos-host.md` is
closed: ToyOS's build, with nothing supplied by hand, makes a clang and an
`ld.lld` for x86_64-unknown-toyos, by CMake and not bootstrap. What bootstrap
still owes is M3's (`issues/rustc-llvm-cannot-build-for-a-toyos-host.md`).
The alarm and libc++ issues are renamed to what stays true of them, and the
track records the owner's ruling of 2026-10-09.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…n, and `image` leaves the build

The build drew the wallpaper, a committed JPEG at quality 99 held it, and
`src/assets.rs` decoded that JPEG back into `share/wallpaper.rgb`. Measured
on this host against `draw(1920, 1080)`: 3,491,059 of 6,220,800 channel
values differed after the round trip, by at most 6 levels, PSNR 48.34 dB,
and the committed file was exactly `encoded()` of that drawing.

Now the build writes `wallpaper::rgb()`, the same width/height header and
`draw`'s triples unencoded, so the shipped file is the drawing itself. It
ships to an image that builds its one reader, the compositor; it went with
the `assets/` sweep before, so an image with no compositor no longer carries
6.2 MB nothing opens.

Gone with it: `assets/wallpaper.jpg` and its licence row, `--regen-wallpaper`,
the encoder's QUALITY, the blocking bound (a measure of a block codec the
file no longer passes through) and the committed-file check. The band bound
now reads the file that ships; with GRAIN at 0.0 it reds, 636 rows of one
red value against the bound of 40.

`image`, `zune-jpeg`, `zune-core`, `moxcms`, `pxfm` and `byteorder-lite`
leave the root Cargo.lock, 700 packages to 694.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…oxide leaves the build

The owner's ruling on the dependency audit, "Drop gix, use git", over the
host-tools issue's earlier refusal of `git` reads in gitoxide's favour.
gitoxide sheds no host tool while `git` stays for worktrees and submodules,
and the build already runs `git` at every other site; for these two reads it
held 84 of the root Cargo.lock's packages (694 to 610).

`release` now asks `git log -1 --no-show-signature --format='%H %ct' HEAD`
for the commit and its committer time, and `git --no-optional-locks status
--porcelain --untracked-files=normal --ignore-submodules=all` for whether the
tree is that commit's: untracked files count whatever
`status.showUntrackedFiles` says, ignored ones and the fork's submodule do
not, and the status reads without rewriting the index another `git` in the
checkout may hold.

`a_tree_records_its_commit_its_commit_time_and_whether_it_is_dirty` is
unchanged and green; with `--untracked-files=normal` removed it reds (Clean
where Dirty), and with `%at` for `%ct` it reds (1000000000 for 1791089159).

The issue's row now admits these reads, with `log` among them, on that ruling.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…racle it is judged by

`src/fatformat.rs` writes the empty volume every FAT partition of an image
starts as: the boot sector and its backup, FSInfo, both FATs and the root
directory with the label. Its geometry is fatgen103's with the choices the
`fatfs` crate made, so every volume keeps its layout: 512-byte sectors, eight
reserved sectors, 512-byte clusters to 260 MiB and 4 KiB to 8 GiB, and the
FAT sized for the clusters left once both FATs are paid for.

One difference, on purpose: no BIOS boot code. `fatfs` wrote 129 bytes of
real-mode "not a bootable disk" stub after the BPB of both boot sectors; the
jump fatgen103 requires stays, the 420 bytes after it are zero.

Here and not in `toyos-fat32`, which is the kernel's driver and whose header
refuses a format path ("no code here that could write a BPB"); the build is
the one program that formats.

`fatfs` moves to the build's dev-dependencies, as the differential oracle:
`differs_from_the_fatfs_format_only_in_the_bios_stub` formats six sizes,
across both cluster-size edges, with both and finds every byte equal outside
the two boot-code ranges. Mutated, it reds on each of: the FAT sized without
its two reserved entries (1052 bytes at 260 MiB + 4 KiB), the end-of-FAT
entries left free (432 bytes at 34 MiB), and sectors-per-track 0x3f for 0x20
(2 bytes). `an_empty_volume_mounts_free_and_checks_clean` mounts each with
`toyos-fat32` and runs `toyos-fat32-check` once the free count is recorded.

`fatfs` stays in the root Cargo.lock as the oracle of this module and of
`toyos-fat32`'s own host suite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
soundserver builds only `SincFixedOut`, which never reaches rubato's
`fft_resampler` feature: that default feature compiles `synchro.rs`
(`FftFixedIn`/`FftFixedInOut`/`FftFixedOut`) and swaps the `FftNum` bound
on `Sample` from realfft's to a local trait of the same bounds. Turning the
default off removes rustfft, realfft, num-complex, strength_reduce,
transpose and primal-check from the lockfile and the image's build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…only the oracle it is judged by

`src/gptwrite.rs` makes the table every disk the build writes carries: the
protective MBR, the primary header and its 128-entry array at the front, the
backup array and header at the back, in 512-byte blocks, with `toyos-gpt`'s
CRC-32 and GUIDs. `src/image.rs` places the partitions as the `gpt` crate
did, each on the first 1 MiB boundary after the last, so every image keeps
its layout byte for byte; its GUIDs are `toyos_gpt::Guid`s from here on, the
on-disk bytes, with no text spelling between the build and the parser.

Here and not in `toyos-gpt`, which is the loader's and the kernel's parser;
the build is the one program that writes a table. `install` reads the
partition names the parser does not off the image's own entry array.

`gpt` moves to the build's dev-dependencies, as the differential oracle:
`the_gpt_crate_writes_the_same_table` lays an install's six partitions with
both, on a disk the alignment rounds and one it does not, and finds every
byte of both disks equal. `toyos_gpt_reads_it_from_either_copy` reads every
partition back through the loader's parser, from the primary and, torn, from
the backup. The install test now holds the names an install carries over.
Mutated, they red on each of: the header CRC over the whole block, the
protective MBR's starting CHS 0x01, the backup header naming the array one
block early, and `name_of` reading no name.

`toyos-gpt`'s `TOYOS_*_TEXT` constants, and the test holding them to the
bytes, existed for the `gpt` crate's text-typed API and go with it.

`gpt` stays in the root Cargo.lock as the oracle of this module and of
`toyos-gpt`'s own `tests/oracle.rs`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…` leaves the build

The build drew every disk and partition GUID with `uuid::Uuid::new_v4` and
converted it to the on-disk order. `gptwrite::random_guid` draws the sixteen
bytes from the `getrandom` the build already takes for a throwaway key's
seed, already in the on-disk order, and sets RFC 9562's version 4 in the high
nibble of byte 7 (the third field is little-endian there) and the variant in
the top two bits of byte 8.

`a_random_guid_is_version_4_of_the_rfc_variant` reads both where the
canonical text shows them; with the version set in byte 6 it reds, three
runs of three (a mutant drawing a 4 there by chance passes one run in 16).

`uuid` stays in the root Cargo.lock only through the `gpt` crate, the
dev-dependency oracle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…he image

The compositor and files rasterized eight committed Phosphor SVGs at start
through resvg, usvg and tiny-skia: 33 third-party crates in each program,
inside the server that owns the framebuffer, for icons that never change and
are drawn at three fixed sizes (cursors 20, title-bar buttons 14, files'
entries 32). Nothing in the tree draws at another scale: the compositor has
no scale factor.

So the build draws them, as it already draws the console font: src/icons.rs
reads the SVG subset the icons are written in, refuses anything past it by
name, and ships each as share/icons/<stem>.alpha, a coverage mask the program
colours. No shipped program carries a rasterizer; userland/sprite keeps only
the mask loader and the blit, and the programs lay out by the size the mask
carries, so the size is declared once, beside the icon.

The owner forbids a visible change, so the rasterizer reproduces resvg's
pixels rather than better ones: tiny-skia's 4x4 point samples worth 16 each
(63 on a pixel's last sample row), kurbo's arc-to-cubic split at usvg's 0.1
tolerance, tiny-skia's chord counts for a cubic edge and for the quads its
stroker approximates an offset curve with, and source-over between shapes.
Exact-area coverage was measured first and differed from resvg by up to
45/255 on 597 of 3836 pixels, all of it resvg's coarser sampling; with the
emulation 35 pixels differ by one sample (16/255) and the rest are equal.
A one-off differential against resvg 0.47, outside the tree, gives the
numbers; the host test pins the digest of the pixels it compared.

The SVGs no longer ship. Removed from the root lock: 22 packages; from the
compositor and files: all 33 third-party crates each.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…es back, and the bootstrap defect stays open

Answers the review of b9f562d on #809.

libc: `signal` and `sigaction` keep SIGALRM's disposition, and a due alarm
under SIG_IGN is dropped instead of ending the process (`alarmreq::ends`,
held on the host). `signal` takes and answers a pointer, as signal.h
declares it: SIG_DFL is null, which no Rust fn pointer may be. A SIGALRM
blocked in every thread still ends the process, since libc keeps each
thread's mask in that thread and std's threads are none of libc's; the
issue records it with its exit extended.

The corpus: 206_libc_refusals reads utimes' ENOSYS, wait's and wait4's
ECHILD and pathconf's EINVAL; 207_libc_names reads truncate through stat,
setbuf's buffer and none, an fseeko/ftello round trip, lround's halves and
its EDOM, pathconf's _PC_PATH_MAX, SIGALRM's disposition through signal and
sigaction, and alarm(5), alarm(0), alarm(0). The owed lines go from the
issues that carried them.

Build: hostedclang's export is llvm::check_out_committed, which now takes
the git directory it reads; static_elf goes, no test having shown it refuse
anything; release.rs's layers are a Part of their own, so the hosted clang
is no layer by type and NOT_A_LAYER goes.

Issues: the bootstrap defect is open again, re-scoped: the CMake build in
src/hostedclang.rs goes once bootstrap's ToyOS-host LLVM makes clang and
lld, owner M3. remove_all's race is a defect of its own with an owner and
an exit that removes REMOVE_ALL_USE_DIRECTORY_ITERATOR. The host-tools rows
name src/hostedclang.rs; the track no longer reads as if M2 waits on HTTPS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
The host gate's clippy pass denied manual midpoints and the tag tuple's complexity; the pixels do not move (the digest test holds).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…vices go

The owner ruled on the dependency audit's uefi row: own bindings, in place
of the loader track's plan to move to the current uefi release.
`bootloader/src/efi/` holds UEFI 2.10's tables, the protocols the loader
opens (LoadedImage, DevicePath, SimpleFileSystem and File, PartitionInfo,
BlockIo, GraphicsOutput, Rng, PciRootBridgeIo), the console it writes, the
status codes and GUIDs, each struct cited to its section and pinned by
compile-time size_of/offset_of! asserts that run on both loader targets at
every build. A module and not a crate: the loader is its one user, and a
crate would add a manifest, a description and a workspace entry for no
second reader; a host test cannot link a no_std, no_main UEFI binary, and
the asserts check the layout on the targets themselves.

The wrappers are safe where the hazard was ours:
- a name crosses to firmware only as CStr16, which carries its NUL;
- a protocol is opened only through BootServices::get (GET_PROTOCOL) or
  ::exclusive, whose bound is the Exclusive marker; the opener is private,
  so the two clippy.toml rules that guarded uefi's openers go with them;
- an open protocol closes when its Scoped drops, a handle buffer is freed;
- the console and the allocator refuse once exit_boot_services has run,
  which nulls the table itself: no SIGNAL_EXIT_BOOT_SERVICES callback is
  registered, so end_this_pass has no event to close;
- BlockIo reads OptimalTransferLengthGranularity only at revision 3 and
  later, which deletes the unsafe cast rootimage.rs needed to reach the
  revision through uefi's type;
- the memory map is taken into &mut [u64], which deletes watchdog.rs's
  unsafe byte-slice cast.

The panic handler says `[PANIC]: <info>` on the console, as uefi-services'
did, and powers the machine off; uefi-services' ten-second stall before
the power-off, a flat wait, does not come with it.

One HARDDRIVE decoder (efi::HardDrive::parse, UEFI 2.10 §10.3.5.1) serves
boot_partition, bootnext's protocol path and its NVRAM load options, and
boot_disk; bootnext's own byte decoder goes, and a load option's HARDDRIVE
node is now held to the spec's 42 bytes.

The ESP's \toyos\log.guid is read off LoadedImage's DeviceHandle, the
volume firmware loaded the image from (§9.1.1), not through
LocateDevicePath.

A status prints by its Appendix D name: `(NOT_FOUND)` where the loader
wrote `(UEFI Error NOT_FOUND: ())`. That is the one change to the loader's
text, and it is on refusal lines alone.

The loader track's stage 4 loses its uefi bullet and its uefi-services
exit, and the owner's ruling joins its bounds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
… and OPENED_BY names its reader

`f32::powf` and `f32::exp` call the host C library's, which no standard
holds to one answer, and ROOT's UUID is derived from the bytes the wallpaper
draws: one tree could name a different ROOT on Linux, macOS and later ToyOS.
The pure-Rust `libm` crate, already in the lock at 0.2.16, computes both the
same on every host. The rest of `draw` is IEEE arithmetic and sqrt, floor and
round, each exactly specified, and Rust contracts no multiply-add.

Measured on the development host (macOS, arm64): the libm draw is byte for
byte the std draw, 0 of 6220808 bytes differ, so the picture is unchanged.
`the_wallpaper_is_the_same_on_every_host` pins its SHA-256, 675f4fbc...1d91,
so `--ci host` on CI's Linux host reds where its draw differs.

`wallpaper::READER` was a second table of which program opens a ROOT file
beside `assets::OPENED_BY`. The wallpaper is a row of `OPENED_BY` now, the
build asks it through `assets::wanted`, and `only_its_reader_opens_an_owned_file`
holds that row as it held doom's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…ow to re-measure it

The asset test carries a tracked and an untracked committed icon again, so
dropping the `.svg` arm's `ships` guard goes red: the untracked icon would
ship as `minus-bold.alpha`. The digest test's failure message now says what
to do (draw the icons against resvg 0.47 out of tree with the differential
posted on #814 and ask the owner again on any visible change) instead of
naming an oracle that exists only in a comment, and the module header no
longer claims the pixels are resvg's exactly: they follow resvg's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…build's own GPT name decoder goes

`image::name_of` decoded the primary header and its array by hand, beside
`toyos-gpt`, with neither CRC checked: where `toyos_gpt::list` had taken the
backup over a torn primary, `install` named partitions from bytes the parser
had refused. A `Partition` now carries its entry's name field, decoded in the
walk whose CRC licenses it, and `Partition::name` answers its UTF-16 units up
to the first zero; decoding them is the caller's.

`Stated` stays as it was, so the `Err` side of an `Entry` does not grow; the
name rides beside it through the walk to `Partition::place`.

The suites carry names now: the generator gives every entry a random name of
0 to 36 non-zero units, `oracle.rs` holds each placed entry's name to the
`gpt` crate's reading of it, and `mutate.rs` holds every answered name to the
copy of the table it came from.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
The cluster size past 8 GiB was reached by no volume the build makes and by
no test; an assert at 8 GiB stands where it was. The 16-bit sector count was
written only below 65,536 sectors, which `format`'s cluster-count assert
already refuses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…ons of the JPEG go

The owner's ruling, "Drop gix, use git", covers the reads that replace
gitoxide's: `release`'s `log` and `status`. The row of `git` reads, the
config write, the index checkout and the HTTPS clones is main's again,
refused in gitoxide's favour, and a row of its own admits those two reads.

README.md and issues/the-tree-says-who-uses-each-thing.md named the deleted
`assets/wallpaper.jpg`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…nic after a refused ExitBootServices goes straight to the reset

The round-1 review of #815 found the load-option walk in bootnext.rs
narrowed from main's rule (SignatureType at byte 41, signature at 24..40,
any node at least 42 bytes long) to HardDrive::parse's exact 42 bytes. Those
bytes are any OS's to write through runtime variable access, and no test at
any tier can see the rule change: QEMU only reaches the "no Boot#### entry"
arm. Main's decoder is restored byte for byte; HardDrive::parse stays for
device paths firmware built (boot_partition, our_partition), and the loader
track's stage 2 still unifies the two under its host tests.

UEFI 2.10 §7.4.6 allows only the memory allocation services after a first
ExitBootServices call, failed or not. A panic in the retry (fill_memory_map's
assert) reached a handler that still wrote through ConOut. EXITING is set
before each exit call; print and the panic handler read the console only
while it is clear, so the handler goes straight to ResetSystem.

The loader track's bound no longer puts the module path in the owner's
ruling, and the arm64 issue no longer says the bootloader is the uefi crate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…, and the hosted clang's export folds into place

Round 2's review of #809 asked three things.

SIGALRM's number was written twice in libc, as 128 + 14 in alarm.rs and as a
const in misc.rs. It is now alarmreq's SIGALRM, beside SIG_DFL and SIG_IGN,
read by both; the host test compares it with signal.h's, which also gives the
const a reader in toyos-libc-copies.

sigaction's oldact for SIGALRM answered sa_flags and sa_mask 0 whatever the
last act set. POSIX answers the previous action whole, so libc keeps the whole
struct sigaction under a lock in place of the handler's atomic, and signal
installs an action of the handler alone. 207_libc_names sets SA_RESTART and
SIGUSR1's bit and reads both back; the C corpus runs only on metal, so the
line is read by the T14's boot:testcases.

hostedclang's export had one caller and three lines; place does it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…NG on, and stage 2 names both HARDDRIVE decoders it folds

Stage 4's handler writes loader.log through the File protocol, which UEFI
2.10 §7.4.6 forbids from the first ExitBootServices call as it forbids the
console; as written it would undo the EXITING fix. It now skips loaderlog
from EXITING on and goes straight to ResetSystem's shutdown.

Stage 2 called toyos_update::entry::partition the one HARDDRIVE rule but
named neither of the loader's two decoders going, efi::HardDrive::parse and
bootnext::gpt_signature, so it could close with three. Both are named, and
the exit gains an rg that finds them today.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…in the store

`--hosted-clang` read the LLVM commit from the primary checkout's
`.git/modules/rust/modules/src/llvm-project`, a repository no build fetches
into: after #790 moved the gitlink to ToyOSOrg/llvm-project b7420fe it held
no such commit (its origin is rust-lang's), and the build died with
`unable to read tree`.

The normal build obtains the commit one way: bootstrap's `Llvm` step checks
the gitlink's commit out in the fork checkout and fetches it there, and
`llvm::place` writes what builds read of it into `llvm/<key>/src` from that
checkout; the C++ runtime is built from there. The LLVM now keeps the hosted
clang's pathspecs there too, and the hosted clang builds from that directory
of the LLVM it holds in use: the commit is the one the host LLVM's key names
on any host, whether the LLVM was built here or found in the store, and no
checkout is read.

The pathspecs an LLVM keeps are now part of its key, so a change to either
list moves it; the recipe moves to 5, and every LLVM key with it. The hosted
clang's key names the LLVM's key, which now names its sources, so it drops
its own copy of them; its recipe moves to 3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…clusively

`--hosted-clang` resolved the host's LLVM holding its worktree's build lock
only shared. When the store lacked it, bootstrap's `Llvm` step then ran in
the fork checkout, updating `src/llvm-project` and writing
`build/toyos-llvm`, beside every other shared holder of the same worktree,
which `buildlock.rs` names as the exclusive mode's job; the compiler and
sysroot builders reach `llvm::resolve` only inside exclusive phases.

`llvm::resolve_held` asks under the shared lock whether the store holds the
LLVM the fork names, and makes one only through `Held::act_if`, with the lock
exclusive; one the store holds is found with the lock shared, at no cost of
serialisation. `an_llvm_is_made_only_with_the_worktree_lock_exclusive`
holds both halves: a shared acquirer is kept out while the LLVM is made, and
a second worktree held shared by another process finds it without waiting.

The store design stays, on two measurements. A linked worktree whose LLVM
came from the store holds no LLVM commit in its fork's `src/llvm-project`:
of the 16 on this host with a fork checkout, none did (`git cat-file -e
<gitlink>^{tree}` exits 128 in each, its directory empty), and only the one
whose bootstrap built the LLVM held it. A fresh depth-1 fetch of the commit
from the fork's remote took 23 s and 278 MiB per worktree. Keeping the
hosted clang's sources in the stored LLVM costs 61.6 MB compressed per
`llvm` entry, packed as actions/cache packs it (posix tar, zstd -T0
--long=30): 102,023,921 bytes at recipe 4 against 163,600,770 at recipe 5,
of one LLVM with only its `src/` differing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
Main brings the app grants (#807) and the C cases linked without DWARF
(#806); neither touches what this branch changes, and the merge is clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…nd makes it if a sweep took it

`choose_held` read `defect` with no lock on the LLVM's key, and only
then took the key's use inside `keyed_made`. A placement elsewhere could
sweep an LLVM unused for the keep time in that gap, since nobody held
its key, and `keyed_made` then found a defect and ran `unbuilt`, which
panicked where the right outcome is to make the LLVM.

It now takes `buildlock::keyed_using` first and reads the defect under
it, which no sweep takes from under it. A whole LLVM is returned held;
one that is not has its use dropped, since the worktree lock orders
before the key's, and goes through `act_if`, whose exclusive branch
makes it; if the second look finds it whole, the loop takes the use
again. `unbuilt` and its panic go.

`choose_held` takes the whole-check as a parameter, as it takes the
build, so `a_sweep_after_the_llvm_is_found_whole_fails_no_build` can run
a real `keystore::sweep` right after the check answers: it panicked
before this change and passes after.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
Cargo.lock: main's side, regenerated by cargo metadata --offline, which
drops the realfft/rustfft/num-complex subtree the branch removed and keeps
main's rcgen and its dependencies; every package it names is in one side's lock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…of the build tool

Cargo.toml: the branch drops gix and its comment; main's webpki-root-certs
and pem (#810) stay.
issues/the-build-runs-host-tools-outside-rust-and-qemu.md: the branch's new
`git log` and `git status` row, and main's `cc` and toolchain-`clang` rows,
which name doom's build script and ring's C in guest test crates (#810).
Cargo.lock: main's side, regenerated by cargo metadata --offline, which
drops gix, image and their dependencies (defmt and heapless were faster-hex's
and jiff's); every package it names is in one side's lock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
Cargo.lock: the batch's side, regenerated by cargo metadata --offline, which
drops resvg, usvg, tiny-skia and their dependencies; every package it names
is in one side's lock. src/assets.rs, src/lib.rs and NOTICE merged without
a conflict.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
Cargo.lock: the batch's side, regenerated by cargo metadata --offline, which
drops uefi, uefi-raw, uefi-services, uefi-macros and their dependencies;
every package it names is in one side's lock. Nothing else conflicted, and
main changed nothing under bootloader/ since the branch's base.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
Japabu and others added 2 commits October 10, 2026 09:52
src/lib.rs: both sides' modules, gptwrite (#813) and hostedclang.
issues/the-build-runs-host-tools-outside-rust-and-qemu.md: the branch's
`git`-reads row, which names src/hostedclang.rs; the batch's `git log` row
and toolchain-`clang` row; and the `cc` row with both sides' insertions,
the branch's NATIVE tablegens and main's doom build script (#810).
Cargo.lock: unchanged by the branch, and cargo metadata --offline leaves the
batch's as it is.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…e SSH server core (#817), toyos-usbhid (#821) and the stop's hold of the console wire (#805), into the batch

Cargo.toml: both sides' build dependencies, the batch's libm (#813) and
main's toyos-ssh (#817). Cargo.lock: git's merge, which cargo metadata
--offline leaves as it is; every package it names is in one side's lock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
@Japabu
Japabu marked this pull request as ready for review October 10, 2026 09:24
@Japabu

Japabu commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator Author

T14 reading at 50d3c8e86 (the batch's head), run by the orchestrator through request.txt: five images (deadlinewedge, foreignrecord, metalcase, testcases-watchdog, testcases). Each one's sha256 was checked in the same command that flashed it, and every boot returned rc=0.

Judge (boot:testcases loader_watchdog_arms blackbox_unclaimed_page blackbox_done_chain blackbox_foreign_record boot_deadline_ends_a_wedge): EXIT=0, 252 passed, 0 failed, 5 boot(s).

Phases per boot (#804's boot.txt):

boot flash (dd) loader (ROOT read) kernel to Boot: complete
testcases 51.3 s (49.8) 9517 ms (6399) 1175 ms
the other four 18.1–19.0 s (16.7–17.6) 1824–2384 ms (212–668) 1176–1181 ms

testcases carries #806's stripped C corpus.

@Japabu
Japabu enabled auto-merge October 10, 2026 09:37
@Japabu
Japabu added this pull request to the merge queue Oct 10, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant