Skip to content

The loader lock takes the per-range maxima and its profile strips debuginfo, the last alignment of the one-workspace track - #738

Merged
Japabu merged 4 commits into
mainfrom
wt/toyos-align3
Oct 4, 2026
Merged

Japabu merged 4 commits into
mainfrom
wt/toyos-align3

Conversation

@Japabu

@Japabu Japabu commented Oct 4, 2026 •

Copy link
Copy Markdown
Collaborator

bootloader/Cargo.lock moves its 8 registry crates that sat below the highest version another of the five main locks carries in the same semver range up to that version, and the loader's [profile.toyos] gains strip = "debuginfo", the one key in which it differed from the kernel's and userland's. This is the third and last alignment of issues/the-tree-resolves-in-five-cargo-locks-not-one.md, the one-workspace track (stage 2 of issues/the-tree-says-who-uses-each-thing.md); #724 and #732 were the first two. After it no registry pair of the five locks sits below its range's maximum, and the three [profile.toyos] tables have the same keys. No other manifest changes, no fork pin moves, and no other lock changes.

What moved

crate from to in the loader's graph
bitflags 2.4.2 2.11.0 uefi, uefi-raw
cfg-if 1.0.0 1.0.4 curve25519-dalek, sha2, uefi-services
libc 0.2.189 0.2.190 in neither UEFI graph: a target-gated dependency of cpufeatures
log 0.4.20 0.4.29 uefi, uefi-services
unicode-ident 1.0.12 1.0.24 proc macros only (ptr_meta_derive, uefi-macros)
proc-macro2 1.0.78 1.0.106 proc macros only
quote 1.0.35 1.0.45 proc macros only
syn 2.0.48 2.0.117 uefi-macros only (syn 1.0.109 stays, for ptr_meta_derive)
  • How. align.sh (evidence comment 1) resets the lock to origin/main's and runs one cargo update -p <name>@<old> --precise <new> per row, 8 rows, each exit 0, leaf first along the proc-macro chain. The lock diff is 18 lines in and 18 out: 8 versions and checksums, and the two syn 2.0.48 references.
  • Where the versions come from (sums.sh). Each of the 8 is one the root lock already carries with the same checksum, and one the userland lock or the kernel lock carries too. Nothing enters or leaves the lock beyond the 8 old versions: no fetch new to the tree.
  • What the loader's libc pulls with it, which the track left unmeasured: nothing. Its lock entry has no dependencies, and reach.sh finds it on neither UEFI triple; on --target all its only edge is cpufeatures'.
  • The pair counts (pairs-run.sh, running The root and kernel locks take the per-range maxima the five main locks already carry, the first stage of the one-workspace track #724's pairs.sh unchanged on the committed locks). At 0613f93f7 it prints the 8 rows above; at the head it prints none.

The profile line

strip = "debuginfo" is a no-op on this target as far as stripping goes: rustc's MSVC-flavour linker ignores -C strip (MsvcLinker::debuginfo in the rust/ fork), and the loader's link already writes no debug information (/DEBUG:NONE in bootloader/.cargo/config.toml). It lands now because the track's merge step must move no byte, and the merged workspace has one profile. It still moves the loader's bytes, because cargo hashes the profile into each unit's -C metadata: meta.sh (comment 4) shows that of the 26 (x86_64) and 24 (aarch64) units the loader links from, only core, alloc, compiler_builtins and rustc's symbols.o keep their names, so every cargo unit is renamed, and lld lays the sections out in another order.

Bytes before and after (negative control)

bytes.sh (comment 2) builds both arches at 92f17c716 and hashes 53 artifacts (both kernels, both loaders, the 49 userland binaries find lists) four times: at the head (head1); with origin/main's bootloader/Cargo.toml, the aligned lock alone (nostrip); with origin/main's manifest and lock, the whole change reverted (base, the control); and at the head again (head2). Every build exits 0, and every link map's rerun links an image cmp-equal to the build's.

  • Deterministic: head1 and head2 are equal in all 53.
  • Only the loaders change: in every comparison, both kernels and all 49 userland binaries are equal; both loaders differ.
  • The control fails where it should: staged-control.sh (comment 3) finds no copy of the base loader in a staged image, and that image differs from the base loader in 263,771 bytes at the place the head's loader sits, the same count analyze.sh gives for base → head.

Which crates' code moved, and by how much

analyze.sh (comment 2) reads each loader's lld map (/lldmap) with funcs.sh: every input section the image carries, by the crate that compiled it, and each .text section's instructions, normalised so that a body at another address reads the same (hex numbers, immediates and branch labels written X). compare.sh then counts per crate the functions whose name and body are unchanged at the same address, unchanged at another address, and the ones whose name or body is in one image only.

The lock (base → nostrip).

x86_64 aarch64
file size 285,184 → 285,184 245,248 → 244,736
.text 207,352 → 207,241 (−111) 173,412 → 173,360 (−52)
.rdata 68,370 → 68,046 (−324) 66,430 → 66,106 (−324)
bytes that differ 262,499 222,057 over the shorter file's length
  • log: 2 of its 4 functions change. log::__private_api::log (218 bytes on x86_64, 168 on aarch64) gives way to <log::__private_api::GlobalLogger as log::Log>::log (53, 76), and log::set_logger goes from 95 to 85 bytes (136 to 124). Its .text is 360 → 185 bytes on x86_64 and 368 → 264 on aarch64, its .rdata 375 → 170 on both.
  • uefi_services: its one changed function is rust_begin_unwind, the panic handler, which logs: 420 → 484 bytes on x86_64 and 300 → 352 on aarch64. Its .rdata is 719 → 600 on both.
  • toyos_elf: one 13-byte (24 on aarch64) function, <toyos_elf::layout::Segment>::image, keeps its body; lld's identical code folding now also places <core::panic::location::Location>::file on it, so it counts as one-sided by name only.
  • Every other crate, bitflags' users uefi and uefi-raw included, keeps every function's name and body. Every function but 6 (x86_64) and 2 (aarch64) sits at another address.

The profile line (nostrip → head1). No function's name or body changes and no crate's size moves, in any section, on either arch. What moves is the layout: 363 of 530 functions sit at another address on x86_64 (219,421 bytes differ) and 133 of 514 on aarch64 (121,694 bytes differ), all of the latter in bootloader, uefi and uefi_services.

Unlike #724 and #732, both changes here change the loader's bytes by design; the T14 is the evidence for how it behaves.

The track

Its counting paragraph says the locks agree; its exit records #732 and this alignment as the second and third; the constraint naming the loader's missing strip and the sentence leaving the loader's libc unmeasured are gone. "Four of them declare their own [profile.toyos]" becomes three: the root's went with toyos-ld in #726 (at the head, git grep '^\[profile.toyos\]' finds it, among the five resolutions' manifests, in the kernel's, userland's and the loader's only). The constraint paragraph measured at 8b4f88446 otherwise stands as measured there.

Gates

The head is f84e57ef8, the merge of origin/main (b75ca2b4e: #734, #735) into 2ad9f8956; the merge changes no loader file and no lock. gates2.sh ran the four in sequence there (orch/align3/gates2.log), and gates.sh ran them at 2ad9f8956 before the merge (orch/align3/gates.log), all green.

gate exit at f84e57ef8 log's closing line
cargo run -- --build-only (x86_64) 0 Build finished. (gate2-build-x86.log)
cargo run -- --build-only --arch aarch64 0 Build finished. (gate2-build-a64.log)
cargo run -- --ci host 0 [ci] Host: 75 step(s), all green (gate2-ci-host.log)
cargo test (whole guest suite) 0 test result: ok. 28 passed, 28 total (36.8s; workers: 197s building, 146s testing), then checks.rs 34 passed and the empty doc-test target (gate2-guest.log)

At f84e57ef8 both loaders hash as bytes.sh's head2; the kernels differ, which #734 changes (gates2.log). At 2ad9f8956 all 53 artifacts hash as head2 (gates.log), so the track commit moves no byte.

T14

The loader boots every T14 image, and every metal boot runs it twice: the pass that hands the kernel the machine, and, after the kernel's reset, the pass that reads the black-box page and appends its report to the same loader.log the driver reads back (tests/common/metal.rs, Boot::loader). stage.sh (comment 3) staged all 28 images of the metal profile at f84e57ef8 with cargo test --test toyos-build -- --metal --metal-readback orch/align3/metal, which touches no machine (exit 2: staged, not judged), and staged.sh finds the head's x86_64 loader, whole and byte for byte, in each of the 28 images at the same offset.

Every row judges a boot of both passes. The rows that read the second pass's report as their verdict are watchdog_fed (testcases-watchdog), blackbox_done_chain and machine_reboot (jobcase), boot_deadline_ends_a_wedge (deadlinewedge), usb_reset_records_the_phase_it_cut (usbload), usb_stick_left (usbbreak), hard_lockup_ends_a_deaf_cpu (hardlockup) and blackbox_foreign_record (foreignrecord). orch/align3/metal/request.txt lists all 28.

T14 RUN REQUESTED: orch/align3/metal/request.txt in the orchestrator's job directory.

What I am unsure of

  • No run on hardware yet. The QEMU guest suite boots this loader on both arches, but the T14 rows above are the evidence that its changed logger and panic handler, and its new layout, behave on firmware that is not OVMF.
  • The body comparison is normalised. funcs.sh writes every hex number and immediate as X, so a changed constant inside an otherwise equal body would read as unchanged. The section sizes, which it does not normalise, agree with it: in nostrip → head1 every crate's size in every section is equal.
  • Who owns monomorphised code. funcs.sh attributes a function to the crate that compiled it, so a generic of log or uefi instantiated by the loader counts as bootloader's; bootloader's bodies are all unchanged under the lock, so no such instance changed.

Net: git diff --shortstat origin/main...f84e57ef8 is 3 files, +27 −31: bootloader/Cargo.lock +18 −18, bootloader/Cargo.toml +1, the track +8 −13. No test is added or changed.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8

Japabu and others added 4 commits October 4, 2026 22:34
…carry

`bootloader/Cargo.lock` moves each of its 8 registry crates that sat
below the highest version another of the five main locks carries in the
same semver range up to that version: bitflags 2.4.2 -> 2.11.0, cfg-if
1.0.0 -> 1.0.4, libc 0.2.189 -> 0.2.190, log 0.4.20 -> 0.4.29,
unicode-ident 1.0.12 -> 1.0.24, proc-macro2 1.0.78 -> 1.0.106, quote
1.0.35 -> 1.0.45 and syn 2.0.48 -> 2.0.117. One `cargo update -p
<name>@<old> --precise <new>` per crate, the proc-macro chain leaf
first. Every version it gains is one the root lock already carries, with
the same checksum; nothing enters or leaves the lock, and no manifest
changes.

This is the last alignment of the one-workspace track
(issues/the-tree-resolves-in-five-cargo-locks-not-one.md): after it no
registry pair of the five locks sits below its range's maximum.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
`[profile.toyos]` in `bootloader/Cargo.toml` gains `strip = "debuginfo"`,
the one key in which it differed from the kernel's and userland's. The
one workspace the track merges the five resolutions into has one
profile, and the track
(issues/the-tree-resolves-in-five-cargo-locks-not-one.md) has this
change, which moves the loader's bytes, land before the merge so that
the merge itself moves none.

On this target the key strips nothing: rustc's MSVC-flavour linker
ignores `-C strip` (`MsvcLinker::debuginfo`), and the loader's link
already writes no debug information (`/DEBUG:NONE` in
`bootloader/.cargo/config.toml`). It enters the profile, and with it
every unit's metadata hash, so the loader's bytes move; the pull request
measures by how much, and in which crates' code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
No registry pair of the five locks now sits below its range's maximum,
and the loader's `[profile.toyos]` carries the `strip` the kernel's and
userland's do. The track's counting paragraph says so; its exit records
the third alignment beside #724 and #732; the constraint naming the
loader's missing `strip`, and the sentence leaving unmeasured what the
loader's `libc` pulls with it (nothing: it is a leaf, and the lock gained
no entry), are gone. "Four of them declare their own `[profile.toyos]`"
becomes three: the root's went with toyos-ld in #726.

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

Japabu commented Oct 4, 2026

Copy link
Copy Markdown
Collaborator Author

Evidence (1 of 3): the alignment, the checksums, the pair counts and what the moved crates reach

Every script is shown as it ran and was not edited after; every log is its whole output, by cat. All live in the orchestrator's scratchpad, orch/align3/, and each ran as sh <script> there; scripts.sha is in comment 3. A .exit file holds the exit of sh <script> where the script prints no exit of its own.

Provenance: align.sh ran at 0613f93f7 (origin/main) and wrote the lock that 61defdfbe then commits unchanged; sums.sh ran on that uncommitted lock (its head line is therefore 0613f93f7). pairs-run.sh and reach.sh ran at the merge head f84e57ef8, whose five locks equal 92f17c716's and 2ad9f8956's (git diff --quiet 2ad9f8956 f84e57ef8 -- bootloader Cargo.lock kernel/Cargo.lock userland/Cargo.lock toyos/Cargo.lock, exit 0). pairs.sh is #724's and #732's, byte for byte (c773c8e3…).

Named so nothing in the directory is unaccounted for: explore/ holds the exploratory builds and drafts of map.sh, funcs.sh and compare.sh before their final form, and explore/staged0.{sh,log}, a first staged.sh that ran outside the C locale and whose grep/cut failed on the image bytes; none of it is evidence. pairs-main.txt and pairs-head.txt are inline runs of pairs.sh on the worktree before and after align.sh, superseded by pairs-run.sh, which reads the committed locks.

align.sh

# Moves bootloader/Cargo.lock, from origin/main's, to the per-range maxima the five main locks carry.
# The proc-macro chain goes leaf first: unicode-ident, proc-macro2, quote, syn.
cd /Users/jan/Dev/jan/toyos-align3/bootloader || exit 1
echo "head $(git rev-parse HEAD) origin/main $(git rev-parse origin/main)"
cargo --version
git checkout origin/main -- Cargo.lock; echo "reset EXIT=$?"
for r in bitflags@2.4.2=2.11.0 cfg-if@1.0.0=1.0.4 libc@0.2.189=0.2.190 log@0.4.20=0.4.29 \
         unicode-ident@1.0.12=1.0.24 proc-macro2@1.0.78=1.0.106 quote@1.0.35=1.0.45 syn@2.0.48=2.0.117; do
  echo "== ${r%=*} -> ${r#*=}"
  cargo update -p "${r%=*}" --precise "${r#*=}"; echo "EXIT=$?"
done
git diff --stat origin/main -- Cargo.lock
git diff origin/main -- Cargo.lock

→ align.log (exit 0)

head 0613f93f742d141148fb93a6333d3fbd10c26ac0 origin/main 0613f93f742d141148fb93a6333d3fbd10c26ac0
cargo 1.98.1 (797e8a9bc 2026-08-05)
reset EXIT=0
== bitflags@2.4.2 -> 2.11.0
    Updating crates.io index
    Updating bitflags v2.4.2 -> v2.11.0
note: pass `--verbose` to see 15 unchanged dependencies behind latest
EXIT=0
== cfg-if@1.0.0 -> 1.0.4
    Blocking waiting for file lock on package cache
    Updating crates.io index
    Updating cfg-if v1.0.0 -> v1.0.4
note: pass `--verbose` to see 15 unchanged dependencies behind latest
EXIT=0
== libc@0.2.189 -> 0.2.190
    Blocking waiting for file lock on package cache
    Updating crates.io index
    Updating libc v0.2.189 -> v0.2.190
note: pass `--verbose` to see 15 unchanged dependencies behind latest
EXIT=0
== log@0.4.20 -> 0.4.29
    Updating crates.io index
    Updating log v0.4.20 -> v0.4.29
note: pass `--verbose` to see 14 unchanged dependencies behind latest
EXIT=0
== unicode-ident@1.0.12 -> 1.0.24
    Updating crates.io index
    Updating unicode-ident v1.0.12 -> v1.0.24
note: pass `--verbose` to see 14 unchanged dependencies behind latest
EXIT=0
== proc-macro2@1.0.78 -> 1.0.106
    Updating crates.io index
    Updating proc-macro2 v1.0.78 -> v1.0.106
note: pass `--verbose` to see 14 unchanged dependencies behind latest
EXIT=0
== quote@1.0.35 -> 1.0.45
    Updating crates.io index
    Updating quote v1.0.35 -> v1.0.45
note: pass `--verbose` to see 14 unchanged dependencies behind latest
EXIT=0
== syn@2.0.48 -> 2.0.117
    Updating crates.io index
    Updating syn v2.0.48 -> v2.0.117
note: pass `--verbose` to see 14 unchanged dependencies behind latest
EXIT=0
 bootloader/Cargo.lock | 36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/bootloader/Cargo.lock b/bootloader/Cargo.lock
index ca2f5e69e..38d15ac36 100644
--- a/bootloader/Cargo.lock
+++ b/bootloader/Cargo.lock
@@ -14,9 +14,9 @@ checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
 
 [[package]]
 name = "bitflags"
-version = "2.4.2"
+version = "2.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
+checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
 
 [[package]]
 name = "block-buffer"
@@ -50,9 +50,9 @@ dependencies = [
 
 [[package]]
 name = "cfg-if"
-version = "1.0.0"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
 
 [[package]]
 name = "cpufeatures"
@@ -96,7 +96,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.48",
+ "syn 2.0.117",
 ]
 
 [[package]]
@@ -148,21 +148,21 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.189"
+version = "0.2.190"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
+checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78"
 
 [[package]]
 name = "log"
-version = "0.4.20"
+version = "0.4.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
+checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.78"
+version = "1.0.106"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
 dependencies = [
  "unicode-ident",
 ]
@@ -189,9 +189,9 @@ dependencies = [
 
 [[package]]
 name = "quote"
-version = "1.0.35"
+version = "1.0.45"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
 dependencies = [
  "proc-macro2",
 ]
@@ -247,9 +247,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.48"
+version = "2.0.117"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -349,7 +349,7 @@ checksum = "26a7b1c2c808c3db854a54d5215e3f7e7aaf5dcfbce095598cba6af29895695d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.48",
+ "syn 2.0.117",
 ]
 
 [[package]]
@@ -382,9 +382,9 @@ checksum = "ab14ea9660d240e7865ce9d54ecdbd1cd9fa5802ae6f4512f093c7907e921533"
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.12"
+version = "1.0.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
 
 [[package]]
 name = "version_check"

sums.sh

# For every registry name@version bootloader/Cargo.lock carries in the worktree and origin/main's does not,
# prints the checksum it carries and every other lock of the five (in the worktree) that carries the
# same name@version with its checksum; "new to the tree" when none does.
cd /Users/jan/Dev/jan/toyos-align3 || exit 1
echo "head $(git rev-parse HEAD)"
rows() { awk '
  function out() { if (n != "" && s ~ /registry/) print n "@" v, c }
  /^\[\[package\]\]/ { out(); n = ""; v = ""; s = ""; c = "" }
  /^name = /     { gsub(/"/, "", $3); n = $3 }
  /^version = /  { gsub(/"/, "", $3); v = $3 }
  /^source = /   { s = $3 }
  /^checksum = / { gsub(/"/, "", $3); c = $3 }
  END { out() }'; }
git show origin/main:bootloader/Cargo.lock | rows | sort > "$TMPDIR/old.$$"
rows < bootloader/Cargo.lock | sort > "$TMPDIR/new.$$"
comm -13 "$TMPDIR/old.$$" "$TMPDIR/new.$$" | while read p c; do
  hits=""
  for l in Cargo.lock kernel/Cargo.lock userland/Cargo.lock toyos/Cargo.lock; do
    h=$(rows < $l | awk -v P="$p" '$1 == P { print $2 }')
    [ -n "$h" ] && hits="$hits $l=$( [ "$h" = "$c" ] && echo same || echo DIFFERENT:$h)"
  done
  echo "$p ${c%%????????????????????????????????????????????????????????} ${hits:- new to the tree}"
done
echo "== removed from bootloader/Cargo.lock"
comm -23 "$TMPDIR/old.$$" "$TMPDIR/new.$$" | awk '{ print $1 }'
rm -f "$TMPDIR/old.$$" "$TMPDIR/new.$$"

→ sums.log (exit 0)

head 0613f93f742d141148fb93a6333d3fbd10c26ac0
bitflags@2.11.0 843867be  Cargo.lock=same userland/Cargo.lock=same
cfg-if@1.0.4 9330f8b2  Cargo.lock=same kernel/Cargo.lock=same userland/Cargo.lock=same
libc@0.2.190 ce5d3ddc  Cargo.lock=same kernel/Cargo.lock=same userland/Cargo.lock=same
log@0.4.29 5e5032e2  Cargo.lock=same userland/Cargo.lock=same
proc-macro2@1.0.106 8fd00f0b  Cargo.lock=same userland/Cargo.lock=same
quote@1.0.45 41f26199  Cargo.lock=same userland/Cargo.lock=same
syn@2.0.117 e665b880  Cargo.lock=same userland/Cargo.lock=same
unicode-ident@1.0.24 e6e4313c  Cargo.lock=same userland/Cargo.lock=same
== removed from bootloader/Cargo.lock
bitflags@2.4.2
cfg-if@1.0.0
libc@0.2.189
log@0.4.20
proc-macro2@1.0.78
quote@1.0.35
syn@2.0.48
unicode-ident@1.0.12

pairs.sh

# Usage: pairs.sh <tree>. Prints "<lock> <name>@<range> <version> <range max>" for every
# registry pair of the five main locks below the highest version any of them carries in its range.
cd "$1" || exit 1
for l in Cargo.lock userland/Cargo.lock kernel/Cargo.lock bootloader/Cargo.lock toyos/Cargo.lock; do
  awk -v L="$l" '
    function out() { if (n != "" && s ~ /registry/) print L, n, v }
    /^\[\[package\]\]/ { out(); n = ""; v = ""; s = "" }
    /^name = /    { gsub(/"/, "", $3); n = $3 }
    /^version = / { gsub(/"/, "", $3); v = $3 }
    /^source = /  { s = $3 }
    END { out() }' "$l"
done | awk '{ split($3, a, /[.+-]/); k = (a[1] > 0) ? a[1] : (a[2] > 0 ? "0." a[2] : "0.0." a[3]); print $1, $2 "@" k, $3 }' > "$TMPDIR/keyed.$$"
sort -k2,2 -k3,3V "$TMPDIR/keyed.$$" | awk '{ m[$2] = $3 } END { for (k in m) print k, m[k] }' > "$TMPDIR/max.$$"
awk 'NR == FNR { m[$1] = $2; next } $3 != m[$2] { print $1, $2, $3, m[$2] }' "$TMPDIR/max.$$" "$TMPDIR/keyed.$$" | sort
rm -f "$TMPDIR/keyed.$$" "$TMPDIR/max.$$"

pairs-run.sh

# Runs pairs.sh on the five main locks as committed at origin/main before this branch (0613f93f7)
# and at this head, each written out of git into a scratch tree, and diffs the two.
S=/Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3
cd /Users/jan/Dev/jan/toyos-align3 || exit 1
echo "head $(git rev-parse HEAD)"
for c in 0613f93f7 HEAD; do
  t=$S/locks-$c; mkdir -p $t/userland $t/kernel $t/bootloader $t/toyos
  for l in Cargo.lock userland/Cargo.lock kernel/Cargo.lock bootloader/Cargo.lock toyos/Cargo.lock; do git show $c:$l > $t/$l; done
  sh $S/pairs.sh $t > $S/pairs-$c.txt; echo "pairs $c EXIT=$? rows=$(wc -l < $S/pairs-$c.txt)"
  cat $S/pairs-$c.txt
done
diff $S/pairs-0613f93f7.txt $S/pairs-HEAD.txt; echo "diff EXIT=$?"
rm -r $S/locks-0613f93f7 $S/locks-HEAD

→ pairs-run.log (exit 0)

head f84e57ef830fe76d272ca24f6d369d9db2194177
pairs 0613f93f7 EXIT=0 rows=       8
bootloader/Cargo.lock bitflags@2 2.4.2 2.11.0
bootloader/Cargo.lock cfg-if@1 1.0.0 1.0.4
bootloader/Cargo.lock libc@0.2 0.2.189 0.2.190
bootloader/Cargo.lock log@0.4 0.4.20 0.4.29
bootloader/Cargo.lock proc-macro2@1 1.0.78 1.0.106
bootloader/Cargo.lock quote@1 1.0.35 1.0.45
bootloader/Cargo.lock syn@2 2.0.48 2.0.117
bootloader/Cargo.lock unicode-ident@1 1.0.12 1.0.24
pairs HEAD EXIT=0 rows=       0
1,8d0
< bootloader/Cargo.lock bitflags@2 2.4.2 2.11.0
< bootloader/Cargo.lock cfg-if@1 1.0.0 1.0.4
< bootloader/Cargo.lock libc@0.2 0.2.189 0.2.190
< bootloader/Cargo.lock log@0.4 0.4.20 0.4.29
< bootloader/Cargo.lock proc-macro2@1 1.0.78 1.0.106
< bootloader/Cargo.lock quote@1 1.0.35 1.0.45
< bootloader/Cargo.lock syn@2 2.0.48 2.0.117
< bootloader/Cargo.lock unicode-ident@1 1.0.12 1.0.24
diff EXIT=1

reach.sh

# For each crate the alignment moves, what reaches it in the loader's graph on each UEFI triple,
# normal and build edges (cargo tree -i); and for libc, every edge on any target.
cd /Users/jan/Dev/jan/toyos-align3/bootloader || exit 1
echo "head $(git rev-parse HEAD)"
cargo --version
for t in x86_64-unknown-uefi aarch64-unknown-uefi; do
  for c in bitflags@2.11.0 cfg-if@1.0.4 libc@0.2.190 log@0.4.29 unicode-ident@1.0.24 proc-macro2@1.0.106 quote@1.0.45 syn@2.0.117; do
    echo "== $t $c"
    cargo tree --locked --offline --target $t -e normal,build -i $c 2>&1; echo "EXIT=$?"
  done
done
echo "== all targets libc@0.2.190, every edge kind"
cargo tree --locked --offline --target all -e all -i libc@0.2.190 2>&1; echo "EXIT=$?"
echo "== libc@0.2.190's own dependencies in the lock"
awk '/^\[\[package\]\]/ { p = 0 } /^name = "libc"$/ { p = 1 } p' Cargo.lock

→ reach.log (exit 0)

head f84e57ef830fe76d272ca24f6d369d9db2194177
cargo 1.98.1 (797e8a9bc 2026-08-05)
== x86_64-unknown-uefi bitflags@2.11.0
bitflags v2.11.0
├── uefi v0.26.0
│   ├── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
│   └── uefi-services v0.23.0
│       └── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
└── uefi-raw v0.5.0
    └── uefi v0.26.0 (*)
EXIT=0
== x86_64-unknown-uefi cfg-if@1.0.4
cfg-if v1.0.4
├── curve25519-dalek v4.1.3
│   └── ed25519-dalek v2.2.0
│       └── toyos-update v0.1.0 (/Users/jan/Dev/jan/toyos-align3/toyos-update)
│           └── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
├── sha2 v0.10.9
│   ├── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
│   ├── ed25519-dalek v2.2.0 (*)
│   └── toyos-update v0.1.0 (/Users/jan/Dev/jan/toyos-align3/toyos-update) (*)
└── uefi-services v0.23.0
    └── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
EXIT=0
== x86_64-unknown-uefi libc@0.2.190
warning: nothing to print.

To find dependencies that require specific target platforms, try to use option `--target all` first, and then narrow your search scope accordingly.
EXIT=0
== x86_64-unknown-uefi log@0.4.29
log v0.4.29
├── uefi v0.26.0
│   ├── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
│   └── uefi-services v0.23.0
│       └── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
└── uefi-services v0.23.0 (*)
EXIT=0
== x86_64-unknown-uefi unicode-ident@1.0.24
unicode-ident v1.0.24
├── proc-macro2 v1.0.106
│   ├── ptr_meta_derive v0.2.0 (proc-macro)
│   │   └── ptr_meta v0.2.0
│   │       ├── uefi v0.26.0
│   │       │   ├── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
│   │       │   └── uefi-services v0.23.0
│   │       │       └── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
│   │       └── uefi-raw v0.5.0
│   │           └── uefi v0.26.0 (*)
│   ├── quote v1.0.45
│   │   ├── ptr_meta_derive v0.2.0 (proc-macro) (*)
│   │   ├── syn v1.0.109
│   │   │   └── ptr_meta_derive v0.2.0 (proc-macro) (*)
│   │   ├── syn v2.0.117
│   │   │   └── uefi-macros v0.13.0 (proc-macro)
│   │   │       └── uefi v0.26.0 (*)
│   │   └── uefi-macros v0.13.0 (proc-macro) (*)
│   ├── syn v1.0.109 (*)
│   ├── syn v2.0.117 (*)
│   └── uefi-macros v0.13.0 (proc-macro) (*)
├── syn v1.0.109 (*)
└── syn v2.0.117 (*)
EXIT=0
== x86_64-unknown-uefi proc-macro2@1.0.106
proc-macro2 v1.0.106
├── ptr_meta_derive v0.2.0 (proc-macro)
│   └── ptr_meta v0.2.0
│       ├── uefi v0.26.0
│       │   ├── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
│       │   └── uefi-services v0.23.0
│       │       └── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
│       └── uefi-raw v0.5.0
│           └── uefi v0.26.0 (*)
├── quote v1.0.45
│   ├── ptr_meta_derive v0.2.0 (proc-macro) (*)
│   ├── syn v1.0.109
│   │   └── ptr_meta_derive v0.2.0 (proc-macro) (*)
│   ├── syn v2.0.117
│   │   └── uefi-macros v0.13.0 (proc-macro)
│   │       └── uefi v0.26.0 (*)
│   └── uefi-macros v0.13.0 (proc-macro) (*)
├── syn v1.0.109 (*)
├── syn v2.0.117 (*)
└── uefi-macros v0.13.0 (proc-macro) (*)
EXIT=0
== x86_64-unknown-uefi quote@1.0.45
quote v1.0.45
├── ptr_meta_derive v0.2.0 (proc-macro)
│   └── ptr_meta v0.2.0
│       ├── uefi v0.26.0
│       │   ├── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
│       │   └── uefi-services v0.23.0
│       │       └── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
│       └── uefi-raw v0.5.0
│           └── uefi v0.26.0 (*)
├── syn v1.0.109
│   └── ptr_meta_derive v0.2.0 (proc-macro) (*)
├── syn v2.0.117
│   └── uefi-macros v0.13.0 (proc-macro)
│       └── uefi v0.26.0 (*)
└── uefi-macros v0.13.0 (proc-macro) (*)
EXIT=0
== x86_64-unknown-uefi syn@2.0.117
syn v2.0.117
└── uefi-macros v0.13.0 (proc-macro)
    └── uefi v0.26.0
        ├── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
        └── uefi-services v0.23.0
            └── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
EXIT=0
== aarch64-unknown-uefi bitflags@2.11.0
bitflags v2.11.0
├── uefi v0.26.0
│   ├── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
│   └── uefi-services v0.23.0
│       └── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
└── uefi-raw v0.5.0
    └── uefi v0.26.0 (*)
EXIT=0
== aarch64-unknown-uefi cfg-if@1.0.4
cfg-if v1.0.4
├── curve25519-dalek v4.1.3
│   └── ed25519-dalek v2.2.0
│       └── toyos-update v0.1.0 (/Users/jan/Dev/jan/toyos-align3/toyos-update)
│           └── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
├── sha2 v0.10.9
│   ├── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
│   ├── ed25519-dalek v2.2.0 (*)
│   └── toyos-update v0.1.0 (/Users/jan/Dev/jan/toyos-align3/toyos-update) (*)
└── uefi-services v0.23.0
    └── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
EXIT=0
== aarch64-unknown-uefi libc@0.2.190
warning: nothing to print.

To find dependencies that require specific target platforms, try to use option `--target all` first, and then narrow your search scope accordingly.
EXIT=0
== aarch64-unknown-uefi log@0.4.29
log v0.4.29
├── uefi v0.26.0
│   ├── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
│   └── uefi-services v0.23.0
│       └── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
└── uefi-services v0.23.0 (*)
EXIT=0
== aarch64-unknown-uefi unicode-ident@1.0.24
unicode-ident v1.0.24
├── proc-macro2 v1.0.106
│   ├── ptr_meta_derive v0.2.0 (proc-macro)
│   │   └── ptr_meta v0.2.0
│   │       ├── uefi v0.26.0
│   │       │   ├── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
│   │       │   └── uefi-services v0.23.0
│   │       │       └── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
│   │       └── uefi-raw v0.5.0
│   │           └── uefi v0.26.0 (*)
│   ├── quote v1.0.45
│   │   ├── ptr_meta_derive v0.2.0 (proc-macro) (*)
│   │   ├── syn v1.0.109
│   │   │   └── ptr_meta_derive v0.2.0 (proc-macro) (*)
│   │   ├── syn v2.0.117
│   │   │   └── uefi-macros v0.13.0 (proc-macro)
│   │   │       └── uefi v0.26.0 (*)
│   │   └── uefi-macros v0.13.0 (proc-macro) (*)
│   ├── syn v1.0.109 (*)
│   ├── syn v2.0.117 (*)
│   └── uefi-macros v0.13.0 (proc-macro) (*)
├── syn v1.0.109 (*)
└── syn v2.0.117 (*)
EXIT=0
== aarch64-unknown-uefi proc-macro2@1.0.106
proc-macro2 v1.0.106
├── ptr_meta_derive v0.2.0 (proc-macro)
│   └── ptr_meta v0.2.0
│       ├── uefi v0.26.0
│       │   ├── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
│       │   └── uefi-services v0.23.0
│       │       └── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
│       └── uefi-raw v0.5.0
│           └── uefi v0.26.0 (*)
├── quote v1.0.45
│   ├── ptr_meta_derive v0.2.0 (proc-macro) (*)
│   ├── syn v1.0.109
│   │   └── ptr_meta_derive v0.2.0 (proc-macro) (*)
│   ├── syn v2.0.117
│   │   └── uefi-macros v0.13.0 (proc-macro)
│   │       └── uefi v0.26.0 (*)
│   └── uefi-macros v0.13.0 (proc-macro) (*)
├── syn v1.0.109 (*)
├── syn v2.0.117 (*)
└── uefi-macros v0.13.0 (proc-macro) (*)
EXIT=0
== aarch64-unknown-uefi quote@1.0.45
quote v1.0.45
├── ptr_meta_derive v0.2.0 (proc-macro)
│   └── ptr_meta v0.2.0
│       ├── uefi v0.26.0
│       │   ├── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
│       │   └── uefi-services v0.23.0
│       │       └── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
│       └── uefi-raw v0.5.0
│           └── uefi v0.26.0 (*)
├── syn v1.0.109
│   └── ptr_meta_derive v0.2.0 (proc-macro) (*)
├── syn v2.0.117
│   └── uefi-macros v0.13.0 (proc-macro)
│       └── uefi v0.26.0 (*)
└── uefi-macros v0.13.0 (proc-macro) (*)
EXIT=0
== aarch64-unknown-uefi syn@2.0.117
syn v2.0.117
└── uefi-macros v0.13.0 (proc-macro)
    └── uefi v0.26.0
        ├── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
        └── uefi-services v0.23.0
            └── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
EXIT=0
== all targets libc@0.2.190, every edge kind
libc v0.2.190
└── cpufeatures v0.2.17
    └── cpufeatures feature "default"
        ├── curve25519-dalek v4.1.3
        │   └── curve25519-dalek feature "digest"
        │       └── ed25519-dalek v2.2.0
        │           └── toyos-update v0.1.0 (/Users/jan/Dev/jan/toyos-align3/toyos-update)
        │               └── toyos-update feature "default"
        │                   └── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader)
        │                       └── bootloader feature "default" (command-line)
        └── sha2 v0.10.9
            ├── ed25519-dalek v2.2.0 (*)
            └── toyos-update v0.1.0 (/Users/jan/Dev/jan/toyos-align3/toyos-update) (*)
            └── sha2 feature "force-soft"
                └── bootloader v0.1.0 (/Users/jan/Dev/jan/toyos-align3/bootloader) (*)
EXIT=0
== libc@0.2.190's own dependencies in the lock
name = "libc"
version = "0.2.190"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78"

@Japabu

Japabu commented Oct 4, 2026

Copy link
Copy Markdown
Collaborator Author

Evidence (2 of 3): the bytes, with the negative control, and which crates' code moved

Same rules as comment 1. bytes.sh ran at 92f17c716 (the lock and the profile line, before the track commit); analyze.sh ran on the loaders and link maps bytes.sh kept in maps/. map.sh, funcs.sh and compare.sh are called by those two and never ran alone.

How the maps are got without moving a byte. CARGO_TERM_VERBOSE=true makes cargo print each rustc call, and gates.sh (comment 3) shows it is no input to any unit: its plain --build-only builds at 2ad9f8956 hash all 53 artifacts as bytes.sh's verbose head2 did. touch bootloader/src/main.rs makes the loader's last unit rerun so its call is printed. map.sh reruns that call by hand with -Clink-arg=/lldmap:… and its own --out-dir, and every one of the eight reruns links an image cmp-equal to the one the build left (same image EXIT=0 in bytes.log). A rustc-workspace-wrapper, tried first in explore/, changes the loader's -C metadata and so its bytes, and was dropped.

bytes.sh

# Builds both arches four times and hashes every kernel, loader and userland binary after each:
# head1, the head; nostrip, the head with origin/main's bootloader/Cargo.toml (the aligned lock
# alone); base, the head with origin/main's bootloader/Cargo.toml and bootloader/Cargo.lock (the
# whole change reverted: the control); head2, the head again. Each loader build is preceded by a
# touch of bootloader/src/main.rs, so its verbose log shows the loader's final rustc call, which
# map.sh reruns for the loader's link map. Restores both files.
S=/Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3
cd /Users/jan/Dev/jan/toyos-align3 || exit 1
echo "head $(git rev-parse HEAD) origin/main $(git rev-parse origin/main)"
git status --porcelain --ignore-submodules=none
hashes() {
  shasum -a 256 kernel/target/{x86_64-unknown-none,aarch64-unknown-none-softfloat}/toyos/kernel \
    bootloader/target/{x86_64,aarch64}-unknown-uefi/toyos/bootloader.efi \
    $(find userland/target/x86_64-unknown-toyos/toyos userland/target/aarch64-unknown-toyos/toyos -maxdepth 1 -type f -perm +111 ! -name '*.*' | sort)
}
build() {
  touch bootloader/src/main.rs
  CARGO_TERM_VERBOSE=true cargo run -- --build-only > $S/build-$1-x86.log 2>&1; echo "build-$1-x86 EXIT=$?"
  sh $S/map.sh $S/build-$1-x86.log x86_64-unknown-uefi $S/maps/$1-x86
  touch bootloader/src/main.rs
  CARGO_TERM_VERBOSE=true cargo run -- --build-only --arch aarch64 > $S/build-$1-a64.log 2>&1; echo "build-$1-a64 EXIT=$?"
  sh $S/map.sh $S/build-$1-a64.log aarch64-unknown-uefi $S/maps/$1-a64
  hashes > $S/$1.sha; echo "hashes-$1 EXIT=$? lines=$(wc -l < $S/$1.sha)"
}
build head1
git checkout origin/main -- bootloader/Cargo.toml; echo "nostrip EXIT=$?"
git diff --stat HEAD
build nostrip
git checkout origin/main -- bootloader/Cargo.lock; echo "base EXIT=$?"
git diff --stat HEAD
build base
git checkout HEAD -- bootloader/Cargo.toml bootloader/Cargo.lock; echo "restore EXIT=$?"
git status --porcelain --ignore-submodules=none
build head2
for p in "base head1" "base nostrip" "nostrip head1" "head1 head2"; do
  set -- $p; echo "== diff $1.sha $2.sha"; diff $S/$1.sha $S/$2.sha; echo "diff EXIT=$?"
done
echo DONE

→ bytes.log

head 92f17c71608f68193df3e09ef198ba8d08a4f6fa origin/main 0613f93f742d141148fb93a6333d3fbd10c26ac0
build-head1-x86 EXIT=0
rustc EXIT=0
same image EXIT=0
build-head1-a64 EXIT=0
rustc EXIT=0
same image EXIT=0
hashes-head1 EXIT=0 lines=      53
nostrip EXIT=0
 bootloader/Cargo.toml | 1 -
 1 file changed, 1 deletion(-)
build-nostrip-x86 EXIT=0
rustc EXIT=0
same image EXIT=0
build-nostrip-a64 EXIT=0
rustc EXIT=0
same image EXIT=0
hashes-nostrip EXIT=0 lines=      53
base EXIT=0
 bootloader/Cargo.lock | 36 ++++++++++++++++++------------------
 bootloader/Cargo.toml |  1 -
 2 files changed, 18 insertions(+), 19 deletions(-)
build-base-x86 EXIT=0
rustc EXIT=0
same image EXIT=0
build-base-a64 EXIT=0
rustc EXIT=0
same image EXIT=0
hashes-base EXIT=0 lines=      53
restore EXIT=0
build-head2-x86 EXIT=0
rustc EXIT=0
same image EXIT=0
build-head2-a64 EXIT=0
rustc EXIT=0
same image EXIT=0
hashes-head2 EXIT=0 lines=      53
== diff base.sha head1.sha
3,4c3,4
< 212a6288ab9e4e6d98c7fb7f9ba672008a652a1b6bdaa877803d1cce148b8c42  bootloader/target/x86_64-unknown-uefi/toyos/bootloader.efi
< 79be80f86157603123c2b2e4b50b4b8b1f103be57edee2987b61abbe788eebbf  bootloader/target/aarch64-unknown-uefi/toyos/bootloader.efi
---
> 1fde0464513c571d88ab0bb4f638ab4528d543cd54fe5cfbdcb7f2ea3d677ce7  bootloader/target/x86_64-unknown-uefi/toyos/bootloader.efi
> bcd7a5052e12ebd22b7ac57d180545b82858f8e30bcd22432631720e510e3f93  bootloader/target/aarch64-unknown-uefi/toyos/bootloader.efi
diff EXIT=1
== diff base.sha nostrip.sha
3,4c3,4
< 212a6288ab9e4e6d98c7fb7f9ba672008a652a1b6bdaa877803d1cce148b8c42  bootloader/target/x86_64-unknown-uefi/toyos/bootloader.efi
< 79be80f86157603123c2b2e4b50b4b8b1f103be57edee2987b61abbe788eebbf  bootloader/target/aarch64-unknown-uefi/toyos/bootloader.efi
---
> 582a80248c30e462a657f5361ff2c7dd4bb07592b9242bf2ee08139133cdcf6b  bootloader/target/x86_64-unknown-uefi/toyos/bootloader.efi
> fe96637bc83c9afd6999efd8027f6a2020c60ba3f40f354b7d1a39d9e5bf4a7f  bootloader/target/aarch64-unknown-uefi/toyos/bootloader.efi
diff EXIT=1
== diff nostrip.sha head1.sha
3,4c3,4
< 582a80248c30e462a657f5361ff2c7dd4bb07592b9242bf2ee08139133cdcf6b  bootloader/target/x86_64-unknown-uefi/toyos/bootloader.efi
< fe96637bc83c9afd6999efd8027f6a2020c60ba3f40f354b7d1a39d9e5bf4a7f  bootloader/target/aarch64-unknown-uefi/toyos/bootloader.efi
---
> 1fde0464513c571d88ab0bb4f638ab4528d543cd54fe5cfbdcb7f2ea3d677ce7  bootloader/target/x86_64-unknown-uefi/toyos/bootloader.efi
> bcd7a5052e12ebd22b7ac57d180545b82858f8e30bcd22432631720e510e3f93  bootloader/target/aarch64-unknown-uefi/toyos/bootloader.efi
diff EXIT=1
== diff head1.sha head2.sha
diff EXIT=0
DONE

map.sh

# Usage: map.sh <build log> <triple> <out dir>. Reruns, by hand, the loader's final rustc call that
# <build log> (a CARGO_TERM_VERBOSE=true build) shows for <triple>, with --out-dir <out dir> and one
# more argument, -Clink-arg=/lldmap:<out dir>/bootloader.map, under the toolchain and the two
# TOYOS_IMAGE_* values the build gave it; then prints whether the image it links is byte-equal
# to the one the build left in the loader's target directory.
cd /Users/jan/Dev/jan/toyos-align3/bootloader || exit 1
mkdir -p "$3" || exit 1
cmd=$(grep "Running \`rustc --crate-name bootloader .*--target $2 " "$1" | sed -e 's/^ *Running `//' -e 's/`$//')
[ -n "$cmd" ] || { echo "no loader rustc call for $2 in $1"; exit 1; }
x=$(printf '%s\n' "$cmd" | sed -E 's/.*-C extra-filename=(-[0-9a-f]+).*/\1/')
d=target/$2/toyos/deps/bootloader$x.d
export RUSTUP_TOOLCHAIN=/Users/jan/Dev/jan/toyos/rust/build/sysroots/$(awk '$1 == "x86_64-unknown-toyos" { print $2 }' target/.deps-stamp)
export TOYOS_IMAGE_KEY=$(sed -n 's/^# env-dep:TOYOS_IMAGE_KEY=//p' $d)
export TOYOS_IMAGE_FLOOR=$(sed -n 's/^# env-dep:TOYOS_IMAGE_FLOOR=//p' $d)
cmd=$(printf '%s\n' "$cmd" | sed "s#--out-dir [^ ]*#--out-dir $3#")
eval "$cmd -Clink-arg=/lldmap:$3/bootloader.map" > "$3/rustc.log" 2>&1; echo "rustc EXIT=$?"
cp "$3/bootloader$x.efi" "$3/bootloader.efi"
cmp "$3/bootloader.efi" target/$2/toyos/bootloader.efi; echo "same image EXIT=$?"

funcs.sh

# Usage: funcs.sh <efi> <lld map> <out>. Reads the loader's lld-link map (/lldmap) and its image.
# <out>.sec: one line per input section the map places: "<output section> <crate> <size>", <crate>
#   being the rlib the section came from, or the loader's own objects: the crate that compiled it.
# <out>.fn: one line per non-empty .text input section: "<crate>\t<name>\t<size>\t<rva>\t<body>",
#   <name> every distinct symbol at the section's start, each with LLVM's .llvm.<N> suffix dropped,
#   sorted and joined by " = " (identical code folding puts several there); <body> its instructions
#   from llvm-objdump with comments dropped, a branch target's <label> written <S>, and every hex
#   number and #immediate written X, so that a body moved to another address reads the same.
B=/Users/jan/Dev/jan/toyos/rust/build/llvm/1425e623e612b348/bin
base=$($B/llvm-readobj --file-headers "$1" | awk '$1 == "ImageBase:" { print $2 }')
awk '
  function hex(x,  i, v) { x = tolower(x); sub(/^0x/, "", x); v = 0
    for (i = 1; i <= length(x); i++) v = v * 16 + index("0123456789abcdef", substr(x, i, 1)) - 1; return v }
  function crate(p) {
    if (p ~ /\.rlib\(/) { sub(/\.rlib\(.*/, "", p); sub(/.*\//, "", p); sub(/^lib/, "", p); sub(/-[0-9a-f]+$/, "", p) }
    else { sub(/:\(.*/, "", p); sub(/.*\//, "", p); sub(/-.*/, "", p) }
    return p
  }
  NR == 1 { next }
  { match($0, /^[0-9a-f]+ [0-9a-f]+ +[0-9]+ +/); c = RLENGTH + 1 }
  c == 25 { out = $4; next }
  c == 33 { k = crate($4); print out, k, hex($2) > SEC
            want = (out == ".text" && hex($2) > 0)
            if (want) { n++; st[n] = hex($1); sz[n] = hex($2); cr[n] = k }
            next }
  c == 41 && want && hex($1) == st[n] { s = substr($0, 41); sub(/ \(\.llvm\.[0-9]+\)$/, "", s); names[n, s] = 1; next }
  END {
    for (x in names) { split(x, p, SUBSEP); list[p[1]] = list[p[1]] "\n" p[2] }
    for (i = 1; i <= n; i++) {
      m = split(substr(list[i], 2), a, "\n")
      for (j = 2; j <= m; j++) { v = a[j]; for (l = j - 1; l >= 1 && a[l] > v; l--) a[l + 1] = a[l]; a[l + 1] = v }
      s = ""; for (j = 1; j <= m; j++) s = s (j > 1 ? " = " : "") a[j]
      printf "%d\t%d\t%s\t%s\n", st[i], sz[i], cr[i], s > RANGES
    }
  }
' SEC="$3.sec" RANGES="$3.ranges" "$2"
$B/llvm-objdump -d --no-show-raw-insn -j .text "$1" \
| sed -E \
    -e 's/[[:space:]]+(# |\/\/ ).*$//' \
    -e 's/^ *([0-9a-f]+):/\1:/' \
    -e '/^[0-9a-f]+:/!d' \
    -e 's/^([0-9a-f]+):(.*)$/\1 \2/' \
    -e 's/ <[^>]*>$/ <S>/' \
    -e 's/ 0x[0-9a-f]+/ X/g; s/([^0-9a-z_])0x[0-9a-f]+/\1X/g' \
    -e 's/#-?[0-9]+/#X/g' \
    -e 's/-X/X/g' \
    -e 's/[[:space:]]+/ /g' \
| awk -F '\t' -v BASE="$base" '
  function hex(x,  i, v) { x = tolower(x); sub(/^0x/, "", x); v = 0
    for (i = 1; i <= length(x); i++) v = v * 16 + index("0123456789abcdef", substr(x, i, 1)) - 1; return v }
  NR == FNR { n++; st[n] = $1 + 0; en[n] = $1 + $2; cr[n] = $3; nm[n] = $4; next }
  FNR == 1 { b = hex(BASE); i = 1 }
  { a = index($0, " "); r = hex(substr($0, 1, a - 1)) - b; ins = substr($0, a + 1)
    while (i <= n && r >= en[i]) i++
    if (i <= n && r >= st[i]) body[i] = body[i] ";" ins }
  END { for (j = 1; j <= n; j++) printf "%s\t%s\t%d\t%d\t%s\n", cr[j], nm[j], en[j] - st[j], st[j], body[j] }
' "$3.ranges" - > "$3.fn"

compare.sh

# Usage: compare.sh <A> <B>, two funcs.sh outputs. Prints, per crate that compiled code into the
# loader: .text functions in A and in B; of those, the pairs with the same name and body at the same
# address, the same name and body at another address, and the functions whose name or body is in
# one image only (count and bytes); then its .text and .rdata bytes in A and in B. A crate that is
# in both and moved nothing prints "same".
awk -F '\t' '
  FNR == 1 { f++ }
  { k = $1 "\t" $2 "\t" $5; c[$1]; n[f, $1]++
    if (!((f, k) in cnt)) { keys[k] }
    cnt[f, k]++; rva[f, k, cnt[f, k]] = $4; size[k] = $3 }
  END {
    for (k in keys) {
      split(k, p, "\t"); a = cnt[1, k] + 0; b = cnt[2, k] + 0; m = a < b ? a : b
      for (i = 1; i <= m; i++) if (rva[1, k, i] == rva[2, k, i]) still[p[1]]++; else moved[p[1]]++
      if (a > m) { onlyA[p[1]] += a - m; bytesA[p[1]] += (a - m) * size[k] }
      if (b > m) { onlyB[p[1]] += b - m; bytesB[p[1]] += (b - m) * size[k] }
    }
    printf "%-18s %5s %5s %6s %6s %12s %12s\n", "crate", "fnA", "fnB", "still", "moved", "onlyA n/B", "onlyB n/B"
    for (x in c) printf "%-18s %5d %5d %6d %6d %5d/%-6d %5d/%-6d\n", x, n[1, x], n[2, x], still[x], moved[x], onlyA[x], bytesA[x], onlyB[x], bytesB[x] | "sort"
  }' "$1.fn" "$2.fn"
echo "-- bytes per crate and output section, A then B (rows where they differ)"
awk '{ s[FILENAME == ARGV[1] ? 1 : 2, $1 " " $2] += $3; k[$1 " " $2] }
  END { for (x in k) if (s[1, x] != s[2, x]) printf "%-28s %8d %8d %+7d\n", x, s[1, x], s[2, x], s[2, x] - s[1, x] }' "$1.sec" "$2.sec" | sort
echo "-- totals per output section, A then B"
awk '{ s[FILENAME == ARGV[1] ? 1 : 2, $1] += $3; k[$1] }
  END { for (x in k) printf "%-10s %8d %8d %+7d\n", x, s[1, x], s[2, x], s[2, x] - s[1, x] }' "$1.sec" "$2.sec" | sort

analyze.sh

# Runs funcs.sh on each loader bytes.sh linked with a map, then, per arch, for base -> nostrip (the
# lock alignment), nostrip -> head1 (the strip line) and base -> head1 (the whole change): file sizes,
# how many bytes differ (cmp -l), and compare.sh. head1 -> head2 checks the measurement is stable.
S=/Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3
cd $S/maps || exit 1
for v in head1 nostrip base head2; do for a in x86 a64; do
  sh $S/funcs.sh $v-$a/bootloader.efi $v-$a/bootloader.map $v-$a/f; echo "funcs $v-$a EXIT=$? fns=$(wc -l < $v-$a/f.fn)"
done; done
for a in x86 a64; do
  for p in "base nostrip" "nostrip head1" "base head1" "head1 head2"; do
    set -- $p
    echo "==== $a: $1 -> $2"
    echo "file bytes $(stat -f %z $1-$a/bootloader.efi) -> $(stat -f %z $2-$a/bootloader.efi), differing $(cmp -l $1-$a/bootloader.efi $2-$a/bootloader.efi | wc -l)"
    sh $S/compare.sh $1-$a/f $2-$a/f
  done
done

→ analyze.log (exit 0)

funcs head1-x86 EXIT=0 fns=     530
funcs head1-a64 EXIT=0 fns=     514
funcs nostrip-x86 EXIT=0 fns=     530
funcs nostrip-a64 EXIT=0 fns=     514
funcs base-x86 EXIT=0 fns=     530
funcs base-a64 EXIT=0 fns=     514
funcs head2-x86 EXIT=0 fns=     530
funcs head2-a64 EXIT=0 fns=     514
==== x86: base -> nostrip
file bytes 285184 -> 285184, differing   262499
crate                fnA   fnB  still  moved    onlyA n/B    onlyB n/B
alloc                 15    15      0     15     0/0          0/0     
bootloader           138   138      2    136     0/0          0/0     
compiler_builtins     12    12      0     12     0/0          0/0     
core                  86    86      0     86     0/0          0/0     
curve25519_dalek      31    31      0     31     0/0          0/0     
ed25519                2     2      0      2     0/0          0/0     
ed25519_dalek          6     6      0      6     0/0          0/0     
log                    4     4      0      2     2/313        2/138   
sha2                   2     2      0      2     0/0          0/0     
toyos_abi              1     1      0      1     0/0          0/0     
toyos_acpi             2     2      0      2     0/0          0/0     
toyos_blackbox        11    11      0     11     0/0          0/0     
toyos_bootmap         20    20      0     20     0/0          0/0     
toyos_elf             26    26      0     25     1/13         1/13    
toyos_gpt             20    20      0     20     0/0          0/0     
toyos_rootimage        1     1      0      1     0/0          0/0     
toyos_tco              4     4      0      4     0/0          0/0     
toyos_tsc              1     1      1      0     0/0          0/0     
toyos_update          38    38      0     38     0/0          0/0     
toyos_wallclock        4     4      0      4     0/0          0/0     
uefi                  83    83      0     83     0/0          0/0     
uefi_raw               8     8      0      8     0/0          0/0     
uefi_services         11    11      3      7     1/420        1/484   
uguid                  4     4      0      4     0/0          0/0     
-- bytes per crate and output section, A then B (rows where they differ)
.rdata log                        375      170    -205
.rdata uefi_services              719      600    -119
.text log                         360      185    -175
.text uefi_services              1106     1170     +64
-- totals per output section, A then B
.data           124      124      +0
.eh_frame        64       64      +0
.pdata           24       24      +0
.rdata        68370    68046    -324
.text        207352   207241    -111
==== x86: nostrip -> head1
file bytes 285184 -> 285184, differing   219421
crate                fnA   fnB  still  moved    onlyA n/B    onlyB n/B
alloc                 15    15      7      8     0/0          0/0     
bootloader           138   138      3    135     0/0          0/0     
compiler_builtins     12    12      7      5     0/0          0/0     
core                  86    86     21     65     0/0          0/0     
curve25519_dalek      31    31     14     17     0/0          0/0     
ed25519                2     2      0      2     0/0          0/0     
ed25519_dalek          6     6      0      6     0/0          0/0     
log                    4     4      0      4     0/0          0/0     
sha2                   2     2      0      2     0/0          0/0     
toyos_abi              1     1      1      0     0/0          0/0     
toyos_acpi             2     2      1      1     0/0          0/0     
toyos_blackbox        11    11      8      3     0/0          0/0     
toyos_bootmap         20    20     17      3     0/0          0/0     
toyos_elf             26    26      1     25     0/0          0/0     
toyos_gpt             20    20     20      0     0/0          0/0     
toyos_rootimage        1     1      1      0     0/0          0/0     
toyos_tco              4     4      4      0     0/0          0/0     
toyos_tsc              1     1      1      0     0/0          0/0     
toyos_update          38    38     36      2     0/0          0/0     
toyos_wallclock        4     4      4      0     0/0          0/0     
uefi                  83    83      8     75     0/0          0/0     
uefi_raw               8     8      2      6     0/0          0/0     
uefi_services         11    11     11      0     0/0          0/0     
uguid                  4     4      0      4     0/0          0/0     
-- bytes per crate and output section, A then B (rows where they differ)
-- totals per output section, A then B
.data           124      124      +0
.eh_frame        64       64      +0
.pdata           24       24      +0
.rdata        68046    68046      +0
.text        207241   207241      +0
==== x86: base -> head1
file bytes 285184 -> 285184, differing   263771
crate                fnA   fnB  still  moved    onlyA n/B    onlyB n/B
alloc                 15    15      0     15     0/0          0/0     
bootloader           138   138      2    136     0/0          0/0     
compiler_builtins     12    12      0     12     0/0          0/0     
core                  86    86      0     86     0/0          0/0     
curve25519_dalek      31    31      0     31     0/0          0/0     
ed25519                2     2      0      2     0/0          0/0     
ed25519_dalek          6     6      0      6     0/0          0/0     
log                    4     4      0      2     2/313        2/138   
sha2                   2     2      0      2     0/0          0/0     
toyos_abi              1     1      0      1     0/0          0/0     
toyos_acpi             2     2      0      2     0/0          0/0     
toyos_blackbox        11    11      0     11     0/0          0/0     
toyos_bootmap         20    20      0     20     0/0          0/0     
toyos_elf             26    26      0     25     1/13         1/13    
toyos_gpt             20    20      0     20     0/0          0/0     
toyos_rootimage        1     1      0      1     0/0          0/0     
toyos_tco              4     4      0      4     0/0          0/0     
toyos_tsc              1     1      1      0     0/0          0/0     
toyos_update          38    38      0     38     0/0          0/0     
toyos_wallclock        4     4      0      4     0/0          0/0     
uefi                  83    83      0     83     0/0          0/0     
uefi_raw               8     8      0      8     0/0          0/0     
uefi_services         11    11      3      7     1/420        1/484   
uguid                  4     4      0      4     0/0          0/0     
-- bytes per crate and output section, A then B (rows where they differ)
.rdata log                        375      170    -205
.rdata uefi_services              719      600    -119
.text log                         360      185    -175
.text uefi_services              1106     1170     +64
-- totals per output section, A then B
.data           124      124      +0
.eh_frame        64       64      +0
.pdata           24       24      +0
.rdata        68370    68046    -324
.text        207352   207241    -111
==== x86: head1 -> head2
file bytes 285184 -> 285184, differing        0
crate                fnA   fnB  still  moved    onlyA n/B    onlyB n/B
alloc                 15    15     15      0     0/0          0/0     
bootloader           138   138    138      0     0/0          0/0     
compiler_builtins     12    12     12      0     0/0          0/0     
core                  86    86     86      0     0/0          0/0     
curve25519_dalek      31    31     31      0     0/0          0/0     
ed25519                2     2      2      0     0/0          0/0     
ed25519_dalek          6     6      6      0     0/0          0/0     
log                    4     4      4      0     0/0          0/0     
sha2                   2     2      2      0     0/0          0/0     
toyos_abi              1     1      1      0     0/0          0/0     
toyos_acpi             2     2      2      0     0/0          0/0     
toyos_blackbox        11    11     11      0     0/0          0/0     
toyos_bootmap         20    20     20      0     0/0          0/0     
toyos_elf             26    26     26      0     0/0          0/0     
toyos_gpt             20    20     20      0     0/0          0/0     
toyos_rootimage        1     1      1      0     0/0          0/0     
toyos_tco              4     4      4      0     0/0          0/0     
toyos_tsc              1     1      1      0     0/0          0/0     
toyos_update          38    38     38      0     0/0          0/0     
toyos_wallclock        4     4      4      0     0/0          0/0     
uefi                  83    83     83      0     0/0          0/0     
uefi_raw               8     8      8      0     0/0          0/0     
uefi_services         11    11     11      0     0/0          0/0     
uguid                  4     4      4      0     0/0          0/0     
-- bytes per crate and output section, A then B (rows where they differ)
-- totals per output section, A then B
.data           124      124      +0
.eh_frame        64       64      +0
.pdata           24       24      +0
.rdata        68046    68046      +0
.text        207241   207241      +0
==== a64: base -> nostrip
cmp: EOF on nostrip-a64/bootloader.efi
file bytes 245248 -> 244736, differing   222057
crate                fnA   fnB  still  moved    onlyA n/B    onlyB n/B
alloc                 15    15      0     15     0/0          0/0     
bootloader           130   130      2    128     0/0          0/0     
compiler_builtins     10    10      0     10     0/0          0/0     
core                  86    86      0     86     0/0          0/0     
curve25519_dalek      31    31      0     31     0/0          0/0     
ed25519                2     2      0      2     0/0          0/0     
ed25519_dalek          6     6      0      6     0/0          0/0     
log                    4     4      0      2     2/304        2/200   
sha2                   2     2      0      2     0/0          0/0     
toyos_abi              1     1      0      1     0/0          0/0     
toyos_acpi             2     2      0      2     0/0          0/0     
toyos_blackbox        11    11      0     11     0/0          0/0     
toyos_bootmap         20    20      0     20     0/0          0/0     
toyos_elf             25    25      0     24     1/24         1/24    
toyos_gpt             20    20      0     20     0/0          0/0     
toyos_rootimage        1     1      0      1     0/0          0/0     
toyos_update          38    38      0     38     0/0          0/0     
toyos_wallclock        4     4      0      4     0/0          0/0     
uefi                  83    83      0     83     0/0          0/0     
uefi_raw               8     8      0      8     0/0          0/0     
uefi_services         11    11      0     10     1/300        1/352   
uguid                  4     4      0      4     0/0          0/0     
-- bytes per crate and output section, A then B (rows where they differ)
.rdata log                        375      170    -205
.rdata uefi_services              719      600    -119
.text log                         368      264    -104
.text uefi_services              1060     1112     +52
-- totals per output section, A then B
.data           124      124      +0
.pdata           16       16      +0
.rdata        66430    66106    -324
.text        173412   173360     -52
==== a64: nostrip -> head1
file bytes 244736 -> 244736, differing   121694
crate                fnA   fnB  still  moved    onlyA n/B    onlyB n/B
alloc                 15    15     15      0     0/0          0/0     
bootloader           130   130      8    122     0/0          0/0     
compiler_builtins     10    10     10      0     0/0          0/0     
core                  86    86     86      0     0/0          0/0     
curve25519_dalek      31    31     31      0     0/0          0/0     
ed25519                2     2      2      0     0/0          0/0     
ed25519_dalek          6     6      6      0     0/0          0/0     
log                    4     4      4      0     0/0          0/0     
sha2                   2     2      2      0     0/0          0/0     
toyos_abi              1     1      1      0     0/0          0/0     
toyos_acpi             2     2      2      0     0/0          0/0     
toyos_blackbox        11    11     11      0     0/0          0/0     
toyos_bootmap         20    20     20      0     0/0          0/0     
toyos_elf             25    25     25      0     0/0          0/0     
toyos_gpt             20    20     20      0     0/0          0/0     
toyos_rootimage        1     1      1      0     0/0          0/0     
toyos_update          38    38     38      0     0/0          0/0     
toyos_wallclock        4     4      4      0     0/0          0/0     
uefi                  83    83     76      7     0/0          0/0     
uefi_raw               8     8      8      0     0/0          0/0     
uefi_services         11    11      7      4     0/0          0/0     
uguid                  4     4      4      0     0/0          0/0     
-- bytes per crate and output section, A then B (rows where they differ)
-- totals per output section, A then B
.data           124      124      +0
.pdata           16       16      +0
.rdata        66106    66106      +0
.text        173360   173360      +0
==== a64: base -> head1
cmp: EOF on head1-a64/bootloader.efi
file bytes 245248 -> 244736, differing   222254
crate                fnA   fnB  still  moved    onlyA n/B    onlyB n/B
alloc                 15    15      0     15     0/0          0/0     
bootloader           130   130      2    128     0/0          0/0     
compiler_builtins     10    10      0     10     0/0          0/0     
core                  86    86      0     86     0/0          0/0     
curve25519_dalek      31    31      0     31     0/0          0/0     
ed25519                2     2      0      2     0/0          0/0     
ed25519_dalek          6     6      0      6     0/0          0/0     
log                    4     4      0      2     2/304        2/200   
sha2                   2     2      0      2     0/0          0/0     
toyos_abi              1     1      0      1     0/0          0/0     
toyos_acpi             2     2      0      2     0/0          0/0     
toyos_blackbox        11    11      0     11     0/0          0/0     
toyos_bootmap         20    20      0     20     0/0          0/0     
toyos_elf             25    25      0     24     1/24         1/24    
toyos_gpt             20    20      0     20     0/0          0/0     
toyos_rootimage        1     1      0      1     0/0          0/0     
toyos_update          38    38      0     38     0/0          0/0     
toyos_wallclock        4     4      0      4     0/0          0/0     
uefi                  83    83      0     83     0/0          0/0     
uefi_raw               8     8      0      8     0/0          0/0     
uefi_services         11    11      3      7     1/300        1/352   
uguid                  4     4      0      4     0/0          0/0     
-- bytes per crate and output section, A then B (rows where they differ)
.rdata log                        375      170    -205
.rdata uefi_services              719      600    -119
.text log                         368      264    -104
.text uefi_services              1060     1112     +52
-- totals per output section, A then B
.data           124      124      +0
.pdata           16       16      +0
.rdata        66430    66106    -324
.text        173412   173360     -52
==== a64: head1 -> head2
file bytes 244736 -> 244736, differing        0
crate                fnA   fnB  still  moved    onlyA n/B    onlyB n/B
alloc                 15    15     15      0     0/0          0/0     
bootloader           130   130    130      0     0/0          0/0     
compiler_builtins     10    10     10      0     0/0          0/0     
core                  86    86     86      0     0/0          0/0     
curve25519_dalek      31    31     31      0     0/0          0/0     
ed25519                2     2      2      0     0/0          0/0     
ed25519_dalek          6     6      6      0     0/0          0/0     
log                    4     4      4      0     0/0          0/0     
sha2                   2     2      2      0     0/0          0/0     
toyos_abi              1     1      1      0     0/0          0/0     
toyos_acpi             2     2      2      0     0/0          0/0     
toyos_blackbox        11    11     11      0     0/0          0/0     
toyos_bootmap         20    20     20      0     0/0          0/0     
toyos_elf             25    25     25      0     0/0          0/0     
toyos_gpt             20    20     20      0     0/0          0/0     
toyos_rootimage        1     1      1      0     0/0          0/0     
toyos_update          38    38     38      0     0/0          0/0     
toyos_wallclock        4     4      4      0     0/0          0/0     
uefi                  83    83     83      0     0/0          0/0     
uefi_raw               8     8      8      0     0/0          0/0     
uefi_services         11    11     11      0     0/0          0/0     
uguid                  4     4      4      0     0/0          0/0     
-- bytes per crate and output section, A then B (rows where they differ)
-- totals per output section, A then B
.data           124      124      +0
.pdata           16       16      +0
.rdata        66106    66106      +0
.text        173360   173360      +0

@Japabu

Japabu commented Oct 4, 2026

Copy link
Copy Markdown
Collaborator Author

Evidence (3 of 3): the gates, the T14 staging, and the staged images' loader

Same rules as comment 1. gates.sh ran at 2ad9f8956 (the track commit); gates2.sh, stage.sh, staged.sh and staged-control.sh at f84e57ef8, the merge of origin/main (b75ca2b4e: #734, #735) that is the pushed head. stage.sh exits 0 because it reports the staging run's exit rather than returning it; the staging run itself exits 2, which is how the harness says staged, not judged. Its log lists the 28 images, as metal/request.txt does. staged.sh's whole-loader-at prints the offset of the 64-byte run, so the loader itself starts 1024 bytes before it, at 1,603,072.

gates2.sh's hash diff against head2.sha is expected to show the two kernels, which #734 changes, and it shows nothing else changed: the three added lines are guest-suite binaries (kernelprobe, test-runner) that gates.sh's cargo test left in the target and --build-only does not build.

scripts.sha

87d6bd8c448e3e2aa891e152190fb60004fb287017fd0b68d3441fb94831d683  align.sh
013dba0ea7d8006f33fd36d9219e36fa45679010305359bfd6924d2d1fde2f05  sums.sh
c773c8e32dd5793c04e8dc99bbdb8f9e2502bbe845428e6d3299c3aef7cd0764  pairs.sh
022166b1fcfc0ae6b92a29ea2cfdc0a7df54bc4eda563931b75e3cdf4152fafe  pairs-run.sh
7db521066f3ebc8886aaa525dbbda63501165ddf8bb50365ff941901d75e054e  reach.sh
63aef87e30fad3e9b84f90e90cb046ccb66a540ba660f007fa549a8902662e17  bytes.sh
3ce85c04280e2a39726bdc950b0ea0d31966290c0530f530adf7037dc9bd1d9c  map.sh
8281a23efb027fd9e5f5fee9264e808f25b5d75299daf965a38911f938c9bc7b  funcs.sh
95886afefcc51fc92bef99a4141f85152a1f63b12d7fc39e794dc76749d0afcc  compare.sh
1d4458483f419329e661d84064f6ce38807c1a6d0422c2a69f9b4289dd8cb96b  analyze.sh
498ddcb5294d7992559acf480e518152357ca421fb0eebc8baf7196e08d78e4f  gates.sh
07d23e69f33d6af35a68c82bfe874cd9f98d597fdcf4402fb8ae546c95da8df4  gates2.sh
cd89d53c1667aa05d2e82fbc93c6bc5af99d70f69a1068ea3df08059531c9e79  stage.sh
f106aca823643792b6ddd3da7d07583114763a4af877269f39e3f79569f04602  staged.sh
5e7b986a374f5fe7ebc1793228ca50733b7f4fb390eb86681d2f5446d6df0fdc  staged-control.sh

gates.sh

# The four gates at this head, in sequence, in this worktree; then every kernel, loader and
# userland binary's hash after the two --build-only builds, compared with bytes.sh's head2.sha.
R=/Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3
cd /Users/jan/Dev/jan/toyos-align3 || exit 1
echo "head $(git rev-parse HEAD)"
git status --porcelain --ignore-submodules=none
cargo run -- --build-only > $R/gate-build-x86.log 2>&1; echo "build-only x86_64 EXIT=$?"
cargo run -- --build-only --arch aarch64 > $R/gate-build-a64.log 2>&1; echo "build-only aarch64 EXIT=$?"
shasum -a 256 kernel/target/{x86_64-unknown-none,aarch64-unknown-none-softfloat}/toyos/kernel \
  bootloader/target/{x86_64,aarch64}-unknown-uefi/toyos/bootloader.efi \
  $(find userland/target/x86_64-unknown-toyos/toyos userland/target/aarch64-unknown-toyos/toyos -maxdepth 1 -type f -perm +111 ! -name '*.*' | sort) > $R/gate.sha
echo "hashes EXIT=$? lines=$(wc -l < $R/gate.sha)"
diff $R/head2.sha $R/gate.sha; echo "diff head2.sha gate.sha EXIT=$?"
cargo run -- --ci host > $R/gate-ci-host.log 2>&1; echo "ci host EXIT=$?"
cargo test > $R/gate-guest.log 2>&1; echo "guest EXIT=$?"
git status --porcelain --ignore-submodules=none
echo GATESDONE

→ gates.log

head 2ad9f8956f7fe381391d6cba89d49fa030d82302
build-only x86_64 EXIT=0
build-only aarch64 EXIT=0
hashes EXIT=0 lines=      53
diff head2.sha gate.sha EXIT=0
ci host EXIT=0
guest EXIT=0
GATESDONE

gates2.sh

# The four gates at the merge of origin/main, in sequence, in this worktree; then every kernel,
# loader and userland binary's hash after the two --build-only builds, compared with bytes.sh's
# head2.sha: the merge brings #734's kernel change, so the kernels may differ and nothing else may.
R=/Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3
cd /Users/jan/Dev/jan/toyos-align3 || exit 1
echo "head $(git rev-parse HEAD)"
git status --porcelain --ignore-submodules=none
cargo run -- --build-only > $R/gate2-build-x86.log 2>&1; echo "build-only x86_64 EXIT=$?"
cargo run -- --build-only --arch aarch64 > $R/gate2-build-a64.log 2>&1; echo "build-only aarch64 EXIT=$?"
shasum -a 256 kernel/target/{x86_64-unknown-none,aarch64-unknown-none-softfloat}/toyos/kernel \
  bootloader/target/{x86_64,aarch64}-unknown-uefi/toyos/bootloader.efi \
  $(find userland/target/x86_64-unknown-toyos/toyos userland/target/aarch64-unknown-toyos/toyos -maxdepth 1 -type f -perm +111 ! -name '*.*' | sort) > $R/gate2.sha
echo "hashes EXIT=$? lines=$(wc -l < $R/gate2.sha)"
diff $R/head2.sha $R/gate2.sha; echo "diff head2.sha gate2.sha EXIT=$?"
cargo run -- --ci host > $R/gate2-ci-host.log 2>&1; echo "ci host EXIT=$?"
cargo test > $R/gate2-guest.log 2>&1; echo "guest EXIT=$?"
git status --porcelain --ignore-submodules=none
echo GATESDONE

→ gates2.log

head f84e57ef830fe76d272ca24f6d369d9db2194177
build-only x86_64 EXIT=0
build-only aarch64 EXIT=0
hashes EXIT=0 lines=      56
1,2c1,2
< a4543dc0ea1b0471fd5ac8846d856153312e41f2ddfbdc6ae7d877ddae005181  kernel/target/x86_64-unknown-none/toyos/kernel
< a9d7f38ed0f41f6904c122895802c7ccb9fea6ec0506329a992bd0a4f7cbd636  kernel/target/aarch64-unknown-none-softfloat/toyos/kernel
---
> 6d0d248ba898d13e6b14aa6662f63280fb2f4eb4e72d01f811e8a8f2ec160217  kernel/target/x86_64-unknown-none/toyos/kernel
> 0620d6eb056c8bab197d60d31a95a2ae4b76d9fd3f75356082512c89ea3f5428  kernel/target/aarch64-unknown-none-softfloat/toyos/kernel
12a13
> b80f6b5bb3aa1c422f8fcdc126e6d012934f925d6d803cc6bfe55833ff0daa48  userland/target/aarch64-unknown-toyos/toyos/kernelprobe
24a26
> 0a17eeaa72df2032bc36746512224299b2c2c07036fa75558c114b43c0a6fc85  userland/target/aarch64-unknown-toyos/toyos/test-runner
50a53
> 1174e09587746fa971e154027ff165563a0e56e9d88c0deb6321cc2db1cebb86  userland/target/x86_64-unknown-toyos/toyos/test-runner
diff head2.sha gate2.sha EXIT=1
ci host EXIT=0
guest EXIT=0
GATESDONE

staged.sh

# Whether each staged T14 image carries, byte for byte, the x86_64 loader gates2.sh hashed at this
# head: finds a 64-byte run of the loader (0x400 into it, holding no newline byte) in the image with
# grep -obaF, then cmp's the loader's whole length at each offset that places, and prints those it matches at.
export LC_ALL=C
S=/Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3
L=/Users/jan/Dev/jan/toyos-align3/bootloader/target/x86_64-unknown-uefi/toyos/bootloader.efi
cd /Users/jan/Dev/jan/toyos-align3 || exit 1
echo "head $(git rev-parse HEAD)"
grep "x86_64-unknown-uefi" $S/gate2.sha; shasum -a 256 $L
dd if=$L of=$TMPDIR/pat.$$ bs=1 skip=1024 count=64 2>/dev/null
[ "$(tr -cd '\n' < $TMPDIR/pat.$$ | wc -c)" -eq 0 ] || { echo "pattern holds a newline"; exit 1; }
size=$(stat -f %z $L)
for d in $(sed -n 's/^  image: //p' $S/metal/request.txt); do
  offs=$(grep -obaF -f $TMPDIR/pat.$$ "$d" | cut -d: -f1 | tr '\n' ' ')
  ok=""; for o in $offs; do tail -c +$((o - 1024 + 1)) "$d" | cmp -s -n $size $L - && ok="$ok $o"; done
  echo "${d#$S/metal/} pattern-at=[$offs] whole-loader-at=[${ok# }]"
done
rm -f $TMPDIR/pat.$$

→ staged.log (exit 0)

head f84e57ef830fe76d272ca24f6d369d9db2194177
1fde0464513c571d88ab0bb4f638ab4528d543cd54fe5cfbdcb7f2ea3d677ce7  bootloader/target/x86_64-unknown-uefi/toyos/bootloader.efi
1fde0464513c571d88ab0bb4f638ab4528d543cd54fe5cfbdcb7f2ea3d677ce7  /Users/jan/Dev/jan/toyos-align3/bootloader/target/x86_64-unknown-uefi/toyos/bootloader.efi
ccorpus/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
deadlinewedge/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
foreignrecord/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
hardlockup/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
iommu-no-remap/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
isa-withheld/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
jobcase/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
lanleasecase/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
lantalkcase/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
latencycase/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
logstallcase/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
metalcase/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
metaldevicecase/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
proctreecase/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
selftests/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
shared/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
shared-2/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
shared-debug/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
testcases/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
testcases-bounds/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
testcases-deaf/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
testcases-debug/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
testcases-mkdir/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
testcases-readdir/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
testcases-watchdog/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
usbbreak/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
usbload/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]
windowscase/image.img pattern-at=[1604096 ] whole-loader-at=[1604096]

staged-control.sh

# staged.sh's search, for origin/main's x86_64 loader (bytes.sh's base build, kept by map.sh) in
# jobcase's staged image: the control, which must place no whole loader.
export LC_ALL=C
S=/Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3
L=$S/maps/base-x86/bootloader.efi
d=$S/metal/jobcase/image.img
shasum -a 256 $L
dd if=$L of=$TMPDIR/pat.$$ bs=1 skip=1024 count=64 2>/dev/null
[ "$(tr -cd '\n' < $TMPDIR/pat.$$ | wc -c)" -eq 0 ] || { echo "pattern holds a newline"; exit 1; }
size=$(stat -f %z $L)
offs=$(grep -obaF -f $TMPDIR/pat.$$ "$d" | cut -d: -f1 | tr '\n' ' ')
ok=""; for o in $offs; do tail -c +$((o - 1024 + 1)) "$d" | cmp -s -n $size $L - && ok="$ok $o"; done
echo "${d#$S/metal/} pattern-at=[$offs] whole-loader-at=[${ok# }]"
echo "== the image at 1604096 - 1024 against that loader: differing bytes"
tail -c +$((1604096 - 1024 + 1)) "$d" | head -c $size | cmp -l $L - | wc -l
rm -f $TMPDIR/pat.$$

→ staged-control.log (exit 0)

212a6288ab9e4e6d98c7fb7f9ba672008a652a1b6bdaa877803d1cce148b8c42  /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/maps/base-x86/bootloader.efi
jobcase/image.img pattern-at=[] whole-loader-at=[]
== the image at 1604096 - 1024 against that loader: differing bytes
  263771

stage.sh

# Stages every T14 row of the metal profile at this head: builds the images and writes request.txt.
# Touches no machine. A staging run is not a pass, so its exit is non-zero by design.
cd /Users/jan/Dev/jan/toyos-align3 || exit 1
echo "head $(git rev-parse HEAD)"
git status --porcelain --ignore-submodules=none
cargo test --test toyos-build -- --metal --metal-readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal; echo "stage EXIT=$?"
git status --porcelain --ignore-submodules=none

→ stage.log

head f84e57ef830fe76d272ca24f6d369d9db2194177
    Finished `test` profile [optimized + debuginfo] target(s) in 0.08s
     Running tests/toyos.rs (target/debug/deps/toyos_build-1b8e461cc3d9c78f)
21:11:17   BUILD x86_64 binaries of tests/toyos-rust-tests
21:11:18 external deps changed: cleaning /Users/jan/Dev/jan/toyos-align3/tests/toyos-rust-tests/tls-dlopen-lib
     Removed 0 files
21:11:18 external deps changed: cleaning /Users/jan/Dev/jan/toyos-align3/tests/toyos-rust-tests/tls-lib
     Removed 0 files
21:11:18 external deps changed: cleaning /Users/jan/Dev/jan/toyos-align3/tests/toyos-rust-tests/tls-multi-crate
     Removed 0 files
21:11:18 external deps changed: cleaning /Users/jan/Dev/jan/toyos-align3/tests/toyos-rust-tests/tls-cranelift
     Removed 0 files
21:12:05   BUILT x86_64 binaries of tests/toyos-rust-tests  (48s)
21:12:05 [toyos] Compiling 137 C tests, and attempting 24 declared ones...
21:12:08 [metal] 66 registration(s) and 228 shared member(s) over 28 boot(s)
21:12:08   BUILD the host's tests/ssh-client-host
21:12:21   BUILT the host's tests/ssh-client-host  (12s)
21:12:21   BUILD x86_64 kernel, loader, ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/ccorpus
21:12:23   BUILT x86_64 kernel, loader, ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/ccorpus  (2s)
21:12:23 [metal] ccorpus: 137 job(s), armed with [] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/ccorpus/image.img
21:12:23   BUILD x86_64 kernel boot-actuators,test-actuators, ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/deadlinewedge
21:12:24   BUILT x86_64 kernel boot-actuators,test-actuators, ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/deadlinewedge  (1s)
21:12:24 [metal] deadlinewedge: 0 job(s), armed with ["wedge-before-reset"] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/deadlinewedge/image.img
21:12:24   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/foreignrecord
21:12:26   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/foreignrecord  (1s)
21:12:26 [metal] foreignrecord: 0 job(s), armed with ["blackbox-foreign-identity"] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/foreignrecord/image.img
21:12:26   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/hardlockup
21:12:27   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/hardlockup  (1s)
21:12:27 [metal] hardlockup: 0 job(s), armed with ["hard-lockup-probe"] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/hardlockup/image.img
21:12:27   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/iommu-no-remap
21:12:28   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/iommu-no-remap  (1s)
21:12:28 [metal] iommu-no-remap: 1 job(s), armed with ["iommu-no-remap"] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/iommu-no-remap/image.img
21:12:28   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/isa-withheld
21:12:30   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/isa-withheld  (1s)
21:12:30 [metal] isa-withheld: 2 job(s), armed with ["i8042-withheld"] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/isa-withheld/image.img
21:12:30   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/jobcase
21:12:31   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/jobcase  (1s)
21:12:31 [metal] jobcase: 0 job(s), armed with [] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/jobcase/image.img
21:12:31   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/lanleasecase
21:12:32   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/lanleasecase  (1s)
21:12:32 [metal] lanleasecase: 1 job(s), armed with [] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/lanleasecase/image.img
21:12:32   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/lantalkcase
21:12:54   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/lantalkcase  (21s)
21:12:54 [metal] lantalkcase: 1 job(s), armed with [] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/lantalkcase/image.img
21:12:54   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/latencycase
21:12:55   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/latencycase  (1s)
21:12:55 [metal] latencycase: 2 job(s), armed with ["tlb-shootdown-bench"] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/latencycase/image.img
21:12:55   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/logstallcase
21:12:56   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/logstallcase  (1s)
21:12:56 [metal] logstallcase: 1 job(s), armed with [] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/logstallcase/image.img
21:12:56   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/metalcase
21:12:58 assets: leaving out assets/soundfont.sf2 — only /system/bin/doom opens it and this image builds no doom
21:12:58 assets: leaving out assets/DOOM1.WAD — only /system/bin/doom opens it and this image builds no doom
21:12:58   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/metalcase  (1s)
21:12:58 [metal] metalcase: 0 job(s), armed with [] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/metalcase/image.img
21:12:58   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/metaldevicecase
21:12:59   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/metaldevicecase  (1s)
21:12:59 [metal] metaldevicecase: 5 job(s), armed with [] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/metaldevicecase/image.img
21:12:59   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/proctreecase
21:13:01   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/proctreecase  (2s)
21:13:01 [metal] proctreecase: 5 job(s), armed with [] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/proctreecase/image.img
21:13:01   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/selftests
21:13:03   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/selftests  (1s)
21:13:03 [metal] selftests: 0 job(s), armed with ["pci-cap-selftest", "revoked-backing-selftest", "leak-rollback-selftest", "lapic-spurious-selftest", "unclaimed-vector-selftest", "xhci-xecp-selftest", "xhci-descriptor-selftest", "sysret-ss-probe", "test-input-merge", "sched-operation-nesting", "iommu-firmware-left"] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/selftests/image.img
21:13:03   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/shared
21:13:04   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/shared  (1s)
21:13:04 [metal] shared: 62 job(s), armed with [] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/shared/image.img
21:13:04   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/shared-2
21:13:06   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/shared-2  (1s)
21:13:06 [metal] shared-2: 22 job(s), armed with [] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/shared-2/image.img
21:13:06   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/shared-debug
21:13:07   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/shared-debug  (1s)
21:13:07 [metal] shared-debug: 7 job(s), armed with [] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/shared-debug/image.img
21:13:07   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases
21:13:08   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases  (1s)
21:13:08 [metal] testcases: 9 job(s), armed with [] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases/image.img
21:13:08   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-bounds
21:13:10   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-bounds  (1s)
21:13:10 [metal] testcases-bounds: 3 job(s), armed with [] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-bounds/image.img
21:13:10   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-deaf
21:13:11   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-deaf  (1s)
21:13:11 [metal] testcases-deaf: 1 job(s), armed with ["dump-deaf-cpu"] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-deaf/image.img
21:13:11   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-debug
21:13:12   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-debug  (1s)
21:13:12 [metal] testcases-debug: 2 job(s), armed with [] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-debug/image.img
21:13:12   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-mkdir
21:13:13   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-mkdir  (1s)
21:13:14 [metal] testcases-mkdir: 1 job(s), armed with [] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-mkdir/image.img
21:13:14   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-readdir
21:13:15   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-readdir  (1s)
21:13:15 [metal] testcases-readdir: 1 job(s), armed with [] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-readdir/image.img
21:13:15   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-watchdog
21:13:16   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-watchdog  (1s)
21:13:16 [metal] testcases-watchdog: 0 job(s), armed with ["watchdog"] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-watchdog/image.img
21:13:16   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/usbbreak
21:13:17   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/usbbreak  (1s)
21:13:17 [metal] usbbreak: 0 job(s), armed with ["usb-transport-break"] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/usbbreak/image.img
21:13:17   BUILD x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/usbload
21:13:19   BUILT x86_64 ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/usbload  (1s)
21:13:19 [metal] usbload: 0 job(s), armed with ["usb-reset-under-load"] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/usbload/image.img
21:13:19   BUILD x86_64 kernel mask-windows, ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/windowscase
21:13:29   BUILT x86_64 kernel mask-windows, ROOT of /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/windowscase  (10s)
21:13:29 [metal] windowscase: 3 job(s), armed with [] — /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/windowscase/image.img
# One boot per image. Each invocation is `cargo <words>` from this worktree.

ccorpus
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/ccorpus/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/ccorpus/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/ccorpus --fat32-check

deadlinewedge
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/deadlinewedge/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/deadlinewedge/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/deadlinewedge --fat32-check

foreignrecord
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/foreignrecord/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/foreignrecord/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/foreignrecord --fat32-check

hardlockup
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/hardlockup/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/hardlockup/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/hardlockup --fat32-check

iommu-no-remap
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/iommu-no-remap/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/iommu-no-remap/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/iommu-no-remap --fat32-check

isa-withheld
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/isa-withheld/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/isa-withheld/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/isa-withheld --fat32-check

jobcase
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/jobcase/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/jobcase/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/jobcase --fat32-check

lanleasecase
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/lanleasecase/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/lanleasecase/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/lanleasecase --fat32-check --nic 0000:00:1f.6

lantalkcase
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/lantalkcase/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/lantalkcase/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/lantalkcase --fat32-check --nic 0000:00:1f.6 --talk /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/lantalkcase/ssh/id_ed25519

latencycase
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/latencycase/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/latencycase/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/latencycase --fat32-check

logstallcase
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/logstallcase/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/logstallcase/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/logstallcase --fat32-check

metalcase
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/metalcase/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/metalcase/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/metalcase --fat32-check

metaldevicecase
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/metaldevicecase/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/metaldevicecase/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/metaldevicecase --fat32-check

proctreecase
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/proctreecase/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/proctreecase/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/proctreecase --fat32-check

selftests
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/selftests/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/selftests/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/selftests --fat32-check

shared
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/shared/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/shared/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/shared --fat32-check

shared-2
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/shared-2/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/shared-2/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/shared-2 --fat32-check

shared-debug
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/shared-debug/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/shared-debug/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/shared-debug --fat32-check

testcases
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases --fat32-check

testcases-bounds
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-bounds/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-bounds/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-bounds --fat32-check

testcases-deaf
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-deaf/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-deaf/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-deaf --fat32-check

testcases-debug
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-debug/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-debug/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-debug --fat32-check

testcases-mkdir
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-mkdir/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-mkdir/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-mkdir --fat32-check

testcases-readdir
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-readdir/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-readdir/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-readdir --fat32-check

testcases-watchdog
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-watchdog/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-watchdog/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/testcases-watchdog --fat32-check

usbbreak
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/usbbreak/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/usbbreak/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/usbbreak --fat32-check

usbload
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/usbload/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/usbload/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/usbload --fat32-check

windowscase
  image: /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/windowscase/image.img
  cargo run --bin toyos-metal -- --image /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/windowscase/image.img --readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/windowscase --fat32-check
21:13:29 [metal] staged 28 image(s); /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal/request.txt lists them. The machine was not touched, so this run establishes nothing about it.
error: test failed, to rerun pass `--test toyos-build`

Caused by:
  process didn't exit successfully: `/Users/jan/Dev/jan/toyos-align3/target/debug/deps/toyos_build-1b8e461cc3d9c78f --metal --metal-readback /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/metal` (exit status: 2)
stage EXIT=2
ALLDONE

@Japabu

Japabu commented Oct 4, 2026

Copy link
Copy Markdown
Collaborator Author

Evidence (4): why the strip line moves the layout

Same rules as comment 1. meta.sh ran on the maps bytes.sh kept. shasum -a 256 meta.sh: ce71fc11bebc9f68abad7ecfd7af1cb9eb67337729a94c518a42e8a8f448d970.

meta.sh

# Which units' output names (crate-name-<metadata hash>) the strip line changes: per arch, the rlib
# and object names the nostrip and head1 maps link from, and how many of them the two share.
cd /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/align3/maps || exit 1
for a in x86 a64; do
  for v in nostrip head1; do
    awk 'NR > 1 && /:\(/ { p = $4; sub(/:\(.*/, "", p); if (p ~ /\.rlib\(/) sub(/\(.*/, "", p); sub(/.*\//, "", p); sub(/\.[^.]*\.[^.]*\.rcgu\.o$/, "", p); print p }' $v-$a/bootloader.map | sort -u > $v-$a/units
  done
  echo "== $a: units nostrip $(wc -l < nostrip-$a/units), head1 $(wc -l < head1-$a/units), in both $(comm -12 nostrip-$a/units head1-$a/units | wc -l)"
  comm -12 nostrip-$a/units head1-$a/units
done

→ meta.log (exit 0)

== x86: units nostrip       26, head1       26, in both        4
alloc-2e8f85b2e3bc2cda
compiler_builtins-97ce80784ed9b84d
core-58c37db6ddbccf09
symbols.o
== a64: units nostrip       24, head1       24, in both        4
alloc-30d8f70dca828e4d
compiler_builtins-097e22fcb8d9fab7
core-467119584c380b62
symbols.o

@Japabu

Japabu commented Oct 4, 2026

Copy link
Copy Markdown
Collaborator Author

Full Drive-mode T14 suite at f84e57ef8 (orchestrator's run, t14-drive.sh; worktree clean at head; the harness built, flashed, booted, read back and judged every boot, each booting this head's loader; 2531 s): EXIT=0, [metal] 294 passed, 0 failed, 28 boot(s). Log: orch/align3/metal/drive/738-full.log in the orchestrator's job directory.

@Japabu

Japabu commented Oct 4, 2026

Copy link
Copy Markdown
Collaborator Author

Review, round 1, head f84e57ef8

Net lines are +27 −31 across 3 files. Production is bootloader/Cargo.toml +1 and bootloader/Cargo.lock +18 −18. The track issue is +8 −13. There are no test changes.

What I checked against the tree and the posted logs:

  • Merge. git merge-tree --write-tree origin/main f84e57ef8 (main at 9de5d7df9) exits 0. Main's three commits since b75ca2b4e change nothing in the loader's graph: git diff f84e57ef8 <merge> -- bootloader toyos-abi toyos-acpi toyos-bootmap toyos-blackbox toyos-wallclock toyos-elf toyos-gpt toyos-rootimage bcachefs toyos-tco toyos-tsc toyos-update is empty. So the loader that was measured is the loader that lands.
  • Alignment. On the merged tree, every registry name@range across the five locks has a single version. At origin/main the only spread is the loader's 8 rows. All 8 new versions have the same checksum in the root lock, and in the userland and kernel locks wherever those carry them. Nothing enters or leaves the lock beyond those 8, so there is no new fetch. No fork pin moves.
  • strip. MsvcLinker::debuginfo in rust/compiler/rustc_codegen_ssa/src/back/linker.rs:1078 ignores _strip, and bootloader/.cargo/config.toml passes /DEBUG:NONE. That matches the body's account. The byte change is explained by the unit-hash renames in meta.log. After this change the kernel, loader and userland [profile.toyos] tables have the same keys.
  • Evidence is verbatim. Comments 1–4 are byte-equal to comment1.md–comment4.md. Every .sh, .log and .exit they quote appears unchanged in the posted text. shasum -c scripts.sha is OK for all 15 scripts, and meta.sh matches its stated hash. File mtimes agree with the UTC stamps in the logs and the comment times.
  • Negative control. In the base build both loaders differ and every other artifact is equal. staged-control.log finds no base loader in the staged image.
  • Gates at f84e57ef8 (gates2.log):
    • Both --build-only builds exit 0 and end in Build finished.
    • --ci host exits 0 and ends [ci] Host: 75 step(s), all green. Its FAILED lines are the planted control arms.
    • cargo test exits 0, 28 passed, 28 total, including the aarch64 virt_* boots of the aarch64 loader.
  • T14. 738-full.log shows every boot's supervisor at build f84e57ef8… clean and ends [metal] 294 passed, 0 failed, 28 boot(s). staged.log places this head's x86_64 loader byte for byte in all 28 images.
  • Owner's ruling. The quoted ruling in the track is unchanged.

BLOCKER

None.

NOTE

  • issues/debug-true-produces-no-debug-info.md:9 — still says "Every [profile.toyos] but the loader's sets strip = "debuginfo"". After this branch every profile sets it, so the record is now false of the tree.
  • issues/the-tree-says-who-uses-each-thing.md:181 — stage 2 (version alignment) is complete with this branch, but the parent track does not record it the way stage 1 is recorded ("Landed in The issue tracker is flat: issues/<slug>.md, and no area is left #723").

LAND

@Japabu
Japabu marked this pull request as ready for review October 4, 2026 22:06
@Japabu
Japabu enabled auto-merge October 4, 2026 22:06
@Japabu
Japabu added this pull request to the merge queue Oct 4, 2026
Merged via the queue into main with commit e559859 Oct 4, 2026
6 checks passed
@Japabu
Japabu deleted the wt/toyos-align3 branch October 4, 2026 22:48
Japabu added a commit that referenced this pull request Oct 4, 2026
Conflicts against #728:
- toyos-logstream: #728's `program_ms` read the old `{…}` program head
  through `shown()`, both gone here. Folded into `parse`: the counters
  judge reads `parse(l).and_then(|p| p.ms)`, one reader for every line;
  its readback test now asserts `parse` on every head `ProgramLine`
  writes.
- console: #728's `logkeeper_api::read()` kept, with this branch's
  `asked_ms` on `stamp_ns()`.

Semantic conflict: #728's idle-second check compared `counters_metal`'s
`at`, read off `nanos_since_boot()` (the kernel clock's zero), with line
stamps that count from the counter's zero here. `counters_metal` now
reads `stamp_ns()` for `at`; the SMI span `at2 - at0` is a difference and
unaffected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
Japabu added a commit that referenced this pull request Oct 4, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
Japabu added a commit that referenced this pull request Oct 8, 2026
…ts two stages landed

`issues/the-tree-resolves-in-five-cargo-locks-not-one.md` named one thing
left, the T14's run of the metal profile on the folded build. It ran green
at `db55db96a`, and the review ruled no boot owed for what followed, so the
exit is met and the file goes. Stages 2 and 3 of
`issues/the-tree-says-who-uses-each-thing.md` cited it: the alignments
landed in #724, #732 and #738, the workspace in #746.

What the file carried that is still true is at its site: the root
manifest's `exclude` says why `userland/libc` and the guest test crates
keep their own resolution. Two facts go with the file. libc's lock resolves
`toyos`, `toyos-abi`, `toyos-elf`, `toyos-osrelease` and `dlmalloc` a
second time and nothing holds it to the root's; both carry `dlmalloc`
0.2.13. `Cargo.lock` carries `miniz_oxide` 0.8.9 for `png` 0.18.1 beside
0.9.1 for `flate2` 1.1.10 until `png` takes 0.9.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RvnWQFcMuGqTHYhvSnTe8A
github-merge-queue Bot pushed a commit that referenced this pull request Oct 8, 2026
…nd the SDK resolve together (#746)

Stage 3 of `issues/the-tree-says-who-uses-each-thing.md`. The root,
`kernel/`, `bootloader/`, `userland/` and `toyos/` were five Cargo
resolutions; they are one workspace with one `Cargo.lock`, one
`[profile.toyos]`, one `[patch]` table and one tracked
`.cargo/config.toml`. No directory moves.

Head `dd12c0b32`, on `origin/main` `6f87cdb9c` (#749; none of #757, #759
or #762 had landed when it was merged and measured). It is `9ef866436`,
where the CI readings of the fold itself were taken, plus two merges of
`main` and the close of the stage's issue. Everything owed at the merged
head is in the next section, measured at `dd12c0b32`.

## The merge of #749, measured at `dd12c0b32`

#749 wrote its new dependency edges into `kernel/Cargo.lock` and
`userland/Cargo.lock`, which this branch deletes. Both modify/delete
conflicts are resolved by deleting the file and re-resolving the root
lock. Git merged the root `Cargo.lock` without a conflict into a lock
that is wrong, as the review found: `cargo metadata --locked` on it
exits 101 (`cannot update the lock file … because --locked was passed`).
It had `toyos-userbound`'s edges to `toyos-abi` and `toyos-bootmap`,
which #749 also wrote into the root lock, and not `acpiserver`'s to
`toyos-acpi` and `toyos-aml`, which #749 wrote into userland's alone.
`cargo metadata --offline` re-resolved it. `diff` of git's merged lock
against the re-resolved one is those two lines under `acpiserver` and
nothing else: no package added, no version moved.

| Owed | Command | Result |
|---|---|---|
| The lock resolves as committed | `cargo metadata --locked
--format-version 1` | exit 0 at this head by the host suite's step "the
licences of what ships", which runs `cargo metadata --locked` for every
shipped crate's manifest and is green in `host.log` and in run
37757675374; the hand run's empty stderr (`metadata-locked.err`)
predates the merge commit and recorded no exit |
| The lock's (name, version) pairs are the union of `main`'s five |
`pairs.sh <worktree> 6f87cdb`: the pairs of `Cargo.lock`, `kernel/`,
`bootloader/`, `userland/` and `toyos/Cargo.lock` at `6f87cdb9c`, `sort
-u`, against the root lock's | 692 against 692, `diff` exit 0
(`pairs.out`) |
| The folded kernel and loader are the control's bytes | `prove.sh
6f87cdb dd12c0b …`, the round 3 script unchanged | exit 0; all four
`control vs fold` byte rows `cmp` exit 0; every row in "The checks"
below (`prove.out`) |
| No new reader of a compiled-in path | `git diff -U0 e3bdff8
dd12c0b -- tests src toyos-blackbox toyos-symbols userland/symbolize`,
its added lines searched for `\.rs`, `taken at`, `panicked at`,
`Location`, `file()`, `PREVIOUS_PANIC`, `strip_prefix`, `src/`, `pure/`
| the merge touches five files there, all under `tests/`; 13 hits, of
which 4 are diff headers and 9 the field `info.rsdp`; none reads a path.
`tests/common/power.rs:429` is still the one reader outside fixtures,
and reads `taken at kernel/src/hardlockup/probe.rs`
(`readers-merge.diff`, `readers-hits.txt`) |
| `cargo run -- --ci host`, once, on the development machine | at
`dd12c0b32`, `cargo run -- --ci host > host.log 2>&1; echo EXIT=$?` |
exit 0; the log ends `[ci] Host: 77 step(s), all green`; 1-minute load
26.60 when it started (`host.log`) |

The logs are in the round's scratch directory (`orch/oneworkspace-r4/`),
which a reader of this pull request cannot reach; `prove.out` and
`pairs.sh` are in the round 4 comment.

## What changed, per decision

- **Members.** `kernel`, `bootloader`, `toyos` and userland's 40
packages join the root `[workspace]`. `userland/Cargo.toml`, four locks,
three `rust-toolchain.toml` and three per-directory `.cargo/config.toml`
are deleted. The toolchain files chose nothing the build read: every
guest `cargo` already runs under `RUSTUP_TOOLCHAIN` naming its sysroot.
- **Flags.** `build.target` is gone, since every guest build already
passes `--target`. The root config holds one `[target.<triple>]` table
per guest triple, six, each with the flags its directory's config gave
it. A host build takes none, as before. Two things do change:
- The guest crates outside the workspace that are built from their own
directory for a ToyOS triple (`tests/toyos-rust-tests` and its `tls-*`
crates) now take `-Dwarnings`, because cargo reads the tracked root
config from above them. On a checkout without a local config they took
no flags.
- The one build that sets `RUSTFLAGS` itself (the test binaries linked
against a `cdylib`, `src/build.rs`) takes none of the table: the
variable replaces it.
- **Profiles.** The root's `[profile.dev]` is `opt-level = 2`. The
kernel library's host tests, its model controls, the SDK's tests and
every surveyed userland crate's host tests used to resolve in their own
workspaces and ran at `opt-level = 0`; they now run at 2.
- **What stays apart** (the root manifest's `exclude` says why at each
entry): `rust/`; `tests/toyos-rust-tests` and its `tls-*` crates and
`tests/ssh-client-host`, because `[patch]` is workspace-wide and they
patch or refuse what the root patches; and `userland/libc`. libc keeps
its own lock because that lock is an input of the sysroot key: as a
member it would be resolved by the root lock, and every dependency
change of any member would move the key and rebuild every sysroot. The
price is a sixth resolution of `toyos`, `toyos-abi`, `toyos-elf`,
`toyos-osrelease` and `dlmalloc` that nothing holds to the root's (both
carry `dlmalloc` 0.2.13 today).
- **The lock** is every `[[package]]` of the five locks, deduplicated
and resolved by `cargo metadata`. Nothing was `cargo update`d. Since the
lock reviewed at `88bcbf4d3` it has changed by #749's four edges alone
(see the section above); `cargo metadata --locked` exits 0 at this head.
- **One target directory.** Every guest is built at the root with `-p`
into `target/`. A stale sysroot used to `cargo clean` a crate's own
target; that would now empty the build system's own, so `Stale::All`
removes `target/toyos` and the guest triples' directories instead, and
the `cargo clean` path, its member assertion and its test are deleted.
- **Kernel and loader build one after the other.** They were built on
two threads. In one target directory cargo serialises them anyway
(measured in round 1: the second prints `Blocking waiting for file lock
on artifact directory`), so the thread scope is deleted.
- **The host suite** can no longer be `--workspace`: the kernel binary,
the loader and most of userland do not build for a host. `src/hostws.rs`
says which members a host tests, and the workspace test and clippy runs
`--exclude` the rest by package name.
- **Fork clones.** The tracked config includes the gitignored
`.cargo/local.toml` when it exists, and `implementer.md` names it.
- **The merge of #745.** `src/sysroot.rs` keeps both sides:
`SYSROOT_SOURCES` carries `"sdk/std"` and `SYSROOT_MANIFESTS` ends in
`".cargo/config.toml"`; its test keeps both loops;
`issues/toyos-has-its-own-allocator.md` keeps `sdk/std/sys/alloc.rs` and
"from the kernel's graph in `Cargo.lock`". Git merged all three without
a conflict.
- **The host's own apps build where the userland tests build.**
`src/ci.rs`'s apps step passes `--target` only where it checks another
host's triple. On `main` the `userland/*` test steps and the host's apps
step both named the host triple and shared `userland/target/<host
triple>`. The fold took `--target` off the test steps, which no longer
need it to keep a guest triple out, and left it on the apps step: the
tests filled `target/debug`, the apps `target/<host triple>`, and every
dependency was compiled twice. That is what made the sealed tree larger
than `main`'s (see CI).
- **The merges of `main`.** #747, #748, #750, #751, #753 and #755 merged
without a conflict. #749 did not: see the section above.
- **The merge of #752.** Git merged it without a conflict: both
workflows' `host` jobs keep `CARGO_PROFILE_DEV_DEBUG: line-tables-only`
in `env:`, and `carry()` no longer sets it. No manifest and no lock
moved in the merge.
- **Issues.**
`issues/the-tree-resolves-in-five-cargo-locks-not-one.md` is deleted:
the one thing it named as left, the T14's run of the metal profile on
the folded build, ran green at `db55db96a`, and review round 2 ruled no
boot owed for what followed on two conditions, both in the section
above. Stages 2 and 3 of `issues/the-tree-says-who-uses-each-thing.md`
now read "Landed in #724, #732 and #738" and "Landed in #746". What the
file carried that stays true is the root manifest's `exclude`, which
says why each excluded directory keeps its own resolution; the deleting
commit's message carries the rest (libc's second resolution of five
crates, and `miniz_oxide` 0.8.9 beside 0.9.1 until `png` takes 0.9).
`issues/cargo-run-inside-kernel-loom-or-kernel-sim-builds-for-a-bare-target.md`
is closed on the two in-directory runs at `9ef866436`.
`issues/the-sdk-is-linted-by-no-clippy-run.md` is filed and names its
owner, the build system.

## The fold changed the kernel's source paths, and the proof did not see
it

The T14's run of the whole metal profile at `88bcbf4d3` exited 1: 295
passed, 1 failed, 30 boots. The red row was
`hard_lockup_ends_a_deaf_cpu`. Its judge looked for `taken at
src/hardlockup/probe.rs` in the previous boot's panic record, and the
readback's loader log says `taken at
kernel/src/hardlockup/probe.rs:145:29`.

**What changed in the kernel's strings.** Cargo hands rustc a workspace
member's source by its path from the workspace root, and rustc writes
that path into every panic and `Location`. The kernel's root was
`kernel/`; it is now the repository. So `src/...` became
`kernel/src/...`, and a path dependency outside the old root, which the
base named by the checkout's absolute path, is now named from the
repository root (`toyos-abi/src/...`). Read from the actuator kernel
staged at this head: 254 distinct `.rs` paths, 158 under `kernel/`, 38
under a `toyos-*` crate or `bcachefs`, none bare `src/` or `pure/`, none
naming the worktree.

**Why the proof did not see it.** Both of its oracles were blind to it
by construction:
- The byte row compared the fold against a control that is the base with
its workspace root moved up. The control moved the root too, so it
carries the same new paths and the bytes agree.
- The `rustc`-lines row compared base against fold after a `sed` that
rewrites `(kernel/|bootloader/)?(src|pure)/x.rs` and
`ROOT/<crate>/src/lib.rs` to one form. That rewrite is needed, or every
path crate's line differs and the row can show nothing else; but it
absorbed the change without reporting it.

`prove.sh` now reports what that rewrite absorbs: per artifact, how many
crates' source arguments were renamed, and a diff of the `.rs` paths the
artifact carries, base against fold and control against fold. The script
is in the round 3 comment and has run twice since, at `9ef866436` and at
this head.

**Every reader of a compiled-in path.** I searched the harness, the
guest tests, the build system, `toyos-blackbox`, `toyos-symbols`,
`userland/symbolize`, the loader and the kernel's panic path for path
literals, prefix strips and `Location` readers. One reader matches a
compiled-in path by its prefix: `tests/common/power.rs`, the red row's
judge, now fixed to the path the kernel records. Everything else is
prefix-blind (`panicked at`, a file name with its line) or a synthetic
fixture. The kernel's panic slot keeps the last 96 bytes of a path; the
longest kernel path is 46, so nothing is cut. Userland's panic sites
gain a `userland/` prefix the same way; no test reads one.

**The record rows.** The judging asked to record three
`boot.testcases-bounds.*` rows. They are not this change's: that boot
was already staged on the base and unrecorded, and `main` recorded it in
#745. They arrive with the merge and nothing is committed here.

## What the fold changes in what is built

The lock row was measured at `dd12c0b32` against `6f87cdb9c`, the
`rustc` row by `prove.sh` at the same pair; the two `cargo tree` rows at
`88bcbf4d3`, and were not taken again.

| Measured | Result |
|---|---|
| Lock: (name, version) pairs, the fold's against the union of
`origin/main`'s five | identical, 692 pairs, `diff` exit 0 |
| Lock: sources | registry `getrandom` 0.2.17, 0.3.4, 0.4.2 are gone;
the forks at the same versions remain |
| Kernel and loader, both arches: every `rustc` command line of `cargo
build -v`, base against fold, path and cargo's path-derived hashes taken
out | identical, `diff` exit 0: 31 units per kernel, 55 and 37 per
loader |
| Userland, both triples: `cargo tree -e features` over every program,
base against fold | identical, `cmp` exit 0 |
| Host members: the same | `diff` exit 1, on `getrandom`'s source alone
|

So one resolved crate changes: the build system and the other host
members compile the ToyOS forks of `getrandom` 0.2.17, 0.3.4 and 0.4.2
instead of the registry's, same versions, same features. And every
source path compiled into the kernel and the loader changes, as above.

## The checks (high-risk: build system)

Measured at `dd12c0b32` against `origin/main` `6f87cdb9c` by `prove.sh`
(the script of the round 3 comment, unchanged), exit 0; its output is in
the round 4 comment. Round 3 measured the same rows at `9ef866436`
against `b432ed21c`, round 1 at `88bcbf4d3` against `e7010129f`.

**Negative control.** The whole change reverted is the base. A second
control is the base with only its workspace root moved up, keeping the
crate's own base lock and its profile. It is given the fold's root
`.cargo/config.toml`, so the control does not hold the flags: the one
row that does is base against fold on normalised `rustc` lines.

**Oracle.** Bytes and cargo's own command lines. Each cell is its own
`cmp` or `diff` exit:

| | kernel x86_64 | kernel AArch64 | loader x86_64 | loader AArch64 |
|---|---|---|---|---|
| control vs fold, bytes | 0 | 0 | 0 | 0 |
| fold vs fold rebuilt, bytes | 0 | 0 | 0 | 0 |
| base vs fold, bytes | 1 | 1 | 1 | 1 |
| base vs fold, `rustc` lines normalised | 0 | 0 | 0 | 0 |
| control vs fold, `rustc` lines verbatim | 0 | 0 | 0 | 0 |

What the normalisation absorbs, reported by the three `paths` rows: base
against fold, cargo hands rustc another source path for 29 of 31 crates
of each kernel and for 35 of 50 and 13 of 35 crates of the loaders
(`diff` exit 1 each, as expected); the `.rs` paths the x86-64 kernel
carries are 250 on both sides, of which the base has 39 under the tree's
absolute path and 150 from the crate's own root and the fold none of
either (`diff` exit 1); control against fold the artifacts' paths are
identical (`diff` exit 0, all four).

**Mutations**, each
on a fresh copy of the fold: M1 (drop the `[target.x86_64-unknown-uefi]`
table) loader build exit 101; M2 (lock `dlmalloc` at 0.2.12) `cmp` exit
1 and lines `diff` exit 1; M3 (select `bcachefs` beside the kernel in
one `cargo`) kernel build exit 101.

## Gates

The rows of the section "The merge of #749" were read at `dd12c0b32`.
Every row below was read at `9ef866436` unless it says otherwise, each
once, the narrowest that judges it. `ci.yml` runs on the push of
`dd12c0b32`; its result is not in this body.

| Gate | Result |
|---|---|
| `cargo run -- --ci host` | at `dd12c0b32`, development machine: exit
0, `[ci] Host: 77 step(s), all green`. Linux runner at `9ef866436`:
`ci.yml` run 37740454881 `host` success; cold inside `--ci seal`,
nightly run 37740449787: `[ci] Seal: 80 step(s), all green`; on macOS,
the same nightly's `portability-macos`: success |
| `cargo test --lib ci::tests` (the changed step's own test) | exit 0,
13 passed |
| The images and the guest suite | at `9ef866436`, run 37740454881:
`toolchain / build` and `guest / suite` success (KVM); run 37740449787:
`toolchain / build` and `tcg / suite` success. At `e3bdff8af`, run
37755369755: `host` and `toolchain / build` success, `guest / suite`
still running when read. Not run locally, and not read at `dd12c0b32` |
| `prove.sh 6f87cdb dd12c0b …` | exit 0; every row as in the table
above |
| `cargo test` inside `kernel/loom` | exit 0 |
| `cargo test` inside `kernel/sim` | exit 0 |
| Cold wall clock, x86-64 kernel and loader (`wall.sh`, one run) | base,
two cargos side by side: 24 s, 1-minute load 34.92 before it. Fold, one
after the other: 20 s, load 42.23. Other agents' builds were running, so
the two are not a controlled pair; the fold was not slower |
| Metal profile | every row green at `db55db96a` (comment 6048782042).
Since then the branch changed `src/ci.rs` and the root lock's two
`acpiserver` edges; the kernel sources that moved are `main`'s own
landings (#747, #748, #749), merged in. Review round 2, ruling (3), owes
no boot for the merge of #749 on two conditions, both met above |
| `cargo test --manifest-path userland/acpiserver/aml/Cargo.toml` at
`e3bdff8af` | exit 0 |
| `git status --porcelain --ignore-submodules=none` at `dd12c0b32` |
empty |

`issues/cargo-run-inside-kernel-loom-or-kernel-sim-builds-for-a-bare-target.md`'s
close now stands on the two in-directory runs at `9ef866436`.

The logs of these rows are files in the scratch directory of the round
that took them (`orch/oneworkspace-r3/`), which a reader of this pull
request cannot reach; the proof's and the measurements' outputs are in
the round 3 comment.

## CI

**Why the sealed tree was larger than `main`'s, measured.** A
`workflow_dispatch` of `nightly.yml` at `88bcbf4d3` (run 37685714260)
sealed `9348536345 B in 20064 files`, red. Units compiled per step,
counted from that log and from `main`'s nightly at `b432ed21c` (run
37717000719, sealed `18708 files, 7664839895 B`):

| step | `88bcbf4d3` | `main` |
|---|---|---|
| the driver's own build | 203 | 203 |
| the build system | 207 | 207 |
| the workspace's host members | 99 | 99 |
| clippy, warnings denied | 412 | 417 |
| the controls | 56 | 56 |
| `userland/*` | 225 | 289 |
| the apps for linux | 282 | 47 |
| the apps for macos | 248 | 248 |
| the apps for windows | 239 | 239 |

Of the 256 distinct crates the apps-for-linux step compiled at
`88bcbf4d3`, 226 had been compiled by an earlier step of the same run;
30 by none. The cause is the target directory: the test steps built
without `--target` into `target/debug`, the apps step with `--target
x86_64-unknown-linux-gnu` into `target/x86_64-unknown-linux-gnu`.
Profile, features and `RUSTFLAGS` are the same in both.

**The fix, measured once on the development machine** (`share.sh` in the
round 3 comment; cold, a target of its own, `aarch64-apple-darwin`):
after the fourteen test steps' builds (271 units), the ten apps with
`--target <host>` compile 270 units and add 616,616 KiB under
`target/<host>` and 135,064 KiB under `target/debug`; the same ten
without `--target` then compile 47 units and add 107,856 KiB. The 47 are
the same crates `main`'s step compiles on the runner.

**The seal at `9ef866436`, nightly run 37740449787** (conclusion
success: `host`, `portability-linux`, `portability-macos`, `toolchain /
build`, `tcg / suite`):

```
the cache entry, read by content: none restored: the run is cold
the apps for linux: 10 app(s) pass `cargo build`; …
the tree, sealed as the host cache's entry: 17010 files, 7493968284 B of the 8000000000 B an entry may hold; sealed: 2496 sources, built on Linux X64 ubuntu24 20261004.327.1, every target dated as built
[ci] Seal: 80 step(s), all green
```

Units per step in its log, against the two columns above:

| step | `9ef866436` | `88bcbf4d3` | `main` |
|---|---|---|---|
| `userland/*` | 225 | 225 | 289 |
| the apps for linux | 42 | 282 | 47 |
| the apps for macos | 264 | 248 | 248 |
| the apps for windows | 240 | 239 | 239 |

Every other step compiles what it did at `88bcbf4d3`. I expected 47 for
the Linux apps: it is `main`'s 47 less `crc32fast`, `log`, `memchr`,
`smallvec` and `toyos-keymap`, which an earlier step had compiled. I did
not expect the macOS step's 16 more: all are host-side units (`syn`,
`thiserror-impl`, `tokio-macros`, `futures-macro`, `autocfg` and the
like), which the Linux step's `--target` build used to compile for the
host and which the first `--target` step now compiles instead. The four
steps together compile 771 units against 994 at `88bcbf4d3` and 823 on
`main`.

- Margin: 506,031,716 B under the limit, 6.3 %, on image 20261004.327.1.
`main`'s 7,664,839,895 B was sealed on 20260927.320.1. The one pair of
figures there is for the two images is `f260e0b98`, built with full
debuginfo before #752 cut it to line tables: 8,540,783,725 B on
20260927.320.1 (run 37292450697) against 8,182,940,473 B on
20261004.327.1 (run 37601225884), 357,843,252 B or 4.2 % less on the
newer. So this head's figure and `main`'s are not a pair, and this head
is unmeasured on the older image.
- Against the same branch before the fix and before #752: 9,348,536,345
B at `88bcbf4d3` on 20260927.320.1.

**`ci.yml` run 37740454881 at `9ef866436`:** `host`, `toolchain / build`
and `guest / suite` success.

After this lands every `host` check runs cold until the first nightly on
`main` seals and saves: the path list is the cache's version.

**Toolchain keys.** The fold moves the sysroot key once:
`userland/.cargo/config.toml` was one of its inputs and
`.cargo/config.toml` replaces it. From now on a change to any guest
triple's flags moves that key. The merges of #747 and #749 moved
`toyos-abi` and `toyos`, so the sysroot key moved with `main`; the key
at this head was not read here.

## No new gate, test or dependency

No guest test is added or changed. No dependency is added. The proof is
a one-off script because its subject is this one change against its
base.

## Size

`git diff --shortstat origin/main...HEAD` at `dd12c0b32`: 53 files,
+5454 −7765. Without the locks: 48 files, +446 −704. `src/`,
`tests/toyos.rs` and `tests/common/`: 12 files, +237 −360, of which
tests are roughly +65 −115 by my reading of the hunks (an estimate, not
a count). `issues/`: 16 files, +49 −115.

## What I am unsure of

- **The seal on the older runner image.** GitHub serves two; this branch
was sealed on the newer one, at `9ef866436`. The only pair of figures
for the two is `f260e0b98` with full debuginfo (above): the older image
sealed it 357,843,252 B larger. Carried unscaled onto this tree that
leaves 148,188,464 B under the limit on the older image; scaled by the
pair's ratio, about 178 MB. Both are arithmetic, not a run.
- **`dd12c0b32` itself:** `ci.yml` run 37757675374 has `host` and
`toolchain / build` success at it; its `guest / suite` is what the
landing waits on. #757 (`b6bcb9691`) landed on `main` after this head
was merged and measured: ten source files under `kernel/src`,
`toyos-abi/src`, `toyos-userbound/src` and `tests/toyos-rust-tests`, no
manifest and no lock; `git merge-tree --write-tree dd12c0b b6bcb96`
exits 0. Nothing here was measured with it in. It differs from the
sealed head by `main`'s #749, #750, #753 and #755 and the root lock's
two edges; the seal's byte count at this head is unmeasured.
- **Build wall clock.** One run under load; the fold was not slower.
- **Clippy reaches further.** The bare-target shapes now also lint the
kernel's and the loader's path dependencies for those targets.
- **The licence gate reads a superset.** `--all-features` for the kernel
now turns on every member's features. It judges more than ships.
- **The runner's cargo.** The nightly's `host` at `88bcbf4d3` parsed the
optional `include`, so the runner's cargo accepts it.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01RvnWQFcMuGqTHYhvSnTe8A
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