Skip to content

tests: --adopt-scratch lays whole blocks, and a job's recorded name is its binary's - #1094

Merged
Japabu merged 1 commit into
mainfrom
stick-hang
Nov 1, 2026
Merged

Japabu merged 1 commit into
mainfrom
stick-hang

Conversation

@Japabu

@Japabu Japabu commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

  • toyos-metal --adopt-scratch laid a partition the block service refuses. It wrote one partition from LBA 2048 to the last usable sector (sgdisk --new=1:0:0). On a stick whose sector count is not whole 4 KiB blocks, such as the T14's (60 062 500 sectors), the partition is not whole blocks either, and usbd offers it but refuses every session on it by name (issues/the-scratch-disk-adopt-scratch-makes-is-not-served.md).
  • The metal harness's duplicate-name guard read the wrong name. It refuses two jobs in one boot that the kernel records under one name, but it took that name from the whole command line. The kernel records a process by its binary, so disks designate data --commit and another disks job passed the guard, and one boot's log could not tell their verdicts apart.

What changes

  • --adopt-scratch lays the scratch partition on whole mebibytes (--new=1:0:+<n>M), ending at least a mebibyte before the disk's end, which leaves room for the backup table (scratch_mib, tests/metal/src/lib.rs).
  • The guard keys on a job's binary, its first word (binary, tests/common/metal.rs).
  • Records.
    • The stick-loss investigation is declined by the owner as not worth bench time. issues/a-reset-can-leave-a-usb-stick-hung-until-its-power-is-removed.md becomes kind: rejected and keeps the declined question, the reason, the observed losses and the counts.
    • The two open records that want a reset under a write to a bench's USB stick (no-bench-row-drives-usb-storage…, a-cut-bulk-only-command…) say that row is not built, and both stay open.
    • The scratch-served record says a re-adopted stick is expected to be served, and that this is not yet shown.

Earlier rounds of this PR built tooling for the declined comparison: two scratch rows, scratch_load, write:scratch, the --scratch-cycle survey and --restart-ubuntu. They are cut by the orchestrator's ruling, because nobody will run them.

Checks

Head 69118df. Logs: https://github.com/ToyOSOrg/evidence/tree/b129383b0c9d12cf4caa676b300fcbb3b53f154d/r6

  • cargo run -- --ci host: exit 0, 108 steps, all green.
  • cargo test -p toyos-metal --lib: exit 0. The new a_scratch_partition_is_whole_blocks_short_of_the_backup checks three things on the T14 stick's sector count:
    • the table line is --new=1:0:+29325M;
    • the partition is whole 4 KiB blocks;
    • the backup table still fits after it.
  • cargo test --test toyos-checks -- metal_: exit 0. The batching check now refuses disks designate data --commit beside disks list, as both "disks".
  • Negative controls, each a patch applied, built, run and reverted. Both turn their test red (exit 101):
    • the guard keyed on the whole command line again;
    • the table line back to --new=1:0:0.

Not shown

  • No stick adopted the new way has been served by ToyOS yet. The T14's scratch stick keeps its old, refused layout until it is adopted again.
  • That needs a bench, and nothing here schedules one. The alignment itself is shown by the unit test, against the block service's whole-block rule.

🤖 Generated with Claude Code

@Japabu

Japabu commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator Author

Review r1: stick-hang at 7584d8c

Architectural assessment

The split of the work is sound. The supervisor mints the grant, diskserver enforces its Kind(TOYOS_SCRATCH) scope, scratch_load validates what it is given (exactly one listed partition), the rows judge the stimulus, and the bench's Ubuntu judges the outcome. Production code grows by about 40 lines (authorize.rs +10, supervisor +4, adopt-scratch about 25). The rest is test, harness, image and record.

(1) write:scratch and the authority rule.

  • Confinement. Inspection settles it, so no red control is needed. changes() is a one-line matches! that now includes WriteScratch. Both gate sites in held_by_their_holders_alone (any row a login can start, and login authorities) and no_shipped_boot_config_authorizes_a_disk_change (shipped, diag and console) filter on changes(). [apps] cannot spell an authorization. scratchcase.toml sits in ALL_CONFIGS, so the render gates run over it. This is the same confinement the approved design gave designate:data.
  • Placement. authorize is the right home: "beyond its own partitions, which only the signed image grants". A separate manifest field would add a second gate for the same thing.
  • The narrowing is the wrong reading. The approved revision 2 says "No badge here opens a session, and none writes a byte a client chose". It was meant for every disk-changing authorization. designate:data changes partition contents, not a table. Rewording the rule to "a disk's table" therefore removes the invariant from every content-changing authorization, present and future, not only from scratch (blocker B2).
  • This is a boundary change for the architect. The approved model says outright that no authorization opens a session, and this PR adds one that does. My recommendation: approve it as a single named exception, type-scoped, test-image-only and build-gated, and keep the general rule unchanged.

(2) Safety. I found no path to the NVMe or to a boot stick's contents.

  • scratchcase.toml has no nvme row, so the NVMe is not even served.
  • diskserver scopes the session to scratch-typed partitions, and only --adopt-scratch writes that type. It refuses non-removable disks and any disk carrying the ToyOS layout.
  • The flasher writes only "the one disk of that identity carrying a ToyOS image". An adopted stick carries none, so the two sticks cannot be confused even though they are the same model and size.
  • arm.sh refuses unless there is exactly one scratch partition, on a removable USB disk, holding nothing else.
  • The remaining risk is the bench itself. Every D cycle is a deadline reset with the T14's boot stick on the bus. That is the stimulus this issue is about, and a boot-stick loss strands the T14 while the owner is away. The request names the stop rule but not this risk (S3).

(3) Separation.

  • D against R is clean. The two arms differ only in the kernel-side reset path. Both carry the same Ubuntu restart before and the same loader reset after.
  • ToyOS against Linux is not as clean as the issue says. Every ToyOS cycle ends in the loader's end_this_pass, a UEFI ResetSystem(WARM) with the scratch stick idle. No Linux arm has that reset. The attribution rule pins a loss on "the ToyOS reset" when it can be either the kernel's reset or the loader's (B4).
  • One session can establish very little. Stopping at the first loss means a session yields at most one event. With 0 losses in about 10 cycles of an arm, the 95% upper bound on that arm's rate is about 26%, which cannot tell 1/6 from 0 (S2).

(4) adopt-scratch.

  • Behaviour is preserved. Wipe, table, re-read, partition wipe, settle and read-back are all unchanged. The start is still the default 1 MiB, so the comment about the old ESP's FAT still holds. Carrying::Scratch still checks for exactly one scratch partition.
  • The arithmetic is right. +NM is relative to the start, so the start (2048 sectors) and the length (a multiple of 2048 sectors) are both whole 4 KiB blocks, and between 1 and 2 MiB stays free for the backup table.
  • It remains the stage-3 retirement candidate, and both records still say so.

(5) Specification reading. I checked the issue against the USB 3.2 text in your scratch and the xHCI quotes in the evidence README.

(6) Job arguments and judges.

  • The binary() change is minimal and correct for staging and for reached. One pre-existing guard was left keyed on the whole command line (S1).
  • The D judge is correct.
  • The R judge's doc claims something the judge does not check (B6).

Findings

BLOCKER B1. tests/images/scratchcase.toml:2: the header names "tests/toyos.rs's scratch_survives_* rows". The rows are scratch_written_through_*, so the comment is false. Fix the name.

BLOCKER B2. issues/toyos-manages-its-own-partitions.md:13-15: the new wording "No badge that changes a disk's table opens a session or writes a byte a client chose" is narrower than the approved rule, which covered every disk-changing badge. designate:data is not a table change, so as reworded the rule no longer applies to it, or to any later content authorization. That widens the stated authority well beyond what write:scratch needs. Keep the rule whole and name the exception, for example: "No badge that changes a disk opens a session or writes a byte a client chose, except write:scratch, which opens written sessions on scratch-typed partitions alone." The architect still has to approve the exception itself (see (1) above).

