04-constraint-patterns
Derived from 271 merged PRs in the ALARM fifty-states redistricting project.
> /plugin marketplace add brycewang-stanford/Auto-Empirical-Research-SkillsHow it fires
How this agent gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
Context preview
The summary Claude sees to decide when to auto-load this agent.
Derived from 271 merged PRs in the ALARM fifty-states redistricting project.
Agent definition
04-constraint-patterns.mdConstraint Pattern Reference
Derived from 271 merged PRs in the ALARM fifty-states redistricting project.
---
Equal Population
**Legal basis:** Federal constitutional requirement; all congressional plans. State law for state legislative.
**Encoding:**
# Set in redist_map() — not a separate constraint
map <- redist_map(shp, existing_plan = cd_2020, pop_tol = 0.005)
**Typical tolerance:** 0.005 (0.5%) for congressional; some states stricter:
- Indiana, Tennessee, Washington: 0.0005–0.001 (strict enacted plans)
- Minnesota: 0.001
- Iowa: 0.0001 (statutory)
**Calibration:** When SMC acceptance rates drop quickly in final splits, increase `pop_temper` by 0.01 (e.g., from 0 to 0.01). Do not go above 0.05–0.06 without strong justification. Higher `pop_temper` trades strict equality for better mixing.
**Common mistakes:**
- Confusing `pop_tol` (tolerance for map object) with `pop_temper` (SMC sampling parameter)
- Loading data from wrong census year → apparent 10%+ deviations
- Utah: state law defines 1% *total range*, implying `pop_tol = 0.005` (not 0.01 or 0.0005)
---
Contiguity
**Legal basis:** Required in all states.
**Encoding:** Enforced by redist's sampling algorithm. The prep stage must ensure a valid connected adjacency graph.
# In 01_prep: modify adjacency graph
adj <- geomander::get_adjacent(shp)
# Remove non-contiguous edges (e.g., across water/mountains)
adj <- geomander::subtract_edge(adj, which(shp$GEOID == "A"), which(shp$GEOID == "B"))
# Add edges for physically connected but non-adjacent units (e.g., ferry routes, bridges)
adj[[i]] <- c(adj[[i]], j)
adj[[j]] <- c(adj[[j]], i)
**State-specific patterns:**
- **Oregon:** Remove edges between counties not connected by a state or federal highway (Or. Rev. Stat. § 188.010)
- **Washington:** Remove edges across water barriers; reconnect via ferry/bridge/highway
- **Maryland/Michigan:** Remove water-area precincts from adjacency; connect islands to nearest land precinct in same county
- **Hawaii:** Islands manually connected (does not affect simulation contiguity, only for visualization)
- **Multi-island states:** Remove offshore/island tracts; reallocate population to nearest mainland precinct
**Calibration:** Binary — either the graph is valid or it isn't. Run `check_plans_piece_contiguity()` after simulation to verify. Document all adjacency modifications in `01_prep_*.R`.
**Common mistakes:**
- Disconnected precincts from water bodies create infeasible plans
- Bay areas (e.g., Chesapeake): use `subtract_edge()` on both sides of the bay
- Using polygon adjacency instead of piece-level adjacency → false negatives for slivers
---
County/Municipality Preservation (Pseudocounty Constraint)
**Legal basis:** Most states require avoiding splits "where practicable" or "to the extent possible."
**Encoding:** Create pseudocounties that group units, then use as the county constraint unit:
# In 02_setup: build pseudocounties
# Counties larger than the district target are split into per-municipality units
pseudo_county <- pick_county_muni(
map,
counties = county,
munis = muni,
pop_muni = get_target(map) # split counties larger than one district
)
# In 03_sim: use in SMC
cons <- redist_constr(map) |>
add_constr_splits(strength = 1.5, admin = pseudo_county)
**Logic:** Counties whose population exceeds the district population target are split into pseudocounties, where each municipality becomes its own unit. Counties below the target remain whole.
**State examples:**
- Illinois: Cook + DuPage counties → each municipality as pseudocounty; all other counties whole
- Pennsylvania: Allegheny, Montgomery, Philadelphia → per-municipality; others whole
- California: ~15 large counties split; remainder treated as county units
- Oklahoma: Oklahoma County → municipalities; all others whole
- Rhode Island: State senate districts used as pseudocounties (statutory boundary requirement)
- Iowa: County + municipal boundaries both enforced (strict statutory requirement)
**County constraint only (no pseudocounties):** Maine, Idaho, Kansas, Nevada, Nebraska (smaller states where no county exceeds district target).
**Calibration:**
- County constraint `strength = 2.0` is the typical sweet spot; test 2.5 and 3.0 if needed
- Strength > 2.5 often causes R-hat values > 1.05 (convergence failure)
- The pseudocounty approach produces fewer municipality splits than a raw county constraint
**Common mistakes:**
- Creating pseudocounties in `02_setup` but forgetting to use `pseudo_county` instead of `county` in `03_sim`
- Not documenting which counties triggered the pseudocounty split in `doc_*.md`
- Stating "no special techniques" when pseudocounties are actually in use
---
Compactness
**Legal basis:** Many states require "geographically compact" districts. Not always encoded as an active constraint.
**Encoding:** Measured post-hoc; seldom constrained directly:
# Validation metrics tracked automatically in summary(plans):
# comp_edge — edge compactness
# comp_polsby — Polsby-Popper compactness
# If compactness constraint needed (rare):
cons <- cons |>
add_constr_compactness(strength = 0.8) # weaken for small/constrained states
**Calibration:**
- Default compactness weight = 1.0; weaken to 0.8–0.9 for small states (Maine) where geographic constraints already limit options
- Iowa requires two statutory compactness measures; verify both pass
- If reviewer flags low compactness: try increasing `rho` parameter in redist_smc(), or weaken other constraints that may be forcing irregular shapes
**Common mistakes:**
- Treating compactness as a hard constraint when state law only requires it "where practicable"
- Leaving Iowa-specific compactness code in another state's files
---
Voting Rights Act / Majority-Minority Districts
**Legal basis:** Federal VRA §2; some states have additional minority representation requirements.
**Encoding:** Hinge Gibbs constraints encouraging minor
Read more
Constraint Pattern Reference
Derived from 271 merged PRs in the ALARM fifty-states redistricting project.
---
Equal Population
**Legal basis:** Federal constitutional requirement; all congressional plans. State law for state legislative.
**Encoding:**
# Set in redist_map() — not a separate constraint map <- redist_map(shp, existing_plan = cd_2020, pop_tol = 0.005)
**Typical tolerance:** 0.005 (0.5%) for congressional; some states stricter:
- Indiana, Tennessee, Washington: 0.0005–0.001 (strict enacted plans)
- Minnesota: 0.001
- Iowa: 0.0001 (statutory)
**Calibration:** When SMC acceptance rates drop quickly in final splits, increase `pop_temper` by 0.01 (e.g., from 0 to 0.01). Do not go above 0.05–0.06 without strong justification. Higher `pop_temper` trades strict equality for better mixing.
**Common mistakes:**
- Confusing `pop_tol` (tolerance for map object) with `pop_temper` (SMC sampling parameter)
- Loading data from wrong census year → apparent 10%+ deviations
- Utah: state law defines 1% *total range*, implying `pop_tol = 0.005` (not 0.01 or 0.0005)
---
Contiguity
**Legal basis:** Required in all states.
**Encoding:** Enforced by redist's sampling algorithm. The prep stage must ensure a valid connected adjacency graph.
# In 01_prep: modify adjacency graph adj <- geomander::get_adjacent(shp) # Remove non-contiguous edges (e.g., across water/mountains) adj <- geomander::subtract_edge(adj, which(shp$GEOID == "A"), which(shp$GEOID == "B")) # Add edges for physically connected but non-adjacent units (e.g., ferry routes, bridges) adj[[i]] <- c(adj[[i]], j) adj[[j]] <- c(adj[[j]], i)
**State-specific patterns:**
- **Oregon:** Remove edges between counties not connected by a state or federal highway (Or. Rev. Stat. § 188.010)
- **Washington:** Remove edges across water barriers; reconnect via ferry/bridge/highway
- **Maryland/Michigan:** Remove water-area precincts from adjacency; connect islands to nearest land precinct in same county
- **Hawaii:** Islands manually connected (does not affect simulation contiguity, only for visualization)
- **Multi-island states:** Remove offshore/island tracts; reallocate population to nearest mainland precinct
**Calibration:** Binary — either the graph is valid or it isn't. Run `check_plans_piece_contiguity()` after simulation to verify. Document all adjacency modifications in `01_prep_*.R`.
**Common mistakes:**
- Disconnected precincts from water bodies create infeasible plans
- Bay areas (e.g., Chesapeake): use `subtract_edge()` on both sides of the bay
- Using polygon adjacency instead of piece-level adjacency → false negatives for slivers
---
County/Municipality Preservation (Pseudocounty Constraint)
**Legal basis:** Most states require avoiding splits "where practicable" or "to the extent possible."
**Encoding:** Create pseudocounties that group units, then use as the county constraint unit:
# In 02_setup: build pseudocounties # Counties larger than the district target are split into per-municipality units pseudo_county <- pick_county_muni( map, counties = county, munis = muni, pop_muni = get_target(map) # split counties larger than one district ) # In 03_sim: use in SMC cons <- redist_constr(map) |> add_constr_splits(strength = 1.5, admin = pseudo_county)
**Logic:** Counties whose population exceeds the district population target are split into pseudocounties, where each municipality becomes its own unit. Counties below the target remain whole.
**State examples:**
- Illinois: Cook + DuPage counties → each municipality as pseudocounty; all other counties whole
- Pennsylvania: Allegheny, Montgomery, Philadelphia → per-municipality; others whole
- California: ~15 large counties split; remainder treated as county units
- Oklahoma: Oklahoma County → municipalities; all others whole
- Rhode Island: State senate districts used as pseudocounties (statutory boundary requirement)
- Iowa: County + municipal boundaries both enforced (strict statutory requirement)
**County constraint only (no pseudocounties):** Maine, Idaho, Kansas, Nevada, Nebraska (smaller states where no county exceeds district target).
**Calibration:**
- County constraint `strength = 2.0` is the typical sweet spot; test 2.5 and 3.0 if needed
- Strength > 2.5 often causes R-hat values > 1.05 (convergence failure)
- The pseudocounty approach produces fewer municipality splits than a raw county constraint
**Common mistakes:**
- Creating pseudocounties in `02_setup` but forgetting to use `pseudo_county` instead of `county` in `03_sim`
- Not documenting which counties triggered the pseudocounty split in `doc_*.md`
- Stating "no special techniques" when pseudocounties are actually in use
---
Compactness
**Legal basis:** Many states require "geographically compact" districts. Not always encoded as an active constraint.
**Encoding:** Measured post-hoc; seldom constrained directly:
# Validation metrics tracked automatically in summary(plans): # comp_edge — edge compactness # comp_polsby — Polsby-Popper compactness # If compactness constraint needed (rare): cons <- cons |> add_constr_compactness(strength = 0.8) # weaken for small/constrained states
**Calibration:**
- Default compactness weight = 1.0; weaken to 0.8–0.9 for small states (Maine) where geographic constraints already limit options
- Iowa requires two statutory compactness measures; verify both pass
- If reviewer flags low compactness: try increasing `rho` parameter in redist_smc(), or weaken other constraints that may be forcing irregular shapes
**Common mistakes:**
- Treating compactness as a hard constraint when state law only requires it "where practicable"
- Leaving Iowa-specific compactness code in another state's files
---
Voting Rights Act / Majority-Minority Districts
**Legal basis:** Federal VRA §2; some states have additional minority representation requirements.
**Encoding:** Hinge Gibbs constraints encouraging minor
📌 文档结构(2026-07-22 起): 本文件是中文默认入口 —— banner + badges + 信任面 + 9 阶段流水线速览 + 76 行合集总表。 每个合集的完整描述、按用途分组、精确数字、验证方法在 docs/CONTENT_ZH.md(扩展正文,总表行内的 → 直接跳转到对应锚点)。 English version: README-en.md · 中文扩展正文:docs/CONTENT_ZH.md · README-zh-CN.md 已弃用(重定向占位) 🌐 语言: English |
Other agents on auto-empirical-research-skills.
- data-detective
Investigates data quality, profiling datasets for distributional anomalies, missingness patterns, panel structure, merge diagnostics, and variable construction issues. Use when working with a new dataset, validating merges, checking panel structure, profiling variables for
Open agent - literature-scout
Conducts systematic literature surveys of econometric methods, seminal papers, and prior applications. Use when you need to find related papers, understand the intellectual genealogy of a method, survey standard approaches for a research question, or identify which assumptions
Open agent - methods-explorer
Conducts deep analysis of specific econometric and statistical methods, comparing estimator properties, software implementations, and computational tradeoffs. Also researches benchmark parameter values, calibration targets, and stylized facts from the literature. Use when
Open agent - econometric-reviewer
Reviews estimation code with an extremely high quality bar for identification, inference, and econometric correctness. Use after implementing estimation routines, modifying econometric models, running regressions, or writing code that uses statsmodels, linearmodels, PyBLP,
Open agent - identification-critic
--- name: identification-critic effort: high maxTurns: 15 skills: [causal-inference, identification-proofs, game-theory, structural-modeling] disallowedTools: [Edit, Write, MultiEdit, NotebookEdit] description: >- Scrutinizes identification arguments for completeness,
Open agent - journal-referee
Simulates a top-5 economics journal referee providing a full report on research quality, contribution, and methodology. Use when reviewing draft papers, written artifacts, research projects before submission, or during /workflows:review on completed work. <examples> <example>
Open agent

