Skip to content

Smokescreen-fork blinding: seeded master-SACC blind, hash-commitment custody, CAMB↔CCL cross-check (PR 6)#253

Draft
cailmdaley wants to merge 4 commits into
feat/sacc-2-sacc-iofrom
feat/sacc-6-blinding
Draft

Smokescreen-fork blinding: seeded master-SACC blind, hash-commitment custody, CAMB↔CCL cross-check (PR 6)#253
cailmdaley wants to merge 4 commits into
feat/sacc-2-sacc-iofrom
feat/sacc-6-blinding

Conversation

@cailmdaley

@cailmdaley cailmdaley commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Closes #252.

Blinds the tomographic master SACC data vector through the UNIONS-WL/Smokescreen fork: the measured statistics are shifted by t(hidden) − t(fiducial) (Muir et al. 2019), with the hidden cosmology drawn inside a fixed amplitude envelope by the fork's own CCL-native, per-key-independent draw. No one can read S8 off the data until the collaboration unblinds; both the blind and the unblind are verifiable without a trusted keyholder.

Stacks on #245 (sacc_io); depends on the fork protocol (ConcealDataVector(fiducial_params, shifts_dict, sacc_data, *, seed, theory_fn), pinned fork SHA 588a6b9). No firecrown anywhere in this PR's diff — the fork is the concealment engine, and every theory vector is a direct CCL computation.

What's in the box

sp_validation/cosmology.pyTheoryConfig (frozen dataclass; fail-fast overrides), the single home of the blinding/inference fiducial (CosmoSIS v1.4.6.3 IA-fiducial values: S8=0.80, Ωm=0.30, h=0.70, n_s=0.96, Σm_ν=0.06 eV, HMCode2020+feedback with logT_AGN=7.5). Carries two halofit tokens (ccl_halofit_version, camb_halofit_version) naming the one recipe per stack; Neff=3.046/T_CMB=2.7255 are emitted explicitly to both stacks. Two independent ξ± paths live here: the CCL-native route (Boltzmann-CAMB P(k) → CCL Limber + FFTLog — the blinding recipe) and an independent pycamb P(k) → Pk2D → CCL projection with a closed-form σ8-matched A_s rescale. numpy-only at module scope.

sp_validation/blinding.py

  • Envelope calibration: the intended (|ΔS8| ≤ 0.075, |ΔΩm| ≤ 0.1) box maps to {sigma8, Omega_c} half-widths at the fiducial (σ8 = S8/√(Ωm/0.3); Ω_c one-to-one). Half-widths are config, not code.
  • Three theory_fn backends matching the master layout: coarse ξ±, fine ξ± (grid tags), and pseudo-Cℓ (W @ Cℓ_EE on the stored BandpowerWindows; ΔBB = ΔEB ≡ 0 — the shift is pure E-mode). Two-tracer cross-pairs; rows aligned to each extracted block's own order.
  • Extract → conceal → merge per block with recorded master indices; the same seed drives all three passes, so the blocks are mutually consistent by construction.
  • COSEBIs and pure-E/B are re-derived, never shifted, through the pipeline's own estimators (cosmo_numba kernels) on the blinded fine ξ±. Covariance and ρ/τ are byte-identical to the input.
  • Custody (hash commitment): blind draws an OS-entropy seed, blinds immediately, publishes sha256(seed) + a canonical config digest (sorted-key JSON, repr-exact floats) as a repo-committable commitment.json, and escrows seed + true vector in a Fernet bundle (smokescreen.encryption), deleting plaintexts. Blinded metadata: concealed=True, blind label, blind_commitment, blind_config_digest; seed_smokescreen stripped. Unblind verifies both hashes before subtracting anything, then restores the true vector bit-for-bit from the escrow (the recomputed subtraction cross-checks it).

scripts/blind_data_vector.pyblind / unblind / verify CLI; refuses to overwrite any existing blind output before touching theory code.

Tests (all observed in the container/venv run on candide)

test_blinding.py covers acceptance criteria AC1–AC9; test_camb_ccl_crosscheck.py (written fresh against cosmology.py) covers AC10–14. Heavy precision tests are @pytest.mark.slow; the COSEBIs/pure-E/B tests importorskip("cosmo_numba"). Full set: 30 passed (19 fast + 11 slow).

Observed numbers from the runs:

Quantity Observed Bound
AC2 on-file shift vs theory difference (all 3 blocks, 2-bin) 6.4e-14 rel ≤ 1e-10
AC3 realized shift vs independently written CCL reference 1.0e-20 abs (coarse ξ±) < 1e-8
AC4 ΔBₙ (COSEBIs) amplitude-independence 1.1e-10 of |ΔBₙ| ≤ 1e-9
AC4 leakage magnitude ΔBₙ/Bₙ = 4.9e-6 (B=2e-5); Δξ⁺_B = 1.5e-9 = 0.07% of a 2e-6 B-mode reported, not asserted
AC10 nominal-A_s σ8 offset 3.4% > 2% (the offset is real)
AC10 σ8-matched residual 1.1e-16 < 1e-4
AC11 ξ± floor at fiducial ξ+ 0.24%, ξ− 0.10% < 0.5% / 1.0%
AC12 ξ± floor off-fiducial (S8+0.075, Ωm−0.05) ξ+ 0.28%, ξ− 0.12% < 0.5% / 1.0%