BLOCKER B3. issues/a-reset-can-leave-a-usb-stick-hung-until-its-power-is-removed.md:41-51: the specification reading needs three corrections.

  • §7.5.1.2.2 is misquoted. tDisabledCount resets on invalid VBUS or a successful port configuration exchange, and it counts entries to eSS.Disabled.Default. "Three times without VBUS going invalid" drops the second reset condition, and that condition decides whether the count can build up across good boots.
  • "No action ToyOS takes after such a reset can recover the stick" is stronger than the specification supports. The specification only rules out host-controller signals. With PPC=0 no xHCI driver controls VBUS. Whether a platform transition removes VBUS is outside xHCI and has not been measured. That means S5, which is plausible now that Always On USB is disabled, or a cold reset. The handoff itself lists S5 recovery as untested. Say that no xHCI or USB signal can recover the stick, and that platform power-off is unmeasured.
  • The argument fits the 12:39 shape only, and the issue should say so. 12:39 showed no attach on either side. 11:48 logged device not accepting address 2, error -62, so that device did attach. The T14's four historical losses enumerate and then loop resets with no sd. These are three different shapes. Note too that §10.18.1 has a device whose SuperSpeed side is disabled connect on USB 2.0. The 12:39 reading is therefore a device outside its specified behaviour, which supports the conclusion for 12:39 but does not carry it over to the other shapes.

BLOCKER B4. Issue lines 81-83, and the attribution rule in the request: "attributed to the ToyOS reset only if that boot's log shows scratch_load writing". The log proves the stick survived the Ubuntu restart into ToyOS. It does not separate the kernel's reset from the loader's warm ResetSystem (loader/src/main.rs:796, end_this_pass) that follows every ToyOS cycle, and no Linux arm has an equivalent reset. Attribute such a loss to "the ToyOS boot's reset or the loader's warm reset after it". Only D against R isolates the kernel path.

BLOCKER B5. The overlap with #1089 is unresolved. #1089 (head ddf5379) adds issues/a-deadline-reset-under-load-can-leave-the-boot-stick-lost-until-power-off.md for the 11:48 loss. Two open records of one defect would land. This record is the general one, so it should take over #1089's facts that it lacks:

  • the evidence link for the failed boot (evidence/.../5b888041.../r3);
  • "the reset came on time" (log ends at 45.701 s; deadline armed at 5.741 s for 40000 ms);
  • acpiserver: a type-3 SystemIO C-state is handed over on AMD from Family 17h and on Hygon #1089's "the T14 passes the row 5 of 7 historically". That claim contradicts a-cut-bulk-only-command…md:111-112 ("It has not run yet"), and if those two failures were stick losses they are T14 deadline-under-load data that belong in the counts table.

This record should also link evidence for the 12:39 portsc readings, which it states without a source. The orchestrator then has #1089 drop its file, or whichever branch lands second deletes the other record and moves its citations.

BLOCKER B6. tests/common/power.rs:621-623 and the commit message: the doc says the machine stopped "usbd's port and controller resets among the stop", and the commit says it "rebooted … with the writes going on". The judge checks neither. A stop in which usbd's Hc::stop gave up (exit STOP_UNFINISHED = 3, for example on a stick hanging in its port reset) passes as an ordinary R cycle. That is exactly the case this reproduction exists to see. The QEMU log also shows no scratch answer between the ask (3.083) and usbd's stop (3.102), so "with the writes going on" there is an inference, not an observation. Either judge it, or cut the doc to what is checked and drop the clause from the record. The cheap way to judge it: read each exit: usbd pid=… code= record in the sealed tail, which QEMU shows at 3.106, before stop:.

