Files
hack-house/REPRODUCE.md
T
leetcrypt 8f30be186c docs: self-contained reproduction — vendor frozen prereg + bibliography, add REPRODUCE.md
Make a clean clone reproducible without a sci-method checkout:
- vendor the frozen pre-registration (docs/prereg/, pinned SHA-256 f22331a7… unchanged)
  and the 36-source bibliography into the repo
- confirmatory_run.py resolves the in-repo prereg first, falling back to the canonical
  sci-method path; the SHA gate is identical (the pin, not the path, is the guarantee)
- add REPRODUCE.md: tiered clone→env→seed→run→analyze checklist, honest about the
  isolated-engine containment rule and the 1.2 GB raw data that is not committed

Defensive-measurement instrument; no change to measured behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-23 09:32:39 -07:00

168 lines
8.3 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.
# Reproducing the `sor-consent` study
A step-by-step checklist for reproducing the linkability / anonymity-set / churn-resilience
measurements reported in `docs/stage-07-paper-draft.md` and `docs/stage-07-companion-methods.md`.
This instrument is built for **defensive measurement** of a trust model's exposure. It moves only
**self-generated fixture traffic** on **our own lab grid**, and every forwarder runs **inside an
isolated engine** (docker / multipass) — never on the host (`assert engine != local` or the code
refuses). Reproduce it in the same spirit: no external targets, no third-party traffic.
**Self-contained.** Everything needed to reproduce is committed in this repo — no `sci-method`
checkout is required. The reproduction deposits are:
| Deposit | Path | Purpose |
|---|---|---|
| Frozen pre-registration | `docs/prereg/sor-consent-prereg.md` (+ `.sha256`) | the hashed, frozen design; the launcher SHA-checks it |
| Bibliography | `docs/sor-consent-bibliography.md` | full 36-source reference list for the paper |
| Analysis + instrument | `cmd_chat/sor/` | every DV measure and analysis pass lives here |
| Analysis results + integrity manifest | `output/sor-confirmatory/<ts>/``analysis/stage06-results.json`, `SHA256SUMS.txt`, `INTEGRITY-REPORT.md`, `provenance.json` | the committed, verifiable outputs of the frozen run |
> **Raw data is *not* committed.** The per-run pcaps + event logs
> (`output/sor-confirmatory/<ts>/confirmatory-data/`, ~1.2 GB: 9,000 `events.jsonl` +
> 27,000 pcaps) are `.gitignore`d for size. What *is* committed is their `SHA256SUMS.txt`
> manifest and the analysis results. To re-run the analysis from raw pcaps you must either obtain
> that archive out-of-band or re-collect it via §5; a clean clone can still **verify** the
> committed results and the integrity manifest.
---
## 0. Where does the code run? (the common confusion)
| Component | Runs where | How |
|---|---|---|
| Clone, venv, orchestration, analysis | **On the host** (your laptop) | you drive everything from the repo checkout |
| Circuit **forwarders / hops** | **Inside an isolated engine** (docker container or multipass VM) | spawned automatically by the code via the isolation prefix (`cmd_chat/agent/bridge.py:517-530`); the host never forwards |
You **clone once, on the host.** You do **not** clone inside the VM. When a run starts, each hop is
launched into its own container/VM for you. There is a hard containment check: if the engine
resolves to `local`, the forwarder refuses to run.
---
## 1. Get the code
```bash
git clone https://git.churchofmalware.org/trilltechnician/hack-house.git
cd hack-house
git checkout feat/sor-consent-relay # the branch this study lives on
```
## 2. Set up the environment (host)
```bash
hh/scripts/bootstrap.sh # Python venv + server deps + Rust client build
# (or: python3 -m venv .venv && . .venv/bin/activate && pip install -r requirements.txt)
```
Requires **Python 3.10+** and a Rust toolchain (bootstrap builds the client).
Install **at least one isolated engine** — forwarders will not run without one:
```bash
hh/scripts/ensure-docker.sh # docker (the default engine, --engine docker)
hh/scripts/ensure-multipass.sh # multipass (full-VM isolation), optional
```
## 3. Verify the instrument (no grid, no confirmatory data)
```bash
pytest tests/ # Python acceptance checks (R1R7)
cd hh && cargo test && cd .. # Rust `_sor` consent-parser proptests
# Safe start-line preflight — runs the §5 gate, grid inventory, cell plan,
# a 2-run deterministic dry provenance pass, and the assembler dry check.
# Collects NO confirmatory data; prints a GO/NO-GO summary.
python -m cmd_chat.sor.confirmatory_run
```
A green preflight means the six instrument-validation gate items pass: 3-hop end-to-end delivery
with per-hop pcap + checksum, seeded reproducibility, correlator calibration (linked AUC≈1 /
unlinked≈0.5), entropy calibration (H=log₂N), isolated-engine-only forwarders, and append-only
provenance whose `events.jsonl` SHA-256 matches the manifest.
## 4. Reproduce the reported analysis
Every number in the paper is deterministically regenerable from the frozen raw data and the single
base seed **S0 = 20260719** — same seed → identical output.
**Two things a clean clone can always do (no grid, no raw data):** re-hash the committed results
and verify the raw-data integrity manifest:
```bash
cd output/sor-confirmatory/20260720T060132Z && sha256sum -c SHA256SUMS.txt # needs raw data present
# and inspect the committed frozen outputs directly:
cat output/sor-confirmatory/20260720T060132Z/analysis/stage06-results.json
```
**To regenerate the numbers from raw pcaps** you need the ~1.2 GB `confirmatory-data/` archive
present (obtain out-of-band, or re-collect via §5). With it in place:
```bash
# Lead paper — RQ1-P1, RQ1-P2, RQ2-P1, RQ2-P3 (Holm family_size=7, report 4)
python -m cmd_chat.sor.analysis.stage06_run \
output/sor-confirmatory/20260720T060132Z/confirmatory-data \
--out output/sor-confirmatory/20260720T060132Z/analysis/stage06-results.json
# Companion — RQ2-P3 mechanism study and RQ3
python -m cmd_chat.sor.analysis.rq2p3_confirm # shared-pool anonymity-set mechanism
python -m cmd_chat.sor.analysis.rq3_confirm # churn-resilience selector
```
Same seed → identical output (10,000 BCa bootstrap resamples, α = 0.05). Verify integrity by
re-hashing each run's `events.jsonl` against its `manifest.json`, and confirming the frozen prereg
still hashes to `f22331a72e0d0ccf38b787e63acabbe9d666456ec76076787a6d545c3193425b`.
## 5. Re-run the full confirmatory battery (human-gated — needs the lab grid)
The immutable data run (**R = 30 runs × C = 50 circuits = 9,000 live circuits**) is deliberately
**human-gated**. It is triple-locked and refuses to launch unless all four hold:
1. **Operator token**`SOR_CONFIRMATORY_GO=1` in the environment.
2. **Frozen prereg** — the on-disk prereg hashes to `f22331a7…` (see §6 caveat).
3. **Isolation**`--engine docker` (or `multipass`); never `local`.
4. **Full grid** — every device reachable (the launcher refuses a degraded grid rather than
fabricate cells).
```bash
SOR_CONFIRMATORY_GO=1 python -m cmd_chat.sor.confirmatory_run --operator-go --engine docker
python -m cmd_chat.sor.rq3_confirmatory_run --engine docker # companion RQ3 battery
```
Then re-run the §4 analysis over the freshly collected `confirmatory-data/`.
---
## Seeds & determinism
- **Base seed:** `S0 = 20260719` (fixed pre-data).
- **Per-cell seed:** `SHA256(S0 ‖ cell_id ‖ run_index)` — drives every stochastic element (path
selection, churn schedule, padding jitter) so two runs with the same seed produce an identical
circuit-build sequence.
- Seed + git SHA + node-role→device mapping are echoed into each run's immutable `manifest.json`.
## Outputs (treat as immutable once written)
```
output/sor-runs/<ts>/ manifest.json · events.jsonl · pcap/hop<N>.pcap · metrics.json
output/sor-confirmatory/<ts>/ preflight artifacts · confirmatory-data/ · analysis/
```
## Honest reproduction caveats
- **The frozen prereg is vendored.** The confirmatory launcher (§5) hard-refuses unless the
pre-registration is present and hashes to `f22331a7…`. The frozen prereg is committed in-repo at
`docs/prereg/sor-consent-prereg.md` (with `.sha256`), so this checkout is self-contained — no
`sci-method` access is needed. The launcher prefers the in-repo copy and falls back to the
operator's canonical `sci-method` checkout; the SHA-256 pin (not the path) is the integrity
guarantee. Verify it yourself: `cd docs/prereg && sha256sum -c sor-consent-prereg.sha256`.
- **The physical grid is lab-specific.** The reported run distributes hops across our own 2 phones
+ laptop + hack-house VM churn fabric. An external reproducer instead uses the
**containerised-hop fallback** (all hops as isolated docker containers) — this reproduces the
instrument and the analysis, but not the exact physical device distribution.
- **Agent arm (RQ3).** Local open-weight (Ollama, temp 0) is **not** bit-identical across machines
(quantization / GPU logit drift). The agent arm reproduces via the **committed decision-log +
`(seed, state-hash)` cache replay**, not via independent cross-hardware model re-execution.
See `CLAUDE.md` for the containment law and `docs/stage-07-paper-draft.md` §4 for the frozen method.