Two empirical notes against the PRD text: (1) the boundary-degenerate pure-E/B reporting point (AC9) is the last point (tmax edge), not the first — the NaN-parity assertion targets it there; (2) the pure-ξ_B leakage identity across injected B amplitudes holds to the adaptive-quadrature floor (1.3e-2 of the tiny leakage, i.e. 2e-11 absolute), not to 1e-10 — cosmo_numba's adaptive Schneider integrals are not bit-linear; the COSEBIs ΔBₙ identity carries the exact criterion.

CI note

This branch stacks on feat/sacc-2-sacc-iofeat/sacc-1-deps, whose dependency set still installs stock Smokescreen 1.5.6 + firecrown; the fork pin (and firecrown removal from pyproject/Dockerfile) lands in the reworked PR #243. Until that rebase, container CI will not have the fork API these tests exercise — the results above are from the shared fork venv + sp_validation container on candide.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KpaRHk3QwN13myduQ3hJyf

cailmdaley and others added 4 commits July 11, 2026 00:41
The single home for the blinding/inference fiducial (TheoryConfig, frozen,
fail-fast overrides; two stack-specific halofit tokens denoting one
HMCode2020+feedback recipe; Neff/T_CMB emitted explicitly as module
constants) and two ξ± routes: the CCL-native path (Boltzmann-CAMB P(k) +
CCL Limber/FFTLog — the blinding backends' recipe) and an independent
pycamb P(k) → Pk2D → CCL projection with the closed-form σ8-matched A_s
rescale. numpy-only at module level; CCL/CAMB are function-local imports.
Cosmology objects are cached per parameter point so the three blinding
backends share two CAMB runs per blind.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KpaRHk3QwN13myduQ3hJyf
Rework of the blinding box onto the UNIONS-WL/Smokescreen fork protocol:
the fork's ConcealDataVector(fiducial_params, shifts_dict, sacc_data, *,
seed, theory_fn) is the concealment engine for every block, with its
internal per-key-independent CCL-native draw — no local draw, no
firecrown, no likelihood object.

- Envelope calibration: the (S8, Ωm) box maps to {sigma8, Omega_c}
  half-widths at the fiducial (σ8 = S8/√(Ωm/0.3); Ω_c one-to-one).
- Three theory_fn backends matching the master layout: coarse ξ±, fine ξ±
  (grid tags), pseudo-Cℓ_EE (W @ Cℓ_EE on the stored BandpowerWindows;
  ΔBB = ΔEB ≡ 0). Two-tracer everywhere; rows aligned to each extracted
  block's own order.
- Extract → conceal → merge per block, with recorded master indices;
  COSEBIs/pure-E/B re-derived through the pipeline estimators
  (cosmo_numba kernels) on the blinded fine ξ±; covariance and ρ/τ
  untouched.
- Custody: sha256(seed) + canonical config digest as a repo-committable
  commitment; seed + true vector escrowed in a Fernet bundle
  (smokescreen.encryption); seed_smokescreen stripped; unblind verifies
  both hashes before subtracting and restores the truth bit-for-bit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KpaRHk3QwN13myduQ3hJyf
One-shot custody semantics: refuses to overwrite any existing blind
output before touching theory code; the seed is drawn from OS entropy and
never printed. verify is a seedless metadata↔commitment check.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KpaRHk3QwN13myduQ3hJyf
…10–14

test_blinding.py: fast coverage of the envelope calibration, canonical
digest, commitment, fork-draw determinism/purity, merge alignment and
guards (monkeypatched factor, no CCL); slow coverage of AC2 (on-file shift
== theory difference, hidden recovered via the fork's draw, all three
blocks, two-bin), AC3 (independently written direct-CCL reference), AC7
(seed reproducibility); slow+cosmo_numba coverage of AC1 (zero-shift
identity through the estimators), AC4 (ΔBₙ independent of injected B —
COSEBIs exact to ~1e-10; the pure-ξ_B leakage bounded at the adaptive-
quadrature floor), AC5 (covariance/ρ/τ/row order untouched), AC9
(boundary-degenerate pure-EB point NaN in both re-derivations), and
AC6+AC8 (end-to-end custody: no plaintext seed on disk, fail-closed on
tampered commitment or wrong config, bit-for-bit restoration).

test_camb_ccl_crosscheck.py: written fresh against sp_validation.cosmology
— AC10 σ8/A_s reconciliation (nominal offset 3.4%; closed-form rescale
lands to 1e-16), AC11/AC12 ξ± agreement at and off the fiducial (observed
floor ξ+ 0.24%/0.28%, ξ− 0.10%/0.12% against 0.5%/1.0% tolerances), AC13
halofit token pinned to the CosmoSIS inference ini, AC14 fast smoke.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KpaRHk3QwN13myduQ3hJyf
@cailmdaley cailmdaley changed the title Smokescreen blinding: seeded data-vector blind, hash-commitment custody, blinded-COSEBIs derivation (PR 6) Smokescreen-fork blinding: seeded master-SACC blind, hash-commitment custody, CAMB↔CCL cross-check (PR 6) Jul 10, 2026
@cailmdaley cailmdaley force-pushed the feat/sacc-6-blinding branch from 971767b to 11b8895 Compare July 10, 2026 22:52
@cailmdaley cailmdaley changed the base branch from feat/sacc-5-firecrown-likelihood to feat/sacc-2-sacc-io July 10, 2026 22:52
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