Skip to content

Track: the supervisor is host-tested and owns the stop - #575

Merged
Japabu merged 6 commits into
mainfrom
wt/toyos-supervisor
Sep 28, 2026
Merged

Japabu merged 6 commits into
mainfrom
wt/toyos-supervisor

Conversation

@Japabu

@Japabu Japabu commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

Tracker only. It files one kind: track issue, issues/isolation/the-supervisor-is-host-tested-and-owns-the-stop.md, and corrects issues/isolation/the-power-broker-authority-with-a-human-in-the-loop.md. No code changes, and nothing is renamed.

What changed and why

  • The power-broker track loses its parenthetical and its item 1. toybox receives the power connector (system.toml, console/system.toml), not Rights::POWER.

Gates

  • cargo test --lib: EXIT=0.

🤖 Generated with Claude Code

https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j

…t's, the rename

One new kind: track issue, issues/isolation/the-supervisor-is-host-tested-and-owns-the-stop.md,
recording the owner's decision to plan three things: init's decisions moved
into a pure host-tested crate, graceful shutdown owned by init, and the
program rename (init -> supervisor, netd -> netstack, logd -> logkeeper,
soundd -> mixer, blockd -> disks, fsd -> files, sshd -> sshserver), each
with an exit a machine can check. No code changes; nothing is renamed.

Verified against the tree at af817e5 and #536's head 5235eda:
- userland/init/src/main.rs is 1,746 lines with no #[test] and no tests/.
- On main the kernel's quiesce runs writeback::drain_all and vfs sync_all
  after freezing userland; on #536 those lines are gone and init's
  Init::stop runs sync_files (one Dir::sync per role but boot, bounded by
  toyos_quiesce::SYNC_MS) after logd's flush.
- #536 deletes quiesce_leaves_the_volume_whole and registers no test for
  the stop's sync.
- src/redlist.rs disables two of the six quiesce tests
  (quiesce_dump_holds_the_stopped, quiesce_wakes_on_the_last_exit); two more
  (quiesce_stops_the_machine, quiesce_wakes_on_the_last_park) run with open
  findings.
- The name `files` is already [programs.files] / userland/files.

Gate: cargo test --lib, EXIT=0.

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

Japabu commented Sep 28, 2026

Copy link
Copy Markdown
Collaborator Author

Review of #575 at d346d9de. CI ci/host run 36416368694 concluded success at this head (run 36416336103 is skipped). The PR is not a draft. The branch has 1 commit: git diff --shortstat origin/main...HEAD gives 1 file, +134. Production 0, tests 0, all of it tracker prose.

Claims about today's tree (checked at origin/main 69d1b53 and at #536 5235eda7)

  • Holds: init flushes logd and then calls the kernel. userland/init/src/main.rs:903-917 (Init::stop: self.log.flush(), then syscap.reboot()/shutdown()).
  • Holds on shipped images only: only init's SysCap carries POWER. It is set at kernel/src/loader/mod.rs:857, and system.toml, console/system.toml and diag/system.toml name no power syscap. It is false for test images: tests/testcases/system.toml:41, tests/blockdcase/system.toml:38, tests/partclaimcase/system.toml:47 and tests/quiescetwicecase/system.toml:16 all grant syscap = [... "power" ...], and toyos-manifest/src/lib.rs:95 makes it nameable. The PR body's "no manifest row names power in syscap" is false.
  • Holds, with one exception: on Storage: file servers for DATA, the log and the boot volume; the kernel's NVMe and FAT go #536 init syncs the file servers. 5235eda7:userland/init/src/main.rs:1233-1234 (flush then sync_files), :1248-1290. drain_all and sync_all are gone from kernel/src/syscall/machine.rs. But the kernel still runs xhci::flush_disks(), the USB write-cache flush, so "the kernel syncs nothing" is not literally true.
  • Holds: [boot] start says its order "means nothing" (system.toml:16). compositor receives filepicker (system.toml:60) and filepicker receives compositor (system.toml:112).
  • True only on Storage: file servers for DATA, the log and the boot volume; the kernel's NVMe and FAT go #536: the logd and log-role cycle. On main /log is the kernel's FAT adapter, and log is logd's own inspect port (system.toml:55). The log role exists at 5235eda7:system.toml:193.
  • Holds: no service is restarted on end on main. close_when_it_ends (userland/init/src/main.rs:511-518) clears the acceptors. On main, Served::Restart only restores the previous binary after a failed swap.

