Files
hack-house/docs/rq2p3-mechanism-prereg.md
T
leetcrypt 7ab3466878 RQ2-P3: re-word §7 calibration gate (naive→mechanical mix), re-run GREEN
Operator ruling (Andre, 2026-07-21): the STOP was correct and the diagnosis
right — §7 items 1-2 did not fail because the instrument is broken, but because
they were worded under the naive-funnel prior. Under the ratified posterior the
pool is a MIX (shared bridge → shared exit_signature → larger anonymity set →
higher H). Corrected pre-freeze, logged transparently (no HARKing).

- rq2p3-mechanism-prereg.md §7: item 1 re-anchored on the FROZEN bridge-federated
  branch (injective fresh-bridge → m_i=1 → H≈0, constant c=1/C — a pool draws with
  replacement so it cannot reproduce the zero-variance degeneracy); item 2 B=1 →
  c=1.0 AND high H (maximal mix, "low H" refuted by construction); added a §7 scope
  note (the gate validates the INSTRUMENT and must NOT pre-assert the H-vs-c sign —
  that stays the two-sided confirmatory question H1/H2). Confirmatory hypotheses
  unchanged.
- docs/stage-05-rq2p3-gate-clarification.md: dated deviation-rationale log (cites
  the dry-pass output, no number invented; records the two-sided direction-agnostic
  pre-commitment is untouched; the mix ρ 0→+0.838 is an exploratory finding that
  strengthens note-unique-bridge-artifact.md).
- rq2p3_calibration.py: item-1 teeth moved to frozen_branch_regression() on the
  untouched bridge-federated branch; item-2 now asserts c=1.0 AND high H; added
  all_pass aggregate. confirm.py/stats.py/confirm_load_rq2.py untouched.

Re-run: all four gate items PASS with real teeth (all_pass=True). Synthetic/DRY
only, no confirmatory record read. FREEZE STAYS A HUMAN GATE: §10 empty, no
confirmatory RQ2-P3 cell until operator records the SHA-256 + signs off. Lead
prereg SHA f22331a72e... untouched; worktree-only.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-21 19:48:55 -07:00

183 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Pre-registration (DRAFT) — RQ2-P3 funnelling-mechanism study
> **STATUS: APPROVED-PATH, PARAMS LOCKED — NOT YET FROZEN.** Design + parameters
> operator-approved 2026-07-21 (grid B∈{2,4,8}×α∈{0,1,2}; run-level cluster bootstrap;
> two-sided/direction-agnostic). Remaining step before any confirmatory cell: **human freeze
> checkpoint** — record the SHA-256 of the final text in §10 and the operator freeze sign-off.
> Build + synthetic tests + the §7 calibration gate MAY proceed now; the confirmatory battery
> MUST wait for the freeze.
> This is a **new study with its own slug** (`sor-consent-rq2p3`). It **does not modify**
> the frozen lead prereg (`sor-consent-prereg.md`, SHA
> `f22331a72e0d0ccf38b787e63acabbe9d666456ec76076787a6d545c3193425b`), whose RQ2-P3
> result stands as reported ("inconclusive — not testable as-instrumented").
## 0. Why this study exists
The lead paper found federation **shrinks** the per-circuit anonymity set (RQ2-P1,
ΔH = 0.96 bits, Holm-significant) but could **not** test the *mechanism* (RQ2-P3): the
bridge-federated instrument assigns a **fresh willing bridge per circuit seed**
(`assembler.py:131`, `_bridge_label(seed)`), so every circuit routes through a distinct
bridge, top-3 concentration is constant (`c_i = 1/C`), the covariate has **zero variance**,
and Spearman ρ is undefined (`stats.spearman` returns 0.0 by construction). The lead paper
reported this honestly as an as-instrumented degeneracy, not a null of a well-posed test.
**The mechanical insight this study exists to test (see `note-unique-bridge-artifact.md`).**
The adversary's observation is `exit_signature = (exit_house, bridge_label)`, and the
per-circuit anonymity set `m_i` = the distinct entry nodes among circuits sharing that
signature (`confirm_load_rq2.py`). A **fresh bridge per circuit ⇒ every signature is unique
⇒ group size 1 ⇒ m_i = 1 ⇒ H ≈ 0.** That — not funnelling — is why bridge-federated produced
H ≈ 0 and drove the lead ΔH negative. Introduce a **finite shared pool** and many circuits
share a bridge ⇒ shared signature ⇒ larger set ⇒ **higher H**. Under this posterior a bridge
is a **mix**: more concentration plausibly *raises* anonymity, the opposite of the naive
funnel story. So this study is, honestly, **a test of whether the lead paper's "shrink" is a
unique-bridge artifact** — and it may *qualify or correct* the lead RQ2-P1 headline.
This study re-instruments the willing-bridge layer with a **finite pool + skewed
willingness** so concentration genuinely varies, and — the key upgrade — treats
concentration as a **manipulated independent variable** (a dose-response design) rather than
a passive covariate. The direction is left **two-sided**: the naive prediction is funnel
(ρ < 0); the mechanical prediction under the ratified posterior is mix (ρ > 0). We pre-commit
to reporting whichever the data shows, including a correction to the lead result if warranted.
The analysis code (`bridge_concentration`, `rq2_p3_funnel`) is already correct; only the
*instrument* and this *prereg* are new.
## 1. Blinding & integrity posture (read first)
- **This study is NOT blind to the RQ2-P1 shrink direction** (the lead paper is published).
Mitigations that keep it honest: (a) the funnelling hypothesis was **pre-stated as a live
mechanism** in the lead paper's introduction, not invented post-hoc; (b) the confirmatory
targets below are **two-sided**; (c) concentration is a *manipulated* IV, so the test is a
designed dose-response, not a re-slice of the lead data.
- **The lead RQ2-P1 result is NOT re-litigated here.** Any ΔH this pool instrument produces
is labeled **EXPLORATORY / replication**, never a re-run of the frozen RQ2-P1.
- **No detector retuning.** The entropy estimator, posterior construction, and Spearman path
are inherited **unchanged** from the frozen lead pipeline; only bridge assignment changes.
## 2. Research question & hypotheses
**RQ2-P3.** Within the consent-gated bridge-federated topology, does willing-bridge
**concentration** causally reduce the per-circuit anonymity set (funnelling)?
- **H1 (within-cell association, two-sided).** Spearman ρ between per-circuit top-3 willing-
bridge concentration `c_i` and per-circuit entropy `H_i`. **Funnel** iff BCa 95% CI < 0;
**mix** iff CI > 0; **inconclusive** iff CI spans 0. Direction is *not* presumed.
- **H2 (dose-response, two-sided).** OLS slope β of H on realized top-3 concentration, over
**per-run mean points** (9 cells × 30 runs = 270 clustered points), cell-level BCa CI.
**Funnel** iff slope CI < 0; **mix** iff slope CI > 0.
- **H3 (joint, direction-agnostic).** Mechanism **RESOLVED** iff H1 and H2 agree in sign and
both exclude 0; the *sign* is the finding (funnel vs mix). **Unresolved** if either spans 0.
## 3. Instrument change (the only new code)
Replace the per-seed fresh bridge with a **willing-bridge pool** of size `B` and a fixed
skewed willingness weight vector, under a **new topology factor** so lead-paper cells stay
bit-reproducible:
```
# new assembler branch: topology == "bridge-federated-pool"
weights = zipf_weights(B, alpha) # fixed from the CELL seed; stable per run
idx = weighted_draw(sha256(f"sor-bridge-pool|{circuit_seed}"), weights)
bridge = f"bridge#{idx:02d}" # B distinct labels, REUSED across circuits
```
- Weights derive from the **cell** seed (not the circuit seed) so the willingness profile is
fixed within a run and circuits genuinely share bridges → concentration varies.
- Everything else (hop structure, houses, exit-signature grouping, posterior, MillerMadow H,
BCa) is **identical to the frozen lead pipeline**.
- Touchpoints: `assembler.py` (new branch + pool helper), `battery.enumerate_cells()` (sweep).
`confirm_load_rq2.py`, `confirm.py`, `stats.py` are **unchanged**.
## 4. Design matrix (concentration as IV)
Bridge-federated-pool, selector `static`, matched-N, bridge willingness the only manipulation:
- **Pool size** `B ∈ {2, 4, 8}` — 3 levels.
- **Willingness skew** `alpha ∈ {0 (uniform), 1.0 (moderate Zipf), 2.0 (heavy Zipf)}` — 3 levels.
- Full 3×3 = 9 concentration cells (each realizes a distinct mean top-3 concentration).
Run order randomized within cell; deterministic from an ordering seed distinct from data seeds.
## 5. Dependent variables
- **Per-circuit H_i** — MillerMadow entropy of the uniform posterior over the observation-
consistent anonymity set (inherited **verbatim** from the frozen lead pipeline).
- **Per-circuit top-3 concentration c_i** — `confirm_load_rq2.bridge_concentration` (unchanged).
## 6. Sampling, seeds, stopping rule
- **R = 30** seeded runs/cell, **C = 50** circuits/run (matched to the lead study).
- Base seed **S0 = 20260719**; per-cell seed = `SHA256(S0 ‖ cell_id ‖ run_index)` (matched).
- **Fixed stopping rule:** all 9 cells × R run to completion. No optional stopping, no interim
looks. An uninformative cell is reported **inconclusive**, never extended.
## 7. Instrument-validation gate (boolean; blocks the confirmatory run)
> **Re-worded 2026-07-21, pre-freeze (deviation logged in `stage-05-rq2p3-gate-clarification.md`).**
> Items 12 were originally written under the naive-funnel prior ("pool reproduces the
> zero-variance degeneracy"; "B=1 → low H"). Both are mechanically wrong under the *ratified*
> posterior and were corrected **before freeze** — see the §7 scope note below. No hypothesis
> changed (H1/H2/H3 in §2 stay two-sided/direction-agnostic); only a mis-specified validation
> gate was fixed. The original dry-pass output that exposed this is cited in the deviation log.
All must pass **before** any confirmatory cell:
1. **Reproduce the lead degeneracy — on the FROZEN branch, not the pool.** The lead
zero-variance degeneracy is a property of the **injective fresh-bridge map** (a unique
bridge per circuit seed = effectively no reuse). A finite pool of **any** size `B` draws
**with replacement**, so birthday collisions make concentration non-constant and ρ defined —
a pool **cannot and must not** be expected to reproduce the fresh-bridge degeneracy. The
regression check therefore anchors on the actual frozen `bridge-federated` branch
(UNTOUCHED): it must still yield **unique exit-signatures → `m_i = 1``H_i ≈ 0`, constant
`c_i = 1/C`**. That is the real "lead reproduces" teeth.
2. **B = 1 boundary.** `B = 1` → all circuits share the one bridge → **`c = 1.0`** (keep this
concentration tooth). Under the ratified posterior the anonymity set is then **all** circuits
sharing the exit house, so `H_i` sits at the **HIGH end (maximal mix)** — the "low H" gloss
was the naive-funnel error and is refuted **by construction** here. Expect high H.
3. **Monotonicity.** Realized mean top-3 concentration is **monotone decreasing in B** and
**increasing in alpha**, across the sweep, on a dry (non-confirmatory) calibration pass.
4. **Entropy calibration unchanged.** H = log₂N on equiprobable synthetic senders (inherited).
**§7 scope note (why items 12 do NOT assert an H-vs-c sign).** This gate validates the
**instrument** — concentration varies monotonically (item 3), entropy is exact (item 4), the
frozen branch is untouched (item 1), and the B=1 boundary hits `c = 1.0` (item 2). It **must not
pre-assert the sign of H-vs-concentration**, because that sign *is* the two-sided confirmatory
question (H1/H2). Baking "expect low H at high concentration" into a validation gate would be
**funnel-circular**; removing it makes the study **more** rigorous, not less. The confirmatory
hypotheses in §2 stay two-sided/direction-agnostic — **UNCHANGED**. (Note: the dry calibration
pass already *previews* a mix, ρ 0→+0.838 across the sweep; this is surfaced openly as an
exploratory preview and does **not** relax the two-sided pre-commitment.)
If any gate item fails → STOP, do not report; surface as NEEDS-OPERATOR.
## 8. Analysis plan
- Effect size + BCa 95% CI for every test; p never reported alone; 10,000 resamples; α = 0.05.
- **H1:** `confirm.rq2_p3_funnel(c, H)` per cell + pooled, but resampled with a **run-level
cluster bootstrap** (resample whole runs, not individual circuits). Rationale: circuits
sharing a bridge have identical `c_i` and correlated `H_i`, so per-circuit resampling
pseudo-replicates and falsely narrows the CI (the same defect noted for lead RQ1-P1). The
run is the independent unit.
- **H2:** OLS slope of per-run mean-H on per-run mean top-3 concentration (270 clustered
points); BCa CI resampling **over runs within cells** (cluster bootstrap).
- **Multiplicity:** HolmBonferroni over **this study's own family** {H1-pooled, H2-slope}
(the lead study's family-of-7 is closed and not reopened).
- **Confirmatory vs exploratory:** the 9-cell sweep is confirmatory; any per-cell ρ contrast or
ΔH replication is labeled EXPLORATORY.
- **Data exclusion (pre-data):** quarantine only on integrity failure (SHA/pcap mismatch,
non-reproducing seed). No performance-based exclusions.
## 9. Rails (immutable, inherited)
Prereg frozen after approval — never edited (deviations only in a stage-05-style log; no
HARKing; nulls are results). Containment: isolated docker only, self-generated fixture traffic,
lab-only. Budget $0. Worktree only on `feat/sor-consent-relay`. Raw data immutable + SHA-256.
## 10. Freeze block (to complete at approval)
```
FROZEN: <date>
PREREG SHA-256: <hash of final text>
APPROVED BY: <operator>
POOL/ SKEW LEVELS LOCKED: B∈{2,4,8}, alpha∈{0,1.0,2.0}
```