7.4 KiB
| title | type | status | date | origin |
|---|---|---|---|---|
| Enforce left-right orientation across all SVD axis labels | refactor | active | 2026-04-05 | docs/superpowers/specs/2026-04-05-svd-axis-labels-design.md |
Enforce Left-Right Orientation Across All SVD Axis Labels
Overview
Update SVD component labels in analysis/config.py so all 10 axes consistently reflect left-right positioning, and add validation tests to ensure canonical right-wing parties (PVV, FVD, JA21, SGP) appear on the right side after flip computation. The flip mechanism already works; this plan focuses on label consistency and test coverage.
Problem Frame
SVD axis labels do not consistently reflect left-right positioning. Some axes describe dimensions like "populist vs mainstream" or "pragmatism vs ideology" without framing how right/conservative and left/progressive parties cluster on each pole. The repo convention (AGENTS.md) requires right-wing parties to appear on the RIGHT side of all axes, and labels should reflect this orientation.
Requirements Trace
- R1. All 10 SVD component labels consistently frame the dimension in left-right terms
- R2. Canonical right-wing parties (PVV, FVD, JA21, SGP) appear on the right side after flip computation
- R3. Backward compatibility preserved for existing callers of
get_svd_label,get_fallback_labels,compute_flip_direction - R4. Unit tests validate flip behavior and label correctness
Scope Boundaries
- In scope:
analysis/config.pySVD_THEMES labels,tests/test_svd_labels.pyadditions - Out of scope:
analysis/political_axis.pyparty sets (follow-up), UI changes, flip logic changes (already works)
Context & Research
Relevant Code and Patterns
analysis/config.py— definesSVD_THEMESwith 10 components, each withlabel,explanation,positive_pole,negative_pole,flipanalysis/svd_labels.py— importsCANONICAL_RIGHT/CANONICAL_LEFTfrom config, exports aliases,compute_flip_directionuses themexplorer.py:2680-2690— dynamically computes flip for all 10 components at runtime, overwrites staticflipvalues
Key Technical Decisions
- Keep flip mechanism as-is:
compute_flip_directionalready uses canonical party sets to force right-wing parties to the right. No changes needed. - Update labels, not flip logic: The work is in
SVD_THEMESlabel text — reframing each component's label to reflect left-right positioning while preserving the underlying voting pattern description. - Preserve explanation text: The
explanationfield can remain detailed and nuanced; only thelabeland pole descriptions need left-right framing.
Implementation Units
- Unit 1: Update SVD_THEMES labels for left-right consistency
Goal: Reframe all 10 SVD component labels to consistently reflect left-right positioning.
Requirements: R1, R3
Dependencies: None
Files:
- Modify:
analysis/config.py
Approach:
- For each component (1-10), update the
labelfield to frame the dimension in left-right terms - Update
positive_poleandnegative_poleto explicitly mention which parties cluster on each side and their left/right positioning - Preserve the
explanationtext (it's already detailed and accurate) - Keep
flipvalues as-is (they're overwritten at runtime anyway)
Patterns to follow:
- Component 1 label pattern: "Rechts kabinetsbeleid versus links oppositiebeleid" — this is the model
- Component 3 label pattern: "Verzorgingsstaat versus bezuinigingen en marktwerking" — economic left-right
- Component 6 label pattern: "Migratie en cultuur versus klimaat en progressieve inclusie" — cultural left-right (GAL-TAN)
Test scenarios:
- Test expectation: none — this is a label text update, no behavioral change. Verification is manual review of label text.
Verification:
-
All 10 component labels explicitly reference left/right positioning or conservative/progressive framing
-
positive_poleandnegative_poledescriptions mention party clusters and their left/right orientation -
Unit 2: Add validation test for canonical right-on-right
Goal: Add a test that verifies canonical right-wing parties appear on the right side after flip computation.
Requirements: R2, R4
Dependencies: Unit 1 (labels updated, flip logic unchanged)
Files:
- Modify:
tests/test_svd_labels.py
Approach:
- Add
test_canonical_right_on_rightthat:- Creates synthetic party scores where canonical right parties have negative values (on the left)
- Asserts
compute_flip_directionreturnsTruefor all components 1-10 - Creates synthetic scores where canonical right parties have positive values (on the right)
- Asserts
compute_flip_directionreturnsFalsefor all components
- Add
test_all_canonical_parties_usedthat verifiesCANONICAL_RIGHTandCANONICAL_LEFTfrom config contain the expected parties (PVV, FVD, JA21, SGP for right; SP, PvdA, GL, etc. for left)
Execution note: Test-first — write failing test, then verify it passes after Unit 1.
Patterns to follow:
- Existing test style in
tests/test_svd_labels.py(synthetic dict-based party scores, assert on boolean flip result) test_auto_flip_computation_for_all_componentsalready tests flip for all 10 components — new test should follow same pattern but explicitly useCANONICAL_RIGHT/CANONICAL_LEFTfrom config
Test scenarios:
- Happy path: Canonical right parties on right side →
compute_flip_directionreturnsFalsefor all components - Happy path: Canonical right parties on left side →
compute_flip_directionreturnsTruefor all components - Edge case: Mixed placement (some right parties on left, some on right) → flip based on majority mean
- Edge case: No canonical parties present → returns
False(existing behavior, verify unchanged)
Verification:
pytest tests/test_svd_labels.py -qpasses with no regressions- New tests explicitly validate canonical right-on-right behavior
System-Wide Impact
- Interaction graph:
explorer.pydynamically computes flip at runtime — no changes needed there. Labels flow fromconfig.py→svd_labels.py→ UI rendering. - Unchanged invariants:
compute_flip_directionlogic unchanged. Public API (get_svd_label,get_fallback_labels,compute_flip_direction) unchanged. Staticflipvalues inSVD_THEMESstill overwritten at runtime. - API surface parity: Labels change text but not structure. Callers expecting string labels continue to work.
Risks & Dependencies
| Risk | Mitigation |
|---|---|
| Label changes may not capture nuance of non-left-right axes | Preserve detailed explanation text; labels are shorthand, explanations carry full context |
| Tests may pass but labels still feel off | Manual review of all 10 labels before committing |
political_axis.py still uses different party sets |
Document as follow-up; out of scope for this plan |
Documentation / Operational Notes
- Update or reference
docs/solutions/best-practices/svd-labels-voting-patterns-not-semantics.mdif label convention changes materially - No rollout or monitoring impacts — label text change only
Sources & References
- Origin document: docs/superpowers/specs/2026-04-05-svd-axis-labels-design.md
- Related code:
analysis/config.py,analysis/svd_labels.py,tests/test_svd_labels.py - Convention reference:
AGENTS.md(right-wing parties must appear on RIGHT side)