BLOCKER

  • issues/isolation/the-supervisor-is-host-tested-and-owns-the-stop.md:110 — the table records fsd → files as decided — the owner left fsd's name open because files is taken. Lines 114-116 then invent a second decision, renaming the file manager, that nobody made. The row must read "open with the owner", and 114-116 go.
  • …the-stop.md:63-64 — stage 1's exit git grep -nE 'fn (resolve|declared)\b' userland/init already answers nothing today (EXIT=1). git's ERE has no \b, and without it the same grep finds main.rs:1170 and :1204 (log stage1-exit.log). The exit is met before any work. It also goes vacuous as soon as the rename removes userland/init. Use a path-independent check that fails today.
  • …the-stop.md:97-98 — stage 3's exit, "--known-red lists no quiesce_ test", is met by deletion: tests: the measured schedule — Fast is every PR, then Nightly, then Weekly; 15 never-caught tests and the kernel code only they armed deleted #564 (617e934) deletes quiesce_wakes_on_the_last_exit and quiesce_dump_holds_the_stopped and moves three more to Tier::Nightly. Storage: file servers for DATA, the log and the boot volume; the kernel's NVMe and FAT go #536 deletes quiesce_leaves_the_volume_whole. "Coverage comes back" is not checked. The exit must name each quiesce test as registered in tests/toyos.rs's tier table at a named tier, with --known-red <name> answering NO for each.
  • …the-stop.md:77-80 — stage 2's exit cannot fail on the owner's order rule. It has one service and one negative control, and no check of reverse dependency order between two non-storage services. Mutation: ask the services in forward start order, or all at once with storage still last. The stated test stays green. The exit needs a two-service ordering assertion.
  • …the-stop.md:118-120 — the rename exit passes on a partial rename. -w, case-sensitive: 3,219 hits today. -i, substring: 3,954. The difference is 110 distinct identifiers the exit never sees: netd_refused_pipes, blockd_io, sshdcase, LOGD, SounddCounters, every_boot_config_runs_logd, swap_netd, and more (logs rename-exit.log, rename-missed-tokens.txt). The init half likewise misses spawn_init, struct Init and every "asks init" line. The exit needs a case-insensitive identifier-boundary pattern with its false positives (klogd, netdev, netdb, ENETDOWN, BlockDevice, fsdir) named.

NOTE

REMOVE (the track is 134 lines, a screen is the bar)

SEND BACK

Japabu and others added 2 commits September 28, 2026 13:54
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
…d's name open

Answers the SEND BACK on #575 at d346d9d.

- fsd's new name is open with the owner (candidate `fileserver`, `files`
  kept for the file manager); the invented rename of the file manager goes.
- The rename is stage 1, first after #536, briefed as an ABI brief since it
  touches toyos/src, toyos-abi/src, userland/libc/src and the rust fork's
  ToyOS files. Its exit is a case-insensitive substring search over the six
  daemon names and a letter-bounded search for `init`, each with an explicit
  exclusion list judged per match; issue bodies are excluded as recorded
  evidence. Measured outside issues/ at 62e7e8c: 3641 daemon substring hits
  (3419 outside the exclusions), 2289 `init` substring hits, 1589
  letter-bounded (1073 outside the exclusions).
- Stage 2's exit names the crate `toyos-supervisor` and its decisions, now
  including the stop-order derivation and a host test refusing an
  undeclared cycle; it is unmet today and cannot go vacuous under the rename.
- Stage 3's exit adds a two-service reverse-order test that reds on forward
  and all-at-once order.
- Stage 4's exit names the five claims the stop's coverage must assert, by a
  host test or a guest test at Tier::Fast or Tier::Nightly with no redlist
  row, so it cannot be met by deleting tests; the per-test lists that
  conflicted with #564 and #574 go.
- The power-broker track loses its false parenthetical and item 1: toybox
  holds the `power` connector, not the bit.
- Every REMOVE the review listed is taken.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
@Japabu Japabu changed the title Track: the supervisor is host-tested and owns the machine's stop Track: the supervisor is host-tested and owns the stop Sep 28, 2026
@Japabu

Japabu commented Sep 28, 2026

Copy link
Copy Markdown
Collaborator Author

Round 2 of the review of #575, at 883a15f5. CI run 36419150347 ran job host at head 883a15f5 and concluded success. The PR is not a draft. git diff --shortstat origin/main...HEAD gives 2 files, +103 -7. Production code is 0 lines and tests are 0 lines: the whole diff is tracker prose. The measurements below were taken on #536's head 5235eda7, because the rename runs after #536.

Round-1 BLOCKERs

  • fsd → files recorded as decided: CLOSED. :30 now reads "open with the owner". :96 names fileserver as the candidate. The invented rename of the file manager is gone.
  • Stage 1's exit (fn (resolve|declared)\b) was met before any work was done: CLOSED. The crate exit is not met today, because git ls-tree -d 5235eda7 toyos-supervisor is empty. It also names no path the rename removes. The move itself has lost its check: see the new BLOCKER on :66-69.
  • The quiesce exit could be met by deleting tests: CLOSED. :84-87 requires a host test, or a guest test at Fast/Nightly with no redlist row, and says "a deleted or disabled test covers nothing".
  • The order exit could not fail: CLOSED. :77-80 reds on forward order and on all-at-once order.
  • The rename exit passed on a partial rename: CLOSED for the daemon half. A case-insensitive substring search catches every token on the round-1 missed list by construction. The search gives 4068 matches (daemon-tok-5235eda7.txt). Outside the seven exclusions, the only tokens that are not daemon names are NetDaemon, TOYOS-BLOCKDIO and aaasoundd (daemon-left-5235eda7.txt), and each is fair to rename. The init half catches spawn_init, struct Init and "asks init". Its exclusions are a new BLOCKER below.