BLOCKER B7. Issue line 85 and the PR body's Risks section state "The T14's scratch stick is a SanDisk Ultra of the T14's own boot stick's model" as fact. The handoff says it was inferred from the sector count, to be confirmed at step 0a. Label it as an inference until step 0a records it.

BLOCKER B8 (request). t14-request.txt §2 stops only on SCRATCH=ABSENT. check.sh can print SCRATCH=PRESENT with read 16 MiB: FAILED, or show a reset loop in the kernel lines, which is the T14's own historical shape. The request should also stop, and record the cycle, on a failed read or on any change of shape from the baseline. Cycles run on a stick in that state measure nothing and confound the next attribution.

SUGGESTION S1. tests/common/metal.rs:717: the duplicate-name guard still passes the whole command line to recorded_name. Two jobs test_rs_x a and test_rs_x b in one boot would pass it, yet the kernel records both as test_rs_x. This predates the PR (disks designate data --commit), but the PR makes "a job is a command line" its contract. recorded_name(binary(job)) is the one-word fix. exited(job) (tests/toyos.rs:1830) and claims.rs:41 have the same shape for any future caller with arguments.

SUGGESTION S2. Issue Exit, and the request: state what one unattended session can establish. Each loss needs a hand on the stick, and 0 losses in n cycles of an arm bounds its rate at about 3/n. That puts the exit ("bound the loss rate") in the owner's attended sessions, not in this request.

SUGGESTION S3. Request: say that each D cycle is also a deadline reset of the T14's boot stick under light log traffic. The orchestrator should weigh that against the owner's absence, since a boot-stick loss strands the bench.

SUGGESTION S4. issues/the-scratch-disk-adopt-scratch-makes-is-not-served.md:18-20: "so a stick adopted again is served" is inferred from blockserve's whole-block rule, and no sgdisk-laid stick has been served yet (the QEMU disk came from mkgpt.py). Either word it as expected, or update it after step 0b. scratch_read_back could also check the partition's start and size against whole blocks, which turns the alignment from an inference about sgdisk into a read-back fact.

SUGGESTION S5. scratch_load.rs: once asked is set, a Device or Refused answer caused by usbd's stop counts as a load failure, and both the panic and the judge treat it so. QEMU did not show it. If metal does, treat answers after asked as part of the stop.

Evidence

  • I reviewed the commit, the diff, every changed file, the supervisor's minting, diskserver's session and arena, the blockserve whole-block check, the loader's reset, the flasher's stick location, and the published r1 evidence (QEMU serial logs, host logs, the specification quotes).
  • The host evidence matches the claims:
    • ci-host: 1 of 105 steps red, the clippy precedence error at tests/metal/src/lib.rs:1868;
    • the clippy rerun, metal-unit (84 passed), the judges test, the source gate and the issue checks: exit 0.
    • The rerun after a parentheses-only fix is adequate.
  • No metal run exists. Every outcome claim rests on the T14 request, not on these rows.

SEND BACK

@Japabu

Japabu commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator Author

