feat(explorer): apply rigorous subagent-produced SVD axis themes

Replace draft SVD_THEMES with themes produced by per-axis analysis of all
10 unique top motions (zero cross-axis overlap, window=2025). Each axis now
has a detailed Dutch-language explanation, positive_pole and negative_pole
labels, displayed as colour-coded columns in the UI.
main
Sven Geboers 1 month ago
parent b85a9cebd7
commit c96c681641
  1. 171
      explorer.py

@ -630,97 +630,156 @@ def build_svd_components_tab(db_path: str) -> None:
for components 1..10 with theme labels/explanations and a detail pane per motion.
"""
# Political polarisation themes per SVD component (1-indexed, window=2025)
# Produced by per-axis analysis of all 10 unique top motions (zero cross-axis overlap).
SVD_THEMES: dict[int, dict[str, str]] = {
1: {
"label": "Regulering vs. status-quo",
"label": "Constructief coalitiebeleid versus radicale PVV-migratiepolitiek",
"explanation": (
"Deze as onderscheidt moties die inzetten op nieuwe regelgeving en "
"handhaving (kansspelen, EU-harmonisatie, parlementaire procedures) van moties "
"die eerder kiezen voor continuïteit of deregulering. "
"Positieve scores wijzen op meer reguleringsbereidheid."
"Deze as scheidt brede, constructieve coalitiemoties (CDA, VVD, NSC, CU, D66, GL-PvdA) "
"over uiteenlopende beleidsterreinen — van zorg en defensie tot multilateralisme en "
"digitale inclusie — van de harde PVV-motie die onmiddellijke uitzetting van Syriërs "
"en Oekraïense mannen eist. De positieve pool vertegenwoordigt het brede parlementaire "
"midden dat procedureel en inhoudelijk samenwerkt, terwijl de negatieve pool de "
"isolationistische en radicaal-nationalistische positie van de PVV symboliseert. "
"Deze dimensie is politiek betekenisvol omdat zij de kloof blootlegt tussen mainstream "
"coalitiepolitiek en populistisch-nationalistisch obstructionisme op het vlak van migratie."
),
"positive_pole": "Breed coalitiebeleid: zorg, defensie, multilateralisme, inclusie",
"negative_pole": "Radicale PVV-eis tot onmiddellijke uitzetting migranten",
},
2: {
"label": "Progressief activisme vs. pragmatisch bestuur",
"label": "Nationalistisch migratiebeleid versus progressief internationaal solidariteitsdenken",
"explanation": (
"De tweede as capteert het spanningsveld tussen linkse-progressieve eisen "
"(Israël-sancties, stikstofminister wantrouwen, klimaatrechtszaken) en "
"pragmatisch bestuur. Negatieve scores corresponderen met progressief-activistische "
"moties; positieve scores met de bestuurspragmatische kant."
"Deze as weerspiegelt de spanning tussen een nationalistisch-conservatieve koers "
"(PVV, BBB, JA21, NSC) die inzet op asielbeperking en nationaal belang, versus een "
"links-progressieve koers (SP, PvdD, DENK, GroenLinks) die internationale solidariteit, "
"reproductieve rechten, LHBT+-zorg en bescherming van minderheden centraal stelt. "
"Moties aan de positieve kant beperken asielzoekers en verdedigen nationaal belang "
"tegenover EU-druk, terwijl moties aan de negatieve kant Israëlisch optreden veroordelen, "
"Gazaanse slachtoffers helpen, abortus en PrEP vergoeden, en moslims beschermen tegen "
"discriminatie. Dit is een van de meest fundamentele breuken in de huidige Nederlandse politiek."
),
"positive_pole": "Asielbeperking, nationaal belang, restrictief migratiebeleid",
"negative_pole": "Pro-Palestina, progressieve zorgrechten, anti-discriminatie minderheden",
},
3: {
"label": "Eigendomsvrijheid en soevereiniteit vs. staatssturing",
"label": "Humanitaire solidariteit en inclusie versus nationalistische handhaving en deregulering",
"explanation": (
"De sterkste as in het stempatroon (hoogste absolute scores). Hij stelt "
"het recht op vrije keuze van de eigenaar en nationale/individuele soevereiniteit "
"tegenover overheidsinterventie (woningmarkt, detentiebeleid, NGO-regulering). "
"Negatieve scores vertegenwoordigen een voorkeur voor eigendomsvrijheid; "
"positieve scores voor staatssturing."
"Deze as scheidt partijen die inzetten op internationale humanitaire solidariteit "
"(sanctieverlichting Syrië, medische evacuatie Gazaanse kinderen), sociale inclusie "
"(gelijke financieringstoegang) en pragmatische justitie (slimmer straffen) van partijen "
"die pleiten voor strikte strafuitvoering, deregulering via afschaffing nationale koppen, "
"beperking van ngo's in het migratiebeleid en bescherming van eigendomsvrijheid zonder "
"discriminatieregels. De uitzonderlijk grote scoremagnitudes (±11,7) duiden op een "
"bijzonder scherpe polarisatie, waarbij links-progressieve en christelijk-sociale partijen "
"(SP, D66, GL, DENK, CU, PvdA, CDA, NSC) tegenover rechts-nationalistisch georiënteerde "
"partijen (PVV, BBB, VVD-rechtsflank, JA21) staan."
),
"positive_pole": "Internationale solidariteit, inclusie en pragmatische overheidsinterventie",
"negative_pole": "Strikte handhaving, deregulering en nationalistisch eigenbelang boven humanitaire verplichtingen",
},
4: {
"label": "Betaalbaarheid publieke diensten vs. vrijhandel",
"label": "Publieke voorzieningen beschermen versus liberale marktwerking",
"explanation": (
"Deze as weerspiegelt het debat over betaalbare zorg, openbaar vervoer en "
"defensie-infrastructuur (positief) tegenover internationale handelsakkoorden "
"zoals EU-Mercosur (negatief). Het scheidt partijen die nationale "
"dienstverlening centraal stellen van partijen die vrijhandel prioriteren."
"Deze as weerspiegelt de klassieke sociaal-economische tegenstelling tussen links en "
"liberaal-economisch rechts. Aan de positieve kant staan moties van SP en DENK die "
"pleiten voor betaalbare zorg, lage treintarieven, bescherming van politiepersoneel en "
"regionale brandweerposten — allemaal gericht op het beschermen van publieke voorzieningen "
"voor gewone burgers. Aan de negatieve kant staan moties van VVD, D66, Volt en NSC die "
"pleiten voor het EU-Mercosur vrijhandelsverdrag en een flexibele kennismigrantenregeling "
"ten behoeve van het economisch verdienvermogen. Deze dimensie is politiek betekenisvol "
"omdat hij de fundamentele vraag raakt of de staat actief moet ingrijpen om collectieve "
"voorzieningen betaalbaar en toegankelijk te houden, of dat vrije markt en open handel "
"leidend moeten zijn."
),
"positive_pole": "Staatsbescherming van betaalbare publieke voorzieningen voor iedereen",
"negative_pole": "Vrije handel, open economie en marktgerichte arbeidsmigratie",
},
5: {
"label": "Confessioneel-conservatief vs. seculier-progressief",
"label": "Christelijk-conservatief sociaal beleid versus seculier progressief",
"explanation": (
"Een klassieke waarden-as: ChristenUnie- en SGP-moties over euthanasie, "
"'Moeder en Kind'-fonds, kerkruimte en gezinsbelasting scoren positief. "
"Deze as reflecteert het diepste sociale-waardenverschil in de Kamer."
"Deze as reflecteert de politieke tegenstelling tussen christelijk-conservatieve "
"partijen (ChristenUnie en SGP) en seculier-progressieve partijen. Aan de positieve "
"pool staan moties over bescherming van het gezin, kritische houding tegenover euthanasie "
"bij jongeren, ruimte voor kerkgemeenschappen, bescherming van de agrarische sector en "
"een zakelijker onderwijscurriculum. Deze as is politiek betekenisvol omdat de SGP en CU "
"consistent vanuit een christelijk-sociale visie stemmen tegenover partijen als D66, "
"GroenLinks-PvdA en SP die een seculier-progressief beleid voorstaan."
),
"positive_pole": "Christelijk-conservatief: gezin, kerk, leven, traditionele waarden",
"negative_pole": "Seculier-progressief: individuele autonomie, progressieve sociale rechten",
},
6: {
"label": "Bescherming kwetsbare groepen vs. marktwerking",
"label": "Christelijk-sociaal beschermingsbeleid versus links-progressieve systeemkritiek",
"explanation": (
"Positieve scores: bescherming van pgb-houders, christelijke minderheden in "
"asielbeleid, en kinderopvangtoeslag voor middeninkomens. Negatieve scores: "
"meer marktwerking bij arbeidsmigratie en internationale hulp. Deze as "
"toont het spanningsveld tussen sociale bescherming en liberalisering."
"Deze as scheidt centrum-rechtse, christelijk-sociale partijen (CU, SGP, BBB, VVD) die "
"via pragmatisch overheidsbeleid specifieke kwetsbare groepen beschermen — zoals "
"pgb-budgethouders, christenen in Syrisch terugkeerbeleid en kinderen online — van "
"links-progressieve partijen (SP, GroenLinks) die structurele systeemkritiek leveren op "
"arbeidsmigratiemisstanden, winstbejag in de zorg en internationale solidariteit met "
"gemarginaliseerde groepen. De politieke tegenstelling gaat over de oriëntatie van sociaal "
"beleid: doelgroepgericht en institutioneel versus structureel-hervormend en solidair."
),
"positive_pole": "Christelijk-sociaal beschermingsbeleid voor pgb, kinderen en geloofsgroepen",
"negative_pole": "Links-progressieve systeemkritiek op zorg, arbeid en internationale solidariteit",
},
7: {
"label": "Democratische controle en sociale rechten vs. marktwerking",
"label": "Liberaal investeren en defensie versus linkse bescherming en controle",
"explanation": (
"Moties die parlementaire controle op buitenlandbeleid (Ukraine-coalitie), "
"sociale rechten (BOSA-sportsubsidies, toeslagencompensatie) en publieke zorg "
"bepleiten scoren positief. Private equity in de zorg en marktgerichte "
"warmteoplossingen scoren negatief."
"Deze as scheidt partijen als D66 en VVD (positief), die inzetten op gerichte "
"investeringen in sport, wetenschap, defensie en slachtofferhulp, van partijen als SP, "
"DENK en NSC (negatief), die nadruk leggen op collectieve sociale bescherming, "
"parlementaire controle over militaire inzet en weren van marktwerking uit publieke "
"sectoren zoals de zorg. De spanning draait om de vraag of de overheid via gerichte "
"liberale investeringen of via collectivistische regulering en bescherming moet opereren."
),
"positive_pole": "Gerichte liberale investeringen in sport, wetenschap en defensie",
"negative_pole": "Collectieve bescherming, parlementaire controle en anti-marktwerking in zorg",
},
8: {
"label": "Orde, veiligheid en soevereiniteit vs. sociale hervorming",
"label": "Confessioneel-sociaal coalitiebeleid versus procedurele blokkade en handhaving",
"explanation": (
"Veiligheidsmoties (illegaal vuurwapen, Dutch Dome, controversiële-onderwerpenlijst) "
"en soevereiniteitsmoties domineren de negatieve pool. "
"Positief: sociaal-hervormende moties zoals afschaffing van de kostendelersnorm, "
"hernieuwbare energie en stikstof-maatwerk. Een klassieke links-rechts "
"veiligheid-versus-sociale-hervorming kloof."
"De positieve pool groepeert moties van CU, NSC, SGP en D66 die concreet beleid bepleiten "
"op uiteenlopende terreinen: kostendelersnorm afschaffen ten gunste van bijstandsgerechtigden, "
"arbeidskorting terugdraaien om gepensioneerden te ontzien, Dutch Dome voor vitale "
"infrastructuurbescherming, stikstofmaatwerk in Regio Foodvalley, versnelling van "
"bouwvergunningverlening en het expliciet stellen van abortusvermindering als beleidsdoel. "
"De negatieve pool bevat het controversieel verklaren van het coffeeshopketen-experiment "
"(procedurele blokkade), een handhavingsdoelstelling voor illegaal vuurwerk en een "
"deregulerende uitzondering voor de topsportsector."
),
"positive_pole": "Coalitie christelijk-sociaal beleid: defensie, stikstofmaatwerk, bouw en ethiek",
"negative_pole": "Procedurele blokkade coffeeshop, handhavingsdoelstelling en topsportderegulering",
},
9: {
"label": "Caribisch koninkrijksbeleid en institutioneel toezicht",
"label": "Brede coalitiemeerderheid versus links marktingrijpen zorg",
"explanation": (
"Deze specifiekere as bundelt moties over Caribische defensie en Syrische "
"VN-coalitie (positief) met zorgtoezicht-WNT-normen (negatief). Het "
"weerspiegelt een combinatie van koninkrijks-betrokkenheid en institutioneel "
"toezicht als onderscheidende dimensie."
"Deze as onderscheidt moties die steun kregen van een brede, rechtse-tot-centrumlinkse "
"meerderheid (positieve pool) van een specifieke linkse motie (SP/GL-PvdA) die strenge "
"inkomenslimieten voor zorgbestuurders en aandeelhouders wil afdwingen (negatieve pool). "
"De positieve moties omvatten uiteenlopende onderwerpen — defensie, onderwijs, asiel, "
"belastingconstructies, natuur — ingediend door partijen als CU, NSC, JA21, D66 en "
"PvdA/GL, die gezamenlijk door de meerderheid werden gesteund. De negatieve pool "
"vertegenwoordigt een socialistische marktinterventie (WNT-normen in de zorg) die door "
"de rechtse regeringsmeerderheid werd weggestemd."
),
"positive_pole": "Breed gedragen beleid door centrum-rechts meerderheidsstemmen",
"negative_pole": "Socialistische inkomensregulering en marktingrijpen in de zorg",
},
10: {
"label": "Arbeidsmigratie, dierenwelzijn en zorgtoezicht",
"label": "Gereguleerde kennismigratie en natuur-landbouwtransitie versus institutionele veiligheid",
"explanation": (
"Positieve pool: zorgfraudetoezicht (Wtza), EU-blauwe kaart voor "
"kennismigranten en dierenwelzijn in de kalverhouderij. Negatieve pool: "
"vitale productie onshoren en EU-Israël-betrekkingen. Een gemengde as die "
"pragmatisch migratiemanagement combineert met dierenwelzijn en zorgregulering."
"De positieve pool groepeert moties die kennismigratie willen beperken tot sectoren met "
"aantoonbaar tekort (blauwe kaart), de kalverhouderij willen inkrimpen via dierrechten, "
"intensieve teelt op vrijgekochte boerengrond willen voorkomen, en humanitaire druk op "
"Israël inzake Gaza willen uitoefenen. Indieners zijn een brede coalitie van NSC, SP, "
"D66, CU en GL-PvdA. De negatieve pool bevat moties over institutionele coördinatie van "
"veiligheidsbeleid (Veilig Thuis), economische soevereiniteit (vitale productie "
"terughalen naar Nederland) en beperking van anonimiteit bij Woo-verzoeken, ingediend "
"door NSC, SGP en SP."
),
"positive_pole": "Beperkte kennismigratie, natuur-landbouwtransitie en Gaza-humanitair",
"negative_pole": "Institutionele veiligheidssturing, economisch nationalisme en Woo-beperking",
},
}
@ -779,10 +838,18 @@ def build_svd_components_tab(db_path: str) -> None:
)
comp_sel = comp_options[comp_sel_idx]
# Show theme explanation
# Show theme explanation + poles
theme = SVD_THEMES.get(comp_sel, {})
if theme:
st.info(f"**{theme['label']}** — {theme['explanation']}")
pos = theme.get("positive_pole", "")
neg = theme.get("negative_pole", "")
if pos or neg:
pcol, ncol = st.columns(2)
with pcol:
st.success(f"▲ **Positieve pool:** {pos}")
with ncol:
st.error(f"▼ **Negatieve pool:** {neg}")
motions = comp_map.get(comp_sel, [])

Loading…
Cancel
Save