Studio 4 — Declare and diagnose provisionally
Studio 4
Write your design down as something specific enough to be diagnosed, then find out how it behaves before it costs you anything.
Studio 4
This studio closes with Milestone 4: Your research contract, v0, a short chapter of its own after the lessons. What it asks you to produce. Research Contract v0 — objective, target estimand, population, setting and time, data strategy, a provisional operationalization you mark for revision, warrant, answer strategy and uncertainty statement — plus the design properties you diagnosed (its bias, its wobble, and how often it would detect what you are looking for), your permission status, and a redesign record. Measurement proper is taught and assessed in Studio 6; here you only commit to a starting choice and say why it is defensible for now.
Studio 4 · Road map
Lesson 1 of this studio · Chapter 10
the four parts of your design, and whether all four point at the same quantity
Chapter 10
The four parts of your own design, written down before any data exist: a model of the world, the one named quantity you want out of it, a plan for how the data arrive, and a plan for turning that data into your quantity. Then the harder call: whether those four parts actually point at the same thing.
Chapter 10 · Why this decision matters
Chapter 10 · Why this decision matters
A design that skips this step is not rigorous. It is a hope with good formatting.
Chapter 10 · The concept
Blair, Cooper, Coppock and Humphreys named that framework MIDA, one letter each (Blair et al. 2019).
Model
your written picture of how the world could work: which things exist and what could affect what
Inquiry
the one exact quantity you want from that world, named before any outcome arrives
Data strategy
every procedure that makes your data exist: who gets sampled, who gets which condition when you assign one, how each outcome is measured
Answer strategy
the whole procedure that turns those data into an answer, uncertainty included
Chapter 10 · The concept
Chapter 10 · The concept