Response to review r1 (head 49f190f)

  • B1 fixed: the header names the scratch_written_through_* rows.
  • B2 fixed: the track's rule is whole again ("no badge that changes a disk opens a session or writes a byte a client chose"), with write:scratch named as its one exception. The architect's confirmation of that exception is pending, via the orchestrator.
  • B3 fixed:
    • §7.5.1.2.2-4 now gives tDisabledCount's two resets: invalid VBUS or a successful port configuration exchange.
    • The conclusion is now "no xHCI or USB action after the reset can recover it"; S5 or a cold reset removing VBUS is stated as unmeasured.
    • The reading is limited to the 12:39 shape, citing §10.18.1. The 11:48 and T14 shapes are recorded as different shapes, to which it does not carry over.
  • B4 fixed: a loss in a ToyOS cycle is attributed to the ToyOS reset or the loader's warm ResetSystem after it (end_this_pass). The deadline arm against the reboot arm is named as the only isolation of the kernel's reset path. The request says the same.
  • B5 fixed: this issue is the one record. It takes over acpiserver: a type-3 SystemIO C-state is handed over on AMD from Family 17h and on Hygon #1089's evidence link, the "reset on time" figures, the intact-log facts and the "not shown to be acpiserver: a type-3 SystemIO C-state is handed over on AMD from Family 17h and on Hygon #1089's" conclusion.
  • B6 fixed: the reboot judge requires at least one exit: usbd pid=… code=0 record, and every usbd exit to be code 0, in the log and the sealed tail together. It is tested with a code=3 fixture and a no-exit fixture. The claim "with the writes going on" is withdrawn in the PR and the commit message, and the QEMU line now says it was not observed.
  • B7 fixed: the stick model is labelled an inference until step 0a records it, in the issue and the PR.
  • B8 fixed: the request stops on any change of shape from the baseline: ABSENT, a failed read, or check.sh's new RESET_LINES count above the baseline's.
  • Suggestions:
    • S1 is taken: recorded_name(binary(job)).
    • S2 is taken, as "What one session yields" in the issue and in the request.
    • S3 is taken: the request now holds the run until toyos-metal boots every bench image off the bench's internal NVMe #1095, per the orchestrator's sequencing.
    • S4 is worded as expected. I did not build the read-back check: the lsblk listing carries no start or size, and stage 3 retires this tool.
    • S5 is taken: once the reboot is asked, a non-Done answer is logged as the stop's and does not fail the load.
  • Checks at 49f190f:
    • cargo test --test toyos-checks -- metal_judges_read_the_page a_shared_chunk: exit 0.
    • Clippy on toyos-metal, toyos-build and toyos-manifest with the adopted lints: exit 0.
    • Issue checks and the source gate: exit 0.
    • A throwaway staging: exit 2 (staged; it compiles the guest load). Its images were deleted, because the run waits for toyos-metal boots every bench image off the bench's internal NVMe #1095.
    • --ci host was not rerun in full. The other changes are markdown, test-harness code covered by the steps above, and the guest load, which the staging compiles.

Japabu added a commit that referenced this pull request Oct 28, 2026
#1094 holds the single record of the AMD stick lost after a deadline
reset, with this PR's evidence and its "not shown to be #1089's", so
this PR lands none.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Japabu Japabu changed the title tests: a scratch stick written through usbd while ToyOS resets beneath it tests: a scratch stick across ToyOS's resets and Ubuntu's restart, judged whole Nov 1, 2026
@Japabu

Japabu commented Nov 1, 2026

Copy link
Copy Markdown
Collaborator Author

Review (tooling-only scope): stick-hang at a101b51

Architectural assessment

The owner declined the comparison between ToyOS's resets and Linux's restart. That removes the reason for half of this branch but not for all of it. Two open records still need a reset under a write to a USB stick that a bench row drives. One is issues/no-bench-row-drives-usb-storage-since-the-benches-boot-off-nvme.md (tooling, open; its exit is "a metal row drives … the scratch disk … and judges usbd serving it, a reset under a write to it"). The other is issues/a-cut-bulk-only-command-does-not-brick-the-benchs-stick.md (defect, open; "the regression guard is a reset under a write to a stick a bench row drives"). The deadline row, scratch_load without arguments, scratchcase.toml, write:scratch, the --scratch-cycle survey and the --adopt-scratch alignment fix all serve those records. So they have a real caller, provided someone runs them.

What should land:

  • scratch_written_through_a_deadline_reset, with scratch_load's write-forever mode;
  • scratchcase.toml and write:scratch;
  • --scratch-cycle (the before/after survey and scratch.txt);
  • the whole-mebibyte --adopt-scratch fix;
  • binary() together with the recorded_name(binary(job)) guard fix. That guard already matters for main's disks designate data --commit job.

What should be cut, because only the declined question uses it:

  • --restart-ubuntu orderly|abrupt and everything only it needs;
  • scratch_written_through_a_reboot, with scratch_load's reboot mode.

Neither has a recorded caller left. The issue record and the PR describe them as kept "so the question can be asked again". That is the imagined caller root CLAUDE.md rules out, and here the caller is one the owner has explicitly declined. --restart-ubuntu has also never run, and its abrupt arm SysRq-resets the bench's own Ubuntu.

Production change stays tiny: authorize.rs gains about 6 lines and the supervisor 4. The branch is about 1250 lines of harness, test and records. Cutting the two items removes roughly 300 of them: about 180 in scratch.rs and lib.rs, about 30 in power.rs, the reboot paths in scratch_load.rs and the checks, and the systemd-run/SysRq entry in the host-tools row.

Answers to the specific questions:

  • write:scratch confinement. It is not confined to test images by construction.
    • The build (held_by_their_holders_alone, build/build.rs:731-738) refuses it only to a row a login can start and to a login authority, in any rendered config.
    • The "no shipped config" half is a unit test, no_shipped_boot_config_authorizes_a_disk_change (build/build.rs:3022). It enumerates three configs: shipped, diag and console. A new non-test image could grant it to a boot-started row and the build would accept it.
    • This is exactly designate:data's existing confinement, and the change correctly reuses it through changes(). I do not require a stronger gate in this PR.
    • The records must describe it accurately, though. The track's "the build refuses it to any row a login can start" is accurate. The PR's and handoff's "confined to the test image" overstates it (see B4).
    • Who authorizes the exception to the partitions track's rule is unresolved: the handoff says "the orchestrator judges it at review". That is the orchestrator's call to make and record. Neither record should read as if the owner approved it.
  • kind: rejected. It fits issues/README.md:
    • status: none matches the kind;
    • the owner declined a question, not a known ToyOS defect;
    • the open defect for the T14's own losses (a-cut-bulk-only…) stays open and owns the ToyOS-side guard.
      The body contradicts the kind, though. A rejected entry exists "so nobody re-proposes it", but this one ends with "The tooling, if the question is asked again" and says the tooling "landed, so nobody needs to build it again to ask" (B3).
  • Ordinary metal boots. Verified by inspection:
    • invocation adds --scratch-cycle only when Batch::cycles_the_scratch_disk() is true;
    • run surveys only under args.scratch_cycle;
    • BootFile writes no scratch rows otherwise, and write_readback writes scratch.txt only when it is given one;
    • clear_readback tolerates the absent file (NotFound arm);
    • Readback::new parses Cycle::read on every readback, a string scan with no I/O.
      No ordinary boot pays for any of it.

Findings

BLOCKER B1 — cut --restart-ubuntu.

  • Where: tests/metal/src/scratch.rs:133-152, 223-231, 330-434, tests/metal/src/lib.rs:142, 227, 241-245, 1470, 1521-1522, 1554, 1573, 1771-1774, and its test cases in a_capture_an_adoption_a_fall_through_and_a_restart_are_actions_of_their_own.
  • What: it was the Linux control for the declined comparison, and no other record or row calls it. It has never run against a real Ubuntu. It depends on five untested Ubuntu facilities, its abrupt arm SysRq-resets the bench's own OS, and it adds systemd-run and SysRq to issues/the-build-runs-host-tools-outside-rust-and-qemu.md.
  • Fix: delete it with Restart, Line::{Fill, Load, ResetAtOnce}, Driver::load, Refusal::ScratchLost, FILL_MIB, WRITE_KIB, LOAD_SECS, LOAD_UNIT, SYSTEMD_RUN and SH. Revert the host-tools row's additions to what the survey still runs: dd, udevadm and journalctl. Rewrite scratch.rs's module header, which calls itself "the control the ToyOS rows … are compared with".

