Opt-in gated composition reweight for the low-mass transverse-spin width deficit - #177
Draft
oshaughnessy-junior wants to merge 5 commits into
Draft
Opt-in gated composition reweight for the low-mass transverse-spin width deficit#177oshaughnessy-junior wants to merge 5 commits into
oshaughnessy-junior wants to merge 5 commits into
Conversation
…seudo-pipe flag NOT FOR MERGE YET: failed the pre-registered two-sided production gate (investigations/rift_transverse_highSNR_study/results_triage/MULTIEVENT_REWEIGHT_2026-08-19.md). Treatment side passed (low-mass deficit exemplars +0.04..+0.12 toward the bilby width, good-composition events exact no-ops), but on bad-composition events whose width is already correct (S240921cw/S240930aa/S240621dy) the thinning overshoots to 1.18-1.54x the reference. The composition statistic is a repair, not a sufficient trigger; a gated variant (e.g. on the marginal-mass ratio) needs its own pre-registered test before this ships. - bin/util_CompositionReweightNet.py: per-chi1_perp-bin near-peak-fraction equalising thinning (self-quantile definitions, fail-safe copy-through on degenerate input). - bin/util_CIPCompositionReweightWrapper.sh: drop-in --cip-exe wrapper (RandomizeOverlapOrder- style modularity); race-safe unique temp file per CIP worker, cleaned on exit; falls back loudly to the untouched all.net on any tool failure. Both --fname forms + all failure paths smoke-tested against a fake CIP. - util_RIFT_pseudo_pipe.py: opt-in --internal-cip-composition-reweight (conflict-guarded against --internal-use-amr, which also sets --cip-exe). Not applicable to the LISA fork (CIP-side change; LISA uses its own driver only for ILE). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… the mandatory validity floor The ungated thinning was rejected by its two-sided production test (it drove three healthy-width bad-composition controls to 1.18-1.54x the reference). This commit lands the gated form Richard approved: thin ONLY on a detected severe deficit, abstain loudly otherwise. - bin/util_CIPTailDeficitGate.py: R = delivered/implied transverse-tail mass from RIFT's own products (all.net + a CIP posterior trained on it). FIRE iff R < 0.32 AND the MANDATORY sample-resolution validity floor (implied >= 50/n_post) holds. The floor has no bypass -- without it the detector returns maximum deficit exactly where it can resolve nothing (proven on known-truth healthy-narrow toys, where only the floor prevented false fires). Threshold is calibrated IN THE DEPLOYMENT CHANNEL (fresh-CIP posterior): the population value 0.42 does not transfer (fresh-CIP reads mid-band healthy events lower by up to ~0.07; the regression fixture caught control S240930aa at 0.386 < 0.42 before anything shipped). Deployment-channel gap 0.270-0.386; shipped 0.32. - bin/util_CIPCompositionReweightWrapper.sh: now gated detect->repair, two CIP passes; pass 1 verbatim-CIP on the original data (temp outputs, exports >= 20000), final CIP on the original argv with --fname swapped only on a FIRE. Every no-op logged with R and the deciding condition; fail-safe everywhere; +1 CIP per invocation when enabled. - util_RIFT_pseudo_pipe.py: --internal-cip-composition-reweight (opt-in, default OFF) with the measured scope in the help: severe deficits only (~half the affected low-mass events), mild-vs-healthy not separable, safety bounds 3.8% / miss bound 22.1%. - test/test_tail_deficit_gate.py (+ measured fixtures, named in ci.yml; 23 tests): exemplars FIRE, the three ungated-broken controls NO-FIRE, T5 family ABSTAINS via the floor (reason asserted -- each has R < threshold), floor unbypassable by property scan and CLI, synthetic + wrapper e2e with fallback. - Live e2e on production data (real CIP): S240629by FIRE (R=0.171, final CIP on thinned set), S240930aa NO-FIRE (R=0.357, verbatim), both rc=0. - PR_DRAFT_comp_reweight_optin.md: draft PR text for review before any push (drop at merge). Evidence record: rift_transverse_highSNR_study results_triage/ MULTIEVENT_REWEIGHT, GATED_REWEIGHT, R_POPULATION_CALIBRATION, R_TOYBENCH_VALIDATION, BRANCH_LANDING (all 2026-08-19). Not applicable to the LISA fork (CIP-side; that fork diverges only in the ILE driver). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…-to-run dispersion Measured (16 independent fresh-CIP detect reps on the closest healthy control, S240930aa): deployment-channel mean R = 0.371, single-rep sigma = 0.024 -- and 1 of 16 single reps read BELOW the 0.32 threshold (0.325), i.e. a single-pass gate has an observed ~6%/run false-fire rate on that event class, each fire costing up to the ungated 1.54x width corruption. The noise is shot-dominated (~300 tail counts in 20k exported samples predicts sd 0.022; observed 0.022-0.027). The earlier 0.386-vs-0.357 discrepancy decomposes into a REAL measurement-channel offset (production consolidated 0.457 vs fresh-CIP mean 0.371) plus this single-rep noise. - util_CIPTailDeficitGate.py: accepts multiple detect-rep posteriors and decides ONCE on the mean R (per-rep values + sd logged and stored in the gate json). decide() unchanged; the mandatory validity floor uses the MIN per-rep sample count (conservative, identical at N=1). - util_CIPCompositionReweightWrapper.sh: runs CIP_REWEIGHT_GATE_REPS detect passes (default 5, chosen from the measured sigma: N=5 gives a ~4.6 sigma no-fire margin on the closest control vs 2.6 sigma single-pass), tolerates partial rep failures (decides on the survivors, loudly), falls back to the original data only if ALL reps fail. - test_tail_deficit_gate.py: multi-rep mean-decides test (a confined rep that would fire alone is outvoted by the mean); wrapper e2e pinned at CIP_REWEIGHT_GATE_REPS=2. 24 tests. - Live N=5 verification on production data: the sub-threshold single rep OCCURRED in the run (rep 2 = 0.325) and the mean (0.358) correctly decided NO-FIRE, final CIP verbatim. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Worst case of a false fire corrected from the real-data 1.54x to the known-truth bound: the independent toybench VETOED the ungated reweight arm at 2.56x / 3.32x / 2.23x truth on genuinely-narrow transverse posteriors (T5/T5b/T5c). Updated everywhere it appears, including the N=5 margin justification. - Reconciliation stated: the toybench predicted the high-mass control group would widen under unconditional reweighting; the real-data test measured exactly that pattern (good-composition controls exact no-ops; bad-composition healthy events 1.18-1.54x). The driver is composition, not mass; T5 is the known-truth instance of the S240930aa class. - Claimed, precisely: the toybench's own remedy -- gate on tail SUPPORT, not row counts -- is this design. R is a tail-support statistic; the mandatory floor covers the unresolvable case; the gate was measured to abstain on the T5 family. Nothing beyond what was measured is claimed. - New scope limit: toybench gate (a) failed (a1 = 1.381 vs <= 0.65; the loop EXPANDS 38% from a fresh bootstrap; third harness to fail this, first on the real cepp_BasicIteration DAG), so the bench cannot reproduce the pathological regime: the known-truth evidence certifies the SAFETY side only, and the repair side rests entirely on the real-data paired-CIP result. - Fixed stale test count (23 -> 24). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ration Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
oshaughnessy-junior
deployed
to
private-review-dispatch-rift-upstream
August 19, 2026 18:04 — with
GitHub Actions
Active
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR is not proposed for merge yet. It is staged as a DRAFT while the paper-scale
demonstration (in preparation) independently establishes the problem and the fix; the merge
decision waits on that demonstration. Please do not review or mark ready until then.
What this is
An opt-in (default OFF) severe-deficit repair for CIP. Across the O4 low-mass catalogue,
RIFT's chi1_perp/a1 posteriors are systematically narrow (median width ratio 0.800 vs bilby
over 25 events; high-mass events sit at 1.007). Root cause, established by intervention:
training-set COMPOSITION — the near-peak fraction of
all.netrows degrades with chi1_perp,and the RF fit (a local average) regresses the transverse tail toward its junk-diluted
neighbours. Density-equalising THINNING of the far-from-peak rows (never truncation, never
invented points; lnL span preserved exactly) repairs it: on 5 deficit exemplars, paired CIP
on identical inputs moved chi1_perp toward the reference by +0.042..+0.115 with mc/q
undamaged.
An UNGATED version of that thinning was tested two-sided and REJECTED, twice and
independently: on real data it overshot three bad-composition events whose widths are
already correct to 1.18–1.54x the reference, and on the known-truth toybench it recovered
2.56x / 3.32x / 2.23x truth on genuinely-narrow transverse posteriors (T5/T5b/T5c) —
a specificity veto at every tail depth, so the true worst case of unconditional thinning is
up to 3.32x, not the 1.54x real data happened to show. The two results reconcile
exactly: the toybench predicted the high-mass control group should widen past the reference
under unconditional reweighting, and the real-data test measured precisely that pattern —
good-composition high-mass controls were exact no-ops (+0.001, +0.013) while
bad-composition healthy events blew up. The driver is COMPOSITION, not mass: unconditional
thinning harms bad-composition events regardless of whether they are deficient, because on
a genuinely narrow posterior it deletes the far rows that teach the fit the tail is
unsupported. The T5 family is the known-truth instance of exactly the S240930aa class.
This PR ships the gated version: thin ONLY on a detected severe deficit.
The gate (
util_CIPTailDeficitGate.py)R = delivered/implied transverse-tail posterior mass, computed from RIFT's own products
only (all.net + a CIP posterior trained on it; no external reference):
implied = per-chi1_perp-bin analytic prior volume x mean exp(lnL-peak) over the bin's real
ILE rows; boundary = the training set's own cp q80. FIRE iff R < 0.32 AND the MANDATORY
sample-resolution validity floor (implied >= 50/n_post) is satisfied; otherwise a loudly
logged no-op.
--floor-counts < 1isrefused;
decide()applies it before the threshold; property-tested). Without it thedetector returns R = 0 — maximum apparent deficit — exactly where it can resolve nothing:
on known-truth healthy-narrow benchmarks (toybench T5/T5b/T5c) every chain read R = 0 and
only the floor prevented false fires.
deployable version must gate on tail support, not row counts — R is exactly a
tail-support statistic (implied tail mass from measured lnL x prior volume), the validity
floor covers the unresolvable-support case, and on the T5 family the shipped gate was
measured to ABSTAIN via that floor. The toys independently veto the ungated tool and
independently endorse the gated one's design principle; no more than that is claimed.
wrapper actually uses. The population calibration (102 production events, perfect
12-vs-77 separation, gap 0.379–0.457) was measured on production consolidated posteriors;
the fresh-CIP channel reads mid-band healthy events lower by up to ~0.07, so the
population threshold 0.42 does NOT transfer — the regression fixture caught this
(control S240930aa: deployment-channel R 0.386 < 0.42). Deployment-channel gap: severe
deficits <= 0.270, healthy controls >= 0.386; 0.32 is the geometric midpoint.
The wrapper (
util_CIPCompositionReweightWrapper.sh, drop-in--cip-exe)Detect -> repair: N detect passes (default N=5,
CIP_REWEIGHT_GATE_REPS) run the REAL CIPon the ORIGINAL data (exports bumped to >= 20000, temp outputs; real output paths
untouched); the gate decides ONCE on the MEAN R over the reps; the final CIP runs the
original argv verbatim, with
--fnameswapped to the thinned set only on a FIRE. Everyno-op is logged with the R value, the per-rep spread, and the deciding condition.
Fail-safe throughout: any tool failure -> final CIP on the original argv, loudly. Costs N
extra CIP passes per invocation when enabled (CIP is the cheap CPU stage).
RandomizeOverlapOrder-style modularity: nothing in CIP or the merge step changes; flag-off
is byte-identical to today.
Opt in via
util_RIFT_pseudo_pipe.py --internal-cip-composition-reweight(conflict-guardedvs
--internal-use-amr).SCOPE — read before enabling
deployment-channel R <= 0.27). Roughly half the affected low-mass events; the mild rest
are loudly left alone: mild deficit and healthy width are NOT separable above the
threshold (out-of-sample, truth-deficient toybench T3 chains at R 0.532–0.634 abut
truth-healthy T2 chains at 0.633–0.673).
events (95% bound 3.8%) and on known-truth healthy-narrow toys. The fire side is
in-sample-validated (12/12 severe-deficit events, 95% miss-rate bound 22.1%) plus the
causal 13-event paired-CIP repair.
reproduce the pathological regime — its gate (a) FAILED (a1 = 1.381 vs required <= 0.65:
from a fresh bootstrap the loop EXPANDS 38% at iteration 1 rather than collapsing; third
independent harness to fail this, and the first running the real cepp_BasicIteration
DAG) — so it cannot certify the fix where the deficit actually develops. The known-truth
evidence certifies the SAFETY side (abstain/no-fire behaviour) only; the REPAIR side
rests entirely on the real-data paired-CIP result.
R_dispersion.json + the live N=5 run in the study record): deployment-channel mean
R = 0.371, single-rep sigma = 0.024, and 1 of the 16 single reps actually read below
the threshold (0.325) -- a single-pass gate has an observed ~6%/run false-fire rate on
this event class, each fire costing up to 3.32x truth (known-truth toybench bound;
1.54x was the real-data instance). The shipped
default N=5 mean-of-reps retires this: effective margin ~4.6 sigma (sem 0.011), and in
the live N=5 verification the sub-threshold rep occurred and the mean correctly decided
NO-FIRE. Fire side: measured exemplar sigma 0.014 (S240629by, 11 sigma single-rep);
the nearest exemplar to the threshold (S241109bn, R = 0.27) keeps ~5 sigma at N=5.
The two S240930aa readings quoted earlier (0.386 pooled, 0.357 live) decompose into a
REAL channel offset (production 0.457 vs deployment 0.371, -0.086 >> sem) plus this
single-rep noise -- both handled: channel-calibrated threshold, averaged decision.
Verification
test/test_tail_deficit_gate.py(named in ci.yml; 24 tests, all passing): measured-valueregressions pinning the shipped gate's decisions on the 5 exemplars (FIRE), the 3
controls the ungated fix broke (NO-FIRE), and 6 known-truth healthy-narrow toybench
chains (ABSTAIN via the floor — each has R < threshold, so the threshold alone would
false-fire; the reason is asserted, not just the outcome); property scans proving no
(implied, R, n_post) below the floor can ever FIRE; CLI bypass refusal; synthetic
end-to-end FIRE/NO-FIRE/ABSTAIN; wrapper e2e (FIRE swaps fname for the final pass only;
broken gate falls back loudly to the original).
(R=0.171), final CIP trained on the thinned set; S240930aa -> NO-FIRE (R=0.357), final
CIP verbatim; both rc=0 with the decision and record path in the log.
Evidence record
rift_transverse_highSNR_study
results_triage/: MULTIEVENT_REWEIGHT_2026-08-19.md (ungatedtwo-sided test, rejected), GATED_REWEIGHT_2026-08-19.md (13-event gate-0),
R_POPULATION_CALIBRATION_2026-08-19.md (102-event calibration; comp-contamination hypothesis
refuted), R_TOYBENCH_VALIDATION_2026-08-19.md (known-truth out-of-sample; floor load-bearing),
TOYBENCH_RESULT_2026-08-19.md (independent campaign: ungated arm VETOED at 2.56-3.32x
truth; gate (a) failure bounding what the bench can certify), BRANCH_LANDING_2026-08-19.md
(channel systematic, live e2e, measured R dispersion).
Not applicable to the LISA fork (CIP-side change; the LISA fork diverges only in the ILE
driver).