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
4 changes: 2 additions & 2 deletions .claude/agents/reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,15 @@ if it meets the bar above; otherwise it is a NOTE.
`cargo run -- --ci <job>`, `seal` in the writer and `host` in the reader, and nothing else;
the reader restores before that step, and the writer saves after it. The save's guard,
`github.ref == 'refs/heads/main'`, is the only step-level `if:` in those jobs; ci.yml's `host`
skips only a draft, and nightly's `host` has no `if:` of its own, a skipped job being a green
skips only a `pull_request` run, and nightly's `host` has no `if:` of its own, a skipped job being a green
check. No `continue-on-error`, `shell:`, `defaults:` or cargo `runner` reaches them.
nightly.yml's `on:` is one daily `schedule` and `workflow_dispatch`.
- **Workflows.** A BLOCKER each:
- Only main's runs save a cache entry other refs restore: GitHub's cache scoping is every entry's provenance.
- `nightly.yml`'s `release` is the only job granted `contents: write`.
- No workflow runs on `pull_request_target`, `workflow_run`, `issue_comment` or any other trigger that runs code other than main's on main's ref.
- No workflow or job declares `cache-mode: write` or `write-only`.
- `guest / suite` has no job-level `if:`, and a job that calls it runs whatever `toolchain` concluded: a skipped required check reads as green.
- `guest / suite`'s only job-level `if:` is `github.event_name != 'pull_request'`, and a job that calls it runs whatever `toolchain` concluded: a skipped required check reads as green.
- A job that saves a cache entry runs only `cargo run -- --ci <job>`.
- **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
Expand Down
13 changes: 6 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
name: ci

# CI runs once per pull request, in the merge queue. On `pull_request` every
# check reports skipped, which a required check reads as green; the skip sits
# in the called workflow's job, because a skipped caller reports its own name
# and not `toolchain / build` or `guest / suite`.
on:
pull_request:
branches: [main]
types: [opened, synchronize, reopened, ready_for_review]
merge_group:

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

# No job here writes: a toolchain release is main's publisher's alone.
permissions:
contents: read

jobs:
host:
if: github.event_name == 'merge_group' || github.event.pull_request.draft == false
if: github.event_name != 'pull_request'
runs-on: ubuntu-24.04
timeout-minutes: 45
env:
Expand All @@ -43,14 +43,13 @@ jobs:
- run: cargo run -- --ci host

toolchain:
if: github.event_name == 'merge_group' || github.event.pull_request.draft == false
uses: ./.github/workflows/toolchain.yml

# A required check that is skipped reads as green, so this runs whatever
# `toolchain` concluded.
guest:
needs: toolchain
if: ${{ !cancelled() && (github.event_name == 'merge_group' || github.event.pull_request.draft == false) }}
if: ${{ !cancelled() }}
uses: ./.github/workflows/guest.yml
with:
kvm: true
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/guest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ on:

jobs:
suite:
# ci.yml's pull request run reports this check skipped.
if: github.event_name != 'pull_request'
runs-on: ubuntu-24.04
# A wedge guard, not a budget.
timeout-minutes: 60
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/toolchain.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ on:

jobs:
build:
# ci.yml's pull request run reports this check skipped.
if: github.event_name != 'pull_request'
# Bare, not a container: its glibc is a build's floor.
runs-on: ubuntu-24.04
timeout-minutes: 350
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Vendor firmware a device or CPU verifies by its maker's signature may be shipped

## Build & test