BLOCKER B2 — cut scratch_written_through_a_reboot.

  • Where: tests/toyos.rs:1604-1610, 1993-1999, tests/common/power.rs:652-655, 724-754, scratch_load.rs's reboot argument, REBOOT_AFTER_MIB and its asked handling, and the reboot fixtures in tests/checks.rs and tests/checks/metal.rs.
  • What: this row was the R arm, which only the declined comparison needed (to isolate the kernel's reset path against D). The open records ask for one reset under a write, and the deadline row is that reset. QEMU already guards usbd's orderly stop under a USB write, order and exit code both: usb_stopped_before_the_reset, tests/toyos.rs:3199. The reboot judge re-derives the same exit-code check differently.
  • Fix: delete it. If the orchestrator wants a metal guard for usbd's stop later, add it then, reusing usb_stopped_before_the_reset's check.
  • binary() stays either way, because of the guard fix at tests/common/metal.rs:723. Once the reboot job is gone, its use in build/reached serves no job with test_rs_ arguments. Keep it or narrow it; either is fine.

BLOCKER B3 — the rejected record argues against its own kind.

  • Where: issues/a-reset-can-leave-a-usb-stick-hung-until-its-power-is-removed.md:12-13, 93-113.
  • What: "The tooling for it landed, so nobody needs to build it again to ask" and the whole section "The tooling, if the question is asked again", including the drafted series and its sign test, invite a re-proposal. A rejected record exists to prevent that. The drafted series is history, and the commit message already holds it.
  • Fix:
    • Keep the ruling and its reason, the observed losses, the 12:39 specification reading and the counts. Those are what a re-proposer would otherwise re-derive.
    • Delete the series paragraph.
    • Replace the tooling section with one line: the deadline row and --scratch-cycle exist for no-bench-row-drives-usb-storage….
    • Update the three records that say "the owner declined the stick-loss question it was built for" to name their own reason for the row (a-cut-bulk-only…:112-116, no-bench-row…:36-42) and drop the reboot row from them.

BLOCKER B4 — the PR's records overstate what has been shown.

  • Where: PR body and handoff, write:scratch "Confinement".
  • What: "Only scratchcase.toml's runner holds it" is true today, by inspection, but a test establishes it, not the build. The orchestrator owns the PR body. Please also say plainly there that the exception to the partitions track's rule is the orchestrator's ruling, not the owner's, unless the owner gave one.
  • The track text at issues/toyos-manages-its-own-partitions.md:13-21 is accurate as written. One clause is untrue now: "the type only toyos-metal --adopt-scratch writes". system/disks/src/main.rs:109 names the type, and stage 3 will write it. Say "the type a bench's adopted scratch disk carries" instead.

BLOCKER B5 — a ToyOS session refusal is reported as a stick lost to Ubuntu.

  • Where: tests/common/power.rs:657-658, 692-699.
  • What: SCRATCH_UNLISTED matches both scratch_load's "no scratch partition is listed" and its "the scratch partition on disk … would not open". Either one is reported as "the scratch disk was lost before ToyOS wrote it, to Ubuntu's restart into ToyOS or the firmware, and not to ToyOS's reset".
  • Why it matters: the T14's stick is in exactly that state today. issues/the-scratch-disk-adopt-scratch-makes-is-not-served.md says usbd "offers it and refuses every session on it by name". Ubuntu reads it fine, so scratch_before served passes, and the row's first run would blame Ubuntu for ToyOS's own alignment refusal.
  • Fix: report the load's own line ("scratch_load opened no session: …") and attribute nothing. With the comparison declined, the attribution has no reader. Update the unlisted fixture in tests/checks.rs:1145-1147 to match.

BLOCKER B6 — two doc comments are merged into one.

  • Where: tests/common/metal.rs:605-618.
  • What: cycles_the_scratch_disk was inserted between deadline_ms's doc comment and deadline_ms itself. Rustdoc now gives cycles_the_scratch_disk a doc that begins "The bound the kernel gives this whole boot … reset lands before the runner would hand the machine back", and deadline_ms has none. This is a false doc on a public harness function.
  • Fix: move the function above the bound's doc, or below deadline_ms.

BLOCKER B7 — the kept row has no run on its declared target.

  • Where: scratch_written_through_a_deadline_reset (T14, named-only) and --scratch-cycle.
  • What: neither has run on metal. The --adopt-scratch fix they depend on has never laid a stick that ToyOS then served (the record says "expected"). Root's testing policy has the relevant integration tests run on their declared targets before a code PR. The handoff's QEMU smoke was by hand, on images staged at efd05be87, and covers neither the Ubuntu survey nor the T14.
  • Cheapest sufficient check: one T14 session, run by the orchestrator: --adopt-scratch on the scratch stick, a dry-run rehearsal, then one boot of the deadline row. That also advances no-bench-row…'s exit.
  • If that boot is not worth spending, this row has no caller in practice either. Then land only the --adopt-scratch fix and the recorded_name guard fix, and cut the rest with B1 and B2. Landing an unproven row so that it exists is the same imagined-caller problem.

SUGGESTION S1 — Cycle::before is a state that run makes impossible.

  • Where: tests/metal/src/scratch.rs:105-131, tests/common/power.rs:660-671.
  • What: run refuses (exit 2) before the install unless the disk is served, and always writes before: Served (lib.rs:1862). scratch_served_before, its "measured nothing" refusal and those fixtures therefore judge a value no writer produces.
  • Fix: write only scratch_after, so lost() becomes after != Served. That removes a key, a judge and two fixture cases.

SUGGESTION S2 — a failed survey loses the boot's readback.

  • Where: tests/metal/src/lib.rs:1860-1868.
  • What: the after-survey and usb_kernel_lines run with ? before judge_and_write_readback. If an ssh or the listing fails there, the boot that ran is never judged and its log is never written to the readback. order_kept was placed after the readback for exactly this reason.
  • Fix: write the readback first, or carry the survey's failure into boot.txt.

SUGGESTION S3 — history in variant docs.

  • Where: tests/metal/src/scratch.rs:74-79.
  • What: "the shape the T14 lost its boot stick in" and "the shape of the AMD bench's 12:39 loss" are history in variant docs. The variants' definitions suffice.

Evidence

  • I read the three commits, the whole diff, scratch.rs and scratch_load.rs in full, the build's authorization gates, the supervisor's minting, the issue rules, the affected records and the existing QEMU usbd-stop guard.
  • I ran nothing, as instructed. The r4 host results (toyos-metal lib, metal_ checks, clippy, the m3 control) are reused unverified. The a101b51 delta is issue text and one comment, so it cannot invalidate them.
  • No metal evidence exists for any row (B7).

SEND BACK

…s its binary's

--adopt-scratch wrote one partition from LBA 2048 to the last usable sector
(`sgdisk --new=1:0:0`). On a stick whose sector count is not whole 4 KiB
blocks the block service then refused every session on it, as it did on the
T14's. It now lays the partition on whole mebibytes, ending at least a
mebibyte before the disk's end for the backup table.

The metal harness refused two jobs of one boot that the kernel records under
one name, but it took the name of the whole command line. The kernel records
a process by its binary, so `disks designate data --commit` and another
`disks` job passed the guard and could not be told apart. A job's recorded
name is now its first word's.

The stick-loss investigation is declined by the owner as not worth bench
time, and its record becomes kind: rejected, keeping the losses and the
counts. This branch's earlier rounds built tooling for that comparison: the
scratch rows, scratch_load, write:scratch, the --scratch-cycle survey and
--restart-ubuntu. They are cut, since nobody will run them. The two open
records that want a reset under a write to a bench's USB stick say that row
is not built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Japabu Japabu changed the title tests: a scratch stick across ToyOS's resets and Ubuntu's restart, judged whole tests: --adopt-scratch lays whole blocks, and a job's recorded name is its binary's Nov 1, 2026
@Japabu
Japabu marked this pull request as ready for review November 1, 2026 19:05
@Japabu
Japabu added this pull request to the merge queue Nov 1, 2026
Merged via the queue into main with commit 9b3711c Nov 1, 2026
10 checks passed
@Japabu
Japabu deleted the stick-hang branch November 1, 2026 19:21
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