3192a1a2bf2f10131ee5100125dd228b7f90a2a3
CRIT-1: Stylistic extremity direction reversed — both dimensions declined (stijl 1.875→1.744, not increased +0.097). Holistic moderation, not divergence. CRIT-2: Masking rate corrected from 36.1% to 9.7% (S≤2, M≥4 on full dataset). Original 36.8% was from 117-motion manual audit, not extrapolatable. CRIT-3: Material impact values harmonized to motion-level means (2.79→2.45). Old values (2.78→2.43) used undisclosed mean-of-yearly-means aggregation. HIGH-1: Migration domain provenance caveat — category column is NULL, analysis relies on title keyword matching (approximate boundaries). HIGH-2: 2026-Q2 bounce caveat — n=44, bimodal distribution, sensitive to composition (many consensus defense motions among CS=1.0 items). HIGH-3: Non-right-wing control group corrected — CS rose 58%→62% (+3.5pp), not 'flat at 49%'. Surge was disproportionate for right-wing content. Also: fixed 6-party centrist definition (line 30) to 4-party, removed 'did not shift rightward' phrasing, added Phase 4 synthesis reminder to build_all_reports.py.
Stemwijzer
A Dutch parliamentary voting compass that lets you vote on real Tweede Kamer motions and see which parties match your positions.
What is Stemwijzer?
Stemwijzer ingests motions and voting records from the Dutch House of Representatives (Tweede Kamer), stores them in DuckDB, generates AI-powered explanations with an LLM, and presents a Streamlit UI where users can vote on real motions and explore party positions through SVD visualizations, trajectory analysis, and embedding-based similarity search.
Features
- Voting Compass — Vote on real parliamentary motions and see which parties align with your choices
- Explorer — Interactive SVD visualizations, party trajectories over time, motion browser, and semantic search
- Analytics — SVD decomposition of voting patterns, UMAP projections, clustering, and drift analysis
- LLM Enrichment — Automatic generation of layman-friendly motion explanations using QWEN via OpenRouter
- Overton Window Analysis — Quantitative analysis of whether the Dutch parliamentary center has shifted rightward, using centrist voting support, SVD spatial drift, 2D extremity scoring, and mechanism classification
Prerequisites
- Python >= 3.13
- uv for dependency management
- (Optional)
OPENROUTER_API_KEYfor LLM enrichment
Quickstart
# Clone and enter the repository
git clone <your-gitea-url>/sgeboers/stemwijzer.git
cd stemwijzer
# Install dependencies
uv sync
# Run the Streamlit app
uv run streamlit run Home.py
# Run the data pipeline (fetch motions, compute embeddings, etc.)
uv run python pipeline/run_pipeline.py
# Run tests
uv run pytest tests/ -q
The app will be available at http://localhost:8501.
Project Structure
├── app.py # Streamlit UI entrypoint
├── database.py # DuckDB schema and queries
├── api_client.py # Tweede Kamer OData API client
├── explorer.py # Explorer page with SVD visualizations
├── pipeline/ # Data ingestion and analysis pipelines
├── analysis/ # SVD, clustering, trajectory, right-wing motion analysis
├── tests/ # pytest test suite
├── docs/ # Documentation, research, and plans
└── data/motions.db # DuckDB database (~18 GB)
Documentation
- ARCHITECTURE.md — Comprehensive architecture overview, tech stack, and contributor guidance
- CODE_STYLE.md — Coding conventions, naming, typing, and testing standards
- docs/solutions/ — Documented solutions to past bugs and best practices
Research
- Overton Window Article — Interactive article: "Has the Dutch Overton window shifted?" with Plotly charts (render with
quarto render) - Overton Synthesis — Detailed synthesis of all indicators and the "acceptance through moderation" verdict
- Overton Reports — 13 appendix reports covering breakpoint analysis, SVD drift, 2D extremity, mechanisms, and more (reading guide)
- Overton Dashboard — Standalone HTML report with gravity-controlled charts and example motions
Tech Stack
- Language: Python 3.13+
- Data: DuckDB via ibis-framework
- UI: Streamlit + Plotly
- ML/Analysis: scipy, scikit-learn, umap-learn
- LLM: QWEN via OpenRouter (OpenAI-compatible)
- Package Manager: uv
License
[Your license here]
Languages
HTML
96.7%
Python
3.2%
