Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
965d7d3
ci: the host cache is read by content, sealed only by a cold run, and…
Japabu Oct 1, 2026
1f86e18
clippy: toyos-abi's own lints check it in a target of their own
Japabu Oct 1, 2026
dd2d210
Merge remote-tracking branch 'origin/main' into wt/toyos-cicache
Japabu Oct 1, 2026
4686e5a
Merge origin/main (#660, #663) into wt/toyos-cicache
Japabu Oct 1, 2026
455780e
toyos-dhcp: a trailing blank line, so this pull request's next run ha…
Japabu Oct 1, 2026
e57e0be
Revert "toyos-dhcp: a trailing blank line, so this pull request's nex…
Japabu Oct 1, 2026
9405012
ci: a runner's steps build with no incremental state
Japabu Oct 1, 2026
47a0d92
cicache: the module doc says which way cargo's comparison is strict
Japabu Oct 1, 2026
410bcc7
Merge origin/main (#668) into wt/toyos-cicache
Japabu Oct 1, 2026
ed87c48
Merge remote-tracking branch 'origin/main' into wt/toyos-cicache
Japabu Oct 1, 2026
59cc178
Review round 1: one writer, no gh, sha2 in-process, packages dated wh…
Japabu Oct 1, 2026
02fa5c5
Review round 2: the runner is read by one function a test reaches, an…
Japabu Oct 1, 2026
d5b7cd0
Merge origin/main (#667) into wt/toyos-cicache
Japabu Oct 1, 2026
db4654f
Each host step is `cargo run -- --ci host`, and the driver says which…
Japabu Oct 1, 2026
e0ced58
Review round 3: no step inherits the driver's target, incremental sta…
Japabu Oct 1, 2026
b4dfda5
Round 6: the seal bounds the bytes it dates, and the runner's tar and…
Japabu Oct 1, 2026
679fbf2
Merge origin/main (#674) into wt/toyos-cicache
Japabu Oct 1, 2026
f9d535d
Every carried run bounds what its save would store, and the writer's …
Japabu Oct 1, 2026
7923051
The seal alone bounds the tree, and a job that names the host cache r…
Japabu Oct 1, 2026
4139868
Round 9: the workflows are read as YAML, and only the job that saves …
Japabu Oct 1, 2026
f7e0bd4
The workflow reader marks an alias through its anchor alone, and read…
Japabu Oct 1, 2026
51fe187
Merge origin/main (#673) into wt/toyos-cicache
Japabu Oct 1, 2026
038da72
Round 10: the workflow gate becomes review rules, and the seal job is…
Japabu Oct 1, 2026
6823ea0
The workflow gates that read workflows as text become reviewer instru…
Japabu Oct 1, 2026
c282a76
The Caches rule holds both host-cache jobs to the driver's target
Japabu Oct 1, 2026
2683ca2
Merge origin/main (#678) into wt/toyos-cicache
Japabu Oct 2, 2026
883adf1
The Caches rule names the writer's `if:`, the jobs' `env:` and each o…
Japabu Oct 2, 2026
79bd4ec
The review prompt takes the one-writer test's rule, and Caches names …
Japabu Oct 2, 2026
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
19 changes: 16 additions & 3 deletions .claude/agents/reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,29 @@ if it meets the bar above; otherwise it is a NOTE.
saying what it is; a new cargo feature or `cfg` arm of one, or an arm a changed `src/clippy.rs`
shape stops building, that no shape in `src/clippy.rs` lints; an `issues/` file added, changed
or deleted against `issues/README.md`.
- **Caches.** No gate reads these; a diff that breaks one is a BLOCKER. Each cache has one
writer, a nightly.yml job, and no workflow uses the combined `actions/cache`, which saves too;
the host cache's is nightly's `host`, and its one reader ci.yml's `host`, on the same
`runs-on`, both caching `src/cicache.rs`'s `PATHS` with its `DRIVER` as their
`CARGO_TARGET_DIR`, the one variable an `env:` gives either: an `ImageOS` or `ImageVersion`
set there outlives an image move. The reader's `restore-keys` is the writer's `key` up to its
run id. A job that names the host cache runs `actions/checkout`, its cache step and
`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
check. No `continue-on-error`, `shell:`, `defaults:` or cargo `runner` reaches them.
nightly.yml's `on:` is one daily `schedule` and `workflow_dispatch`.
- **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 needs a reason you accept; a branch that could delete more than it adds and does not goes
back with the deletion named, and so does a new gate, check, lock or test that guards what a
reader can check: that rule is a sentence in a prompt. What could be deleted, merged into what
exists, or made smaller? An abstraction with one caller, a parameter with one value, dead code,
code kept "just in case" or because nobody knows whether it is needed. Size is never bought with
a weaker check: a test is cut only when it tests nothing, or as **Guest tests** says. A
compromise the branch found is removed or recorded in `issues/` with an owner, evidence and an
exit condition.
a weaker check: a test is cut only when it tests nothing, when this prompt takes its rule, or
as **Guest tests** says. A compromise the branch found is removed or recorded in `issues/` with
an owner, evidence and an exit condition.
- **Tests.** The refusals and the boundary, not the happy path.
- **Edges.** Untrusted input never panics the kernel; it is refused. Check-then-act races. A lock
held across a user copy or a device wait. Arithmetic on a value the caller chooses. A short
Expand Down
11 changes: 7 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
name: ci

# A pull request and the merge queue: the host tests, and no guest. Each step
# is `cargo run -- --ci <job>` (src/ci.rs), which runs the same on a dev host;
# A pull request and the merge queue: the host tests, and no guest.
# nightly.yml boots the guests.

on:
Expand All @@ -19,6 +18,10 @@ jobs:
if: github.event_name == 'merge_group' || github.event.pull_request.draft == false
runs-on: ubuntu-24.04
timeout-minutes: 45
# The driver's own target, and no step's: it says this job carries the
# host cache (src/cicache.rs).
env:
CARGO_TARGET_DIR: target/ci-driver
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

Expand All @@ -35,7 +38,7 @@ jobs:
toyos/target
kernel/target
bootloader/target
key: host-linux-${{ github.run_id }}
restore-keys: host-linux-
key: host-sealed-${{ runner.os }}-${{ runner.arch }}-${{ github.run_id }}
restore-keys: host-sealed-${{ runner.os }}-${{ runner.arch }}-

- run: cargo run -- --ci host
28 changes: 14 additions & 14 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,28 @@ concurrency:
cancel-in-progress: false

jobs:
# The host cache's writer restores nothing, and `seal` is green only once
# src/cicache.rs has sealed the tree the save stores.
host:
runs-on: ubuntu-24.04
timeout-minutes: 90
# The driver's own target, and no step's: it says this job carries the
# host cache (src/cicache.rs).
env:
CARGO_TARGET_DIR: target/ci-driver
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
fetch-depth: 0

- uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
- run: cargo run -- --ci seal

# The host cache's one writer. Only main's entries are readable from
# every branch.
- if: github.ref == 'refs/heads/main'
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: &host-paths |
path: |
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
Expand All @@ -35,18 +46,7 @@ jobs:
toyos/target
kernel/target
bootloader/target
key: host-linux-${{ github.run_id }}
restore-keys: host-linux-

- run: cargo run -- --ci host

# The host cache's one writer. Only main's entries are readable from
# every branch.
- if: github.ref == 'refs/heads/main'
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: *host-paths
key: host-linux-${{ github.run_id }}
key: host-sealed-${{ runner.os }}-${{ runner.arch }}-${{ github.run_id }}

# Publishes this tree's toolchain if nobody has, and on main moves the SDK
# alias onto it. Bare `ubuntu-24.04`, not a container: its glibc is the
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
status: open
kind: tooling
opened: 2026-10-01
---

# A warm host run keeps what a registry proc macro expanded from a file it never named

A registry proc macro is compiled once and runs inside every compile of the
crate that expands it. One that reads a file without telling rustc, the way
`wayland-scanner`'s `generate_client_code!` opens its XML, reads it again only
when cargo recompiles the expanding crate. A warm `host` run
(`src/cicache.rs`) recompiles a path crate only when its own package changed,
so when that file sits outside the expanding crate's package and changes
alone, the warm run keeps the old expansion where a cold run makes a new one.
Cargo never dates a registry source, so nothing dates the macro's package.

Of the proc macros in the lockfiles of the five workspaces the host job builds,
`wayland-scanner` alone reads a file it does not name, and no tracked source
names it.

Owner: the host cache (`src/cicache.rs`).

Done when a warm read serves what a cold build serves for a path crate that
expands a registry proc macro reading another package's file, with a test.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
status: open
kind: tooling
opened: 2026-10-01
---

# A warm host run never relinks for a file only a flag names

A file that reaches a build only through a flag, a linker script named by
`-Clink-arg=-T…` in a `.cargo/config.toml` or in `RUSTFLAGS`, is read by the
linker, and cargo compares the flag, never the file. When that file sits
outside the package that links with it and changes alone, a warm `host` run
(`src/cicache.rs`) keeps the old link where a cold run makes a new one.

No flag the host job passes names a file: the tracked `.cargo/config.toml`
files pass none, and its steps set no `RUSTFLAGS`.

Owner: the host cache (`src/cicache.rs`).

Done when a warm read refuses a flag that names a tracked file, or dates whole
the package that links with it, with a test.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
status: open
kind: tooling
opened: 2026-10-01
---

# The guest cache is read by mtime, and its writer restores before it saves

`nightly.yml`'s `tcg` restores the newest `guest-` entry, builds on it and saves
the result: nothing prunes what no step rebuilt, so every write keeps the last
one's artifacts and adds its own (3,281,375,938 B on 2026-10-01, beside the
host entry in the repository's 10 GB). And every guest job restores its targets
under a checkout that dated every source at the checkout, so cargo calls every
path crate in them stale.

The guest entry's ceiling is what H + 2G ≤ 10 GB leaves it, and that sum binds
every night: 4,002,930,524 B at the host's `LIMIT` (`src/cicache.rs`), or
4,298,336,717 B at run 36878222090's H. Above it, `tcg`'s save evicts that
night's host entry unless a pull request has read the entry since the guest
restore; every pull request then runs cold, and nothing reds.

Owner: the orchestrator.

Done when the guest entry is written cold, read by content, and bounded.
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
status: open
kind: tooling
opened: 2026-10-01
---

# The host cache's limit reaches the 10 GB only through one measured ratio

`src/cicache.rs` refuses a tree whose `PATHS` hold more than `LIMIT`,
8,000,000,000 B, uncompressed. The repository evicts its caches past 10 GB of
what actions/cache stores, compressed, and both two host entries beside a guest
one (2H + G) and one beside two (H + 2G) must fit.

One ratio ties `LIMIT` to H, measured once. Run 36878222090 (e0ced587c) sealed
5369 MiB of targets, at least 5,629,804,544 B. That head's own archive of the
cache's paths, made with the runner's `tar` and `zstdmt`, held 1,403,326,566 B:
a ratio of 4.01. At that ratio `LIMIT` stores at most 1,994,138,951 B. With the
guest entry's 3,281,375,938 B (run 36696295750's `tcg`), 2H + G is
7,269,653,840 B and H + 2G is 8,556,890,827 B. The ratio may fall to 2.38
before 2H + G reaches 10 GB. The lowest measured is 3.08: run 36844536500
sealed 9553 MiB on macOS and saved 3,250,736,567 B.

No gate reads a stored size. If the targets compress worse, H moves toward the
floor and nothing reds.

`LIMIT` is checked only by nightly's `host`, the one job that saves an entry,
before it seals its tree. A pull request's run and the merge queue's, warm or
cold, never seal and are never refused by `LIMIT`. So a landing that takes the
cold tree past `LIMIT` is first refused by the next nightly's seal, loudly:
that run is red and saves nothing. Until an entry is sealed again, a pull
request restores the last sealed one, or runs cold once the runner image has
moved; either way its verdict is its steps'.

Owner: the host cache (`src/cicache.rs`).

**Exit condition.** Two gates that red:
- after nightly's `host` saves, a step reads that entry's stored bytes and the
newest guest entry's from the repository's cache list, and fails when
2H + G or H + 2G passes 10 GB;
- the merge queue's `host` reds a landing whose cold tree passes `LIMIT`,
before `main` moves.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
status: open
kind: tooling
opened: 2026-10-01
---

# The workflow gates that read workflows as text become reviewer instructions or go

Three tests read `.github/workflows/` as text, and each passes a patch that
breaks its rule as GitHub reads the YAML. Each patch, alone, left all three
green (EXIT 0):
- `src/ci.rs`'s `workflows_run_against_main_on_hosted_runners` reads `runs-on:`
and `pull_request:` off single lines. On `publish.yml`: `runs-on:` with its
label on the next line, `- self-hosted`; and `pull_request: {branches: [dev]}`
beside `workflow_dispatch`.
- `src/ci.rs`'s `the_required_check_is_a_job_on_every_pull_request` finds
ci.yml's triggers and its `host` by substring. On `ci.yml`: `host`'s `if:`
made `false`. A skipped job reports success, so the required check is green.
- `src/hostws.rs`'s
`nothing_that_runs_names_a_target_directory_a_member_does_not_have` finds a
`<member>/target` by substring. On `publish.yml`: a step
`run: "ls userland/sshd/targe\x74"`, which YAML reads as
`ls userland/sshd/target`. The same step spelled plainly reds it (EXIT 101).

Owner: `issues/build/the-tooling-is-a-review-prompt-and-three-workflows.md`.

Done when each test is deleted with its rule a sentence in
`.claude/agents/reviewer.md`, or reds on its patch above.
Loading
Loading