agent-browser: make Rust CLI + pnpm tree reproducible#264
Conversation
Two independent causes of cross-rebuild divergence: 1. Rust CLI codegen: parallel codegen-units (.llvm.<hash> symbols) plus ahash/const-random's compile-time seed. Pin both via RUSTFLAGS (-C codegen-units=1, path remaps) and CONST_RANDOM_SEED=0. 2. pnpm state files embed wall-clock timestamps (.modules.yaml prunedAt, .pnpm-workspace-state-v1.json lastValidatedTimestamp) and aren't needed at runtime. Drop both before packaging. Verified on aarch64: with the codegen fixes, two from-scratch builds were identical in 12737/12738 files (sole diff = the pnpm timestamp file); removing it yields byte-identical output (repro-check diff, 0 differences). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
📝 WalkthroughWalkthrough
ChangesReproducible Build Hardening
Estimated code review effort🎯 2 (Simple) | ⏱️ ~5 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/agent-browser/build.sh (2)
1-2:⚠️ Potential issue | 🟠 Major | ⚡ Quick winEnable required strict mode for build scripts.
This script currently sets only
-e; it should enforce unset-variable and pipeline failure checks too.As per coding guidelines: "
packages/*/build.sh: Useset -euo pipefailat the beginning of build scripts to ensure error handling and strict variable expansion."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/agent-browser/build.sh` around lines 1 - 2, Update the shell script strict mode initialization by replacing the current `set -e` line with `set -euo pipefail`. This will enable all three strict mode options: exit on error (e), error on unset variables (u), and error on pipe failures (o pipefail), which ensures comprehensive error handling and variable expansion checks throughout the build script execution.Source: Coding guidelines
42-49:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winDrop libtool archives from the output tree after install.
The script should remove
.lafiles from$OUTPUT_DIRas part of post-install cleanup.Suggested patch
cp -R dist bin node_modules package.json $OUTPUT_DIR/usr/libexec/agent-browser/ +find "$OUTPUT_DIR" -name '*.la' -deleteAs per coding guidelines: "Post-install, drop libtool archives with
find "$OUTPUT_DIR" -name '*.la' -delete."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/agent-browser/build.sh` around lines 42 - 49, The build script is missing post-install cleanup to remove libtool archive files (.la files) from the output directory. After the chmod command that sets executable permissions on the agent-browser wrapper script, add a find command that searches through $OUTPUT_DIR for all files matching the pattern '*.la' and deletes them using the -delete action to comply with post-install cleanup guidelines.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/agent-browser/build.sh`:
- Around line 6-8: In the build.sh script, add two additional environment
variable exports for deterministic builds after the existing RUSTFLAGS and
CONST_RANDOM_SEED exports. Export SOURCE_DATE_EPOCH=0 to pin the build timestamp
and PYTHONHASHSEED=0 to ensure deterministic Python hashing during any
Python-based build steps, as required by the reproducible-build contract.
---
Outside diff comments:
In `@packages/agent-browser/build.sh`:
- Around line 1-2: Update the shell script strict mode initialization by
replacing the current `set -e` line with `set -euo pipefail`. This will enable
all three strict mode options: exit on error (e), error on unset variables (u),
and error on pipe failures (o pipefail), which ensures comprehensive error
handling and variable expansion checks throughout the build script execution.
- Around line 42-49: The build script is missing post-install cleanup to remove
libtool archive files (.la files) from the output directory. After the chmod
command that sets executable permissions on the agent-browser wrapper script,
add a find command that searches through $OUTPUT_DIR for all files matching the
pattern '*.la' and deletes them using the -delete action to comply with
post-install cleanup guidelines.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 5c63048a-add2-4e5d-a9de-4952f053af39
📒 Files selected for processing (1)
packages/agent-browser/build.sh
| export RUSTFLAGS="-C linker=gcc --remap-path-prefix=$(pwd)=/builddir --remap-path-prefix=$HOME/.cargo=/cargo -C codegen-units=1" | ||
| export CONST_RANDOM_SEED=0 # pin ahash/const-random compile-time seed | ||
|
|
There was a problem hiding this comment.
Add deterministic timestamp/hash environment exports.
Please export SOURCE_DATE_EPOCH=0 and PYTHONHASHSEED=0 in this script to satisfy the reproducible-build contract.
Suggested patch
export LD=gcc
export RUSTFLAGS="-C linker=gcc --remap-path-prefix=$(pwd)=/builddir --remap-path-prefix=$HOME/.cargo=/cargo -C codegen-units=1"
export CONST_RANDOM_SEED=0 # pin ahash/const-random compile-time seed
+export SOURCE_DATE_EPOCH=0
+export PYTHONHASHSEED=0As per coding guidelines: "For embedded timestamps and Python-based build steps, export SOURCE_DATE_EPOCH=0 and PYTHONHASHSEED=0."
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export RUSTFLAGS="-C linker=gcc --remap-path-prefix=$(pwd)=/builddir --remap-path-prefix=$HOME/.cargo=/cargo -C codegen-units=1" | |
| export CONST_RANDOM_SEED=0 # pin ahash/const-random compile-time seed | |
| export RUSTFLAGS="-C linker=gcc --remap-path-prefix=$(pwd)=/builddir --remap-path-prefix=$HOME/.cargo=/cargo -C codegen-units=1" | |
| export CONST_RANDOM_SEED=0 # pin ahash/const-random compile-time seed | |
| export SOURCE_DATE_EPOCH=0 | |
| export PYTHONHASHSEED=0 |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/agent-browser/build.sh` around lines 6 - 8, In the build.sh script,
add two additional environment variable exports for deterministic builds after
the existing RUSTFLAGS and CONST_RANDOM_SEED exports. Export SOURCE_DATE_EPOCH=0
to pin the build timestamp and PYTHONHASHSEED=0 to ensure deterministic Python
hashing during any Python-based build steps, as required by the
reproducible-build contract.
Source: Coding guidelines
|
Thanks @coderabbitai — dispositions on the three findings:
|
|
Tip For best results, initiate chat on the files or code changes.
✏️ Learnings added
|
What
Makes the
agent-browserpackage reproducible — its Rust CLI and its pnpmnode_modulestree both diverged across rebuilds.Why / fixes
Two independent causes, both addressed:
Rust CLI codegen non-determinism. The release build split each crate into parallel codegen units (non-deterministic
.llvm.<hash>symbols + function partitioning) andahash/const-randombaked a compile-time random seed. Fixed by extendingRUSTFLAGS:pnpm state-file timestamps. pnpm writes wall-clock timestamps into two
node_modulesstate files that aren't needed at runtime —.modules.yaml(prunedAt) and.pnpm-workspace-state-v1.json(lastValidatedTimestamp). Drop both before packaging.Verification
Two from-scratch forced rebuilds (
--rebuild --no-fetch, aarch64) produced output identical in 12,737 / 12,738 files — with the codegen fixes in place, the only remaining difference was the.pnpm-workspace-state-v1.jsontimestamp. After removing that file the two builds are byte-for-byte identical (repro-check diff, 0 differences). The Rust binary and all other artifacts were already byte-identical, confirming the codegen flags resolve the CLI non-determinism.🤖 Generated with Claude Code
Summary by CodeRabbit