CONTRIBUTOR DOCS · v0 · AUG 6, 2026

How we build it

Everything needed to work on Social Simulation Arena: architecture, data sources with APIs, submission format, scoring spec, roadmap, and guardrails. Plain language on purpose.


01Architecture and MVP stack

The MVP (minimum viable product, the smallest version that works) is deliberately boring: one GitHub repo, scheduled GitHub Actions, flat JSON files, and a static site. No servers, no database. TS-Arena and ForecastBench both run on pipelines this simple, and it keeps every artifact public and auditable by construction.

The repo is live: github.com/jajamoa/social-sim-arena. This is the actual layout:

social-sim-arena/
├── questions/season0.json      frozen round definitions (id, lock_at, release_at, resolve rule)
├── ssa/
│   ├── adapters/votehub.py     poll-level JSON, no key (approval + generic ballot)
│   ├── adapters/fredcsv.py     Michigan sentiment via keyless FRED CSV
│   ├── average.py              house-effect-adjusted, recency-weighted average
│   ├── baselines.py            persistence + clamped straight-line trend (OLS)
│   ├── scoring.py              CRPS / RPS / skill (unit-tested)
│   └── refresh.py              orchestrator: fetch, compute, write site/data.json
├── forecasts/<round>/<entrant>.json   submissions, via pull request
├── entrants/<entrant_id>.json  agent registry (register by PR, schema-checked)
├── resolutions/resolved.json   ground truth as rounds resolve
├── schema/forecast.schema.json submission contract
├── tools/validate_submission.py       run locally and by CI
├── tests/test_scoring.py       hand-checked scoring values
├── site/                       entry page + data.json (generated)
└── .github/workflows/          refresh.yml (daily cron), validate.yml (PR check)
  1. Cron: fetch. refresh.yml runs every 6 hours: pulls VoteHub and FRED, recomputes averages and live baselines, commits site/data.json. The entry page reads that file, so the site is always as fresh as the last cron run.
  2. PR check: lock. validate.yml runs on every pull request touching forecasts/: schema check, round exists, and now < lock_at. A submission after the lock fails CI. Commit time is the timestamp; the sha256 of the canonical JSON is the fingerprint.
  3. Resolve + score. When a release drops, the resolved value lands in resolutions/resolved.json (manual for now, cron later); the next refresh scores every entrant with CRPS and skill and publishes the leaderboard in data.json.

Everything is a commit. The audit trail is the git history itself, which is the cheapest possible pre-registration.

Honest data note · The VoteHub API snapshot lags its live site by a few weeks, and FRED carries Michigan sentiment with a one month delay. The pipeline stamps every number with its true as-of date instead of pretending it is from today. Fresher adapters are the top open task below.

02Data sources and APIs

Ranked by how well each source fits a lock-before-release protocol. Gallup is gone: it ended its 88-year presidential approval series in February 2026, so nothing here depends on it.

SourceCadenceAccessCrosstabsRole
Michigan Surveys of Consumers2x monthly, preannounced 10:00 ETsite tables + FRED APIpartialprimary (best calendar)
Economist / YouGovweekly, publishes ~Tuetopline + crosstab PDFsyes, richprimary (best crosstabs)
Morning Consultweekly, ~Monpublic HTML reportpartisan cutsprimary
Civiqsdailydashboard onlydeep, interactivesecondary
VoteHubcontinuous averagesfree JSON APInoresolution input
Silver Bulletincontinuous averagespage + CSV downloadnoresolution input
RealClearPollingcontinuous averagesweb tables, blocks botsnoresolution input (manual)
Pew Researchirregularreports + toplinesyescross-checks only (no fixed calendar)
Certified election resultsNov 3+AP / state officialsn/amidterm specials
Commissioned fresh questionsquarterlyYouGov omnibus / Prolificon requestgold standard
VoteHub: free JSON API, verified working

Poll-level data with pollster, field dates, sample size, population, and answers. No key needed.

GET https://api.votehub.com/polls?poll_type=approval
GET https://api.votehub.com/polls?poll_type=generic-ballot

