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
7 changes: 5 additions & 2 deletions .claude/agents/implementer.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ One brief, one worktree, one branch. What the brief does not name you do not tou
find off your path is filed in `issues/`, never fixed. If something blocks you, stop and say so in
one clause; do not work around it.

Before adding kernel behaviour, ask whether userland can own it. When the clean design changes the
ABI, change the ABI; never pick a lesser design to avoid that. A clean design that reaches past
your fence blocks you.

## Measure, build, test

Where hardware or anything uncertain is involved, take the cheap measurement before you build on a
Expand Down Expand Up @@ -56,8 +60,7 @@ Fork sources live outside this repository: a search for callers must also cover

`git commit -F <file>`, never `-m`. No `--amend`, no rebase, no force: merge `origin/main`, never
rebase onto it. Never run `git submodule` in a linked worktree: it writes `core.worktree` into the
fork's shared config and breaks git in the primary checkout's `rust/`. Never touch `toyos-abi/src`, `toyos/src` or `userland/libc/src` unless the brief is
an ABI brief. No new dependency.
fork's shared config and breaks git in the primary checkout's `rust/`. No new dependency.

Push from your branch, never `main`, with `git status --porcelain` empty: `git push -u origin
<branch>`, and `gh pr create --draft` at the first push. The pull request body is the handoff the reviewer reads,
Expand Down
12 changes: 5 additions & 7 deletions .claude/agents/reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ above; otherwise it is a NOTE.
- **Fit.** Does the tree already do this? Is each new thing where it belongs: a pure decision in a
pure crate, the user/kernel boundary in `toyos-userbound`, a device claim in a userland server?
One declaration read by every reader, refusal by name, authority moved in by the parent. Zero
legacy: no shim, no workaround, no silent default. No new
legacy: no shim, no workaround, no silent default. A BLOCKER each: a kernel addition that
userland could own; a design made worse to spare the ABI. No new
dependency or fetch. Nothing outside the brief's fence.
Assembly, a naked function and a `core::arch` or `std::arch` path live only in an
architecture's own module; `target_arch` only there, in its selector, in `src/arch.rs` and in
Expand All @@ -68,12 +69,9 @@ above; otherwise it is a NOTE.
A file added to or deleted from `tests/testcases/tinycc/` moves the count
`tests/testcases/LICENSE` states in the same diff, and `46_grep.c` never comes back. Nothing
else is tracked under `tests/testcases/` but that `LICENSE`, `system.toml` and `hello.c`.
- **What no gate reads.** A BLOCKER each: a diff that declares a retired ABI name or reuses a
retired syscall, `SYS_DEBUG` action or inbox op number (the retired numbers are
`kernel/src/syscall/dispatch.rs`'s `retired_syscalls!` and the "formerly …" and "retired and
unused" entries in `toyos-abi/src/syscall.rs` and `toyos-abi/src/inbox.rs`; the retired names
include `SharedToken` and `services::connect`); a workspace member's `Cargo.toml` declaring `[profile]` or `[patch]`, which
cargo ignores with only a warning; a new package without a `description` saying what it is.
- **What no gate reads.** A BLOCKER each: a workspace member's `Cargo.toml` declaring `[profile]`
or `[patch]`, which cargo ignores with only a warning; a new package without a `description`
saying what it is.
A new cargo feature or `cfg` arm of one, and every arm a changed `src/clippy.rs` shape stops building, is shown linted in the pull request body: a `mem::forget` planted in that arm turns `cargo run -- --clippy` red.
- **Growth.** Every line is a responsibility, not an asset. State the branch's net lines
(`git diff --shortstat origin/main...HEAD`), production and tests apart. Production code that grows
Expand Down
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ A subdirectory `CLAUDE.md` loads when a file in that subtree is `Read`, and not

> A snapshot, deliberately shallow — always read the code.

**Kernel** — minimal; new additions are discussed and justified. Resource management, scheduling, process lifecycle, filesystem, device arbitration. 2 MB pages, demand paging, PIE binaries, full SMP.
**Kernel** — takes on only what userland cannot. Resource management, scheduling, process lifecycle, device arbitration; files: see Capabilities. 2 MB pages, demand paging, PIE binaries, full SMP.

**Userspace daemons** — compositor, netd, soundd, sshd, logd. Each claims a device or capability from the kernel and serves its function; crash one and the kernel is fine.

**The log is a userland file.** `/system/bin/logd` reads records on a cursor and owns `/log`; the kernel keeps the record ring, the console and the panel, and writes no file. `SYS_FSYNC` reaches the device's cache flush because logd's durability claim rests on it.

**Syscall ABI** — `toyos-abi/`: struct layouts, syscall numbers, typed wrappers; completely unstable, read the code. Never add or change a syscall without discussion; a deleted syscall's number is retired, never reused. `toyos/` builds on it with typed handles, IPC framing, ports, namespaces and `surface` — userland uses `toyos`, the kernel uses `toyos-abi` only.
**Syscall ABI** — `toyos-abi/`: struct layouts, syscall numbers, typed wrappers; completely unstable. The cleanest, most sustainable ABI beats convenience; a removed number is free. `toyos/` builds on it with typed handles, IPC framing, ports, namespaces and `surface` — userland uses `toyos`, the kernel uses `toyos-abi` only.

**Capabilities** — a process holds exactly what its parent moved into it, and among kernel objects there is nothing it can name to get more. No registry, no connect-by-name, no pid-as-authority: `/system/bin/init` builds every program's namespace and device claims from `system.toml` before spawning it, and a handle a process does not hold is a bug in that process — the kernel ends it rather than answering a word it can ignore. **Isolation is non-negotiable, and the filesystem is inside it**: a process names only the paths in the view its parent built for it, the unit of isolation is the program, and a user is the part of the tree a session was handed. Not yet true of files: the kernel still resolves every path against one machine-wide tree until the storage track's per-program views land.

Expand Down
42 changes: 42 additions & 0 deletions issues/design-debt/the-abi-still-keeps-retired-syscall-numbers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
status: open
kind: defect
opened: 2026-10-01
---

# The ABI still keeps retired syscall numbers

The ABI is completely unstable and a removed syscall's number is free (owner,
2026-10-01): there are no retired numbers and no compatibility shims. The tree
still keeps them:

- `kernel/src/syscall/dispatch.rs`'s `retired_syscalls!` names deleted calls so
that "an old binary is told which call it was", logging each call of one;
every other unassigned number answers `InvalidArgument` silently.
- `toyos-abi/src/syscall.rs` and `toyos-abi/src/inbox.rs` carry a "formerly …"
or "retired and unused" entry per deleted syscall, `SYS_DEBUG` action and
inbox op, `SYS_INBOX_SETUP`'s doc states the retirement rule, and
`kernel/src/inbox/mod.rs` names op 2 retired.
- `toyos-abi/src/syscall.rs`'s `device_classes!` keeps device classes 3 (`Nic`)
and 4 (`Audio`) "retired rather than reused", and the decode test in
`toyos-abi/src/inventory.rs` refuses them as retired.
- `tests/toyos-rust-tests/src/bin/log_hold.rs`,
`tests/toyos-rust-tests/src/bin/panic_halts_first.rs`,
`tests/common/origin.rs` and `tests/toyos.rs` take syscall 26 as their logged
refusal and read `syscall 26 is retired`.
- Plans still follow the old rule:
`issues/kernel/sys-clock-realtime-is-now-a-format-of-sys-clock-epoch.md`,
`issues/kernel/a-childs-end-is-an-event-and-a-parent-takes-its-children-down.md`,
`issues/kernel/the-kernel-still-parses-what-userland-writes.md`,
`issues/kernel/the-capability-end-state-is-twelve-answers.md`,
`issues/diagnostics/the-kernel-keeps-nothing-it-enumerates.md`,
`issues/diagnostics/no-cyclictest.md`, and
`issues/isolation/the-supervisor-is-host-tested-and-owns-the-stop.md`, whose
"ABI brief" names a gate `.claude/agents/implementer.md` no longer has.

**Exit**: `retired_syscalls!` and every retirement entry are gone, a deleted
number answers as an unassigned one does, the four test sites take their logged
refusal from something live, and no issue plans by retirement.

Owner: `toyos-abi` and `kernel/src/syscall/dispatch.rs`, whoever next changes
the ABI.
Loading