From ac13387db0f6be9e6af36ea6014fc746695ef0e5 Mon Sep 17 00:00:00 2001 From: igneum-josh <337424239+igneum-josh@users.noreply.github.com> Date: Mon, 5 Oct 2026 10:12:38 +0100 Subject: [PATCH] Stale-build class closed: every script that copies sources re-stamps them before building, CI check, repo rule Co-Authored-By: Claude Fable 5.1 --- .github/workflows/ci.yml | 2 ++ CLAUDE.md | 6 ++++++ app/igneum-app/src/jobbuild.rs | 3 +++ .../cloud-devnet/builder/build-on-builder.sh | 2 +- proving/windows-wsl2/make-package.sh | 2 ++ proving/windows-wsl2/prove-block.sh | 3 +++ proving/windows-wsl2/setup-wsl.sh | 3 +++ tools/ci/copied-sources-check.sh | 19 +++++++++++++++++++ 8 files changed, 39 insertions(+), 1 deletion(-) create mode 100755 tools/ci/copied-sources-check.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c0562bf13..c2f1535f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,5 +61,7 @@ jobs: run: node tools/ci/link-check.mjs - name: identity grep of the public export list run: bash tools/ci/identity-check.sh + - name: copied sources are re-stamped before a build + run: bash tools/ci/copied-sources-check.sh - name: relay unit tests (parsers, secret compare, the wake endpoint) run: node --test relay/test/parse.test.mjs relay/test/auth.test.mjs relay/test/wake.test.mjs diff --git a/CLAUDE.md b/CLAUDE.md index 7b1317698..7c1029cc3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -69,6 +69,12 @@ Every Igneum task in Claude in Chrome runs in the Chrome profile "josh (igneum.n binaries come from `infra/cross/build-linux.sh`; nothing is built on a server. - Never launch /Applications/Google Chrome.app headless (it blocks the owner's Chrome); use the built-in browser pane. - Keep the Mac on mains with the 140 W charger; on 4 October it hibernated at 1% battery and took node 1 and the observer down. +- A source tree copied to another machine (rsync, zip, tar, scp) is re-stamped with `touch` before anything builds it, + because cargo rebuilds by mtime and the far side keeps its target dir (the stale-build class: shard run 2 on + 4 October, the 0.3.6 PC build on 5 October). `tools/ci/copied-sources-check.sh` fails CI on any script that copies + and builds without it. When a bug is fixed, fix its CLASS: grep for every other script with the same shape the same + day, and add a check that fails when the shape comes back (Josh, 5 October 2026: "we should not be having same bugs + repeated"). - A watcher or gate is trusted only after it has been shown to fire on one known-finished and one known-failed case (4 October 2026: three job watchers waited for a line the closing report never starts with, and a failed shard run reported exit 0; the failure was found by hand half an hour later). Every job's outcome and its error lines are read diff --git a/app/igneum-app/src/jobbuild.rs b/app/igneum-app/src/jobbuild.rs index 08d4cd11b..a75bf585b 100644 --- a/app/igneum-app/src/jobbuild.rs +++ b/app/igneum-app/src/jobbuild.rs @@ -284,6 +284,9 @@ pub fn extract_script(p: &BuildParams, job_id: &str, zip_wsl: &str) -> String { s.push_str("rm -rf \"$B/src\" && mkdir -p \"$B/src\" && cp \"$ZIP\" \"$B/inputs.zip\" || { echo \"RESULT extract cannot copy the zip into $B\"; exit 2; }\n"); s.push_str("unzip -q -o \"$B/inputs.zip\" -d \"$B/src\" || { echo \"RESULT extract unzip failed\"; exit 2; }\n"); s.push_str("[ -f \"$SRC/manifest.json\" ] || { echo \"RESULT extract no manifest.json under $SRC\"; exit 2; }\n"); + // the stale-build class (5 October 2026): the target dir persists and cargo rebuilds by mtime, so every extracted + // source is stamped now, else a file older than the last build links against the cached crate of the old version + s.push_str("find \"$B/src\" -type f -exec touch {} + 2>/dev/null || true\n"); s.push_str("echo \"RESULT extract ok $(find \"$B/src\" -type f | wc -l) files, $(du -sh \"$B/src\" | cut -f1) at $(now)\"\n"); s } diff --git a/infra/cloud-devnet/builder/build-on-builder.sh b/infra/cloud-devnet/builder/build-on-builder.sh index 3c8e2d219..62a752753 100755 --- a/infra/cloud-devnet/builder/build-on-builder.sh +++ b/infra/cloud-devnet/builder/build-on-builder.sh @@ -20,7 +20,7 @@ fi cd /root if [ -f src.tar.gz ]; then - rm -rf src; tar -xzf src.tar.gz; log "unpacked src.tar.gz" + rm -rf src; tar -xzf src.tar.gz; find src -type f -exec touch {} +; log "unpacked src.tar.gz (sources re-stamped: cargo rebuilds by mtime)" fi [ -d src/vendor/igneum-node ] || { echo "no src/vendor/igneum-node"; exit 1; } cd src/vendor/igneum-node diff --git a/proving/windows-wsl2/make-package.sh b/proving/windows-wsl2/make-package.sh index 19fc474a6..8d5e9d8f8 100755 --- a/proving/windows-wsl2/make-package.sh +++ b/proving/windows-wsl2/make-package.sh @@ -13,6 +13,8 @@ cp "$HERE/SETUP-PROVER.bat" "$HERE/setup-prover.ps1" "$HERE/setup-wsl.sh" "$HERE rsync -a --exclude "target*" --exclude Cargo.lock "$ROOT/proving/igneum-prove" "$PKG/proving/" cp "$ROOT/proving/igneum-prove/Cargo.lock" "$PKG/proving/igneum-prove/" 2>/dev/null || true rsync -a "$ROOT/proving/fixtures" "$PKG/proving/" +# the package travels to a PC and is built there against a kept target dir: stamp every file now (cargo rebuilds by mtime) +find "$PKG" -type f -exec touch {} + rsync -a --exclude target "$ROOT/vendor/igneum-node-exec/igneum/evm-types" "$PKG/vendor/igneum-node-exec/igneum/" # evm-types inherits thiserror from the node's workspace; pin it inline (the node's Cargo.toml line 346: 2.0.18) so the crate builds alone. perl -pi -e 's/^thiserror\.workspace = true/thiserror = { version = "2.0.18", default-features = false }/' "$PKG/vendor/igneum-node-exec/igneum/evm-types/Cargo.toml" diff --git a/proving/windows-wsl2/prove-block.sh b/proving/windows-wsl2/prove-block.sh index 524a8819a..ca2612ff0 100755 --- a/proving/windows-wsl2/prove-block.sh +++ b/proving/windows-wsl2/prove-block.sh @@ -38,6 +38,9 @@ PY # Fresh sources from the package (edits on the Windows side are picked up), build with the cuda feature. mkdir -p "$DEST" rsync -a --delete --exclude target "$HERE/package/" "$DEST/" 2>/dev/null || cp -r "$HERE/package/." "$DEST/" +# Re-stamp every copied source: rsync keeps the Mac's dates and cargo rebuilds by mtime, so a file older than the last build +# here would be taken as unchanged (the stale-build class, 4 and 5 October 2026). +find "$DEST" -path "$DEST/*/target" -prune -o -type f -exec touch {} + 2>/dev/null || true cd "$DEST/proving/igneum-prove" echo "building (first time: 10 to 30 minutes, approximate; both guests are compiled by cargo-prove inside the host build)" if ! cargo build --release -p igneum-prove-host --features igneum-prove-host/cuda 2>&1 | tail -3; then diff --git a/proving/windows-wsl2/setup-wsl.sh b/proving/windows-wsl2/setup-wsl.sh index 75d6709a8..a57a25841 100755 --- a/proving/windows-wsl2/setup-wsl.sh +++ b/proving/windows-wsl2/setup-wsl.sh @@ -60,6 +60,9 @@ log "5/5 copying the proving sources into the Linux file system (cargo on /mnt/c DEST="$HOME/igneum-prove" mkdir -p "$DEST" rsync -a --delete --exclude target "$HERE/package/" "$DEST/" 2>/dev/null || cp -r "$HERE/package/." "$DEST/" +# Re-stamp every copied source: rsync keeps the Mac's dates and cargo rebuilds by mtime, so a file older than the last build +# here would be taken as unchanged (the stale-build class, 4 and 5 October 2026). +find "$DEST" -path "$DEST/*/target" -prune -o -type f -exec touch {} + 2>/dev/null || true cd "$DEST/proving/igneum-prove" # The guest is built by host/build.rs through cargo-prove; the host links sp1-sdk with the cuda feature. cargo build --release -p igneum-prove-export -p igneum-prove-host --features igneum-prove-host/cuda 2>&1 | tail -5 diff --git a/tools/ci/copied-sources-check.sh b/tools/ci/copied-sources-check.sh new file mode 100755 index 000000000..a7b7f1390 --- /dev/null +++ b/tools/ci/copied-sources-check.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +# The stale-build class (4 and 5 October 2026): a script copies a source tree to another machine (rsync, unzip, tar, +# Expand-Archive keep the Mac's file dates) and builds it there against a cargo target dir that survives between +# runs; cargo rebuilds by mtime, so sources older than the last build are taken as unchanged and the new code links +# against stale crates (shard run 2 on 4 October, the 0.3.6 PC build on 5 October). Rule: every script that copies +# sources and then runs cargo re-stamps the copied files (`touch`) before building. This check fails CI when a +# script copies AND builds without a touch. Scripts that copy binaries only are listed in the allow list below. +set -euo pipefail +cd "$(dirname "$0")/../.." +ALLOW='^(packaging/windows/make-payload\.sh|app/igneum-app/src/jobrun\.rs)$' +fail=0 +while IFS= read -r f; do + [[ "$f" =~ $ALLOW ]] && continue + if grep -qE 'rsync|unzip|tar -x|tar x|Expand-Archive|Copy-Item' "$f" && grep -qE 'cargo (build|test)' "$f"; then + if ! grep -qE '\btouch\b' "$f"; then echo "copied-sources: $f copies sources and runs cargo without re-stamping them (touch)"; fail=1; fi + fi +done < <(git ls-files 'packaging/**' 'proving/**' 'infra/**' 'tools/**' 'relay/playbooks/**' 'app/igneum-app/src/**' | grep -E '\.(sh|ps1|mjs|rs)$') +[ "$fail" = 0 ] && echo "copied-sources: every copying build script re-stamps its sources" +exit $fail