Skip to content

Reproducible 202609 chain, step 8: tools/verify_release.py — hash a release, re-verify any host or mirror against it - #356

Merged
rdhyee merged 6 commits into
isamplesorg:mainfrom
rdhyee:pipeline/verify-release
Aug 28, 2026
Merged

Reproducible 202609 chain, step 8: tools/verify_release.py — hash a release, re-verify any host or mirror against it#356
rdhyee merged 6 commits into
isamplesorg:mainfrom
rdhyee:pipeline/verify-release

Conversation

@rdhyee

@rdhyee rdhyee commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

🤖 rbotyee (Claude, operated by @rdhyee) — Raymond's intent: keep going on Part B under the standing rule ("keep going as long as you get CC+Codex+LGTM, deployment to rdhyee looks good"). What I did: wrote the release verifier the plan's step 8 calls for, took it through six Codex rounds, and tested each verdict path against local files and one live production file. No published file changes.

What it is

tools/verify_release.py

  • hash --dir <release dir> --release-id <id> --out <manifest.json> — every .parquet/.json (except *.manifest.json build sidecars) with bytes + SHA-256. Complete for a quiescent directory: no filters, symlinked entries and unreadable subtrees are errors, not omissions.
  • check --manifest <manifest.json> (--base https://host | --dir <mirror>) [--only glob] [--skip-prefix p] [--report r.json] — re-reads every listed file and compares size + SHA-256.
    • VERIFIED (exit 0) only when every listed file was checked and matched; PARTIAL (exit 3; 0 with --allow-partial) when a filter left files unchecked; FAILED (exit 1) on any mismatch, missing file, or operational error (including a report that can't be written).
    • Redirects refused (a "mirror" that redirects to the origin is not a copy); Accept-Encoding: identity and any Content-Encoding fails the file; HEAD size fast-fail; GET status/framing checked; short bodies fail; paths percent-encoded per segment; manifest strictly validated (schema tag, counts, path grammar, types); --dir containment; destinations (--out, --report) may not sit inside the tree they describe, be symlinks, or hard-link a listed file; atomic writes.
    • Contract stated plainly in the docstring: "matched when read" — a target that changes during the run is outside it.

The #334 release manifest (size/ETag) stays the Explorer's boot-time cross-check; this is the byte-level truth for a release, usable against R2, a mirror, or an unpacked Zenodo deposit.

Evidence

16 local 202609 derived files hashed and re-verified; live vocab_labels_202608.parquet VERIFIED against data.isamples.org; tampered hash → FAILED/1; wrong size → fast FAILED/1 (no body fetched); --only → PARTIAL/3; ../x.json, sub/./x.json, bool file_count, fragment-bearing --base, symlinked subdir, hard-linked --report/--out, unwritable report dir — each rejected as specified. Requires an explicit User-Agent (Cloudflare 403s Python-urllib).

Review

Codex ×6, each asked to refute "VERIFIED means every listed byte matches": R1 changes-required (partial→VERIFIED; unencoded URLs; redirects; containment; framing; hash --only) → R2 (report inside target; walk completeness; fragment base; typing; canonical paths) → R3 (hard links; contract wording) → R4 (destination symlinks; report-write ordering) → R5 (stdout manifest) → R6 LGTM. Verdict posted below.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LtTxB4jfTZgaTR7CK4zKqy

rdhyee and others added 6 commits August 28, 2026 15:40
… or mirror against it (chain step 8)

hash: every .parquet/.json under a dir → release_hashes.json (bytes + sha256).
check: HEAD size fast-fail then streamed sha256 per file against --base URL or
--dir; --only/--skip-prefix (skipped is reported, never counted as verified);
JSON --report; exit 0 only when every listed file matches. Explicit User-Agent
(Cloudflare 403s Python-urllib). Tested: 16 local files verified; live
vocab_labels_202608 verified against data.isamples.org; tampered sha256 and
wrong size both FAIL with exit 1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LtTxB4jfTZgaTR7CK4zKqy
…otherwise); refuse redirects; URL-encode + validate paths; contain --dir; strict GET framing; complete hash mode (Codex round 1)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LtTxB4jfTZgaTR7CK4zKqy
…ete walks, strict manifest typing, canonical paths (Codex round 2)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LtTxB4jfTZgaTR7CK4zKqy
…lace), commonpath containment, non-empty release id, 'matched when read' contract (Codex round 3)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LtTxB4jfTZgaTR7CK4zKqy
…links), report written before the verdict and its failure is FAILED (Codex round 4)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LtTxB4jfTZgaTR7CK4zKqy
@rdhyee

rdhyee commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

🤖 rbotyee — Codex round 6 (final) verdict, verbatim:

No P1/P2 findings.

Verdict: LGTM

Round 5’s issue is resolved:

  • --out is required by argparse.
  • Omitting it exits 2, writes zero bytes to stdout, and prints usage to stderr.
  • Successful hash mode only writes JSON to the specified file; stdout contains progress/status only.

Offline checks passed: syntax compilation, local hash/check smoke tests, and git diff --check. Review remained scoped to tools/verify_release.py; no network used.

@rdhyee rdhyee added the CC+Codex+LGTM Claude and Codex both reached LGTM; ready for human review label Aug 28, 2026
@rdhyee
rdhyee merged commit fcfee5e into isamplesorg:main Aug 28, 2026
1 check passed
@rdhyee

rdhyee commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

🤖 rbotyee — staging check before merge: fork Pages run 33207335311 on this branch built green; explorer-smoke 4 passed (9.4s) against https://rdhyee.github.io/isamplesorg.github.io. Merged under RY's standing rule.

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

Labels

CC+Codex+LGTM Claude and Codex both reached LGTM; ready for human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant