- Add AGENTS.md with documented solutions reference - Include SVD label convention (right-wing parties on right side) - Document SVD insight: labels reflect voting patterns, not semantics - Fix SQL verification example to use Python approachmain
parent
92c3c0ee01
commit
0308d20f12
@ -0,0 +1,10 @@ |
|||||||
|
# Agents |
||||||
|
|
||||||
|
## Documented Solutions |
||||||
|
|
||||||
|
`docs/solutions/` — documented solutions to past problems (bugs, best practices, workflow patterns), organized by category with YAML frontmatter (`module`, `tags`, `problem_type`). Relevant when implementing or debugging in documented areas. |
||||||
|
|
||||||
|
## Project Conventions |
||||||
|
|
||||||
|
- Right-wing parties (PVV, FVD, JA21, SGP) must appear on the RIGHT side of all axes in visualizations |
||||||
|
- SVD labels should reflect voting patterns, not semantic content — see `docs/solutions/best-practices/svd-labels-voting-patterns-not-semantics.md` |
||||||
@ -0,0 +1,140 @@ |
|||||||
|
--- |
||||||
|
title: "SVD Labels Should Reflect Voting Patterns, Not Semantic Content" |
||||||
|
date: "2026-04-04" |
||||||
|
category: docs/solutions/best-practices |
||||||
|
module: stemwijzer |
||||||
|
problem_type: best_practice |
||||||
|
component: brief_system |
||||||
|
severity: medium |
||||||
|
applies_when: |
||||||
|
- Labeling SVD (Singular Value Decomposition) components in voting analysis |
||||||
|
- Interpreting PCA/SVD dimensions in political party voting data |
||||||
|
- Creating axis labels for voting compass or similar applications |
||||||
|
tags: |
||||||
|
- svd |
||||||
|
- voting-analysis |
||||||
|
- axis-labels |
||||||
|
- dimensionality-reduction |
||||||
|
- party-voting-patterns |
||||||
|
--- |
||||||
|
|
||||||
|
# SVD Labels Should Reflect Voting Patterns, Not Semantic Content |
||||||
|
|
||||||
|
## Context |
||||||
|
|
||||||
|
When labeling SVD components in the Stemwijzer explorer (`explorer.py`), initial labels were based on **semantic analysis** of motion titles — what topics motions appeared to discuss. However, SVD captures **voting patterns**, not semantic content. |
||||||
|
|
||||||
|
This mismatch led to: |
||||||
|
- Labels that didn't match how parties actually voted |
||||||
|
- Right-wing parties appearing on the LEFT side of axes (violating the right-wing parties → right side constraint) |
||||||
|
- Confusion about what each component actually represents |
||||||
|
|
||||||
|
## Guidance |
||||||
|
|
||||||
|
### The Core Principle |
||||||
|
|
||||||
|
**SVD components represent voting unity patterns, not topic clusters.** |
||||||
|
|
||||||
|
When a motion appears on a component with a positive loading, it means parties that vote positively on that motion tend to vote similarly. The component captures this behavioral pattern, not the topic's semantic meaning. |
||||||
|
|
||||||
|
### Example: Component 1 |
||||||
|
|
||||||
|
| Approach | Label | Why It's Wrong | |
||||||
|
|----------|-------|----------------| |
||||||
|
| Semantic | "Sociale zekerheid vs economische liberalisering" | Assumes defense + social care = welfare state | |
||||||
|
| Voting | "Rechts kabinetsbeleid vs links oppositiebeleid" | Matches actual coalition vs opposition voting | |
||||||
|
|
||||||
|
**Why Component 1 captures coalition-opposition:** |
||||||
|
- 9 coalition + center parties vote one way |
||||||
|
- 6 opposition parties vote the other way |
||||||
|
- Motion topics can include defense (right votes for) AND social care (left votes for) because they're on opposite sides of the coalition-opposition divide |
||||||
|
|
||||||
|
### How to Label SVD Components |
||||||
|
|
||||||
|
1. **Analyze actual voting patterns first** |
||||||
|
- Query which parties vote positively vs negatively on each component |
||||||
|
- Look for coalition/opposition splits, cross-block alliances, or isolated parties |
||||||
|
|
||||||
|
2. **Verify right-wing parties on RIGHT side** |
||||||
|
- Check PVV, FVD, JA21, SGP positions |
||||||
|
- If they vote negatively while left parties vote positively, flip the axis |
||||||
|
|
||||||
|
3. **Don't assume semantics match voting** |
||||||
|
- A "defense" component may include social care motions if right-wing parties vote the same way on both |
||||||
|
- Cross-block alliances (e.g., PVV with SP on welfare) create components that don't fit left-right semantics |
||||||
|
|
||||||
|
4. **Test with sample motions** |
||||||
|
- Top positive-loading motions should align with positive-voting parties' priorities |
||||||
|
- Top negative-loading motions should align with negative-voting parties' priorities |
||||||
|
|
||||||
|
## Why This Matters |
||||||
|
|
||||||
|
Without understanding that SVD captures voting patterns: |
||||||
|
- Labels will be misleading to users |
||||||
|
- Right-wing parties may appear on the wrong side of axes |
||||||
|
- Components may be mislabeled as "left" when they're actually "opposition" |
||||||
|
- Users get incorrect information about party positions |
||||||
|
|
||||||
|
## When to Apply |
||||||
|
|
||||||
|
Apply this guidance when: |
||||||
|
- Creating or updating SVD/PCA component labels |
||||||
|
- Interpreting dimensionality reduction results in voting analysis |
||||||
|
- Building voting compasses or similar political guidance tools |
||||||
|
- Analyzing roll call votes or legislative voting data |
||||||
|
|
||||||
|
## Examples |
||||||
|
|
||||||
|
### Wrong Approach (Semantic) |
||||||
|
|
||||||
|
```python |
||||||
|
# ❌ BAD: Based on motion topics, not voting patterns |
||||||
|
SVD_THEMES = { |
||||||
|
1: { |
||||||
|
"label": "Sociale zekerheid vs economische liberalisering", |
||||||
|
# Reality: 9 coalition parties vote same way, 6 opposition vote opposite |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
### Correct Approach (Voting Patterns) |
||||||
|
|
||||||
|
```python |
||||||
|
# ✅ GOOD: Based on actual voting behavior |
||||||
|
SVD_THEMES = { |
||||||
|
1: { |
||||||
|
"label": "Rechts kabinetsbeleid vs links oppositiebeleid", |
||||||
|
"explanation": ( |
||||||
|
"Deze as scheidt het kabinetsbeleid van de oppositie. " |
||||||
|
"9 coalitiepartijen stemmen aan de positieve kant, " |
||||||
|
"6 oppositiepartijen aan de negatieve kant." |
||||||
|
), |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
### Verification Approach |
||||||
|
|
||||||
|
To verify SVD component labels, check which parties have positive vs negative loadings on each component: |
||||||
|
|
||||||
|
```python |
||||||
|
# From explorer.py - check party loadings for each component |
||||||
|
for comp_num in range(1, 11): |
||||||
|
component_parties = svd_scores[svd_scores['component'] == comp_num] |
||||||
|
positive_parties = component_parties[component_parties['loading'] > 0]['party'].tolist() |
||||||
|
negative_parties = component_parties[component_parties['loading'] < 0]['party'].tolist() |
||||||
|
|
||||||
|
print(f"Component {comp_num}:") |
||||||
|
print(f" Positive ({len(positive_parties)}): {positive_parties}") |
||||||
|
print(f" Negative ({len(negative_parties)}): {negative_parties}") |
||||||
|
``` |
||||||
|
|
||||||
|
Use this to verify: |
||||||
|
- Right-wing parties (PVV, FVD, JA21, SGP) appear on the correct side |
||||||
|
- The label matches the voting pattern, not just the topic |
||||||
|
|
||||||
|
## Related |
||||||
|
|
||||||
|
- [SVD Label Unification Plan](docs/superpowers/plans/2026-04-02-svd-label-unification.md) |
||||||
|
- [SVD Label Unification Design](docs/superpowers/specs/2026-04-02-svd-label-unification-design.md) |
||||||
|
- Commits: `33edb33`, `e77f0ec`, `bfe37c6`, `f7fc908`, `92c3c0e` |
||||||
Loading…
Reference in new issue