diff --git a/.claude/agents/reviewer.md b/.claude/agents/reviewer.md index 44a3af6749..28eedce959 100644 --- a/.claude/agents/reviewer.md +++ b/.claude/agents/reviewer.md @@ -96,7 +96,7 @@ if it meets the bar above; otherwise it is a NOTE. `cargo run -- --ci `, `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: @@ -104,7 +104,7 @@ if it meets the bar above; otherwise it is a NOTE. - `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 `. - **Growth.** Every line is a responsibility, not an asset. State the branch's net lines (`git diff --shortstat origin/main...`), production and tests apart. Production code that diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7521a0b6af..d23d5844aa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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: @@ -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 diff --git a/.github/workflows/guest.yml b/.github/workflows/guest.yml index 712965682a..2879f7e9b4 100644 --- a/.github/workflows/guest.yml +++ b/.github/workflows/guest.yml @@ -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 diff --git a/.github/workflows/toolchain.yml b/.github/workflows/toolchain.yml index 22ba02bfbd..bd8c3a105b 100644 --- a/.github/workflows/toolchain.yml +++ b/.github/workflows/toolchain.yml @@ -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 diff --git a/CLAUDE.md b/CLAUDE.md index 3b0691e139..a51d2762b2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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. diff --git a/issues/ci-runs-the-whole-guest-suite.md b/issues/ci-runs-the-whole-guest-suite.md index 2bcab2c021..a9903b33e5 100644 --- a/issues/ci-runs-the-whole-guest-suite.md +++ b/issues/ci-runs-the-whole-guest-suite.md @@ -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. diff --git a/issues/general-crates-are-published-and-toyos-consumes-them.md b/issues/general-crates-are-published-and-toyos-consumes-them.md new file mode 100644 index 0000000000..26deaa1f47 --- /dev/null +++ b/issues/general-crates-are-published-and-toyos-consumes-them.md @@ -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.