The four parts of a design. The top row is what you want to learn; the bottom row is how you plan to learn it. All four are written down before you collect anything, and the dashed arrow is the check that matters: your answer strategy has to reach the inquiry you named.
Chapter 10 · The concept
Chapter 10 · The concept
Chapter 10 · A worked example
Chapter 10 · A worked example
Chapter 10 · A worked example
Chapter 10 · A worked example
import numpy as np, pandas as pd
SEED = 464
rng = np.random.default_rng(SEED)
n = 4000
# MODEL: each listener has two accept rates; the new recommender adds 4 points.
heavy = rng.random(n) < 0.45 # heavy listeners accept more anyway
accept_old = 0.30 + 0.18 * heavy
accept_new = accept_old + 0.04
# DATA STRATEGY 1 — random bucketing: nothing about the listener decides arm.
new_arm = rng.random(n) < 0.5
kept = np.where(new_arm, rng.random(n) < accept_new, rng.random(n) < accept_old)
randomized = kept[new_arm].mean() - kept[~new_arm].mean()
# DATA STRATEGY 2 — the shortcut: ship "new" to new users, who differ.
is_new_user = ~heavy # new users are the lighter listeners
kept2 = np.where(is_new_user, rng.random(n) < accept_new, rng.random(n) < accept_old)
shortcut = kept2[is_new_user].mean() - kept2[~is_new_user].mean()
print(f"true caused lift : {0.04:+.3f}")
print(f"randomized buckets : {randomized:+.3f}")
print(f"new-vs-existing users : {shortcut:+.3f}")
print("\nsame inquiry both times. the second design does not answer it —")
print("the inquiry stays causal and is now unidentified")Chapter 10
Where the tool failed
You paste your streaming question and ask for MIDA. The tool returns four confident, well-formatted parts and calls the design “rigorous.” Read closely: it wrote the data strategy as “compare new users on the new recommender to existing users on the old one,” and it kept the inquiry worded as a caused lift. That is two failures at once. The data strategy is plausible-but-wrong, because user tenure moves accept rate on its own. And the draft presents that comparison as if it answers the caused-lift inquiry, a silent scope change from what the evidence supports (an association) to what the write-up claims (a cause). The inquiry may keep its causal wording; what it may not do is borrow this comparison as its answer. You catch it two ways: set the inquiry’s words beside the data strategy and ask whether randomization actually happened, then sketch the model as a diagram and look for an arrow from “user tenure” into both the version seen and the accept rate. That open arrow is the confounder the fluent draft never mentioned.
Chapter 10
This stays yours
Three choices stay yours. Which world your question assumes (the model, and so what could confound it). Which single quantity you want (the inquiry, named in your words, not the AI’s paraphrase). Whether your four parts align, and therefore whether your claim boundary is causes, only is associated with, or causal but not yet identified by this design. That third state is a real answer, and keeping your question while admitting the design cannot reach it is more honest than shrinking the question to fit the data. An AI can draft candidate parts. Deciding they agree, and owning the claim that follows, is research judgment you cannot hand off.
Chapter 10 · Your move
Work it in the companion notebook with Chapter 10 open beside it. Log every delegation in your AI Research Ledger.
Lesson 2 of this studio · Chapter 11
Chapter 11
What quantity you are actually after, what recipe you will use to guess it, and what you will say about how much that guess could have moved. You decide all three before you inspect the outcomes, because each one changes what the others are allowed to mean.
Chapter 11 · Why this decision matters
The honest question is not ‘is my number right?’
Chapter 11 · Why this decision matters
Chapter 11 · The concept
Estimand
the quantity you want, defined in the world before you touch the outcome data
Estimator
the recipe you apply to data to guess the estimand
Estimate
what one run of the recipe returns
Chapter 11 · The concept
Chapter 11 · The concept
import numpy as np
SEED = 464
rng = np.random.default_rng(SEED)
town = rng.lognormal(mean=7.3, sigma=0.35, size=4000) # every household's rent
estimand = town.mean() # the quantity we want
# the recipe: survey 60 households at random, take the mean
means = np.array([rng.choice(town, size=60, replace=False).mean()
for _ in range(2000)])
print(f"estimand (true average rent): {estimand:,.0f}")
print(f"one survey said: {means[0]:,.0f}; another said: {means[1]:,.0f}")
print(f"centre of the pile: {means.mean():,.0f}")
print(f"spread of the pile: {means.std(ddof=1):,.0f}")
print(f"middle 95% of the pile: {np.percentile(means, 2.5):,.0f}"
f" to {np.percentile(means, 97.5):,.0f}")Chapter 11 · The concept
Chapter 11 · The concept
Standard error
the typical distance between one run’s estimate and the centre of the pile
Confidence interval
a range built by a recipe that catches the estimand a stated share of the time, when the same recipe is repeated
Chapter 11 · The concept
rng = np.random.default_rng(SEED)
n, runs, hits = 60, 2000, 0
for _ in range(runs):
s = rng.choice(town, size=n, replace=False)
se = s.std(ddof=1) / np.sqrt(n) # width estimated from ONE survey
lo, hi = s.mean() - 1.96 * se, s.mean() + 1.96 * se
hits += lo <= estimand <= hi
print(f"share of intervals that caught the truth: {hits / runs:.1%}")Chapter 11 · The concept
my estimate is 1,621, from a procedure whose 95% intervals catch the true average about 95 times in 100
Chapter 11 · A worked example
Chapter 11 · A worked example
Chapter 11 · A worked example
rng = np.random.default_rng(SEED)
B, K, truth, runs = 12, 5, 2000.0, 2000 # 12 buildings, 5 flats each
naive_hits = cluster_hits = 0
for _ in range(runs):
building_effect = rng.normal(0, 260, B) # landlord/neighbourhood effect
data = np.array([truth + building_effect[b] + rng.normal(0, 120, K)
for b in range(B)])
flats = data.ravel() # pretend: 60 independent flats
se_naive = flats.std(ddof=1) / np.sqrt(60)
naive_hits += (flats.mean() - 1.96 * se_naive <= truth
<= flats.mean() + 1.96 * se_naive)
b_means = data.mean(axis=1) # honest: 12 independent buildings
se_cluster = b_means.std(ddof=1) / np.sqrt(B)
cluster_hits += (b_means.mean() - 1.96 * se_cluster <= truth
<= b_means.mean() + 1.96 * se_cluster)
print(f"treating 60 flats as independent: {naive_hits / runs:.1%} caught the truth")
print(f"treating 12 buildings as the unit: {cluster_hits / runs:.1%} caught the truth")Chapter 11 · A worked example
Chapter 11 · A worked example
With the variability this example assumes, and not as a general rule.
Chapter 11
Where the tool failed
Ask an assistant to interpret an interval and you will very often get this, fluently and confidently:
Chapter 11 · An AI failure case
Chapter 11
This stays yours
Chapter 11 · Your move
Work it in the companion notebook with Chapter 11 open beside it. Log every delegation in your AI Research Ledger.
Lesson 3 of this studio · Chapter 12
whether this design is strong enough to run, judged before you spend anything collecting data
Chapter 12
Whether the design you wrote down is strong enough to run, decided before you collect a single data point: you simulate it, read how often it lands on the truth, and name the one change that most improves it. Then you either run it, fix it, or narrow what you promised.
Chapter 12 · Key terms
Diagnose
running that declared design many times on fresh simulated worlds and watching how its estimate behaves.
Bias
the average of your errors across the runs, counting direction: each estimate minus the truth, averaged.
Variance
how much the estimate wobbles from one run to the next.
Power
how often the design detects a real effect, and it means nothing until you say how you would decide (Greenland et al. 2016).
Chapter 12 · Why this decision matters
Chapter 12 · Why this decision matters
Chapter 12 · The concept
Chapter 12 · The concept
Chapter 12 · The concept
Chapter 12 · The concept
Chapter 12 · The concept
Chapter 12 · The concept
Bias, variance, and power are properties of the design read across many runs, never off a single study.
Diagnosand
a property of a design you want to diagnose
Root mean-squared error
the typical size of a miss, with big misses weighted extra
Coverage
how often the range you report around your estimate actually contains the truth
Chapter 12 · The concept
Chapter 12 · The concept
You can go around as many times as the diagnosis asks, changing one thing each time.

The loop, and the call that ends it. You can go around as many times as the diagnosis asks, changing one thing each time, but the decision to run, revise, or narrow the claim is never inside the loop.
Chapter 12 · A worked example
Chapter 12 · A worked example
Chapter 12 · A worked example
Chapter 12 · A worked example
import numpy as np, pandas as pd
SEED = 464
rng = np.random.default_rng(SEED)
TRUE_EFFECT = -8.0 # seconds the button really saves
def run(n_per_arm, randomize, runs=2000):
"""Declare a design once, then diagnose it by running it many times."""
out = []
for _ in range(runs):
base = rng.normal(150, 32, size=2 * n_per_arm) # people differ a lot
if randomize:
treated = rng.random(2 * n_per_arm) < 0.5
else: # shoppers opt in — the fast ones do
treated = rng.random(2 * n_per_arm) < 1 / (
1 + np.exp((base - 150) / 170))
secs = base + TRUE_EFFECT * treated + rng.normal(0, 8, size=2 * n_per_arm)
out.append(secs[treated].mean() - secs[~treated].mean())
est = np.array(out)
se = est.std(ddof=1)
return {"estimate": est.mean(), "bias": est.mean() - TRUE_EFFECT,
"power": float((np.abs(est) > 1.96 * se).mean())}
designs = {"pilot, randomized, 12/arm": run(12, True),
"randomized, 400/arm": run(400, True),
"opt-in, 400/arm": run(400, False)}
print(pd.DataFrame(designs).T.round(2).to_string())
print("\nsize cured the variance. it did nothing for the opt-in design's bias")Chapter 12
Where the tool failed
You paste your confounded observational design and ask, “My estimate is noisy. What should I do?” The tool answers with confidence: “Collect more observations to tighten your estimate.” That sounds obviously right and is exactly wrong for your case. Your problem is bias from self-selection, not variance, and more data only makes a biased estimate a more precise wrong number. You catch it the way this chapter teaches: run the confounded design in simulation at a large sample and watch the estimates cluster tightly around 14 seconds when the truth is 8. The spread shrank; the error did not. That is the plausible-but-wrong-method failure, and your own diagnosis unmasks it.
Chapter 12
This stays yours
Three calls stay yours. Which world your question assumes, the model you declare, is a claim about reality no tool can make for you. Which single quantity you name as your inquiry decides what “success” even means. And the honest call of whether to run a design your own diagnosis says is too weak is a judgment you sign your name to. An AI can propose threats and draft simulation code, but it cannot decide that your under-powered study is worth months of your life anyway.
Chapter 12 · Your move
Work it in the companion notebook with Chapter 12 open beside it. Log every delegation in your AI Research Ledger.
Lesson 4 of this studio · Chapter 13
Chapter 13
Whether you are permitted to collect the data your design calls for, who decides that, and how you will hold the data once you have them. You settle this before collection starts, because it is the one design flaw no later analysis can repair.
Chapter 13 · Key terms
Cleared
no formal determination is needed and you can say why in one sentence.
Formal determination required
a competent authority has to rule before you collect.
Pending
you asked and are waiting.
Not authorized — stop
you may not proceed as planned.
Chapter 13 · Why this decision matters
Chapter 13 · The concept
This chapter is not legal advice, and rules differ by country, institution, and data source.
Permission status
a statement of whether you may collect, who decided, and what you are waiting on
Competent authority
whoever, at your institution, is empowered to make this ruling
Chapter 13 · The concept
Chapter 13 · The concept
Chapter 13 · The concept
Chapter 13 · A worked example
Chapter 13 · A worked example
share_unique is the share of rows whose combination of columns occurs exactly once.import numpy as np
from collections import Counter
SEED = 464
rng = np.random.default_rng(SEED)
n = 800
dept = rng.integers(0, 12, n) # 12 departments
year = rng.integers(1, 5, n) # 4 class years
country = rng.choice(np.arange(28), size=n,
p=np.r_[0.45, 0.10, 0.07, 0.05, 0.04, np.full(23, 0.29 / 23)])
age = np.clip(rng.normal(20.5, 2.2, n).round().astype(int), 17, 35)
def share_unique(*cols):
keys = list(zip(*cols))
counts = Counter(keys)
return sum(1 for k in keys if counts[k] == 1) / len(keys)
print(f"unique on department alone: {share_unique(dept):.1%}")
print(f"unique on department + year: {share_unique(dept, year):.1%}")
print(f"unique on department + year + country: {share_unique(dept, year, country):.1%}")
print(f"and adding age: {share_unique(dept, year, country, age):.1%}")Chapter 13 · A worked example
rare = country >= 5 # students from less-common countries
common = country == 0 # students from the most common one
print(f"unique among less-common-country students: "
f"{share_unique(dept[rare], year[rare], country[rare], age[rare]):.1%}")
print(f"unique among most-common-country students: "
f"{share_unique(dept[common], year[common], country[common], age[common]):.1%}")Chapter 13 · A worked example
Chapter 13 · Consent is a process
Chapter 13 · AI and the exposure question
Chapter 13 · AI and the exposure question
Chapter 13 · Data governance for a small project
Chapter 13 · Four situations that must stop or wait
When the answer is stop, you are one design decision away from a different project.
Chapter 13
Where the tool failed
Describe a study to an assistant and ask whether you need approval, and you will usually get a fluent, specific, reassuring answer:
Chapter 13 · An AI failure case
Chapter 13
This stays yours
Chapter 13 · Your move
Work it in the companion notebook with Chapter 13 open beside it. Log every delegation in your AI Research Ledger.
Studio 4 closes here
What the lessons handed you becomes one artifact you can defend.
Milestone 4
The artifact
What this milestone produces. Research Contract v0 — objective, target estimand, population, setting and time, data strategy, a provisional operationalization you mark for revision, warrant, answer strategy and uncertainty statement — plus the design properties you diagnosed (its bias, its wobble, and how often it would detect what you are looking for), your permission status, and a redesign record. Measurement proper is taught and assessed in Studio 6; here you only commit to a starting choice and say why it is defensible for now.
Milestone 4 · Check before you start
Milestone 4 · In the studio
Milestone 4 · Every studio, these four
Ethics, permissions, and data exposure
The permission status produced here gates every later studio; nothing downstream may proceed past a stop.
Evidence, provenance, and reproducibility
Your data strategy names actual sources from the Studio 3 registry, not source types.
AI activity, verification, and human decisions
Diagnosis is delegable; the choice of what to fix is not.
Uncertainty, claim boundary, and revision history
This is where your uncertainty statement is first written down and first tested.
Milestone 4
How the record works
Your milestone artifact is a dated, numbered version with the reason for the version attached. When later evidence changes it, you write the next version rather than editing the last one, because the sequence of changes is itself part of your research record.
AI is your arm and your research assistant, not your brain.
AI can review AI, and a second model is a real auditor of the first. The last decision is always human.

EDR|AI · Studio 4 — Declare and diagnose provisionally