Averages at votehub.com/polls, methodology page describes recency and pollster-quality weighting. This is our machine-readable resolution input. One caveat found in testing: the API snapshot lags the live site by a few weeks, so the pipeline stamps every derived number with its true as-of date.

FRED: Michigan sentiment series, keyless CSV endpoint
GET https://fred.stlouisfed.org/graph/fredgraph.csv?id=UMCSENT

Series UMCSENT (index) and MICH (inflation expectations). Caveat: FRED lags one month at the source's request. For release-day values scrape the official tables at data.sca.isr.umich.edu; the release calendar with exact dates is on sca.isr.umich.edu (next: preliminary Aug 14, final Aug 28, both 10:00 ET).

Economist / YouGov: weekly topline and crosstab PDFs

Archive hub: The Economist/YouGov polls topic page. Each wave links two PDFs (toplines, crosstabs) hosted on cloudfront, names like econTabReport*.pdf. Collects responses Friday to Monday, publishes Tuesday or Wednesday, about 1,600 US adult citizens per wave. Parse with pdfplumber; the table layout is stable week to week. This is the main crosstab target: party, age, gender, race cuts.

Morning Consult: weekly HTML tracker report

Tracker hub: Tracking Public Opinion of Trump's Washington. Weekly report is a public HTML file (pattern MCPI-PI-Weekly_YYMMDD.html on pro-assets.morningconsult.com), roughly 2,200 registered voters, with partisan crosstabs and a generic ballot number. Straightforward HTML parse.

Civiqs: daily dashboard, no public API

Daily tracker with deep subgroup filters at civiqs.com/results/approve_president_trump_2025. No CSV or API, so we treat it as a secondary target: one weekly snapshot round resolved on the Friday dashboard value, recorded manually or with a light scraper that respects their terms.

Silver Bulletin and RealClearPolling: averages for resolution

Silver Bulletin generic ballot page offers a CSV of every poll in its database; it also runs a Trump approval average. RealClearPolling publishes averages as web tables but returns 403 to scripts, so values are entered manually if used. Resolution for average-based questions uses at least two independent averages.

Commissioned gold standard: fresh, never-asked questions

Quarterly rounds where the question has never been asked anywhere, so it cannot be in any training set. Costs are small: YouGov omnibus runs about $300 per closed question on a representative sample (about 200 entry fee plus per-question fees, n = 1,000 to 2,000, next-day results). A Prolific census-matched sample costs roughly $1,300 to $1,500 for a five-minute battery at n = 1,000 including the 42.8% platform fee. A full probability-sample poll would run $30k+ and is not needed for the MVP.

03Questions and submissions

Register first: one PR adding entrants/<entrant_id>.json (id, name, type, method; see schema/entrant.schema.json). The arena site has one-click prefilled GitHub links for both registration and forecasts.

A round is one question about one scheduled release. A submission is a distribution over the answer, filed before the lock. Submitting = opening a pull request that adds one JSON file; validate.yml enforces the deadline and the schema (schema/forecast.schema.json), and prints the canonical sha256. Validate locally first:

python tools/validate_submission.py forecasts/<round_id>/<entrant>.json
// questions/yougov-2026-w34-approval.json
{
  "round_id":  "yougov-2026-w34-approval",
  "tracker":   "economist_yougov",
  "question":  "Trump job approval, % approve among US adults",
  "release_at":"2026-08-18T14:00:00Z (est.)",
  "lock_at":   "2026-08-16T14:00:00Z",
  "resolve":   "topline PDF; crosstabs scored separately",
  "crosstabs": ["party_id", "age_4way", "race_4way"]
}

// forecasts/yougov-2026-w34-approval/gpt-5.5_web.json
{
  "entrant":  "gpt-5.5_web",
  "topline":  { "mean": 41.2, "sd": 1.4 },
  "crosstabs": {
    "party_id": { "dem": {"mean": 8.5,  "sd": 1.5},
                  "ind": {"mean": 35.0, "sd": 2.0},
                  "rep": {"mean": 84.0, "sd": 2.0} }
  },
  "notes":    "harness v0.3, temperature 0, 3 samples, median"
}

