Cross-Language Replication Check
Level 1 of the verification hierarchy: same specification → same estimate across languages. If two independent implementations disagree, at least one has a bug.
Output Path
Per rules/review-artefact-routing.md (auto-loads in research projects (path-scoped to paper-*/ and paper/)):
- Source slug:
cross-language-check
- Write reports to:
reviews/<scope>/cross-language-check/<YYYY-MM-DD-HHMM>.md inside the project, where <scope> is the paper slug (e.g., paper-jtp) for paper-level checks or _project for project-level checks. Path is relative to the research project root, not the Task-Management repo.
- Never at project root (
./CRITIC-REPORT.md-style filenames are forbidden — pre-rule layout).
- Idempotency: if today's file exists, append a same-day descriptor (
{date}-revision.md, {date}-r2.md, {date}-pre-submission.md) — never overwrite.
- Index update: if
reviews/INDEX.md exists, write a one-line entry under "Latest per source" pointing at the new file. Otherwise review-recap will rebuild the index next time it runs.
- Infrastructure repos (Task-Management, atlas-workspace, etc.): this section does not apply — the path-scoped rule won't load there.
When to Use
- Before submitting a paper with quantitative results
- When you suspect a subtle bug in estimation code
- After refactoring analysis scripts
- As a robustness check that reviewers increasingly expect
- When switching languages for a collaborator
When NOT to Use
- Pure simulation code with no statistical estimation →
computational-experiments
- The analysis is trivial (descriptive stats only) — not worth the overhead
- The source script uses language-specific packages with no equivalent (e.g., bespoke Bayesian MCMC)
Workflow
Phase 1: Parse Source Script
- Read the source script — identify language, packages, estimation calls
- Extract the specification:
- Data loading and cleaning steps
- Variable construction and transformations
- Estimation command(s) with exact formula/model specification
- Standard error clustering, weights, fixed effects
- Sample restrictions and filters
- Identify key outputs — point estimates, standard errors, p-values, confidence intervals, N
- Flag untranslatable elements — language-specific features that may need adaptation (e.g., R formula syntax, Stata factor variables, Python sklearn pipelines)
Phase 2: Choose Target Language
If --target is specified, use that. Otherwise:
| Source |
Default target |
Rationale |
| R |
Python |
Widest package overlap |
| Python |
R |
Strongest econometrics ecosystem |
| Stata |
R |
Both strong on panel/causal methods |
| Julia |
Python |
Closest syntax mapping |
Ask the user to confirm if the default seems wrong for the specific analysis.
Phase 3: Translate
Write the replication script to code/replication/ (or src/replication/):
code/replication/{original_name}_{target_lang}.{ext}
Translation rules:
- Mirror the specification exactly — same formula, same controls, same sample restrictions
- Use equivalent packages (see
shared/multi-language-conventions.md for mappings)
- Match output format — both scripts should produce a CSV with columns:
estimate, se, pvalue, ci_lower, ci_upper, n, model_label
- Document every adaptation — comment blocks explaining where the translation required judgment calls
- Use the same data file — both scripts read from the same cleaned dataset
Phase 4: Run Both & Compare
- Run the source script, capture output CSV
- Run the replication script, capture output CSV
- Comparison thresholds:
| Metric |
Threshold |
Verdict |
| Point estimates |
Differ by < 0.1% |
PASS |
| Point estimates |
Differ by 0.1–1% |
WARN — likely rounding or optimizer differences |
| Point estimates |
Differ by > 1% |
FAIL — investigate |
| Standard errors |
Differ by < 1% |
PASS |
| Standard errors |
Differ by 1–5% |
WARN — check SE type (robust, clustered, HC1 vs HC3) |
| Standard errors |
Differ by > 5% |
FAIL — likely different SE computation |
| Sample size N |
Must be identical |
FAIL if different — data filtering diverged |
- Generate comparison table saved to
code/replication/comparison.md:
| Model | Estimate (source) | Estimate (replica) | Diff (%) | SE (source) | SE (replica) | Diff (%) | N match | Verdict |
Phase 5: Diagnose Discrepancies
If any FAIL or WARN:
- Check N first — if sample sizes differ, the data pipeline diverged (most common source of bugs)
- Check SE type — HC1 vs HC3 vs clustered vs bootstrap defaults differ across languages
- Check optimizer — MLE/GLM may converge to different optima with different starting values
- Check missing value handling —
NA dropping rules differ (R drops per-variable, Stata drops listwise, Python varies)
- Check factor variable encoding — reference category defaults differ across languages
Report the root cause, not just the symptom.
Phase 6: Report
Save to code/replication/cross-language-report.md:
# Cross-Language Replication Report
**Source:** {source_path} ({source_language})
**Replica:** {replica_path} ({target_language})
**Date:** {date}
## Summary
- Models checked: N
- PASS: N | WARN: N | FAIL: N
## Comparison Table
[from Phase 4]
## Discrepancies
[from Phase 5, if any]
## Verdict
[REPLICATED | REPLICATED WITH NOTES | FAILED — action required]
Common Package Mappings
| Task |
R |
Python |
Stata |
Julia |
| OLS + FE |
fixest::feols |
linearmodels.PanelOLS |
reghdfe |
FixedEffectModels.reg |
| IV |
fixest::feols (iv syntax) |
linearmodels.IV2SLS |
ivregress 2sls |
FixedEffectModels.reg |
| DiD |
did::att_gt |
differences |
csdid |
— |
| Clustered SE |
vcov = ~cluster |
cov_type='clustered' |
vce(cluster var) |
Vcov.cluster(:var) |
| Logit/Probit |
glm(family=binomial) |
statsmodels.Logit |
logit |
GLM.jl |
Log to REVIEW-STATE.md (final step)
Write the comparison report to reviews/<scope>/cross-language-check/<YYYY-MM-DD-HHMM>.md (where <scope> is the paper slug for paper-level checks or _project for project-level checks; mkdir -p reviews/<scope>/cross-language-check/ first). Then append a row to the project's REVIEW-STATE.md:
bash <skills-root>/_shared/review-state-log.sh \
--check cross-language-check \
--paper "<paper-{venue} dir, or — for project-level cross-language checks>" \
--verdict "<MATCH|DIVERGENCE>" \
--score "<pass-count>/<total-comparisons>" \
--open-issues "<fail-count>/<total-comparisons>" \
--report "reviews/<scope>/cross-language-check/<YYYY-MM-DD-HHMM>.md" \
--notes "<one-line: e.g. 'all match within tol'; or 'IV SE differs in §4'>" \
[--trigger "pre-submission-report|review-cluster"]
- Verdict: MATCH if every comparison passes (within tolerance); DIVERGENCE if any FAIL.
- Score: PASS count / total comparisons.
- Open issues: FAIL count / total at run time.
- Trigger: pass orchestrator name only if invoked as a sub-agent. Otherwise omit.
Schema: the installed shared resource shared/review-state-schema.md.
Cross-References
| Resource |
When read |
shared/multi-language-conventions.md |
Phase 3 (language-specific style) |
multi-perspective/references/computational-many-analysts.md |
Context (verification hierarchy) |
the code-review agent |
Phase 6 (optionally review both scripts) |
replication-package skill |
After (include both scripts in replication materials) |
1---2name: cross-language-check3description: Replicate a quantitative analysis in a second language (R↔Python↔Stata↔Julia) and compare outputs for implementation errors. Use when an existing empirical result needs independent cross-language verification. Not for reviewing one implementation in place; use $code-suite.4---56# Cross-Language Replication Check78> Level 1 of the verification hierarchy: same specification → same estimate across languages. If two independent implementations disagree, at least one has a bug.910## Output Path1112Per `rules/review-artefact-routing.md` (auto-loads in research projects (path-scoped to `paper-*/` and `paper/`)):1314- **Source slug:** `cross-language-check`15- **Write reports to:** `reviews/<scope>/cross-language-check/<YYYY-MM-DD-HHMM>.md` inside the project, where `<scope>` is the paper slug (e.g., `paper-jtp`) for paper-level checks or `_project` for project-level checks. Path is relative to the research project root, not the Task-Management repo.16- **Never** at project root (`./CRITIC-REPORT.md`-style filenames are forbidden — pre-rule layout).17- **Idempotency:** if today's file exists, append a same-day descriptor (`{date}-revision.md`, `{date}-r2.md`, `{date}-pre-submission.md`) — never overwrite.18- **Index update:** if `reviews/INDEX.md` exists, write a one-line entry under "Latest per source" pointing at the new file. Otherwise `review-recap` will rebuild the index next time it runs.19- **Infrastructure repos** (Task-Management, atlas-workspace, etc.): this section does not apply — the path-scoped rule won't load there.202122## When to Use2324- Before submitting a paper with quantitative results25- When you suspect a subtle bug in estimation code26- After refactoring analysis scripts27- As a robustness check that reviewers increasingly expect28- When switching languages for a collaborator2930## When NOT to Use3132- Pure simulation code with no statistical estimation → `computational-experiments`33- The analysis is trivial (descriptive stats only) — not worth the overhead34- The source script uses language-specific packages with no equivalent (e.g., bespoke Bayesian MCMC)3536## Workflow3738### Phase 1: Parse Source Script39401. **Read the source script** — identify language, packages, estimation calls412. **Extract the specification:**42 - Data loading and cleaning steps43 - Variable construction and transformations44 - Estimation command(s) with exact formula/model specification45 - Standard error clustering, weights, fixed effects46 - Sample restrictions and filters473. **Identify key outputs** — point estimates, standard errors, p-values, confidence intervals, N484. **Flag untranslatable elements** — language-specific features that may need adaptation (e.g., R formula syntax, Stata factor variables, Python sklearn pipelines)4950### Phase 2: Choose Target Language5152If `--target` is specified, use that. Otherwise:5354| Source | Default target | Rationale |55|--------|---------------|-----------|56| R | Python | Widest package overlap |57| Python | R | Strongest econometrics ecosystem |58| Stata | R | Both strong on panel/causal methods |59| Julia | Python | Closest syntax mapping |6061Ask the user to confirm if the default seems wrong for the specific analysis.6263### Phase 3: Translate6465Write the replication script to `code/replication/` (or `src/replication/`):6667```68code/replication/{original_name}_{target_lang}.{ext}69```7071Translation rules:721. **Mirror the specification exactly** — same formula, same controls, same sample restrictions732. **Use equivalent packages** (see `shared/multi-language-conventions.md` for mappings)743. **Match output format** — both scripts should produce a CSV with columns: `estimate`, `se`, `pvalue`, `ci_lower`, `ci_upper`, `n`, `model_label`754. **Document every adaptation** — comment blocks explaining where the translation required judgment calls765. **Use the same data file** — both scripts read from the same cleaned dataset7778### Phase 4: Run Both & Compare79801. Run the source script, capture output CSV812. Run the replication script, capture output CSV823. **Comparison thresholds:**8384| Metric | Threshold | Verdict |85|--------|-----------|---------|86| Point estimates | Differ by < 0.1% | PASS |87| Point estimates | Differ by 0.1–1% | WARN — likely rounding or optimizer differences |88| Point estimates | Differ by > 1% | FAIL — investigate |89| Standard errors | Differ by < 1% | PASS |90| Standard errors | Differ by 1–5% | WARN — check SE type (robust, clustered, HC1 vs HC3) |91| Standard errors | Differ by > 5% | FAIL — likely different SE computation |92| Sample size N | Must be identical | FAIL if different — data filtering diverged |93944. **Generate comparison table** saved to `code/replication/comparison.md`:9596```markdown97| Model | Estimate (source) | Estimate (replica) | Diff (%) | SE (source) | SE (replica) | Diff (%) | N match | Verdict |98```99100### Phase 5: Diagnose Discrepancies101102If any FAIL or WARN:1031041. **Check N first** — if sample sizes differ, the data pipeline diverged (most common source of bugs)1052. **Check SE type** — HC1 vs HC3 vs clustered vs bootstrap defaults differ across languages1063. **Check optimizer** — MLE/GLM may converge to different optima with different starting values1074. **Check missing value handling** — `NA` dropping rules differ (R drops per-variable, Stata drops listwise, Python varies)1085. **Check factor variable encoding** — reference category defaults differ across languages109110Report the root cause, not just the symptom.111112### Phase 6: Report113114Save to `code/replication/cross-language-report.md`:115116```markdown117# Cross-Language Replication Report118119**Source:** {source_path} ({source_language})120**Replica:** {replica_path} ({target_language})121**Date:** {date}122123## Summary124- Models checked: N125- PASS: N | WARN: N | FAIL: N126127## Comparison Table128[from Phase 4]129130## Discrepancies131[from Phase 5, if any]132133## Verdict134[REPLICATED | REPLICATED WITH NOTES | FAILED — action required]135```136137## Common Package Mappings138139| Task | R | Python | Stata | Julia |140|------|---|--------|-------|-------|141| OLS + FE | `fixest::feols` | `linearmodels.PanelOLS` | `reghdfe` | `FixedEffectModels.reg` |142| IV | `fixest::feols` (iv syntax) | `linearmodels.IV2SLS` | `ivregress 2sls` | `FixedEffectModels.reg` |143| DiD | `did::att_gt` | `differences` | `csdid` | — |144| Clustered SE | `vcov = ~cluster` | `cov_type='clustered'` | `vce(cluster var)` | `Vcov.cluster(:var)` |145| Logit/Probit | `glm(family=binomial)` | `statsmodels.Logit` | `logit` | `GLM.jl` |146147## Log to REVIEW-STATE.md (final step)148149Write the comparison report to `reviews/<scope>/cross-language-check/<YYYY-MM-DD-HHMM>.md` (where `<scope>` is the paper slug for paper-level checks or `_project` for project-level checks; `mkdir -p reviews/<scope>/cross-language-check/` first). Then append a row to the project's `REVIEW-STATE.md`:150151```bash152bash <skills-root>/_shared/review-state-log.sh \153 --check cross-language-check \154 --paper "<paper-{venue} dir, or — for project-level cross-language checks>" \155 --verdict "<MATCH|DIVERGENCE>" \156 --score "<pass-count>/<total-comparisons>" \157 --open-issues "<fail-count>/<total-comparisons>" \158 --report "reviews/<scope>/cross-language-check/<YYYY-MM-DD-HHMM>.md" \159 --notes "<one-line: e.g. 'all match within tol'; or 'IV SE differs in §4'>" \160 [--trigger "pre-submission-report|review-cluster"]161```162163- Verdict: MATCH if every comparison passes (within tolerance); DIVERGENCE if any FAIL.164- Score: PASS count / total comparisons.165- Open issues: FAIL count / total at run time.166- Trigger: pass orchestrator name only if invoked as a sub-agent. Otherwise omit.167168Schema: the installed shared resource `shared/review-state-schema.md`.169170## Cross-References171172| Resource | When read |173|----------|-----------|174| `shared/multi-language-conventions.md` | Phase 3 (language-specific style) |175| `multi-perspective/references/computational-many-analysts.md` | Context (verification hierarchy) |176| the `code-review` agent | Phase 6 (optionally review both scripts) |177| `replication-package` skill | After (include both scripts in replication materials) |