causal-inference — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited causal-inference (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Use when the question is "what is the causal effect of X on Y" but a clean A/B test isn't possible. Triggers:
If a clean A/B test IS possible, use ab-test-design + ab-test-analysis — they always beat quasi-experimental methods.
If the question is "predict Y" not "what causes Y," use linear-regression or logistic-regression.
Answer these questions in order:
1. Is there a clear before/after time and a comparison group not affected by the change?
YES → Difference-in-Differences (DiD)
NO → continue
2. Did some users opt into a feature/treatment based on observable characteristics?
YES → Propensity Score Matching (PSM) or weighting
NO → continue
3. Is there a "lever" that affects treatment but doesn't directly affect outcome?
YES → Instrumental Variable (IV)
NO → none of these will work cleanly; recommend RCT or accept correlational evidence with explicit caveats.| Input | Why it matters |
|---|---|
| Treatment definition | Who/what gets the intervention |
| Outcome definition | The metric you want to estimate the effect on |
| Pre/post time periods (DiD) | When did the change occur? |
| Comparison/control group | Who isn't treated? |
| Confounders | Variables that affect both treatment and outcome |
| Mechanism story | Why might treatment cause outcome? |
The treated and control groups would have followed parallel trends in the outcome absent the treatment. Show this by plotting both groups' outcome over time in the pre-period.
import statsmodels.formula.api as smf
# panel data: one row per (unit, period)
model = smf.ols(
formula='outcome ~ treated * post',
data=df
).fit(cov_type='cluster', cov_kwds={'groups': df['unit_id']})
# The coefficient on `treated:post` is the DiD estimatefrom sklearn.linear_model import LogisticRegression
from sklearn.neighbors import NearestNeighbors
# Step 1: fit propensity
p_model = LogisticRegression().fit(df[confounders], df['treated'])
df['propensity'] = p_model.predict_proba(df[confounders])[:, 1]
# Step 2: 1:1 match (treated → nearest control)
treated = df[df['treated'] == 1]
control = df[df['treated'] == 0]
nn = NearestNeighbors(n_neighbors=1).fit(control[['propensity']])
distances, indices = nn.kneighbors(treated[['propensity']])
matched_control = control.iloc[indices.flatten()].reset_index(drop=True)
# Step 3: compute ATT (average treatment effect on the treated)
att = (treated['outcome'].values - matched_control['outcome'].values).mean()Anything affecting both treatment selection AND outcome must be in the confounders list. This is unfalsifiable — you must defend it with domain knowledge.
Examples:
import statsmodels.formula.api as smf
from linearmodels.iv import IV2SLS
# Treatment = f(instrument, controls)
# Outcome = f(predicted_treatment, controls)
model = IV2SLS.from_formula(
'outcome ~ 1 + control_x + [treatment ~ instrument]',
data=df
).fit()# Causal Inference: <treatment> → <outcome>
## Question
What is the causal effect of <treatment> on <outcome>?
## Why not a randomized experiment?
<e.g., feature is already launched, can't randomize at this point>
<e.g., regulatory constraint>
<e.g., ethical reason>
## Method: <DiD | PSM | IV>
- **Rationale:** <why this method fits this question>
- **Critical assumption:** <parallel trends | no unmeasured confounders | exclusion restriction>
- **Defense of assumption:** <evidence and domain reasoning>
## Setup
- Treatment: <definition + when>
- Outcome: <definition + grain>
- Comparison group: <who, why valid>
- Sample: N treated, N control
- Confounders adjusted for: <list>
## Estimated effect
- **Point estimate:** <δ> (units: <e.g., $ per user>)
- **95% CI:** [<low>, <high>]
- **Interpretation:** <plain English what this means>
## Sensitivity checks
- <parallel trends plot — pre-trends look parallel>
- <propensity balance table — covariates balanced after match>
- <first-stage F-stat > 10 for IV>
- <robust to alternative specifications?>
## Caveats
- <causal claim limited to ...>
- <effect estimate applies to ...>
- <what could overturn this finding>
## Decision implications
- <recommendation based on effect size and uncertainty>scripts/did.py — Difference-in-differences with cluster-robust SEs.scripts/psm.py — Propensity score matching with balance diagnostics.ab-test-design / ab-test-analysis — gold standard; use whenever feasiblelinear-regression — non-causal modelinglogistic-regression — propensity scoring underlies PSMstakeholder-readout — package the result with clear caveats~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.