BLOCKER

  • issues/isolation/the-supervisor-is-host-tested-and-owns-the-stop.md:41-58 — The init exclusion list is inexact in both directions. Applying it at 5235eda7 leaves 1152 lines (init-excl.pl, init-residual-5235eda7.txt).
    • It excludes too much. init( matches process::spawn_init(); at kernel/src/main.rs:446 and every other *_init( call.
    • It excludes too little. Hits that do not name the program remain:
      • TinyCC's corpus, which is third-party (NOTICE:336): init (data) at tests/testcases/tinycc/121_struct_return.c:48, and test_init_bf and test_init_struct_from_struct at 90_struct_init.c:201,240 and in its .expect;
      • tests/test-durations' *_init rows;
      • doom's init: field at userland/doom/src/sound.rs:61,78,115,130;
      • the initial address space in toyos-pcid's oracle, at oracle.rs:77,153,157,158;
      • init_array_vaddr and init_array_size in toyos-ld, and init_array_ptr in toyos-abi;
      • pub use wait::boot::{init, …} at kernel/src/drivers/xhci/mod.rs:10;
      • sftp's a_second_init_ends_the_session.
    • Lines 57-58 make the rename reword about 45 kernel bring-up lines. They include the log string {}ms init budget, which tests/toyos.rs:14760 finds by "init budget".
    • Fix: replace lines 41-58 with a categorical rule: "a match stays only where init means initialise, initial or the CPU's INIT signal (a function, method or field named init, an identifier of that meaning, ELF's init arrays, bring-up prose), or is third-party text (tests/testcases/, the C ports); every other match names the program and goes." Each match is already judged by hand, so this is exact, and it is about 4 lines instead of 18.
  • …the-stop.md:66-69 — Stage 2's exit passes with every decision in two places. A new toyos-supervisor holding copies of the decisions with host tests, and userland/supervisor left unchanged, meets all three clauses. That is a sibling code path, and nothing checks :61's "keeps only handles, spawns and the loop". Add: "the stage deletes each decision from userland/supervisor, which calls the crate for it, named per decision in the PR."
  • …the-stop.md:90-91 — "the thread count" and "the console drain" are nouns, not claims, so any assertion about either meets the exit. State them as claims, for example "a dump served during the stop counts every thread it stopped as held" (origin/main:tests/common/power.rs:389) and "every record reaches the console, Rebooting. last" (:159).

NOTE

  • …the-stop.md:41 — Bounding the search by any letter misses a CamelCase join (the InitRefusal/TimerInit form). At 5235eda7 six such tokens exist and none names the program. "No lowercase letter on either side" would catch SpawnInit and InitPort too.
  • …the-stop.md:39-40 — Say that the exclusions match case-insensitively. BlockDevice, UsbBlockDevice, FLAP_NETDEV, KLOGD and _NETDB_H rely on that, and spelling out VirtioSoundDev in mixed case invites a case-sensitive reading.
  • …the-stop.md:35 — "the fork's ToyOS files" is undefined. src/forkcheck.rs:19 defines the fork's delta as git log <base>..toyos, which also covers cfg-gated blocks in files shared with other platforms. Say "the fork's delta".
  • …the-stop.md:77-83 — Stage 3's two guest tests lack stage 4's "registered at Tier::Fast or Tier::Nightly with no src/redlist.rs row", so landing them redlisted meets the exit. Move that clause so it covers every guest test the track names.
  • …the-stop.md:25-29 — Some new names collide with words the tree already uses. At 5235eda7, disks occurs 174 times (for example flush_disks) and mixer 74 times. After the rename, a search for either program is as ambiguous as init is today. The names are the owner's decision; raise the collision before stage 1 is briefed.
  • issues/isolation/the-power-broker-authority-with-a-human-in-the-loop.md:16-29 — The edit is correct: toybox receives the power connector (system.toml:152, console/system.toml:48) and not the bit. It is not complete, because :34 still cites "the applet", which was defined only in the deleted parenthetical (REMOVE below).

REMOVE

  • …the-stop.md:11-13 — describes the stop on Storage: file servers for DATA, the log and the boot volume; the kernel's NVMe and FAT go #536, which is unmerged, and rots when stage 3 lands; no stage needs it.
  • …the-stop.md:73-76 — describes the manifest and names logd, which stage 1 renames before stage 3 is worked.
  • …the-stop.md:96-97 "; files stays the file manager's" — a decision nobody recorded; the candidate is enough.
  • …the-power-broker-authority-with-a-human-in-the-loop.md:33-34 "because asking the applet is inconvenient — the broker is the answer to that itch" — its antecedent went with item 1.
  • PR body, "What changed and why" stage list — restates the track file.
  • PR body, "Measurements" table — counts at 62e7e8c7 that rot before stage 1 starts, in text that becomes main's record.
  • PR body, "Gates" log pointer "(supervisor-r2/cargo-test-lib.log in the job scratchpad)" — a private path the record cannot reach.

SEND BACK

Japabu and others added 2 commits September 28, 2026 14:26
…ion, claims as sentences

The rename's init exclusions become one rule: a match stays only where
init means initialise, initial or the CPU's INIT signal, or sits in
third-party text; every other match names the program. The search is
bounded so CamelCase joins hit: no lowercase letter follows, and a
letter precedes only a capital I. The review's literal "no lowercase
letter on either side" misses TimerInit, which occurs 6 times outside
issues/ at origin/main cd2e630; this bound catches it.

Stage 2's exit now requires each decision deleted from
userland/supervisor, which calls the crate for it. Stage 4's claims are
sentences. The tier-and-redlist clause covers every guest test the
track names. "The fork's delta" is forkcheck's definition. soundd's and
blockd's new names reopen with the owner beside fsd's: mixer and disks
are words the tree already uses.

Removed: the stop on #536, the manifest's current order, the file
manager's name, and the power-broker clause citing the deleted applet.

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

Japabu commented Sep 28, 2026

Copy link
Copy Markdown
Collaborator Author

Round 3 of the review of #575, at 6f6e925c. CI run 36421960822 ran job host at head 6f6e925c and concluded success, with every step success. The PR is not a draft. git diff --shortstat origin/main...HEAD gives 2 files, +96 -9: 0 lines of production code and 0 lines of tests. The merge 6f6e925c adds nothing beyond e8ba2219: git diff cd2e6307 6f6e925c shows only the two branch files. The measurements below were taken at #536's head 06c6195f (origin/wt/toyos-fsd) and at origin/main cd2e6307. The bound is applied per match to every tracked text file outside the bodies of issues/, and the fork is not included. The files are bound.pl, matches-*.txt and missed-tokens-fsd.txt.

Round-2 BLOCKERs

  • The init rule is inexact in both directions: OPEN. The 18-line list is gone, but the categorical rule that replaced it is still inexact both ways. Part of the rule's wording came from round 2's suggested fix, specifically the tests/testcases/ scope and the "every other match names the program" dichotomy. The first three BLOCKERs below give the measurements.
  • Stage 2's exit passes with every decision in two places: CLOSED. :62-64 requires each decision to be deleted from userland/supervisor, which then calls the crate for it, named per decision in the PR.
  • Stage 4's claims were nouns: CLOSED. Each line at :78-82 is now a sentence that can fail.

BLOCKER

  • issues/isolation/the-supervisor-is-host-tested-and-owns-the-stop.md:42-44 — the bound still lets a partial rename pass.
    • What it misses: "followed by no lowercase letter" skips the possessive joined to an s. At both heads, fn a_boot_record_without_inits_stop_is_not_a_pass (src/bootlog.rs:567) and fn inits_lines_are_heard_in_every_form_the_log_renders_them (toyos-swap/src/lib.rs:399) name the program and escape the search.
    • Fix: "followed by no lowercase letter other than one s", which is the regex …(?i:nit))s?(?![a-z]). Measured at both heads, it adds exactly these two matches and nothing else.
    • The CamelCase half of the bound is right. TimerInit is 6 matches at Storage: file servers for DATA, the log and the boot volume; the kernel's NVMe and FAT go #536's head. Round 2's "no lowercase letter on either side" would not catch SpawnInit either, so the implementer's bound is the correct one.
  • …the-stop.md:49 — "third-party text (tests/testcases/…)" also covers tests/testcases/system.toml, which is ours. At both heads it names the program 3 times (:10, and twice on :32: "init hands", "init through the power connector, and init has…"), and under the rule those matches stay. Fix: tests/testcases/tinycc/.
  • …the-stop.md:45-50 — the rule's two classes do not cover every match, so it cannot be judged without ambiguity.
    • (a) The rule says "every other match names the program and goes", but the bound also hits matches that are neither the program nor a stay-class. Examples at both heads: f32::INFINITY and NEG_INFINITY (toyos-mixer/src/corpus.rs:538-539, gain.rs:102-103), f64::INFINITY and #define INFINITY (userland/libc/src/math.rs:138,151, include/math.h:5), and INITIATE_FLR (toyos-pci/src/af.rs:20, express.rs:33, kernel/src/pcidev/mod.rs:1066). "Initiate" is not initialise. Read literally, the exit requires renaming them.
    • (b) :48 "a log string a test matches such as init budget" reads as a stay-class of its own. Yet 26 lines in tests/ and src/ at Storage: file servers for DATA, the log and the boot volume; the kernel's NVMe and FAT go #536's head match "init: … log strings that name the program. Examples: tests/common/origin.rs:576 and src/metalswap.rs:103 const INIT: &str = "init". Other matches also name the program: INIT_WITHOUT_A_DISK's "boot: init spawned…" (kernel/src/rootfs.rs:30, tests/toyos.rs:20166) and 17init: started test-runner (tests/common/console.rs:641).
    • Fix: replace :45-50 from "A match stays only where" with "A match goes where it names the program and stays otherwise; third-party text (tests/testcases/tinycc/, the C ports) stays." This deletes the stay-class parenthetical.

NOTE

  • The fork's delta was not measured in this round, only the superproject. The stage-1 brief should apply the same search there before it is dispatched.

REMOVE

  • …the-stop.md:86-89 "The orchestrator's candidate for fsd is fileserver. mixer and disks are refused: …" — nobody made that decision, so "refused" records one that does not exist. It also records one candidate out of the three the owner will be asked about. The first sentence of the bullet is the neutral record.
  • PR body, "What changed and why", the first three bullets — they restate the track file and the commit message. Round 2's REMOVE was reworded here, not deleted.
  • PR body, "which occurs 6 times outside issues/ at cd2e6307", together with the whole "Unsure" section — a count that goes stale, in text that becomes main's record, and a question to the reviewer that this round answers.

The power-broker edit is clean. "because asking the applet … itch" is deleted and not reworded, and no mention of "applet" remains.

SEND BACK

…ral fsd note

The init bound missed a possessive s (a_boot_record_without_inits_stop_is_not_a_pass,
inits_lines_are_heard_in_every_form_the_log_renders_them at origin/main); it now
allows one trailing s. The third-party exclusion named tests/testcases/ broadly,
which also covers our own system.toml; it now names tests/testcases/tinycc/. The
stay/goes rule is replaced with the reviewer's sentence, which covers matches that
are neither the program nor third-party text. Stage 1 now measures the rust/
fork's delta before it is briefed, not only the superproject. The fsd bullet
records only the open question, not a rejected candidate nobody decided on.

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

Japabu commented Sep 28, 2026

Copy link
Copy Markdown
Collaborator Author

Round 4 of the review of #575, at 0e49e251. CI run 36424866787 ran job host at head 0e49e251 and concluded success, with every step success. The PR is not a draft. git diff --shortstat origin/main...HEAD gives 2 files, +92 -9: 0 lines of production code and 0 lines of tests. Round 4 is 6f6e925c..0e49e251: one commit, one file. Main has moved to d4e41022 since the merge base cd2e6307, and none of that movement touches issues/isolation/.

Round-3 BLOCKERs

  • The bound misses the inits possessive: CLOSED. :44-45 now reads "followed by no lowercase letter other than one s". That is the prose form of (?i:init)s?(?![a-z]). The implementer ran that regex (supervisor-r4/bound2.pl) at origin/main, and its 1749 matches include both src/bootlog.rs:567 and toyos-swap/src/lib.rs:399.
  • The tests/testcases/ scope covered our own system.toml: CLOSED. :49 now names tests/testcases/tinycc/. The other files at that level, LICENSE and hello.c, produce no hit under the bound: grep -i init finds only "definition" in LICENSE, and there the match is preceded by a lowercase letter.
  • The rule's classes did not cover every match: CLOSED. :48-49 is round 3's fix text verbatim, "A match goes where it names the program and stays otherwise". So INFINITY, INITIATE_FLR and the "init: …" log strings are each judged by whether they name the program, and no stay-class remains that could contradict that.

Round-3 NOTE and REMOVEs

  • The fork's delta was not measured: addressed. :17-19 runs the exit's search over the fork's delta before stage 1 is briefed.
  • The fsd candidate and "refused": deleted, and :85 is the neutral record.
  • The PR body's first three bullets, the "6 times" count and the "Unsure" section: deleted, not reworded.

BLOCKER
None.

NOTE
None.

REMOVE
None.

LAND

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