Add replicate-weight variance and PSU-level bootstrap to dCDH#311
Add replicate-weight variance and PSU-level bootstrap to dCDH#311
Conversation
Extends the group-level Taylor Series Linearization survey support landed in PR #307 with two opt-in variance mechanisms: 1. Replicate-weight variance (BRR / Fay / JK1 / JKn / SDR) routed through the unified compute_replicate_if_variance helper at every IF site (overall DID_M, joiners DID_+, leavers DID_-, multi-horizon DID_l, placebo DID^pl_l, heterogeneity beta^het_l, twowayfeweights helper). Uses inline-branch pattern mirroring EfficientDiD (efficient_did.py:1119-1142) and TripleDifference (triple_diff.py:1206-1238). Effective df_survey reduces to min(n_valid) - 1 across IF sites when replicates fail, matching the precedent in efficient_did.py:1133-1135 and triple_diff.py:676-686. 2. PSU-level Hall-Mammen wild bootstrap via group_to_psu_map threaded through _compute_dcdh_bootstrap. Under auto-inject psu=group the identity-map fast path preserves pre-change behavior bit-for-bit. Under an explicitly coarser PSU (e.g., psu=state with county-level groups), all groups in the same PSU receive the same bootstrap multiplier so within-PSU correlation is preserved. Locked contracts: - Replicate weights and n_bootstrap > 0 are mutually exclusive (replicate variance is closed-form; bootstrap would double-count). Raises NotImplementedError, matching efficient_did.py:989 etc. - Strata participate only through analytical TSL variance, not the bootstrap (multiplier weights stay unit-by-unit). - Warning fires only when n_psu_eff < n_groups_eff (strictly coarser PSU). Under auto-inject psu=group the warning is correctly suppressed. Adds 36 regression tests in tests/test_survey_dcdh_replicate_psu.py covering Class A sites (via _survey_se_from_group_if), Class B sites (heterogeneity + twowayfeweights), PSU bootstrap semantics, and cross-cutting invariants (replicate+bootstrap rejection, HonestDiD under replicate). REGISTRY.md lines 651-653 updated to document both mechanisms. Full suite: 525 passing (was 489 before this change).
Addresses local AI review findings:
1. P1: `_slice_psu_map` now enforces strict length equality between
`target_size` and the full PSU map. Under the current bootstrap
architecture all targets (overall DID_M, joiners DID_+,
leavers DID_-, multi-horizon DID_l, placebo DID^pl_l) use the
same variance-eligible group ordering from `_eligible_group_ids`,
so the old prefix-slicing was a silent no-op. Making the check
strict converts a fragile unstated invariant into a loud
`ValueError` if a future refactor introduces a target whose group
subset differs from the overall ordering (e.g., an aggregated
target built from a non-prefix mask) — preventing a silent
miscluster bug.
2. P2: `fit()` `survey_design` docstring updated to describe:
- Replicate-weight variance support (BRR/Fay/JK1/JKn/SDR).
- PSU-level Hall-Mammen wild bootstrap contract.
- Replicate + `n_bootstrap > 0` rejection.
3. P2: `twowayfeweights()` docstring updated to document replicate
acceptance.
4. P2: Added 3 regression tests in
`tests/test_survey_dcdh_replicate_psu.py`:
- `test_psu_map_size_mismatch_raises`: exercises the new strict
equality check.
- `test_generate_psu_or_group_weights_broadcast`: direct unit test
of PSU-level broadcast — groups in the same PSU receive the same
multiplier within a bootstrap replicate.
- `test_generate_psu_or_group_weights_identity`: verifies the
identity-map fast path is bit-identical to the non-PSU path.
All 321 dCDH-related tests still pass.
Addresses the AI review R2 finding that the prior shared-map +
length-assertion approach still relied on an unstated invariant
(all bootstrap targets use the variance-eligible group ordering).
Changes:
- `_compute_dcdh_bootstrap` now accepts `group_id_to_psu_code: Dict[Any, int]`
and `eligible_group_ids: np.ndarray` instead of a pre-built flat
`group_to_psu_map` array. Every target call constructs its PSU
map via `_map_for_target(target_size, group_id_to_psu_code,
eligible_group_ids)` — a dict lookup per group ID, not a positional
reuse. The length-assertion is retained for the size-mismatch
case and now sits alongside a KeyError-based check for missing
group IDs.
- `_slice_psu_map` removed; `_map_for_target` replaces it. The
explicit per-target construction removes the hidden semantic
assumption that was previously enforced only by cardinality.
- `fit()` builds the dict from `_eligible_group_ids` + the dense PSU
codes. The per-target maps are all identical today (because every
current target uses `_eligible_group_ids` ordering), but that is
now a consequence of the caller's choice rather than a brittle
assumption buried in the mixin.
- Test `test_psu_map_size_mismatch_raises` replaced by
`test_map_for_target_id_lookup`, which exercises the ID-lookup
semantics including:
- Correct map construction for a given eligible-group ordering.
- Non-prefix reordering produces a different map (proving the
ordering-from-IDs contract).
- Length mismatch → ValueError.
- Missing-group → ValueError.
Full regression: 401 passing (previously 321).
AI review R3 flagged the remaining positional truncation in the
multi-horizon shared-draw path:
w_h = shared_weights[:, : u_h.size]
Under the current contract every horizon's IF vector uses the full
variance-eligible group ordering, so `u_h.size == n_groups_mh` always
holds and the slice is a no-op. But the truncation itself is a hidden
positional assumption — if a future refactor introduced horizon-
specific masking, the shared-weight alignment would break silently.
Replace the truncation with:
1. An explicit assertion `u_h.size == n_groups_mh` that raises with a
message pointing future refactors at the right fix (threading
target-specific group IDs through `multi_horizon_inputs`).
2. Direct reuse of the full `shared_weights` matrix — removes the
slice semantic entirely.
Add `TestPSUBootstrap.test_multi_horizon_shared_draw_under_coarser_psu`
covering an end-to-end L_max=2 + coarser PSU case that exercises the
shared-draw path + assertion.
Full regression: 312 passing.
|
Overall Assessment Highest unmitigated severity: P1 on replicate-survey Executive Summary
Methodology
Code Quality No additional findings beyond the P1 df propagation bug above. Performance No findings in the changed code. Maintainability No separate maintainability finding. Fixing the authoritative Tech Debt No existing TODO entry mitigates the P1 above. The dCDH TODO items at TODO.md#L57 cover placebo SE and parity-test scope, not replicate-df propagation. Security No findings. Documentation/Tests
Path to Approval
|
…ance Addresses R1 P1 from PR #311 AI review. The R1 reviewer flagged that `_effective_df_survey()` was overwriting the design-level `resolved_survey.df_survey` with `min(n_valid) - 1` whenever any replicate-aware IF site ran. For replicate designs with rank deficiency, `ResolvedSurveyDesign.df_survey` returns `QR-rank - 1` (per R's `survey::degf()` convention at `diff_diff/survey.py:590`), which can be strictly smaller than `R - 1`. The old behavior produced anti-conservative t-critical values on the top-level dCDH surface. Additionally, the final effective df was never persisted into `survey_metadata.df_survey`, so HonestDiD (which reads from `results.survey_metadata.df_survey` at `honest_did.py:973`) could use a different df than the main dCDH surface. Changes: - `_effective_df_survey()` now returns `min(resolved_survey.df_survey, min(n_valid) - 1)` when both are defined; returns None if base df is undefined (rank ≤ 1) or reduced df is degenerate (< 1). - In `fit()`, immediately before constructing `ChaisemartinDHaultfoeuilleResults`, mutate `survey_metadata.df_survey` to the final effective df (post-all- IF-sites, including heterogeneity). `SurveyMetadata` is a mutable `@dataclass` so direct assignment is safe. - `_compute_heterogeneity_test()` docstring updated to describe the replicate-weight dispatch and effective-df rule (R1 P3). Regression tests in `TestInvariants`: - `test_rank_deficient_replicate_uses_design_df`: duplicated replicate columns → `design_df < R - 1` → persisted `survey_metadata.df_survey` must equal `design_df` (not `R - 1`). - `test_dropped_replicate_reduces_df`: zeroed replicate columns produce rank deficiency in the design → persisted df must be bounded by `design_df`. Full regression: 324 passing.
|
/ai-review |
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment Highest unmitigated severity: Executive Summary
Methodology
Code Quality Performance Maintainability Tech Debt Security Documentation/Tests
Path to Approval
|
…stency Addresses R2 P0 + P1 from PR #311 AI review. R2 P0: `_effective_df_survey` returns None when replicate design has undefined base df (QR-rank ≤ 1), but `safe_inference(df=None)` uses z-inference — NOT NaN. So a rank-1 replicate design with finite SE silently produced valid-looking p-values/CIs where REGISTRY.md mandates NaN. R2 P1: `_compute_heterogeneity_test` re-derived its local df_s from `min(replicate_n_valid_list) - 1` directly — bypassing the base-df cap the rest of dCDH uses. When df_s was None, the in-loop fallback promoted it to `n_valid_het - 1`, which rescued a rank-deficient design in heterogeneity inference that the main surface correctly treated as NaN. Separately, heterogeneity appended its own n_valid AFTER main inference had frozen, leaving `overall_t`, `event_study _effects`, etc. computed with a larger-than-final df while HonestDiD (reading the post-heterogeneity `survey_metadata.df_survey`) used the smaller final df. Changes: - Add `_inference_df(effective_df, resolved_survey)` helper next to `_effective_df_survey`: coerces None to 0 when replicate (triggers safe_inference's NaN branch), else returns effective_df as-is. - Wrap every dCDH `safe_inference(df=...)` call site (~14 sites) with `_inference_df(df, resolved_survey)`. - In `_compute_heterogeneity_test`, derive `df_s` via `_effective_df_survey(resolved, list(replicate_n_valid_list or []))` instead of the ad-hoc `min - 1`. When `df_s is None` (undefined base df), keep `df_s_local = None` — never promote. - Add a post-heterogeneity finalization block in `fit()` that re-runs `safe_inference` for every public surface (overall, joiners, leavers, multi-horizon, placebo-horizon, heterogeneity) with the FINAL effective df. This guarantees every surface and `survey_metadata.df_survey` use the same df. - Update REGISTRY.md heterogeneity Note to document replicate-weight dispatch and the effective-df rule. Regression tests (TestInvariants): - `test_rank_1_replicate_forces_nan_inference`: identical replicate columns → rank-1 design → design df None → all inference fields NaN. - `test_heterogeneity_replicate_cross_surface_df_consistency`: rank-deficient replicate design with `heterogeneity=` active — asserts `overall_p_value` matches `t(final_df)` distribution and heterogeneity fields agree. Full regression: 326 passing.
|
/ai-review |
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment✅ Looks good Highest unmitigated severity: Executive Summary
Methodology
Code QualityNo findings. PerformanceNo findings. MaintainabilityNo findings. Tech DebtNo findings. The remaining items above are not currently tracked in SecurityNo findings. Documentation/Tests
I could not run the tests here because the sandbox is missing |
Two non-blocker items from PR #311 AI review R3: - P2: `test_placebo_under_replicate` queried `placebo_event_study[1]` but placebo horizons are stored under NEGATIVE keys (REGISTRY.md line 546 — `-l` corresponds to backward outcome difference `Y_{g, F_g-1-l} - Y_{g, F_g-1}`; storage at `chaisemartin_dhaultfoeuille.py:2402` uses `-lag_l` as the key). The test's assertion silently skipped (`.get(1)` returned None) so the replicate placebo SE path was effectively unverified. Fixed to use key `-1` and added explicit assertions on `se`, `p_value`, and `conf_int`. - P3: REGISTRY line 653 described the replicate-effective df as `min(n_valid_across_sites) - 1`, but the actual rule (and the detailed heterogeneity note at line 618) is the capped form `min(resolved_survey.df_survey, min(n_valid) - 1)`. Updated the wording to include the design-df cap and the undefined-base-df NaN case — matching the code and line 618. Full regression: 316 passing.
|
/ai-review |
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment ✅ Looks good Highest unmitigated severity: Executive Summary
Methodology
Code Quality
Performance
Maintainability
Tech Debt
Security
Documentation/Tests
|
Addresses PR #311 AI review R4 (1 × P2 + 2 × P3). P2: The cross-surface df consistency test used a duplicated-replicate design where `resolved.df_survey` binds as the cap BEFORE heterogeneity contributes. That scenario can't detect a broken late-propagation path. Added a monkeypatch-based regression (`test_heterogeneity_late_nvalid_propagates_to_all_surfaces`) that: 1. First counts the main-surface calls to `compute_replicate_if_variance` (no heterogeneity). 2. Then runs fit with `heterogeneity=` active and a patched helper that returns a SMALLER n_valid ONLY on the heterogeneity call (call index > main_count), leaving main surfaces at full n_valid. 3. Asserts every public surface (`overall_p_value`, `event_study_effects`, `placebo_event_study`, `heterogeneity_effects`, `survey_metadata.df_survey`) uses the reduced df via t(reduced_n_valid - 1) distribution. The test caught two real bugs that the duplicated-column test missed: - `effective_overall_t/p/ci` are set by copying from the raw `overall_t/p/ci` at line ~2331 (before heterogeneity runs) and are used as the results-constructor inputs at line ~2776. The R2 recompute block only reassigned `overall_*` — so `effective_overall_*` (what actually shipped) stayed on the pre-heterogeneity df. Fix: recompute `effective_overall_*` from `effective_overall_att/se` (covering both the normal and cost-benefit delta paths), and keep `overall_*` in sync for downstream consumers. - `placebo_event_study_dict[-lag]` holds VALUE copies of `placebo_horizon_inference[lag]`, so mutating the inner dict in the recompute block does NOT propagate to the public surface. Fix: explicitly update `placebo_event_study_dict[-lag]` alongside the mutation in the recompute loop. P3a: REGISTRY overview line 466 still said "Replicate weights and PSU-level bootstrap are deferred" — contradicting the updated checklist at lines 651-653. Rewrote to match the new contract. P3b: `diff_diff/guides/llms-full.txt:325` still said "Replicate weights and PSU-level bootstrap deferred". Updated to reflect replicate support + opt-in PSU-level Hall-Mammen bootstrap + the mutual-exclusion contract with `n_bootstrap > 0`. Full regression: 327 passing.
|
/ai-review |
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment ⛔ Blocker Highest unmitigated severity: Executive Summary
Methodology Affected methods checked: dCDH survey IF expansion / replicate-weight analytical variance, heterogeneity under replicate weights, and PSU-level Hall-Mammen wild bootstrap. The new extensions are documented in docs/methodology/REGISTRY.md:L466, docs/methodology/REGISTRY.md:L618, and docs/methodology/REGISTRY.md:L651. I did not find an undocumented paper/registry mismatch in those mechanics.
Code Quality
Performance
Maintainability
Tech Debt
Security
Documentation/Tests
Path to Approval
|
…branch Addresses PR #311 AI review R5 P0 + P2. P0: The R2 post-heterogeneity finalization block updated overall, joiners, leavers, multi-horizon event-study, placebo-horizon, and heterogeneity surfaces, but missed `normalized_effects_out` — which is built at line 2472-2487 from a delta-method SE (`SE(DID_l) / delta^D_l`) using the pre-heterogeneity `_df_survey`. Under a late-arriving replicate `n_valid` from heterogeneity, the public `results.normalized_effects` dict shipped stale p-values/CIs and could miss the all-NaN gate when the final replicate df turned undefined. Fix: extend the finalization block to also recompute every `normalized_effects_out[h]` entry with `_final_inf_df`. P2: Extended `test_heterogeneity_late_nvalid_propagates_to_all_ surfaces` to assert `res.normalized_effects` p-values match `t(final_df)` distribution. Added a new case `test_late_nvalid_below_two_forces_all_surfaces_nan` that drives the final `n_valid` to 1 (reduced df = 0 → None via `_inference_df` coercion) and verifies EVERY public surface (overall, event_study_effects, placebo_event_study, heterogeneity_effects, normalized_effects) flips to NaN — not silently keeps the finite values computed with the larger intermediate df. Full regression: 328 passing.
|
/ai-review |
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment ✅ Looks good Highest unmitigated severity: Executive Summary
Methodology
Code Quality
Performance
Maintainability
Tech Debt
Security
Documentation/Tests
|
Addresses PR #311 AI review R6 (2 × P3 cleanups). P3 #1: Warning gate was computed from raw positive-weight groups, not the post-filter eligible-group set used to build the bootstrap PSU map. Panels where upstream dCDH filtering drops groups that share PSUs with kept groups could emit a misleading "PSU coarser than group" warning even when the effective bootstrap is one group per PSU. Fix: count PSUs and groups from `_eligible_group_ids` (the same set feeding `group_id_to_psu_code_bootstrap`), preserving the within- group-constant-PSU invariant by taking each eligible group's first positive-weight PSU label. P3 #2: Two docstrings said the bootstrap is "clustered at the group level" only — now incomplete after the PSU-level survey path: - `diff_diff/chaisemartin_dhaultfoeuille.py` class docstring: extended to note PSU-level Hall-Mammen wild clustering under `survey_design` with coarser PSU. - `diff_diff/chaisemartin_dhaultfoeuille_bootstrap.py` module docstring: documents the identity-map fast path (auto-inject `psu=group`), the PSU-level broadcast when PSU is strictly coarser, and points to REGISTRY.md for the full contract. Full regression: 318 passing.
|
/ai-review |
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment Looks good Highest unmitigated severity: Executive Summary
Methodology
Code Quality
Performance
Maintainability
Tech Debt
Security
Documentation/Tests
|
Addresses PR #311 AI review R7 (2 × P3 doc drift cleanups). R7 P3 #1: Several sites still said dCDH "always clusters at the group level" — which was true when the PR was written but is now incomplete given the PSU-level Hall-Mammen wild bootstrap path under `survey_design`. Updated to distinguish user-specified `cluster=` (still unsupported, raises NotImplementedError) from automatic PSU-level clustering (takes over under `survey_design` with strictly-coarser PSUs; identity under auto-inject `psu=group`): - `docs/methodology/REGISTRY.md:592` Note (cluster contract) — rewrote to describe both paths; dropped "Phase 1" framing. - `docs/methodology/REGISTRY.md:636` checklist — added the automatic PSU-level upgrade clause. - `diff_diff/chaisemartin_dhaultfoeuille.py:321` constructor docstring — same contract split. - `diff_diff/chaisemartin_dhaultfoeuille.py:432` / `:503` `cluster=` error messages — removed "Phase 1" phrasing, added PSU-level-under-survey_design context. - `tests/test_chaisemartin_dhaultfoeuille.py:405` regex updated to match the new error wording (no longer pins "Phase 1"). R7 P3 #2: `diff_diff/guides/llms-full.txt:321` said Phase 2 will add multiplier-bootstrap support for placebo and bootstrap covers `DID_M`, `DID_+`, `DID_-` only — both stale after this PR's L_max >= 1 placebo and event-study bootstrap paths. Rewrote to scope the NaN-SE contract to `L_max=None` only and describe the full bootstrap coverage (overall, joiners, leavers, per-horizon event-study, placebo horizons, shared weights for sup-t bands). Full regression: 336 passing.
|
/ai-review |
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment Looks good Highest unmitigated severity: Executive Summary
Methodology No findings. Affected methods are the dCDH survey IF/replicate variance path on the main ATT, event-study, and placebo surfaces diff_diff/chaisemartin_dhaultfoeuille.py:L1718-L1768, diff_diff/chaisemartin_dhaultfoeuille.py:L1836-L1909, the survey heterogeneity path diff_diff/chaisemartin_dhaultfoeuille.py:L3540-L3818, PSU-level Hall-Mammen bootstrap diff_diff/chaisemartin_dhaultfoeuille_bootstrap.py:L68-L399, and survey-backed Code Quality No findings. Performance No findings. Maintainability No findings. Tech Debt No findings. I did not find a silent-correctness issue being deferred via TODO.md:L51-L83. Security No findings. Documentation/Tests
|
Absorbs #312 (sdid scale fix), #313 (roadmap refresh + dCDH docstring rewrite), and #314 (within_transform convergence warnings) from main. Conflicts resolved in: - diff_diff/chaisemartin_dhaultfoeuille.py: took main's comprehensive Phase 1-3 feature list in the class docstring but merged in the PR #311 group-vs-PSU bootstrap-clustering framing and the replicate-weight survey-support line. Kept the PR #311 'user-specified cluster= not supported + automatic PSU-level under survey_design' wording for the cluster= parameter docstring (strictly more accurate than main's 'always clusters at the group level' text). - diff_diff/guides/llms-full.txt: kept main's more detailed placebo SE contract paragraph (which already distinguishes single-period NaN from multi-horizon analytical/bootstrap) and appended the sup-t / shared-weights / cross-horizon coverage details from the PR #311 update. Kept the PR #311 survey_design signature comment that mentions TSL + replicate + PSU bootstrap. Full regression across touched areas: 336 + 324 passing.
|
/ai-review |
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment ✅ Looks good Executive Summary
Methodology
Code Quality
Performance
Maintainability
Tech Debt
Security
Documentation/Tests
|
…ariance-extensions
…odo config Packages five merged PRs since v3.1.2 as patch release 3.1.3: - #311 Replicate-weight variance and PSU-level bootstrap for dCDH — new variance_method="replicate" (BRR / Fay / JK1 / JKn / SDR) and PSU-level multiplier bootstrap, with df-aware inference and group-level PSU map. - #321 Zenodo DOI auto-minting config — .zenodo.json + top-level LICENSE so the next GitHub Release mints a concept + versioned DOI automatically. - #319 Silent sparse->dense lstsq fallback signaling in ImputationDiD and TwoStageDiD — emits ConvergenceWarning instead of switching paths silently. - #317 Non-convergence signaling in TROP alternating-minimization solvers, including LOOCV and bootstrap aggregation. Top-level warning aggregation. - #320 /bump-version skill now updates CITATION.cff; single RELEASE_DATE resolved upfront and threaded through all date-bearing files. Version strings bumped in diff_diff/__init__.py, pyproject.toml, rust/Cargo.toml, diff_diff/guides/llms-full.txt, and CITATION.cff (version: 3.1.3, date-released: 2026-04-18). CHANGELOG populated with Added / Fixed / Changed sections and comparison-link footer. Per project SemVer convention, minor bumps are reserved for new estimators or new module-level API; additive extensions to existing estimators (like PR #311's new variance_method values) are patch-level. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
compute_replicate_if_variancehelper, routed through the inline branch in_survey_se_from_group_if(Class A IF sites) and a parallel branch in_compute_heterogeneity_test(Class B). Effectivedf_surveyreduces tomin(n_valid) - 1across IF sites when replicates fail, matching the precedent inefficient_did.pyandtriple_diff.py.group_id_to_psu_codedict threaded through_compute_dcdh_bootstrap. Every target's PSU map is now constructed by group-ID lookup (not positional reuse), so a future horizon-specific masking cannot silently miscluster bootstrap draws — size mismatch raises loudly. Under the default auto-injectpsu=group, the identity-map fast path preserves pre-change behavior bit-for-bit.replicate_weights + n_bootstrap > 0as mutually exclusive (replicate variance is closed-form; combining would double-count), matchingefficient_did.py:989,staggered.py:1869,two_stage.py:251-253.n_psu_eff < n_groups_eff); auto-injectpsu=groupno longer triggers the stale "PSU-level deferred" warning.twowayfeweights()accepts replicate designs (diagnostic numbers matchfit(..., survey_design=sd).twfe_*).Methodology references (required if estimator / math changes)
compute_survey_if_variance).compute_replicate_if_variance.docs/methodology/REGISTRY.md(ChaisemartinDHaultfoeuilleNotes on survey expansion + survey+bootstrap contract). RDIDmultiplegtDYNdoes not natively support either mechanism.Validation
tests/test_survey_dcdh_replicate_psu.py(new file, ~40 tests across 4 classes — TestReplicateClassA, TestReplicateClassB, TestPSUBootstrap, TestInvariants).tests/test_survey_dcdh.pyupdated to reflect the new contract (replicate-only fits now succeed;replicate + n_bootstrap > 0rejection tested; auto-inject no-warning invariant tested).test_survey_dcdh_replicate_psu.py, including convergence-to-TSL parity for JK1 at n=5000 and end-to-end shared-draw bootstrap under a strictly coarser PSU withL_max=2.Security / privacy
Generated with Claude Code