Skip to content

Audit hashes of regenerated gzip containers and propose a one-paragraph rule (no κ) - #220

Closed
maxime-fleury wants to merge 1 commit into
CrocSwap:mainfrom
maxime-fleury:research/gzip-container-reproducibility
Closed

maxime-fleury wants to merge 1 commit into
CrocSwap:mainfrom
maxime-fleury:research/gzip-container-reproducibility

Conversation

@maxime-fleury

@maxime-fleury maxime-fleury commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

No κ, no certificate change, no new mathematics. This audits one reproducibility pattern and proposes a rule for it.

The pattern

A package writes a container with gzip.compress(...), hashes the compressed bytes, and requires that hash to equal a value committed or pinned when the container was produced elsewhere. A gzip container's deflate stream depends on the writing interpreter and zlib build, so that check can fail on unchanged inputs and can hide a real change behind an environment difference.

Two observations establish it, from opposite directions:

  1. A check that fails on unchanged inputs. Compose the v4 source-assisted complex word with the PR200 bit supplier: conditional κ = 6.768823e-4 #202's headline verifier (research/source-assisted-v4/verify.py:162) stops with Canonical certificate does not reproduce. Exactly seven leaves differ and all derive from one value: the sha256 of the compressed lift certificate, written by research/source-assisted/decision/exact_complex_flow_lift.py:409 and recorded at :419 as certificate_sha256=digest(cert_path) of the file. Every other leaf, including κ, the complex saving, the bit effective saving and the assembly records, is equal. PR Replays of the verifiers of #207, #202, #197 and #199 (no new κ) #214 reproduces this on CPython 3.13.16 with the pinned numpy 2.3.5 / scipy 1.17.0, and reports the same failure for Source-assisted v4 complex word with PR189's bit supplier: conditional κ = 6.674324e-4 #194's own verifier under CPython 3.12.3, with the lift inputs unchanged between the two commits; Source-assisted v4 complex word with PR189's bit supplier: conditional κ = 6.674324e-4 #194's CI passed the same check under the same versions.
  2. A rebuild instruction that does not reproduce. A frame-layout ceiling for #200's bit word: coarse < 6.964e-4 under the banked ledger, so κ < 6.959e-4 on #205–#207's word (no new κ) #212's pinned archive rebuilds byte for byte as a tar payload from a1175449 (verified), but not as a container: shipped 316aa694… / 1,405,363 bytes against cb71d72d… / 1,404,558 bytes here, and no zlib level 1–9 reproduces the shipped length. No number changes; ceiling.py still checks the archive's file hashes.

What the repository already does right

What is added here

research/gzip-container-reproducibility/ with the audit above (file and line evidence), gzip_hash_audit.py (a heuristic scanner: writes / container-digest / comparison, printed with its evidence), and CONTRIBUTING-note.md, which carries the paragraph proposed for CONTRIBUTING.md — place it after the paragraph asking contributors to include regenerated certificates. Its text: compare payloads not containers when a check regenerates a file; pin payloads or semantic fields rather than container digests; committed containers are fine to pin; a container digest may be recorded only as an environment receipt, with the interpreter and zlib versions beside it, and must not be required to match across environments.

Scanner findings, one full-tree checkout per pinned head (git worktree add --detach), "risky" being a file that writes a container and records a digest of it: main 3b6b668 639 .py files, 3 risky (research/pair-assembly/frame/frame_compile.py:48, research/machine-transfer-verification/stream-transfer/experiments/balanced_split.py:64, scripts/experiments/probe_pair_ranked.py:41); #194 a8c8778 578 files, 3 (those three, plus research/source-assisted/decision/exact_complex_flow_lift.py:419, the record observation 1 follows); #202 8d8d67b 605 files, 3 (the same three); #207 cd14825 650 files, 4 (the merged tree's three plus coordinated-crossover-pr200/geometry/audit-gauge-charts.py:50); #212 9b6ad03 640 files, 3 (the merged tree's three); #216 34abdc5 660 files, 5 (theirs plus audit-gauge-charts.py:50 twice, in the package and in its vendored baseline); #217 b739fc2 654 files, 3 (the merged tree's three; the scanner does not flag run_bit.py:151). Opened rather than counted, the three shared flags read as records beside the payload digest (frame_compile.py:48), a record nothing reads back (probe_pair_ranked.py:41), and the one container digest in the merged tree that is required against a stored value -- balanced_split.py:64 with verify_balanced_split.py:67, safe while the container and its receipt travel together from one run, observation 1 if a harness ever regenerates the container from the candidate's inputs. The scanner is a heuristic, not a proof of absence: it cannot see a digest recorded in one file and required in another (the #202 case is written out as a chain of file and line for that reason).

Prepared with Anthropic Claude assistance; Apache-2.0. No existing file is changed; the CONTRIBUTING.md edit is left to the maintainers.

@maxime-fleury
maxime-fleury force-pushed the research/gzip-container-reproducibility branch from eed0de4 to d656775 Compare October 9, 2026 19:24
Two observations establish the failure mode: CrocSwap#202's canonical check requires the
sha256 of a container it regenerates (exact_complex_flow_lift.py:409 and :419,
required by source-assisted-v4/verify.py:162) and fails on unchanged inputs,
while CrocSwap#194 passes in the same environment; and PR212's pinned archive rebuilds
byte for byte as a tar payload but not as a container. The repository already has
the fixes in use -- CrocSwap#194 decompresses before comparing, CrocSwap#217 pins payload hashes
and CrocSwap#207 checks semantic fields -- so this adds a scanner that locates the
pattern, the audit with file and line evidence, and one CONTRIBUTING.md paragraph
stating the rule once.

Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
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.

2 participants