- `cargo run` builds everything (toolchain, kernel, bootloader, userland, image) and launches QEMU; `--build-only` skips the launch. `cargo test` runs the QEMU harness, and `cargo test --test toyos-build -- --metal` the T14's. `cargo run -- --ci host` runs every host suite: it is the `host` check a ready pull request and the merge queue run. The guest suite is their `guest / suite` check, under KVM; the nightly runs it under TCG.
- `cargo run` builds everything (toolchain, kernel, bootloader, userland, image) and launches QEMU; `--build-only` skips the launch. `cargo test` runs the QEMU harness, and `cargo test --test toyos-build -- --metal` the T14's. `cargo run -- --ci host` runs every host suite: it is the merge queue's `host` check, which a pull request's own run reports skipped. The guest suite is its `guest / suite` check, under KVM; the nightly runs it under TCG.
- **A behaviour is tested on the cheapest tier that reaches it**: a type that makes the bug unrepresentable, then a host test, then a metal row on the T14, and a QEMU guest test last.
- **Agents run their own guest tests**, the whole suite or a filter, side by side. **Every metal bench is the orchestrator's alone: no other agent runs `--metal` without `--metal-readback`, which touches no machine.**
- **Timing and audio verdicts come only from metal.** A QEMU test asserts order, completion, content and counts, never how long something took, and plays no audio; its only clock is a hang ceiling.
Expand Down
6 changes: 3 additions & 3 deletions issues/ci-runs-the-whole-guest-suite.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ opened: 2026-10-10

The owner's ruling: guest tests run on demand, and CI's small tier holds only the tests that must
break when something important breaks. `guest.yml` runs `cargo run -- --ci guest` (`build/ci.rs`,
`guest`), which is every registration in `tests/toyos.rs`, on every ready pull request, in the
merge queue (`ci.yml`) and nightly (`nightly.yml`); no tier is declared, so no review can keep a
`guest`), which is every registration in `tests/toyos.rs`, in the merge queue (`ci.yml`) and
nightly (`nightly.yml`); no tier is declared, so no review can keep a
new guest test out of it.

The question: which tests belong in the tier. Once the owner names them, the orchestrator
dispatches the reshape.

**Exit condition**: `--ci guest` runs a declared list in `tests/toyos.rs` and nothing else, the
rest of the suite runs on demand, and root `CLAUDE.md`'s "The guest suite is their `guest /
rest of the suite runs on demand, and root `CLAUDE.md`'s "The guest suite is its `guest /
suite` check" and `reviewer.md`'s **Guest tests** say so in the same diff. The same diff deletes
`ON_DEMAND` in `tests/toyos.rs`, the stopgap that keeps a test out of an unfiltered run until then:
once `--ci guest` runs a declared list, everything outside it is on demand.
33 changes: 33 additions & 0 deletions issues/general-crates-are-published-and-toyos-consumes-them.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
status: open
kind: track
opened: 2026-10-11
---

# General-purpose crates are published, and ToyOS consumes them

**The owner's direction:**
- Crates that are general-purpose get published on crates.io with an owner of their own (an AI owner).
- ToyOS becomes one consumer of each. It may request changes, but the crate stays general.
- Not during the current rapid-development era: nothing is built for this until the owner says go.

**Candidates** (scan of the restructured tree, 2026-10-11), best first:
1. `toyos-fat32-check`: FAT32 checker written from Microsoft's fatgen103. No ToyOS dependencies, `no_std`.
2. `toyos-fat32`: FAT32 read/write hardened against hostile volumes. It needs `toyos-wallclock` folded in, and its tests made self-contained.
3. `toyos-cpuvuln`: Linux's CPU vulnerability verdicts from CPUID/MSR facts. Its parity is pinned to one Linux tag.
4. The bcachefs `upstream` reader, split out of `lib/bcachefs`.
5. `toyos-microcode` and `toyos-usbhid`.
6. Later: the TCP stack (once `wire`'s grab-bag is factored out), the SSH server (once its track and defect issues close), and the AML interpreter (once it is decoupled from `toyos-acpi`).

**Not candidates:** sha2/sha2-hw, random, crc, wallclock and tmpdir. Widely used crates already do their jobs.

**What exists:** `build/sdkversion.rs`'s `PUBLISHED` already publishes six SDK crates from the monorepo, with crates.io trusted publishing.

**Open design:**
- Publish from the tree, or move out to a repository of its own? Publishing from the tree keeps atomic changes and self-hosting. A repository of its own gives the crate a real owner and its own history.
- How an owning agent is run.
- How ToyOS pins and requests.

**Exit:** a crate ToyOS used to build from its tree is published under its own owner, and ToyOS builds against the published version.

**Owner:** the owner (Jan) decides when it starts.