Skip to content

fix(test): make cd_boot_matrix build stamps converge across chunked runs - #227

Open
JoeMatt wants to merge 1 commit into
developfrom
fix/cd-matrix-stamp-converge-develop
Open

fix(test): make cd_boot_matrix build stamps converge across chunked runs#227
JoeMatt wants to merge 1 commit into
developfrom
fix/cd-matrix-stamp-converge-develop

Conversation

@JoeMatt

@JoeMatt JoeMatt commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Problem

test/tools/cd_boot_matrix.sh stamps every row it writes with scripts/build-id.sh's output, and on resume re-runs any row whose stamp differs from the current build. That stale-row guard exists for a good reason — it is what stops an old docs/cd-boot-matrix.md from resurrecting ancient results as if they were fresh (the phantom "intermittent" Battle Morph ? (pc_escape) row, final_pc=$8FBFB758, was exactly that).

But the default results file is itself tracked, and build-id.sh appends -dirty when any tracked file is modified. So:

  1. Invocation 1 on a clean tree computes e.g. abc1234 and stamps its rows with it. Writing those rows dirties the tree.
  2. Invocation 2 computes abc1234-dirty, sees every row invocation 1 recorded as "recorded by a different build", and re-runs all of them.
  3. Invocation 3 sees the same thing. It never settles.

Observed directly: a chunked sweep produced 6 rows stamped 5a83d3d, and the next invocation reported pass 1: 0/20 rows stamped 5a83d3d-dirty and started over from the top. Only a single unlimited invocation (CD_MATRIX_MAX_RUNS=0) from a clean tree could ever finish — which defeats CD_MATRIX_MAX_RUNS, whose documented reason for existing is "lets a long sweep be chunked across short invocations".

Fix

Exclude the results file from the dirty check via a new BUILD_ID_IGNORE list in scripts/build-id.sh.

The exclusion has to live in build-id.sh specifically, not in the matrix script: gen-version-h.sh stamps the binary from that same script, so an exclusion known only to the matrix would desync the binary's embedded id from the harnesses' VJ_EXPECT_BUILD and put the script into a rebuild loop that fails the build-identity guard on every run. One list, both sides agree.

Implemented as name filtering rather than an :(exclude) pathspec, so it needs no pathspec-magic support and a malformed entry can only fail toward -dirty (safe) instead of silently matching everything and disabling the guard.

The guard is not weakened. A real source edit still yields -dirty and still invalidates earlier rows; only writes to the results file — which cannot change a byte of the binary — are ignored. The script also now warns if CD_MATRIX_OUT points at some other tracked file, which hits the identical wall without being covered by the list.

Verification

From a clean tree at this commit, with the core rebuilt to match (v2.3.2 d8a7c79):

  • Two chunked invocations back to back — chunk 2 printed already recorded by this build, skipping for exactly the rows chunk 1 wrote, then advanced to the next titles. This is the behaviour the bug prevented.
  • Negative control — appending a line to src/cd/cdrom.c flipped the stamp to -dirty, triggered the core rebuild, and made previously-recorded rows read as stale row (recorded by 'd8a7c79', current 'd8a7c79-dirty'). Stale-row resurrection stays impossible.
  • Dirty-check directions — results file alone → clean; source edit and tool-script edit → -dirty; multi-entry ignore lists behave as documented.
  • Sufficiency of the one-path list — after a genuine disc run (real Battle Morph hle + bios, GAME_CODE 1/1 on the hle row), git status --porcelain showed only docs/cd-boot-matrix.md dirty. No other tracked file is written by a sweep.

The matrix table was restored after each run, so no measured rows are included here — this is a tooling fix only, with no stage re-baseline.

🤖 Generated with Claude Code

The matrix stamps every row it writes with scripts/build-id.sh's output and,
on resume, re-runs any row whose stamp differs from the current build. But
the default results file (docs/cd-boot-matrix.md) is tracked, so writing the
first row flipped the tree to "-dirty": the next invocation computed a
different id, judged all the rows it had just written stale, and re-ran them.
A chunked sweep (CD_MATRIX_MAX_RUNS) could therefore never settle, which is
the one thing chunking exists for. Observed as 6 rows stamped 5a83d3d
followed by "pass 1: 0/20 rows stamped 5a83d3d-dirty".

Exclude the results file from the dirty check in build-id.sh, which both
sides of the guard already share: gen-version-h.sh stamps the binary from the
same script, so the binary's embedded id and the harnesses' VJ_EXPECT_BUILD
stay in agreement. A source edit still yields "-dirty" and still invalidates
earlier rows, so the stale-row guard keeps doing its job.

