Conversation
`cargo run -- --release-boot --build-only` builds `target/bootable-release.img`: the shipped config less every program whose package the licence gate holds pending the owner (doom), and so less the assets only doom opens (DOOM1.WAD and the SoundFont). `cargo run -- --ci release`, a new nightly job that needs every other lane green and runs on main alone, installs the toolchain, builds that image, and publishes it as `image-x86_64-<12 hex of the commit>`: the image gzipped, its SHA256SUMS, the notes as README.md, and ToyOS's licences, NOTICE and the texts NOTICE names for what the image ships. It keeps the newest seven image releases and deletes the rest with their tags. The notes print one QEMU command line per host, declared once in `imagerelease::Host::command` with QEMU's own edk2 firmware; the harness boots exactly those lines: `release_command_boots` to the desktop, and `release_writes_no_other_disk` beside an NVMe disk laid out as another operating system's and a stick with no table, comparing both byte for byte. Measured on the dev host before this commit: the macOS line over a copy of `target/bootable.img` early-panics on Homebrew QEMU 11.1.1's edk2 firmware (memory allocation of 4096 bytes failed, right after pmm), and reaches `compositor: ready` with the repository's `ovmf/` firmware in its place. Filed as issues/kernel/the-kernel-dies-at-boot-on-the-edk2-firmware-qemu-ships.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rch names it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review of #556 at 748890e (first round) Readiness is not met, and under Net: +1053/−21.
BLOCKER
NOTE
REMOVE
SEND BACK |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… notice The release job needs only `build`, runs in the pinned Debian KVM container, builds `Boot::release`'s image once in-process, boots a copy of it under the Linux line the notes print (`imagerelease::boots`), and on main uploads those same bytes: created as a draft, checked to carry the image, then published. Off main it builds and boots and publishes nothing, so a branch dispatch measures the Debian OVMF paths and the KVM line. `--release-boot` and its refusal list are gone; `--ci release` shares the guest jobs' frame (instrument, toolchain, private $TMPDIR). `boots` fingerprints both firmware files before and after the guest, so a line that lets edk2 write the shared variable-store template is red. `licence::notices` is written from the licence gate's own walk: every package with its own licence files, or the standard texts of its licence from the fork's LICENSES/ where the package publishes none, with its source (the crates.io download, the git URL, or the fork at its pinned commit for std); and every NOTICE section over a shipped file with its texts, less what is pending the owner. It is on the release's ROOT at share/licences.txt and beside the release. A package with no text reds `the_release_notice_carries_every_package_and_file_it_ships`. Where the toolchain was installed, std's library is fetched sparse beside rust/, since a source tree at rust/ makes the toolchain the checkout's to build. This replaces LICENCE_ASSETS and its hand-mirror test. The notes name the floor variable (its name's head and the vendor GUID, now `toyos_update::floor::VENDOR`, which the loader parses), that only `dmpstore -d` removes it, and that BootNext boots the stick once, before the dd line; the dd line gains its unmount step; the withheld list comes from `pending_owner`. `gh release view` answering anything but `release not found` is an error, and a listing that fills its limit or carries an entry without a tag and a time is refused. `release_writes_no_other_disk` is deleted. `foreign_disk_untouched` gains a USB disk whose table names only other systems' partitions and a USB stick with no table, asserts the kernel read both, and waits for QEMU to exit after `run shutdown` rather than draining for a fixed time. `release_command_boots` is disabled while the kernel dies on Homebrew's edk2; the loader writing a second stick of one release is filed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`held_of` reads `gh release view` and takes only its own `release not found` as nothing published; `releases` reads `gh release list` and refuses a listing that filled its limit or an entry without a tag and a time. foreign_disk_untouched hands its disks to the boot without clones. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review of #556 at 002bc8d (round 2) Readiness is still not met. PR CI Net: +1494/−94. Production is about +928: Round-1 BLOCKERs
BLOCKER
NOTE
REMOVE
SEND BACK |
…ed one way The release job builds and boots with a token that only reads, and hands the four assets on as an artifact and their digest as a job output. A new `release-publish` job holds `contents: write`, restores no cache, builds only toyos-build with no token in reach, rechecks the digest (`imagerelease::digest`) and publishes on main. `ci::a_token_that_writes_meets_no_cache_and_only_the_step_that_needs_it` holds every workflow to that. The post-publish re-read and the GITHUB_ACTIONS guard are gone; `gh` is no longer installed in the container. std's `library/` comes from a linked worktree's fork checkout, from `rust/library` where the checkout holds it, and from `fetched_library` everywhere else; the submodule-init path is deleted. The fetch sits at `.licence-fork/`, a direct child of the checkout, because std's manifest names `toyos` and `toyos-abi` three levels above its crates: under `target/` it never resolved. It is fetched into `target/licence/fork.partial` under its own lock and renamed into place, reused only at the pinned commit and sparse set, and the release build writes the notice before any build lock. The release notice test fetches the way the release job does. An OR takes Apache-2.0's standard text where it is a branch. The notice's opening sentence says what the walk leaves out. The notes name the loader defect as the one disk a boot may write though it was not given it. `foreign_disk_untouched` boots twice on `Profile::UsbDisk`, one foreign USB disk beside the NVMe disk each time: the USB driver serves two disks and the boot stick is one, so `UsbDiskCrowd`'s third was never read. `release_command_boots` is in a new Apple Silicon tier and boots that line; `Host::this` is gone, and the release job boots the Linux line. Filed: the toolchain install unpacks an asset no digest vouches for. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A copy of the Rust project's COPYRIGHT carried by another package satisfied the old check, so a fetch that dropped the fork's own left it green. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… boots it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
src/build.rs: main deleted the build slot `shipped_parts` took; the release notice, written before any lock, stays where the slot was, and the slot goes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review of #556 at 20179a7 (round 3) Readiness is not met, so under Net: +1896/−109.
Round-2 BLOCKERs
Round-1 BLOCKERs
BLOCKER
NOTE
REMOVE
SEND BACK |
licence.rs: main's ls_files went to sysroot::tracked_files; the branch's std_library and fetched_library replace main's submodule fetch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
…lity-macos; the writing-token gate reads write-all and persisted credentials - release-publish needs build, guest and tcg besides release. - Tier::AppleSilicon is gone. release_command_boots is in no tier: the suite's --release-command runs it and nothing else, and the nightly's portability-macos runs that on its Apple Silicon runner after the build, with the QEMU Homebrew already installed there. - The writing-token gate reads a job's permissions inline or nested, from any line of the job, and requires persist-credentials: false on every checkout of a job whose token writes. build, nightly-red and publish.yml's publish take it. - The notice test takes std from std_library, so a host test fetches nothing where the checkout holds the fork. - The fork's sparse set is derived from LICENCE_FILES, in any case. - The licence lock (was the fork-fetch lock) also covers the walk's scratch Cargo.lock and the release notice's write. - The re-read of the draft after `gh release create` is deleted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
A disk image anyone can download from GitHub and start under QEMU or write to a USB stick. The nightly builds it once and boots it. On
main, on a night the guest suite passed, it publishes the bytes that booted, from a job whose token is the only one that writes.This branch lands after the kernel boots on the edk2 firmware Homebrew's QEMU ships (
issues/kernel/the-kernel-dies-at-boot-on-the-edk2-firmware-qemu-ships.md,status: expected-red). Until thenrelease_command_bootsis disabled insrc/redlist.rsagainst that issue.What changed, per decision
The image.
build::Boot::releaseis the shippedsystem.tomlless every program whose package the licence gate holds pending the owner (licence::pending_owner).assets::collectalready leaves out what only a missing program opens. The image goes totarget/bootable-release.img, and its licence notice totarget/bootable-release-licences.txt. There is no command-line flag for it. The release job and the test build it in-process, so one path builds the image. The notice is computed before the build takes its lock, and written underbuildlock::licence.Two jobs; the write token never meets a build.
release(needs: build) runs in the pinned*kvmDebian container withpermissions: contents: read. It restores the guest cache, so it compiles and runs third-party build code. Its logic iscargo run -- --ci release, in the guest jobs' frame (the instrument, the toolchain, thenimagerelease::release, in a private$TMPDIRthat must be empty at the end).release:imagerelease::boots,Host::LinuxKvm) to a painting desktop;target/image-release:toyos.img.gz,SHA256SUMS, the notes andlicences.txt;imagerelease::digest(the SHA-256 of onesha256sumline per asset) as the step outputdigest.image-releaseartifact.release-publish(needs: [build, guest, tcg, release]) is the one job withcontents: write. So a night whose build, any guest shard ortcgwent red publishes nothing. It restores no cache, and its checkout keeps no credential (persist-credentials: false). It downloads the artifact and runscargo build -p toyos-buildwith no token in its environment. Only the last step getsGH_TOKEN, together withIMAGE_RELEASE_DIGEST, thereleasejob's output. That step iscargo run -- --ci release-publish(imagerelease::publish):main, it stops there, so a branch dispatch measures the handover.main, it creates the release as a draft carrying the assets. Oncegh release createhas exited 0, it publishes (--draft=false --latest) and deletes image releases past the newest 7.GITHUB_SHAis set and is the checkout's HEAD.ci::a_token_that_writes_meets_no_cache_and_only_the_step_that_needs_itholds every workflow to this. A job's permissions are read from its ownpermissions:key, written on one line (write-all) or nested, and otherwise from the workflow's. A job whose permissions write:persist-credentials: false, directly or through a step anchor;GH_TOKENin job-levelenv.build(contents: write),release-publish,nightly-red(issues: write) andpublish.yml'spublish(id-token: write). Each checks out withpersist-credentials: false.nightly-redhas its own checkout step for this, not the shared*checkout.actions/download-artifactv4.3.0 joinsCI_ACTIONS, pinned by commit.timeout-minutes: 60onreleaseis a wedge guard. It is sized from thetcgjob, the same container building and booting one image: 13m07s, 9m41s and 10m17s on three nightly runs (gh run view). Both jobs joinnightly-red'sneeds.imagerelease::boots, shared by the job andrelease_command_boots, requires, within a liveness ceiling:[boot] startnames says it started;compositor: ready,netd: readyand logd's line;Any
PANICorpanicked atline fails it. It fingerprints both firmware files (fingerprint::whole_device) before the boot and again after QEMU is reaped, and fails if either changed. A missing firmware file is refused by name.Hosts. The notes print two lines:
Host::MacosAppleSilicon(Homebrew's QEMU, TCG) andHost::LinuxKvm(Debian'sqemu-system-x86andovmf, KVM). The reader is assumed to have QEMU installed.releasejob's own boot.release_command_boots(tests/common/release.rs). It is in no tier and in no test table. The suite's--release-commandflag runs it and nothing else, and refuses any other word beside it. A disabled row makes that run exit 1, so a run that booted nothing is never green.portability-macosjob runs on an Apple Silicon runner with Homebrew's QEMU. After its--build-onlyit runsenv -u GITHUB_ACTIONS -u CI cargo test --test toyos-build -- --release-command. Nothing else runs the flag.std's
library/, one way.licence::std_libraryanswers:rust/library;fetched_library.main'sgit submodule update --initbranch is deleted.fetched_libraryworks as follows:--depth 1 --filter=blob:none, sparse. The sparse set is/library/plus one pattern for each name inLICENCE_FILES, the listlicence_filesreads a package's texts by, matched in any case. So a top-level licence file of the fork cannot be left out of the fetch while a dev host's notice has it.target/licence/fork.partialunderbuildlock::licence, and is then renamed to.licence-fork/. A fetch that is cut short is therefore never at the path a later call reads..licence-fork/is a direct child of the checkout, hidden and ignored as.build-locks/is. std's manifest namestoyosandtoyos-abiat../../../from its crates. Undertarget/they do not resolve: with the fork attarget/licence/fork/<commit>/,cargo metadatafailed withfailed to read `…/target/licence/fork/toyos/Cargo.toml`.buildlock::licenceis one exclusive lock per worktree over three writes: the fork's fetch, the walk's scratchtarget/licence/Cargo.lock(copy throughcargo metadata), and the release notice. It is taken with no other lock held.the_release_notice_carries_every_package_and_file_it_shipstakes std fromstd_library, as the build does. On a dev host it reads the checkout's fork and fetches nothing. On CI's host runner, which has norust/source, it isfetched_library.a_fetch_cut_short_is_fetched_again_and_a_new_pin_replaces_the_forkcovers the fetch offline against afile://remote. That remote carries two top-level files perLICENCE_FILESname, one upper-case and one lower-case, and the test asserts that each is checked out.Licence notices (
licence::notices), written from the licence gate's own walk:authors, where its source is, and its licence texts. The source is:.cratedownload for a registry package;uefi,uefi-raw,uefi-servicesanducs2.license,licence,unlicense,copying,copyrightornotice, plus itslicense_file..git.LICENSES/, one for each part of anAND. For anOR, it gets the Apache-2.0 branch where there is one: that text is whole as it stands, while MIT's asks for a copyright line. Otherwise it gets the first branch the fork holds.fortanix-sgx-abi, std's for SGX only). The notice's opening sentence says so.NOTICEsection over a file that ships is included, less what is pending the owner.The notice goes on the release's ROOT at
share/licences.txtand beside the release aslicences.txt. Both are the one file the build wrote.The notes. Before the
ddline they name:ToyOSImageFloor-Iand 16 hex digits, under vendor GUID33be3d4a-30e6-49f5-8050-f169d93a20fb, fromtoyos_update::floor);dmpstore -din a UEFI shell does;BootNext;The disk paragraph names the one disk a boot may write though it was not given it. With two sticks of one image plugged in, the loader can write its log to the one it did not boot from. The notes cite
issues/boot-media/the-loader-writes-the-first-disk-carrying-its-log-guid-not-the-one-it-booted-from.md, and a test requires that issue to be open while the sentence stands. The withheld list comes frompending_owner.gh's answers. Two pure functions read them:held_oftakes onlygh's ownrelease not foundas nothing published. A bad token was measured to answernon-200 OK status code: 401 Unauthorized …, exit 1, and that is an error here.releasesrefuses a listing that fills its 1000 limit, and an entry without a tag and a time.The disk test.
storage::foreign_disk_untouchedboots twice onProfile::UsbDisk. Each boot has the NVMe disk, whose TOYOS-DATA partition holds another system's volume, and one USB disk beside the boot stick:Each boot asserts, in order:
run shutdownand QEMU's exit (await_exit), the kernel's line for reading that USB disk's table is in the log;Gates (d30dfff)
cargo run -- --ci host: EXIT=0,Host: 49 step(s), all green.cargo test --lib: EXIT=0, 393 passed, 1 ignored.cargo run -- --clippy: EXIT=0,10 invocations clean.cargo test --test toyos-build --no-run: EXIT=0.Host red arms at this head. Each is a checked patch (
git apply --check), run, then reversed, withgit statusempty after. The test binary compiled in each run; the two workflow patches change only YAML the test reads at run time:release'spermissions:block replaced bypermissions: write-all(m-a.patch):a_token_that_writes_meets_no_cache_and_only_the_step_that_needs_itEXIT=101,nightly.yml: release restores a cache with a token that writes.with: persist-credentials: falsedeleted fromrelease-publish's checkout (m-b.patch): the same test EXIT=101,nightly.yml: release-publish keeps a token that writes in its checkout./library/,/COPYRIGHT,/LICENSE-*,/LICENSES/(m-sparse.patch):a_fetch_cut_short_is_fetched_again_and_a_new_pin_replaces_the_forkEXIT=101,LICENCE-A was not checked out.The notice test with no fetched fork and no network for git:
.licence-forkmoved out of the checkout, thenGIT_ALLOW_PROTOCOL=file CARGO_NET_OFFLINE=true cargo test --lib -- licence::tests::the_release_noticeEXIT=0. No.licence-forkwas made.Host red arms at 20179a7:
fetched_libraryput back as it was, fetching into its final path:a_fetch_cut_short_is_fetched_again_and_a_new_pin_replaces_the_forkEXIT=101,git rev-parse HEAD exited exit status: 128: fatal: ambiguous argument 'HEAD'. That is the unborn HEAD a failed fetch left, refused on the next call./COPYRIGHTdropped from the sparse set:the_release_notice_carries_every_package_and_file_it_shipsEXIT=101,std cites no COPYRIGHT.ORgiven its first branch held:an_or_is_given_apache_2_0s_standard_text_where_it_is_a_branchEXIT=101,left: ["MIT.txt"] right: ["Apache-2.0.txt"].the_digest_covers_every_asset_and_refuses_anything_elseEXIT=101,SHA256SUMS is outside the digest.contents: writeback on thereleasejob:a_token_that_writes_meets_no_cache_and_only_the_step_that_needs_itEXIT=101,nightly.yml: release restores a cache with a token that writes.never writtenagain:the_notes_cite_the_open_defect_behind_the_disk_a_boot_may_writeEXIT=101.At 002bc8d:
shipped package(s) carry no licence text;ghfailure read as absent: EXIT=101;Run by the orchestrator
At 20179a7 (556r3):
foreign_disk_untouched: EXIT=0.byte-oracle-nvme-designated.patch: EXIT=1,the kernel wrote to …/foreign-disk.img, a disk it was not given.byte-oracle-usb-designated.patch: EXIT=1,the kernel wrote to …/bare-stick.img, a disk it was not given.Owed:
release_command_bootson an Apple Silicon Mac after the edk2 fix, with the row removed (redlist-enable-release-command-boots.patch):cargo test --test toyos-build -- --release-command. Then withreadonly-removed.patchon top.release-publish'sneeds, thebuildandnightly-redcheckouts without a persisted credential, andportability-macos's--release-command.gh's draft path.High-risk: the two checks
A boot writes no disk it was not given:
The published command line writes no firmware file:
readonly-removed.patch, owed.The token that writes releases meets no code a build ran:
m-a.patchandm-b.patch, EXIT=101 above.GITHUB_TOKEN Permissionsblock GitHub prints in each job's set-up log, which the branch dispatch owes.Unsure
release-publishdoes not needportability-macos. So a night whose macOS line did not boot still publishes notes that print that line. Until the edk2 fix lands, that line does not boot andportability-macosis red every night.build's bootstrap and toolchain steps have not yet run with no persisted credential.ToyOSOrg/ToyOSandToyOSOrg/rustare public (gh repo view … --json visibility), so their anonymousgit ls-remoteand submodule fetch are expected to work. The dispatch owes that measurement.Filed
issues/build/the-toolchain-install-unpacks-an-asset-no-digest-vouches-for.md:release::installunpacks and links the toolchain asset with no digest check. The nightly'sbuildjob andrelease-publishhold a token that can replace it. The owner is the release module. The exit condition is a digest that no job holding a write token can rewrite.issues/boot-media/the-loader-writes-the-first-disk-carrying-its-log-guid-not-the-one-it-booted-from.md.issues/kernel/the-kernel-dies-at-boot-on-the-edk2-firmware-qemu-ships.md,expected-reduntil the edk2 fix lands.issues/build/a-toolchain-release-takes-the-latest-badge-from-the-image-release.md.🤖 Generated with Claude Code