Checks (P4)
- Clean re-run (deleted results.json, table1.csv, figure1.png, exclusions.csv; re-ran analysis.py): results.json byte-identical -> PASS
- Count identity 1200 - 12 removed = 1188 = n_analysed -> PASS
- effect_se > 0 -> PASS
- CIs contain point estimates (effect and naive) -> PASS
- model_metric (1.976) <= baseline_metric (3.860) -> PASS (adjusted model nests the unadjusted one)
- conclusion code consistent with CI (lower bound 0.234 > 0) -> PASS
- Sign flip vs baseline (naive -0.132, adjusted +0.254) explained by confounding: corr(skill, hours)=0.69, skill coefficient -4.62 -> consistent with omitted-variable bias formula direction (positive x negative = negative bias) -> PASS
- Sensitivity: all 1200 rows 0.252; quadratic skill 0.254; (exploratory, not in script) hours x skill interaction -0.0003 (SE 0.006) -> homogeneity not contradicted -> PASS
- Information rule: only data/firms.csv read; skill_index is pre-programme -> PASS
- figure1.png visually inspected: scatter + both lines -> PASS