Skip to content

cadical: pin build.hpp's date and host (reproducible, 2.1.3) - #757

Draft
bryan-minimal wants to merge 4 commits into
mainfrom
cadical-repro
Draft

bryan-minimal wants to merge 4 commits into
mainfrom
cadical-repro

Conversation

@bryan-minimal

@bryan-minimal bryan-minimal commented Sep 24, 2026 •

Copy link
Copy Markdown
Member

cadical 2.1.3 is not byte-reproducible without this. scripts/make-build-header.sh puts date and uname -srmn (the build's wall clock plus the host's hostname and kernel release) into build.hpp's DATE macro, which lands in .rodata. That script is unchanged from 2.1.2 to 2.1.3: upstream HEAD's SOURCE_DATE_EPOCH support isn't in a release yet, and HEAD still embeds uname.

Its other inputs are already deterministic in our sandbox: the git id is empty (no .git in the tarball), COMPILER is g++ --version, and FLAGS are our CXXFLAGS.

The fix (build.sh only): instead of editing the upstream script, the make step gets pinned commands on PATH:

  • date → date -u -d @$SOURCE_DATE_EPOCH (the sandbox's epoch, per AGENTS.md)
  • uname → kernel name and machine only, with no hostname and no kernel release

A fixed-string check then fails the build if build.hpp's DATE is not the pinned value, so a future upstream script that stops reading date/uname from PATH can't silently reintroduce host data. The result is DATE "Thu Jan 1 12:00:00 AM UTC 1970 Linux aarch64". cadical --version reports that pinned string, which is the intended trade.

This also reverts minimal.toml, which an earlier commit on this branch changed by mistake (repro-lab tasks).

Verified in remote sessions, aarch64, a fresh activate per build, --rebuild --verbose, each a real build with 87 compiler invocations. A temporary, uncommitted probe printed output hashes into the build log:

build recipe usr/bin/cadical sha256 build.hpp DATE
A this PR dc05982c40847e87a2cf86852c408dfc5f1ec06c6f772368cb729d678ec9d4a5 Thu Jan 1 12:00:00 AM UTC 1970 Linux aarch64
B this PR dc05982c40847e87a2cf86852c408dfc5f1ec06c6f772368cb729d678ec9d4a5 same
C main (no fix) f0467e6db7400f2ca36f50526956bfdf687ff3e9bda46e38cf9ac471e4f95ffb Fri Oct 23 07:47:43 PM UTC 2026 Linux (none) 6.12.111 aarch64
D main (no fix) f46e68f2525d513c24e1123647c0087b6a247973d72881f73bdae5bdf47e76c0 Fri Oct 23 07:49:02 PM UTC 2026 Linux (none) 6.12.111 aarch64

min check --packages cadical passes every check, standalone tests included, with no Skip. nickel format --check, bash -n and mip dump (amd64 + arm64) are clean.

Not covered: a cross-host comparison on the same arch. With the hostname and kernel release removed and the date pinned, the remaining header inputs don't depend on the host, so it should hold, but only same-host double builds ran here.

Relates to gominimal/inbox#253.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@bryan-minimal

Copy link
Copy Markdown
Member Author

Verification update from the x86_64 lab box (48-core, native minimald):

4-build gauntlet, all byte-identical. Four forced real builds (min package build --rebuild, evicted between), each compared against build 1 — no differences. A double-build can clear an intermittent bug about half the time, so this is the stronger check.

One honest caveat on scope. A same-host gauntlet proves the DATE pin: both builds saw different wall-clock and now agree. It cannot prove the OS pin, because every build on one machine sees the same uname -srmn. That half is reasoned rather than measured — uname embeds the build host's kernel version and hostname, so it would differ across machines and defeat a cross-host comparison. Cross-host verification is not something this lab can run yet.

🤖 Generated with Claude Code

@bryan-minimal

Copy link
Copy Markdown
Member Author

Follow-up: the uname half is now measured, not just reasoned. Two builds of unpatched cadical at the pin on the x86_64 lab box embed:

A="Thu Sep 24 10:37:47 PM UTC 2026 Linux cachyos-x8664 7.2.6-1-cachyos x86_64"
B="Thu Sep 24 10:38:52 PM UTC 2026 Linux cachyos-x8664 7.2.6-1-cachyos x86_64"

That is the build host's hostname and kernel release in .rodata, alongside the wall clock. Same-host builds only disagree on the time; any two hosts would also disagree on the rest. The earlier aarch64 run showed Linux (none) 6.12.105 aarch64 from inside the Mac's VM — a third distinct value for the same source. So the OS= pin is doing real work, not just defending a hypothetical.

🤖 Generated with Claude Code

bryan-minimal and others added 3 commits October 14, 2026 17:23
… stray minimal.toml

2.1.3's scripts/make-build-header.sh is unchanged from 2.1.2: it still puts
`date` and `uname -srmn` (wall clock, hostname, kernel release) into the DATE
macro in .rodata. Instead of sed-editing the upstream script, the make step
gets pinned `date` (SOURCE_DATE_EPOCH, UTC) and `uname` (kernel name +
machine) on PATH, and a fixed-string check fails the build if build.hpp's
DATE is not the pinned value. Also reverts minimal.toml, which an earlier
commit on this branch changed by mistake (repro-lab tasks).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@bryan-minimal bryan-minimal changed the title cadical: pin build date and uname in build.hpp (reproducible) cadical: pin build.hpp's date and host (reproducible, 2.1.3) Oct 23, 2026
@bryan-minimal

Copy link
Copy Markdown
Member Author

Reworked for cadical 2.1.3 (now on main via #999) in d45d1b9, on a merge of main. 2.1.3's make-build-header.sh is unchanged, so both pins are still needed. They now go in through PATH shims for date and uname, with a fail-closed header check, instead of a sed on the upstream script. Two fresh-session builds are byte-identical (dc05982c…), and the unfixed main recipe built twice differs (f0467e6d… vs f46e68f2…). The table is in the body. The stray minimal.toml change is reverted. Leaving this as a draft.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant