Skip to content

feat: determinism envelope, k-of-N chain audit, and replay-free forgery detection - #95

Merged
Archit381 merged 20 commits into
mainfrom
tree
Aug 10, 2026
Merged

feat: determinism envelope, k-of-N chain audit, and replay-free forgery detection#95
Archit381 merged 20 commits into
mainfrom
tree

Conversation

@ryoari

@ryoari ryoari commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Answers the two open questions in #37 with measured evidence rather than assumption, and adds the machinery needed to produce it.

On "is checkpoint hashing sufficient?" : No. Hashing final checkpoints alone cannot distinguish an honest training run from a forged one. This PR adds a k-of-N checkpoint-chain trainer that commits to full training state at segment boundaries, plus a sampled segment auditor that re-executes a random subset and compares bitwise.

On "software vs hardware nondeterminism?" : Software entropy is fully controllable; hardware is the hard boundary. Same model on same architecture reproduces bitwise (PASS); cross-architecture does not (FAIL), and that failure is clean and detectable rather than noisy. DDP at 2x3090 is bitwise reproducible both run-to-run and cross-rank, so data parallelism is not itself a source of drift.

Addressed Issues:

Fixes #37

What's included

Verification core : src/chain.py (k-of-N chain trainer + sampled segment auditor), src/forgery.py (replay-free forgery detectors over full-state chain boundaries, robust median/MAD norm profile), src/envelope.py (determinism envelope across SDPA backends and torch.compile). Hash mismatch now fails verify(), and the falsifiability suite is enforced in CI.

Evidence : committed under proofs/ as reproducible JSON artifacts with the nvidia-smi output for each run:

Directory Result
chain_a40/ Mid-scale k-of-N chain audit (RUNBOOK section 8)
chain_cross/ Cross-hardware controls: same-model PASS, cross-arch FAIL
envelope_l40s/ Execution-variant envelope; compile is verifiable, but every variant is its own bit-universe
forgery_l40s/ Replay-free forgery detection at 116M params; segment length is a detectability dial
smartforger_l40s/ Adaptive forger sweep; moment forging only pays with small deltas
ddp_2x3090/ DDP bitwise reproducible, run-to-run and cross-rank

Supporting ~ paper/DRAFT.md writing up the result and positioning it against Proof-of-Training-Data and deterministic unlearning; scripts/pod_*.sh unattended runners for the GPU evidence runs; generated artifacts routed to a gitignored runs/ directory; tests/test_experiment.py.

Screenshots/Recordings:

N/A - no user-facing interface changes. This PR is verification machinery and evidence artifacts.

The reviewable equivalent is the committed audit output. Cross-architecture control, showing the intended PASS/FAIL split:

proofs/chain_cross/trainer_audit_report.json   same arch    PASS
proofs/chain_cross/a4000b_audit_report.json    cross arch   FAIL
proofs/chain_cross/l4_audit_report.json        cross arch   FAIL

Every run under proofs/ ships with its nvidia.txt so the hardware context is auditable without re-running on a GPU.

Additional Notes:

#37 proposed an experiments/ directory for contributors to validate assumptions. This PR takes a slightly different shape: the experiment harnesses live in src/ as first-class, tested, CI-enforced modules so they are importable rather than scratch scripts, and their outputs are committed under proofs/ so results stay auditable without GPU access. Happy to reshape into the proposed experiments/ layout if maintainers prefer that structure.

The GPU evidence runs (A40, L40S, 2x3090) were executed on rented pods via scripts/pod_chain_run.sh and scripts/pod_forgery_run.sh. Reviewers without that hardware can verify the committed reports and manifests directly; re-running from scratch requires the matching architecture, which is precisely the cross-architecture result this PR documents.

Sized for review: 48 files, but the great majority of the line count is generated JSON evidence under proofs/. The code to review is src/chain.py, src/forgery.py, src/envelope.py, and the src/reproducibility.py changes.

I have used the following AI models and tools: Claude Code (Claude Opus) for implementation assistance, harness scaffolding, and drafting this description. All experimental results are real measured GPU runs, not generated - the committed artifacts under proofs/ are the raw outputs. Design decisions and result interpretation are my own.

ryoari and others added 19 commits July 7, 2026 05:31
…n CI

verify() previously returned the loss-trajectory verdict and only reported a
parameter-hash mismatch, so post-training sabotage (matching telemetry,
differing bits) returned a passing verdict. Tolerance-based acceptance is the
loophole that broke proof-of-learning (Fang et al. 2023); with bit-exact
replay the window is zero, so the exact hash is the verdict and the 1e-6
trajectory comparison is kept as a divergence-localization diagnostic.

- verify() returns match AND hash_match; loss-pass/hash-fail is now a FAIL
- reproducibility.py __main__ asserts every scenario against its expected
  outcome (clean passes; bad seed / noise / sabotage / broken seal fail)
  and exits nonzero on any violation, making the contract CI-enforceable
- new VerifyVerdictTests pin the semantics (4 cases)
- new ci.yml runs unit tests + the falsifiability suite on CPU torch
- README: debate paragraph resolved into the verification-bar statement;
  new "What a spot-check audit buys" section with the k/N sampling bound,
  multi-auditor compounding, cost model, and the open detectability question

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The audit pipeline wrote checkpoints, detached signatures, telemetry logs,
and manifests into whatever directory it was launched from, littering the
repo root and src/ with regenerable outputs. All generated paths are now
anchored at REPO_ROOT/runs (override with OVL_RUNS_DIR), created on demand,
and gitignored.

- artifacts.py: RUNS_DIR + checkpoint paths as absolute Paths; mkdir on save
- reproducibility.py / eval.py / global_manifest.py: logs, corrupted-seal
  scenario, and eval/pipeline manifests all resolve under RUNS_DIR
- signing.py / telemetry.py: create parent dirs before writing
- manifests and signed checkpoints embed artifact file NAMES, not
  machine-specific absolute paths, so sealed hashes stay portable

Verified: 18 unit tests OK; falsifiability suite PASS (exit 0) launched from
src/, with all 13 generated files landing in runs/ and none in the cwd.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Implements the audit mechanism the README's soundness section describes but
no code performed: reproducibility.py proves single-segment replay; chain.py
runs it at chain scale.

- train: seals a SIGNED full-training-state boundary checkpoint (weights,
  optimizer, all four RNG streams) at every segment boundary, starting from
  the seeded init (boundary 0), plus a signed chain_manifest.json carrying
  the commitment (dataset sha256, full config, seed) and per-segment wall
  times
- audit: verifies the manifest signature, checks the dataset against the
  committed hash (substitution detection), samples k of N segments with a
  seeded RNG (audits are themselves reproducible), replays each from its
  opening boundary with zero tolerance, and reports measured economics:
  auditor-vs-prover wall time (realized k/N cost ratio) and the k/N
  detection probability against a minimal single-bad-segment forgery
- replay rebuilds the model from the COMMITTED config in the manifest, not
  local env-var state
- new gpt120m preset (~116M params) for the mid-scale evidence run;
  RUNBOOK section 8 has the smoke, pod, and tamper-drill commands
- 4 new tests: clean full audit, sampled k/N reporting, tampered boundary
  rejected via signature before deserialization, tampered manifest rejected
- CI runs the CLI smoke (train 4 segments, audit 2)

Measured honestly at smoke scale: cost ratio EXCEEDS k/N because fixed
per-segment overhead dominates a 3-step segment; the k/N economics require
segment compute to dominate, which the mid-scale run is designed to show.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e run

Clones assumed at /workspace/repo; serves /workspace over HTTP :8000 from the
start so status/results are pollable through the RunPod proxy, then runs
chain.py train + a k-segment audit and writes audit_report.json,
chain_manifest.json, chain_size.txt, nvidia.txt into /workspace/out.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rrors

Ubuntu 24.04 pod images mark the system python externally-managed, so the
bare pip install exited 1 and every downstream step cascaded. Install into
/workspace/venv instead, and park with a FATAL status line if setup or
training fails so the failure is observable rather than cascading.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The default PyPI torch wheel targets a newer CUDA than the pod's 12.8
driver and fails at CUDA init; install torch from the index matching the
image driver (env-tunable via OVL_TORCH_INDEX) before the rest of
requirements.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
gpt120m (116,343,808 params) on enwik8, 20 segments x 500 steps, strict
deterministic fp32, RunPod secure A40, torch 2.11.0+cu128:

- all 20 segments sealed at a steady ~63.6s each
- k=3 sampled audit (segments 4, 10, 12, audit_seed=7): every replay
  bit-exact -- GPU bitwise determinism holds at 116M params through full
  save/restore checkpoint boundaries
- measured audit cost ratio 0.173 vs theoretical k/N = 0.15 (replay
  overhead ~1.44x a prover segment: checkpoint load + tensor hashing)
- chain storage 28.5 GB / 21 boundaries = 1.36 GB per boundary, matching
  the 3x-weights prediction for Adam state
- dataset commitment check passed (enwik8 sha256)

proofs/chain_a40/ carries the signed chain manifest, the audit report,
storage measurement, GPU info, and the training log. Total pod cost ~$0.32.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…-arch FAIL)

One gpt120m chain (5x200 steps, enwik8, strict deterministic fp32) trained
on a secure RTX A4000, audited with identical sampled segments (1, 2,
audit_seed=7) from three positions:

- same pod (positive control): PASS, cost ratio 0.460
- second RTX A4000 pod, different physical GPU: PASS bit-exact, ratio 0.461
- L4 pod, different datacenter (Ampere -> Ada): FAIL, closing hash mismatch
  on both segments; opening hashes matched, isolating the divergence to
  replay arithmetic rather than transfer corruption

Findings: (1) the verification equivalence class is (GPU model, software
stack), not the physical machine -- auditors need the prover's GPU model,
not the prover's box; (2) the falsifiability contract holds for hardware:
the audit fails reliably, and legibly, when the architecture differs.
Auditors fetched the 7.5 GB chain over plain untrusted HTTP; ed25519
signatures over the manifest and every boundary established integrity.

Three-pod cost ~$0.20. Evidence: proofs/chain_cross/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pillar-4 first result: cheap O(params) statistics on consecutive boundary
checkpoints flag forged transitions without replaying them, converting
detection quality directly into audit efficiency (flagged segments get
replayed first, pushing effective soundness above k/N).

Detectors (enabled by boundaries being FULL training states -- the Adam
moments travel with the weights): adam reachability (max elementwise
|dW|/(S*lr)), segment delta-norm profile z-score, and moment consistency
cos(dW, -exp_avg). Thresholds are the genuine chain's widened envelope,
zero false positives by construction.

Forgery models: alt-seed splice (the classic PoL spoof), gradual
interpolation toward a target (alpha 0.10/0.03), gaussian weight edits
(sigma 1e-2/1e-4). CPU smoke (mlp): splice, both interpolations, and the
1e-2 edit are detected AND localized; the 1e-4 edit evades the envelope
(honest miss -- negligible attacker utility, still caught by sampled
replay). 4 new tests; pod runner script for the at-scale run.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The at-scale run exposed self-masking: a spliced transition inflates the
chain's own std enough to shrink its z-score. Median/MAD is insensitive to
the outlier being scored.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…h is a detectability dial

Segment-length sweep on an L40S (gpt120m/enwik8, genuine + alt-seed donor
chains per condition, MAD-robust detectors, zero false positives everywhere):

- alt-seed splice and alpha=0.10 interpolation: detected AND localized at
  S=200, S=100, S=10
- alpha=0.03 interpolation (the stealthy splice): MISSED at S=200,
  detected+localized at S=100 and S=10 -- segment length is a replay-free
  detectability dial, joining storage and per-audit cost as the third axis
  of the checkpoint-spacing trade
- sigma=1e-2 gaussian edits evade the detectors at this scale (honest
  limit; caught by sampled replay, and by the manifest hash for the final
  model); genuine moment-cosine range rises from [0.013,0.050] at S=200 to
  [0.052,0.128] at S=10, confirming the moment-correlation-decay mechanism

Evidence: proofs/forgery_l40s/ (three sweep reports + pre-MAD v1 report +
GPU record). README pillar-4 paragraph upgraded from open question to first
results; RUNBOOK section 9 added. L40S wall clock: ~14s per 200-step
segment (2.5x the A40), sweep total ~22 min, ~$0.40.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The arms-race escalation: forgers who know the detectors and forge the
Adam moments too.

Detector upgrades:
- moment_cos envelope is now TWO-SIDED: a forger setting moments perfectly
  anti-aligned with the fake delta (cos=1) previously PASSED the one-sided
  check; too consistent is as damning as too little
- v-continuity HARD invariant: Adam's v-update adds a non-negative term
  each step, so v_{k+1} >= beta2^S * v_k elementwise for any genuine
  trajectory (beta2=0.999 -> 82% of v persists across even a 200-step
  segment). A necessary condition, not a heuristic; fabricated second
  moments must thread ~1e8 coordinate-wise inequalities
- m-autocorrelation envelope: m_{k+1} carries beta1^S * m_k, giving
  cross-boundary moment continuity at short segments
- norm-profile normalization stays median/MAD (outlier-robust)

Smart forgers implemented: sf-aligned (perfect anti-alignment),
sf-calibrated (moment_cos engineered into the genuine envelope, genuine v
copied -- the strongest cheap forger), sf-freshv (fabricated v; exists to
demonstrate the hard invariant). CPU smoke: all three detected+localized
at zero false positives, sf-freshv via the v-invariant as designed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ly with small deltas

Second L40S sweep (gpt120m/enwik8, S in {200,100,10}, 8 forgeries per
condition, zero false positives everywhere):

- sf-aligned (perfectly anti-aligned moments): detected+localized at every
  S via the two-sided moment envelope -- the one-sided check it would have
  defeated no longer exists
- sf-calibrated (moment cosine engineered into the genuine envelope,
  genuine v copied): its moment forging WORKS at S=200/100 (no moment
  flag) but the weight-side reach/norm detectors catch the splice
  regardless; at S=10 the moment envelope flags it too
- sf-freshv (fabricated second moments): trips the elementwise hard
  invariant v_{k+1} >= beta2^S * v_k at every segment length

Clean separation result: forging moments only benefits an attacker whose
weight delta is also small, and small-delta forgeries at long segments
are precisely the residual hole that shorter segments and sampled replay
close. README arms-race paragraph and RUNBOOK section 9 updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ompiled-chain audit

- TinyGPT gains attn_impl ("manual" | "sdpa"); backend (math/flash/
  efficient) selected via device.sdpa_context
- chain.py honors cfg["compile"] and cfg["sdpa_backend"]: the execution
  variant is part of the COMMITTED config, so the auditor replays with the
  producer's exact variant; state/hashes always come from the raw module
- envelope.py: per-variant twin runs (run-to-run) x deterministic on/off,
  bitwise agreement vs the eager/manual reference, strict-mode kernel
  refusals recorded as data, plus the headline exhibit: a chain trained
  under compile+flash then segment-audited

CPU smoke preview: SDPA math backend is run-to-run reproducible but
already bit-differs from manual attention on CPU (fused reduction order).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…variant is its own bit-universe

L40S envelope run (gpt10m, 300 steps, twin runs per cell, evidence in
proofs/envelope_l40s/):

- eager manual attention: reproducible det on AND off (reference)
- SDPA math / efficient backends: run-to-run reproducible but bitwise
  DIFFERENT from manual attention -- even the nominally-identical math
  backend. The execution variant is part of the commitment; the chain
  format already carries attn_impl/sdpa_backend/compile in the signed
  manifest
- SDPA flash backend: NO fp32 kernel ("No available kernel") -- flash is
  structurally outside the strict-fp32 envelope; bf16/fp16 flash training
  is open work
- torch.compile (manual): bit-exact run-to-run under strict determinism,
  NOT reproducible with determinism off (the flags are load-bearing), bits
  differ from eager
- headline: a chain trained with compile:true in its committed config
  passes the full segment audit BIT-EXACTLY (compiled_chain_audit.json) --
  verification survives compilation when the auditor replays the
  committed variant

DDP probe deferred: no 2-GPU secure stock at run time (3 types tried);
src/ddp_repro.py is ready via torchrun.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Consolidates the day's measured evidence into a workshop-paper draft:
protocol + k/N soundness bound, 116M-param positive control (cost ratio
0.173 vs 0.15), hardware equivalence class (GPU model, not machine),
replay-free detection with the segment-length dial and the smart-forger
arms race (incl. the v-continuity proposition with proof), and the
execution-variant envelope (compile verifiable; flash outside fp32).
Limitations section names all seven open gaps, DDP measurement first
among them. Every number traces to an artifact in proofs/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…eterministic unlearning

Literature check for post-2023 PoL follow-ups: closest neighbor is Choi/
Shavit/Duvenaud 2023 (Proof-of-Training-Data, tolerance-based spot checks)
-- differentiated on zero-tolerance replay, full-optimizer-state
boundaries, and committed execution variants. Deterministic bit-identical
replay also appears in unlearning work (2508.12220), supporting
buildability. No paper found claiming the determinism-repairs-PoL thesis.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ss-rank

torchrun --nproc_per_node=2 ddp_repro.py on a community 2x RTX 3090 pod
(NCCL, deterministic per-rank kernels, gpt10m, 20 steps): run-to-run
bitwise identical AND both ranks hold identical models (matching hashes).
Stated as a per-topology qualification, not a general NCCL guarantee.
README scope section and paper limitations updated; evidence in
proofs/ddp_2x3090/. Two prior community hosts failed CUDA init despite
healthy nvidia-smi -- the runner now health-checks CUDA before setup.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
dist/, *.egg-info/, .ovllm-cache/, and openverifiable-smoke/ are all
generated locally and were showing up as untracked noise on every status.
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@ryoari, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 58 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e75409e0-a5af-4a9e-9cc1-200afb31c053

📥 Commits

Reviewing files that changed from the base of the PR and between 02c76b4 and 437b023.

⛔ Files ignored due to path filters (3)
  • proofs/chain_a40/train.log is excluded by !**/*.log
  • proofs/chain_cross/trainer_train.log is excluded by !**/*.log
  • proofs/ddp_2x3090/ddp.log is excluded by !**/*.log
📒 Files selected for processing (44)
  • .github/workflows/ci.yml
  • .gitignore
  • RUNBOOK.md
  • demo.py
  • paper/DRAFT.md
  • proofs/chain_a40/audit_report.json
  • proofs/chain_a40/chain_manifest.json
  • proofs/chain_a40/chain_size.txt
  • proofs/chain_a40/nvidia.txt
  • proofs/chain_cross/a4000b_audit_report.json
  • proofs/chain_cross/l4_audit_report.json
  • proofs/chain_cross/l4_gpu.txt
  • proofs/chain_cross/trainer_audit_report.json
  • proofs/chain_cross/trainer_chain_manifest.json
  • proofs/chain_cross/trainer_nvidia.txt
  • proofs/ddp_2x3090/nvidia.txt
  • proofs/envelope_l40s/compiled_chain_audit.json
  • proofs/envelope_l40s/envelope_report.json
  • proofs/envelope_l40s/nvidia.txt
  • proofs/forgery_l40s/forgery_report_S100_N10.json
  • proofs/forgery_l40s/forgery_report_S10_N10.json
  • proofs/forgery_l40s/forgery_report_S200_N5.json
  • proofs/forgery_l40s/l40s_report_v1_S200.json
  • proofs/forgery_l40s/nvidia.txt
  • proofs/smartforger_l40s/forgery_report_S100_N10.json
  • proofs/smartforger_l40s/forgery_report_S10_N10.json
  • proofs/smartforger_l40s/forgery_report_S200_N5.json
  • proofs/smartforger_l40s/nvidia.txt
  • scripts/pod_chain_run.sh
  • scripts/pod_forgery_run.sh
  • src/artifacts.py
  • src/chain.py
  • src/config.py
  • src/device.py
  • src/envelope.py
  • src/eval.py
  • src/experiment.py
  • src/forgery.py
  • src/global_manifest.py
  • src/model.py
  • src/reproducibility.py
  • src/signing.py
  • src/telemetry.py
  • tests/test_experiment.py
✨ Finishing Touches 💡 1
⚔️ Resolve merge conflicts 💡
  • Resolve merge conflict in branch tree
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@Archit381
Archit381 merged commit 2355603 into main Aug 10, 2026
4 checks passed
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.

[GOOD FIRST ISSUE]: Add experiments/ folder to validate determinism and verification assumptions

2 participants