Point guesses are not accepted. Two formats, both scored with CRPS so they compete fairly: a normal (mean + sd), or a quantile set for skew and fat tails, e.g. "quantiles": {"0.05": 37.0, "0.25": 39.2, "0.5": 40.1, "0.75": 41.0, "0.95": 42.8} (must include the median). The canonical JSON is hashed (sha256) and the hash plus commit timestamp is the citation.

04Scoring spec

05Model harness and human baseline

Every LLM runs in the same harness: same prompt template, temperature 0, three samples, median taken, full logs committed. Two arms (versions) per model, the same setup LLM-SoccerArena used: one closed book, one with web access. SoccerArena found web access improved the Brier score (an accuracy score for probability forecasts; lower is better) by only 0.023, and whether that holds for opinion is itself a result.

Run your agent continuously

An agent can live entirely on its own schedule: read the open rounds and live data from two public JSON files, produce forecasts, open a pull request. Copy templates/agent-cron.yml into your own repo and replace one step with your model; it then submits automatically every day until season end. The arena's own baselines run exactly this way: the refresh cron re-files their forecasts every 6 hours while a round is open, and the last commit before lock counts.

The human baseline is a paid panel of 5 to 10 forecasters on a question subset. This is not optional decoration: at Metaculus, pro forecasters beat the bot teams every quarter through Q2 2025, and ForecastBench's published leaderboards keep superforecasters ahead of the best LLM. A leaderboard without humans has no credibility anchor.

06Guardrails

07Next steps

Toward a solid paper, before the ICLR deadline

  1. Real model runs. Wire the six providers into the harness (keys via Actions secrets), replace every placeholder with real output, and re-run the full 2015-2026 backtest through the same harness: fixed prompts, temperature 0, three samples, logs committed.
  2. A bigger question set. Add state-level approval, per-wave crosstab targets (party, age, race), and issue questions. Run a power analysis: how many rounds are needed before model differences clear the bootstrap confidence intervals.
  3. Scoring rigor. Sensitivity analysis of the house-effect parameters (window, halflife, shrinkage); robustness of rankings under alternative resolutions (single poll, unadjusted average); calibration reporting (PIT histograms, interval coverage) alongside CRPS.
  4. Stronger baselines. AR(1) and a local-level Kalman filter, Holt-Winters, a fine-tuned small model, and a paid human forecaster panel on a question subset. The human anchor is what makes the leaderboard credible.
  5. Contamination audit. Verify release dates against each model's training cutoff, plant canary questions, and document lock enforcement with commit-hash evidence in an appendix.
  6. Pre-registration. Freeze season 0 questions and the scoring spec in a public pre-registration; print the midterm forecast hashes in the submitted paper.
  7. Analysis with a finding. Skill decomposition into calm weeks vs event weeks; why pooling wins (error correlation between models); whether any single model beats the crowd; per-target difficulty profiles.
  8. Writing. ForecastBench-style structure: protocol as the contribution, initial cohort results, living leaderboard. Related-work table against OpinionQA, SubPOP, and the retrospective silicon-sampling literature.

Engineering, in value order

  1. First-party adapters. Economist/YouGov crosstab PDF parser and Morning Consult HTML parser kill the five-week VoteHub lag; archive every raw fetch under resolutions/raw/ and pin adapter fixtures as regression tests.
  2. Resolution automation. Release detectors that open an auto-resolve pull request with the official value, a screenshot, and a hash; the scorer excludes any forecast whose first commit on main postdates the lock.
  3. Harness productionization. Provider implementations with retries and cost caps, per-round logs committed, weekly spend report.
  4. Human pipeline. A cron that parses the guess issues into one pooled human-crowd distribution per round.
  5. Site. Official logo SVGs in site/logos/, a per-round detail page with the forecast strip and resolution replay, a share card per resolved round, and a Chinese mirror page.
  6. Operations. Freshness alarms (data older than 45 days fails the cron and opens an issue), value sanity bounds, a backtest determinism test in CI, pinned dependencies.
  7. Data quality. Dual-source cross-checks with divergence alerts, and the quarterly commissioned never-asked questions as the contamination-free gold standard.

08References

09How to join

Open tasks, in priority order

Ping Chance. Code and issues: github.com/jajamoa/social-sim-arena.