The do-operator is surgery on the graph: it severs a variable from its causes so we can ask what forcing a value does, not merely what seeing it predicts. do(X=x) deletes every edge into X (the mutilated graph) and pins X=x; the interventional law is the truncated factorization P(v | do(x)) = ∏i : Xi∉X P(xi | pai). Under confounding, seeing and doing part ways — and here the engine proves it.
A discrete, fully-enumerable Structural Causal Model with a back-door confounder U. Every variable is a deterministic function of its parents and its own noise (canonical response form), so the whole law is exact — no sampling needed.
Graph: U → X · U → Y · X → Y
Because U pushes X and Y the same way, a plain regression of Y on X is contaminated. do() is the fix: cut U→X, keep U~P(U), and read Y off the surgery.
This is the algebra that feeds the-backdoor-criterion: once do() has been written down, the back-door adjustment rewrites it into a sum over observed strata — something we can actually estimate. do() states the target; the criterion licenses the estimator.
On Pearl’s ladder it is the second rung — intervention — standing above the-bayes, which lives on rung one and only ever sees. Conditioning cannot climb; only surgery can.
A live re-check of the load-bearing invariant: under this confounder, do(X=1) must differ from see(X=1). If the engine in window 0 is corrupted into mere conditioning, the two collapse together and this badge flips red.
Choose the intervention. The engine performs graph surgery on the model above — it does not look anything up.
booting…
Cross-checked three ways: truncated-factorization formula, direct noise simulation (same noise, X forced), and a fixed-seed Monte-Carlo — all agree to 1e-9 (exact) / 1e-2 (sampled).
do() is a target, not a guarantee. The algebra is only as good as the graph, and the graph can make the effect non-identifiable:
• If U is unobserved and no valid adjustment set exists, no formula in observed quantities equals P(Y|do X). The bow-arc X←→Y kills identification outright.
• A wrong DAG gives a wrong do(). Conditioning on a collider or a mediator opens or closes the wrong paths — the surgery inherits every modelling lie.
• do() assumes the intervention is atomic and well-defined. “do(obesity=0)” has no single surgery. Positivity failures (P(X=x|U)=0) leave strata with nothing to push through.
“P(Y|do X) is just P(Y|X) with fancier notation.”
→ Here see(X=1)=0.780 but do(X=1)=0.690. The confounder inflates the seen number; only surgery removes it.
“Adjust for everything you measured to be safe.”
→ Adjusting for a collider or mediator biases do(). More covariates is not more truth.
“Enough data makes causation appear.”
→ Infinite samples fix variance, not confounding. do() needs the graph, not just N.
The disclosed planted void: rewire do() as ordinary conditioning — keep X’s incoming edges and just filter to X=x. Back-door paths stay open, so do() collapses onto the observational see(). The WITNESS in window 7 catches it live.