Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,21 @@ privileged service, a policy engine, an authentication agent) because its
base model only knows identities. ToyOS's capability model IS the mechanism,
so the native shape is smaller:

1. **No user-facing program holds `POWER`.** One small daemon — the power
broker — is endowed it in `system.toml`, and its whole job is deciding.
(Today the toybox shutdown applet holds the bit directly; the broker
moves that single endowment one level up, behind judgment.)
2. **Programs request, the broker decides** — a port/connection like every
1. **Programs request, the broker decides** — a port/connection like every
other daemon protocol in the tree, under the server-never-blocks
doctrine.
3. **The confirmation rides the trusted UI path.** The broker asks the
2. **The confirmation rides the trusted UI path.** The broker asks the
compositor to present it, and the tree's own architecture is what makes
that mean something: the compositor owns the panel and the kernel
delivers key transitions per surface, so no ordinary program can draw a
fake dialog or fake the click on a real one. "A human physically present
confirmed" is the single-user machine's honest equivalent of Linux's
password prompt.
4. **Inhibitors**: a program may register "unsaved work" with the broker;
3. **Inhibitors**: a program may register "unsaved work" with the broker;
the broker delays, or names the holdouts in the dialog. Registration is
a connection, so a crashed registrant releases its inhibit by the same
teardown that releases everything else.

Unstaffed until the owner opens it; sequenced naturally with the userland/
product era. What must not happen meanwhile is the accident this track
exists to prevent: `POWER` spreading to more manifest rows because asking
the applet is inconvenient — the broker is the answer to that itch.
exists to prevent: `POWER` spreading to more manifest rows.
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
status: assigned
kind: track
opened: 2026-09-28
---

# The supervisor is host-tested and owns the machine's stop

Held by the orchestrator. Every stage waits on PR #536 (`wt/toyos-fsd`).

## Stages

Every guest test this track names is registered at `Tier::Fast` or
`Tier::Nightly` with no `src/redlist.rs` row. A deleted or disabled test covers
nothing.

1. **The rename**, one mechanical PR, first after #536. Before stage 1 is
briefed, the exit's search below runs once over the `rust/` fork's delta as
well as the superproject, so its hits are known going in. It touches `toyos/src`,
`toyos-abi/src`, `userland/libc/src` and the `rust/` fork's delta, so it is
briefed as an ABI brief, and its `CLAUDE.md` edits are placed in the same PR
by an agent briefed for them. Issue slugs carrying an old name are renamed
with every citation.

| today | becomes |
|---|---|
| `init` | `supervisor` |
| `netd` | `netstack` |
| `logd` | `logkeeper` |
| `soundd` | open with the owner |
| `blockd` | open with the owner |
| `fsd` | open with the owner |
| `sshd` | `sshserver` |
| `compositor` | unchanged |

**Exit**: over every tracked path and every text file's content, in the
superproject and the `rust/` fork's delta as `src/forkcheck.rs` defines it,
excluding the bodies of `issues/` files (recorded evidence), no hit remains
outside the exclusions, each judged per match and not per line:
- a case-insensitive substring search for `netd`, `logd`, `soundd`,
`blockd`, `fsd`, `sshd`, excluding, case-insensitively, an identifier
containing `klogd`, `blockdev`, `VirtioSoundDev`, `netdev`, `netdb`,
`ENETDOWN` or `fsdir`;
- a case-insensitive search for `init` followed by no lowercase letter
other than one `s` (so `inits` hits alongside `init`) and preceded by a
letter only where it starts with a capital `I` (so `spawn_init`,
`struct Init`, `SpawnInit`, `TimerInit`, `InitPort` and "asks init" all
hit). A match goes where it names the program and stays otherwise;
third-party text (`tests/testcases/tinycc/`, the C ports) stays.
2. **Decisions in a pure crate.** The supervisor's decisions live in
`toyos-supervisor`, with host tests; `userland/supervisor` keeps only
handles, spawns and the loop. The decisions: namespace and claim selection
from a manifest row; the claims a restart is owed; `SysCap` narrowing;
launch resolution and every launcher refusal; the swap ladder and
probation; restart policy; the stop order derived from the manifest, with a
cycle broken only by declaration.
**Exit**: the crate's tests pass in
`cargo test --workspace --exclude toyos-build`; a host test refuses a
manifest whose dependencies form an undeclared cycle; each refusal and
each decision above has a mutation that reds a host test, named in the PR;
and the stage deletes each decision from `userland/supervisor`, which calls
the crate for it, named per decision in the PR. No decision exists in two
places.
3. **The supervisor owns the stop.** It asks each service it started to
finish, in reverse dependency order, storage last, each ask bounded; only
then does it call the kernel, whose part is to stop whatever is left and
cut power.
**Exit**: two guest tests. In one, two non-storage services with a declared
dependency are asked to finish in reverse dependency order; it reds when
they are asked in forward order, and when they are asked all at once with
storage still last. In the other, a service holding unwritten state is
asked to finish, answers, and has its state on disk after the reboot; its
negative control is the same service never answering, where the stop still
lands at the bound and the supervisor's line names the service.
4. **The stop's coverage comes back.** **Exit**: each claim below is asserted
by a host test or a guest test, and a mutation named in the PR reds it.
- A held thread's transition wakes the stop.
- No block operation is open at the stop.
- A dump served during the stop counts every thread it stopped as held.
- Every record reaches the console, `Rebooting.` last.
- Storage is durable before power is cut.

## Open with the owner

- The new names of `fsd`, `soundd` and `blockd`.
- Before stage 3: the ask's ABI (no syscall is proposed); whether a program
started through `launcher` is asked or only stopped; whether
`SYS_SHUTDOWN`/`SYS_REBOOT` change at all.
Loading