Also warn when CD_MATRIX_OUT points at some other tracked file, which would
hit the same non-convergence without being covered by the ignore list.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 31, 2026 04:04
@github-actions github-actions Bot added tests test harnesses, regression baselines build Makefile / Makefile.common / scripts/ labels Jul 31, 2026
@github-actions

Copy link
Copy Markdown

Regression: linux-x64

Regression Test Results

ROM Status Details Diff
jagniccc 🆕 NEW no baseline -
yarc 🆕 NEW no baseline -
jagniccc (determinism) ✅ PASS identical across runs -
yarc (determinism) ✅ PASS identical across runs -
jagniccc (frameskip) ✅ PASS skip=0 matches skip=3 -
yarc (frameskip) ✅ PASS skip=0 matches skip=3 -
jagniccc (save state) ✅ PASS round-trip matches -
yarc (save state) ✅ PASS round-trip matches -
jagniccc (rewind) ✅ PASS rewind matches -
yarc (rewind) ✅ PASS rewind matches -

Platform: Linux x86_64

Updated by CI at 2026-07-31T04:05:46.227Z

@github-actions

Copy link
Copy Markdown

Regression: linux-arm64

Regression Test Results

ROM Status Details Diff
jagniccc 🆕 NEW no baseline -
yarc 🆕 NEW no baseline -
jagniccc (determinism) ✅ PASS identical across runs -
yarc (determinism) ✅ PASS identical across runs -
jagniccc (frameskip) ✅ PASS skip=0 matches skip=3 -
yarc (frameskip) ✅ PASS skip=0 matches skip=3 -
jagniccc (save state) ✅ PASS round-trip matches -
yarc (save state) ✅ PASS round-trip matches -
jagniccc (rewind) ✅ PASS rewind matches -
yarc (rewind) ✅ PASS rewind matches -

Platform: Linux aarch64

Updated by CI at 2026-07-31T04:05:53.148Z

@github-actions

Copy link
Copy Markdown

Regression: macos-arm64

Regression Test Results

ROM Status Details Diff
jagniccc 🆕 NEW no baseline -
yarc 🆕 NEW no baseline -
jagniccc (determinism) ✅ PASS identical across runs -
yarc (determinism) ✅ PASS identical across runs -
jagniccc (frameskip) ✅ PASS skip=0 matches skip=3 -
yarc (frameskip) ✅ PASS skip=0 matches skip=3 -
jagniccc (save state) ✅ PASS round-trip matches -
yarc (save state) ✅ PASS round-trip matches -
jagniccc (rewind) ✅ PASS rewind matches -
yarc (rewind) ✅ PASS rewind matches -

Platform: Darwin arm64

Updated by CI at 2026-07-31T04:06:43.413Z

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a convergence issue in the CD boot-matrix tooling where chunked runs would continuously invalidate prior rows because writing the tracked results file made the working tree appear “dirty”, changing the build stamp across invocations.

Changes:

  • Adds a BUILD_ID_IGNORE mechanism to scripts/build-id.sh (and a --ignores flag) so tracked results files don’t force a -dirty build id.
  • Updates test/tools/cd_boot_matrix.sh documentation and behavior to rely on the stable stamp across chunked invocations, and warns when CD_MATRIX_OUT points at a tracked file not covered by the ignore list.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
test/tools/cd_boot_matrix.sh Improves chunked resume behavior docs and adds a warning when the output file would cause non-converging stamps.
scripts/build-id.sh Introduces an ignore list and --ignores output to prevent results-file writes from toggling the build id to -dirty.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/build-id.sh
Comment on lines +33 to +37
# Repo-root-relative paths, ONE PER LINE -- the list is fed to `grep -vxF`,
# which reads a newline-separated pattern set. Space-separating two entries
# makes a single literal pattern that matches no filename at all, silently
# restoring the non-convergence this list exists to prevent.
BUILD_ID_IGNORE='docs/cd-boot-matrix.md'
Comment on lines +125 to +132
if git ls-files --error-unmatch "$OUT" >/dev/null 2>&1 \
&& ! scripts/build-id.sh --ignores 2>/dev/null | grep -qxF "$OUT"; then
echo "WARNING: CD_MATRIX_OUT=$OUT is tracked by git but is not in" >&2
echo " scripts/build-id.sh's ignore list. Writing rows will flip the build" >&2
echo " id to '-dirty', so the next chunked invocation will treat every row" >&2
echo " this one records as stale and re-run it. Add the path to" >&2
echo " BUILD_ID_IGNORE, or point CD_MATRIX_OUT at an untracked file." >&2
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build Makefile / Makefile.common / scripts/ tests test harnesses, regression baselines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants