Regular push/PR runs the test job only. workflow_dispatch and v* tags
then build linux-amd64, windows-amd64, and macos-arm64 as separate
jobs. Windows is cargo-xwin from Ubuntu (MSVC ABI, Unix-host protoc)
instead of native windows-latest. Registry/git cache is shared on
Ubuntu; release target/ is not cached; xwin splat has its own cache.
Cargo on this box was suspected of writing the disk to death. Measuring
it says otherwise: 4 CPUs, load peaks at 3.0 during a full build, while
writes peak at 30 MB/s and sit at zero for most samples. The long poles
are single-crate rustc compiles that cannot be parallelised, so the
binding constraint is CPU and `nice -n 19` is the first-line tool.
The disk itself reads at 210 MB/s and writes at 50 MB/s, identically
across block sizes and IO modes -- a volume-level write cap rather than
disk physics. A short burst reaches ~150 MB/s on what look like burst
credits; calibrating against that number is a mistake, and it is the one
that made an earlier 40 MB/s ceiling do nothing.
paced.sh is the fallback for the phase that does write hard -- linking
the 643 MB debug binary saturates writes for about 13 seconds. It
duty-cycles a process group against the observed rate in
/proc/diskstats, because every kernel-side lever is unavailable here:
/sys/fs/cgroup is read-only and cannot be remounted or re-mounted
elsewhere even under sudo (no CAP_SYS_ADMIN), /proc/sys is read-only,
and the scheduler cannot be switched to BFQ so ionice is a no-op. Each
of those is verified, not assumed; the header records them so the next
person does not re-derive it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
No behaviour change. Explicit `cd || die` (set -e already covered it),
split declare/assign for PROTOC, if-blocks instead of `A && B || C`,
and array-length instead of a counter loop in count_patches. The
lib.sh constants get disable=SC2034 since they are consumed by the
scripts that source it, which shellcheck cannot see per-file.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two issues found by exercising the scripts end to end:
- `git checkout -B` refuses to run when the worktree is dirty, so
`make apply FORCE=1` aborted in exactly the situation FORCE exists
to handle. Use `checkout -f -B`; the non-forced path has already
verified the tree is clean, so forcing changes nothing there.
- The commit-count guard claimed the user forgot `make rebuild`, but
deleting a patch file on purpose trips it identically. Say both,
and document the FORCE=1 form in the README's "drop the example
patches" instructions, which would otherwise have failed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Upstream is a periodic one-way export of xAI's monorepo (linear
"Synced from monorepo" commits, SOURCE_REV pinning the internal SHA)
and explicitly refuses external contributions. So local changes can
never be upstreamed, and upstream re-drops the whole tree on every
sync -- structurally the same problem CraftBukkit has with Mojang.
Adopt the Spigot/BuildTools model: patches/ is the source of truth,
work/ is a disposable build artifact regenerated from upstream.rev
plus patches/.
scripts/apply-patches.sh ~ applyPatches.sh
scripts/rebuild-patches.sh ~ rebuildPatches.sh
scripts/update-upstream.sh forward-ports patches onto a new sync
scripts/setup.sh toolchain: rust 1.94.0, dotslash/protoc
upstream.rev ~ BuildTools versions/*.json pin
format-patch uses --zero-commit so rebases do not rewrite the From
line of every patch, and apply's git clean preserves work/target so
replaying patches does not cost a cold Rust rebuild.
Ships two [EXAMPLE PATCH] commits demonstrating a source edit and a
new-file addition; both are safe to delete.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>