feat(overton): coherent narrative architecture — Quarto article, Explorer Overton tab, report cleanup
- U1: Remove stale findings_report.md and blog_post.html, add cross-reference headers to all 13 appendix reports, switch HTML report to canonical 4-party centrist definition - U2: Create Quarto narrative spine (overton_window.qmd) with 9 sections and 6 interactive Plotly charts. Includes 'About Stemwijzer' platform section. - U3: Add Overton tab to Explorer (centrist support trend, right-wing motion browser, explore-further links). Add Overton context expander to Kompas tab and 2024 breakpoint annotation to Trajectories tab. - U4: Create build_all_reports.py master regeneration script (3-phase, dependency-ordered, --skip-llm support) - U5: Update README with Research section, create reports/overton_window/README.md reading guide, update STATUS.md with broader platform framing Plan: docs/plans/2026-06-06-001-overton-coherent-narrative-plan.md 282 tests pass.
This commit is contained in:
@@ -0,0 +1,327 @@
|
||||
---
|
||||
title: feat: Overton window coherent narrative architecture
|
||||
type: feat
|
||||
status: active
|
||||
date: 2026-06-06
|
||||
---
|
||||
|
||||
# feat: Overton Window Coherent Narrative Architecture
|
||||
|
||||
## Summary
|
||||
|
||||
The Overton window analysis is Stemwijzer's most ambitious analytical output — a multi-indicator answer to "Has the Dutch Overton window shifted?" built on top of the platform's SVD compass, voting records, and 2D extremity scoring. But it landed as 17 fragmented reports with no narrative spine, no connection to the live Explorer dashboards that visualize the same dynamics, and stale public-facing artifacts. This plan weaves the Overton findings into a coherent story (Quarto article + cleaned reports + Explorer integration) while positioning it as a showcase for what the Stemwijzer platform can do — not as a standalone project.
|
||||
|
||||
---
|
||||
|
||||
## Problem Frame
|
||||
|
||||
Stemwijzer is a Dutch parliamentary analysis platform with three tracks: data pipeline reliability, analytical depth, and agent-native architecture (see `STRATEGY.md`). The Overton window analysis is a flagship deliverable of track 2 — it demonstrates the platform's SVD compass, voting data, and LLM scoring capabilities in service of a real political science question.
|
||||
|
||||
But the Overton output landed fragmented: 17 files across `reports/overton_window/` with no reading order, no cross-references, and no connection to the live Explorer dashboards (Kompas, Trajectories, SVD Components) that directly visualize the same dynamics. The blog post uses stale 1D data and the wrong centrist definition. The analysis scripts work but there's no single entry point for a reader or a user.
|
||||
|
||||
This plan organizes the Overton findings into a coherent multi-surface narrative while ensuring it serves the broader platform — the Explorer integration and Quarto article should make users want to explore the Stemwijzer compass, not just read about Overton findings.
|
||||
|
||||
---
|
||||
|
||||
## Requirements
|
||||
|
||||
- R1. A single Quarto article (`overton_window.qmd`) serves as the narrative spine — telling the story from question ("Has the Overton window shifted?") to answer ("Acceptance through moderation"), with embedded interactive Plotly charts
|
||||
- R2. All public-facing outputs use the strict 4-party centrist definition (D66, CDA, CU, NSC)
|
||||
- R3. The Overton narrative drives traffic TO the live Stemwijzer Explorer — readers should finish the article wanting to explore the compass themselves. The 3 live Explorer dashboards connect to the Overton narrative through explanatory text and a dedicated Overton tab
|
||||
- R4. Stale/drifted reports are removed or explicitly archived
|
||||
- R5. All remaining reports cross-reference each other consistently
|
||||
- R6. A `build_all_reports.py` script regenerates all outputs in dependency order
|
||||
- R7. The blog post is replaced with a current-data version
|
||||
- R8. The Overton narrative showcases Stemwijzer's platform capabilities (SVD compass, voting data, 2D scoring) — it should read as both a political science finding AND a demonstration of what the tool can do
|
||||
|
||||
---
|
||||
|
||||
## Scope Boundaries
|
||||
|
||||
- No new analytical findings — this is about organization, narrative, and presentation
|
||||
- No backend infrastructure changes (the Streamlit app already works)
|
||||
- No European comparative analysis (deferred)
|
||||
- No mechanism taxonomy revision (deferred)
|
||||
- No forward-looking scenario analysis (deferred)
|
||||
- Install Quarto CLI as a new tool dependency
|
||||
|
||||
### Deferred to Follow-Up Work
|
||||
|
||||
- European comparison (AfD, Meloni, Le Pen, Sweden Democrats)
|
||||
- Mechanism taxonomy revision (κ=0.41)
|
||||
- Forward-looking scenario analysis (permanent vs temporary shift)
|
||||
- Anti-institutional pivot deep-dive (abolition → contestation)
|
||||
|
||||
---
|
||||
|
||||
## Context & Research
|
||||
|
||||
### Relevant Code and Patterns
|
||||
|
||||
- `analysis/right_wing/` — 19+ analysis scripts that generate the reports
|
||||
- `analysis/explorer_data.py` — data layer feeding the Streamlit Explorer
|
||||
- `analysis/tabs/` — Streamlit tab modules (compass, trajectories, components, browser, search)
|
||||
- `explorer.py` — Explorer orchestration, currently registers 3 tabs
|
||||
- `reports/overton_window/` — 17 output files (14 MD, 2 HTML, 1 synthesis)
|
||||
- `.opencode/skills/score-extremity/SKILL.md` — 2D scoring methodology
|
||||
|
||||
### Institutional Learnings
|
||||
|
||||
- `docs/solutions/best-practices/overton-window-shift-methodology-2026-05-24.md` — 7-step methodology
|
||||
- `docs/solutions/best-practices/overton-narrative-architecture-2026-06-06.md` — narrative structure guidance (just created)
|
||||
- `docs/solutions/best-practices/domain-decomposition-hidden-overton-variance-2026-05-25.md`
|
||||
- `AGENTS.md` — strict 4-party centrist definition, SVD sign convention, right-wing on RIGHT
|
||||
|
||||
### External References
|
||||
|
||||
- Quarto: `quarto.org/docs/get-started/` — standalone CLI, Jupyter engine for Python/Plotly
|
||||
- Plotly 6.6.0 already installed
|
||||
|
||||
---
|
||||
|
||||
## Key Technical Decisions
|
||||
|
||||
- **Quarto Jupyter engine** over static HTML: Interactive Plotly charts survive in the output, readers can hover/zoom/filter. Same dependency (plotly) already in pyproject.toml.
|
||||
- **Strict 4-party centrist definition** enforced across all public outputs: D66, CDA, CU, NSC only. The 6-party definition (adding VVD, BBB) survives only in the breakpoint_analysis.md appendix for comparison.
|
||||
- **Three-tier output structure**: Narrative spine (Quarto) → Detailed appendices (Markdown in reports/overton_window/) → Live exploration (Streamlit Explorer tab)
|
||||
- **Remove, don't accumulate**: findings_report.md removed. blog_post.html replaced. Duplicate section content between reports consolidated.
|
||||
- **Master build script** as single-source-of-truth for reproducibility: `analysis/right_wing/build_all_reports.py` runs scripts in dependency order.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Units
|
||||
|
||||
- U1. **Clean up stale and drifted reports**
|
||||
|
||||
**Goal:** Remove superseded artifacts, fix inconsistent content, archive early-draft reports.
|
||||
|
||||
**Requirements:** R4, R5
|
||||
|
||||
**Dependencies:** None
|
||||
|
||||
**Files:**
|
||||
- Remove: `reports/overton_window/findings_report.md`
|
||||
- Remove: `reports/overton_window/blog_post.html`
|
||||
- Modify: `reports/overton_window/overton_window_synthesis.md` (fix hashline formatting corruption at top)
|
||||
- Modify: `reports/overton_window/breakpoint_analysis.md` (add note at top linking to synthesis as primary narrative)
|
||||
- Modify: `reports/overton_window/overton_report.html` (switch to strict 4-party centrist definition from current 6-party)
|
||||
|
||||
**Approach:**
|
||||
- Remove findings_report.md — fully superseded by synthesis
|
||||
- Remove blog_post.html — will be recreated as Quarto output (U3)
|
||||
- Fix hashline corruption in synthesis (duplicate `#HL` header lines)
|
||||
- Add cross-reference header to each remaining report: "See also: [overton_window_synthesis.md](...)" with one-sentence relationship
|
||||
- Switch overton_report.html centrist definition from 6-party (VVD/D66/CDA/NSC/BBB/CU) to strict 4-party (D66/CDA/CU/NSC)
|
||||
|
||||
**Test expectation:** none — editorial/content changes, no behavioral change
|
||||
|
||||
**Verification:**
|
||||
- findings_report.md and blog_post.html removed
|
||||
- synthesis hashline headers cleaned up
|
||||
- All remaining reports contain cross-reference to synthesis
|
||||
- overton_report.html uses 4-party centrist numbers
|
||||
|
||||
---
|
||||
|
||||
- U2. **Create the Quarto narrative spine**
|
||||
|
||||
**Goal:** Write `reports/overton_window/overton_window.qmd` — a single self-contained article with embedded interactive Plotly charts that tells the Overton story from question to answer, while showcasing Stemwijzer's platform capabilities.
|
||||
|
||||
**Requirements:** R1, R2, R8
|
||||
|
||||
**Dependencies:** U1 (cleanup), external prerequisite: Quarto CLI installed
|
||||
|
||||
**Files:**
|
||||
- Create: `reports/overton_window/overton_window.qmd`
|
||||
- Create: `reports/overton_window/_quarto.yml` (project config)
|
||||
- Modify: `pyproject.toml` (add quarto render script if needed)
|
||||
|
||||
**Approach:**
|
||||
- 9-section narrative arc:
|
||||
1. **Introduction** — The question, why it matters, Dutch political context (PVV election 2023)
|
||||
2. **About Stemwijzer** — Brief platform introduction: what it is (data-driven political compass from real voting records), how it works (SVD on 29K+ motions), what readers can do with it. This positions the article as both a finding and a platform demo.
|
||||
3. **Methodology** — Right-wing motion classification, 2D extremity scoring, strict centrist definition, data sources
|
||||
4. **Indicator 1: Centrist Voting** — Breakpoint at 2024, opposition-controlled, gravity-stratified
|
||||
5. **Indicator 2: Spatial Divergence** — SVD compass drift, acceptance without conversion
|
||||
6. **Indicator 3: Content Moderation** — 2D extremity trajectories, all-motion comparison
|
||||
7. **Mechanisms** — Consensus framing, institutional appeals, JA21 as driver
|
||||
8. **Temporal Dynamics** — Electoral jump, 2024-Q4 peak, 2026 reversion signal
|
||||
9. **Verdict: Acceptance Through Moderation** — What it means, limitations, open questions, call-to-action to explore the live compass
|
||||
- Embedded Plotly charts (not static PNGs):
|
||||
- Yearly centrist_support_strict with CI bands + opposition-only overlay
|
||||
- Gravity-controlled bar chart (M1-M5 centrist support)
|
||||
- SVD trajectory plot (centrist vs right-wing center)
|
||||
- 2D extremity temporal with all-motion reference lines
|
||||
- Mechanism classification bar chart
|
||||
- Quarterly temporal trajectory
|
||||
- Use `plotly.graph_objects` for chart construction (consistent with existing analysis scripts)
|
||||
- YAML header with `jupyter: python3` engine, `embed-resources: true`
|
||||
- Reference back to Explorer dashboard: "Explore this data live at [localhost:8501](http://localhost:8501), Explorer > Kompas"
|
||||
|
||||
**Execution note:** Write the QMD content before setting up Quarto — the charts can initially be embedded as static PNGs and upgraded to interactive Plotly in a second pass.
|
||||
|
||||
**Test expectation:** none — content/documentation
|
||||
|
||||
**Verification:**
|
||||
- `quarto render overton_window.qmd` produces valid HTML
|
||||
- All 9 sections present with embedded charts
|
||||
- Section 2 introduces Stemwijzer as a platform (not just the Overton analysis)
|
||||
- Uses strict 4-party centrist definition throughout
|
||||
- References the live Explorer dashboard
|
||||
- References the detailed appendices for methodology deep-dives
|
||||
- Final section includes a call-to-action to explore the Stemwijzer compass
|
||||
|
||||
---
|
||||
|
||||
- U3. **Wire Explorer with an Overton context panel**
|
||||
|
||||
**Goal:** Add explanatory Overton context to the existing Explorer tabs so readers of the narrative can drill into the live data, AND ensure the Overton tab drives engagement with the broader Stemwijzer platform (compass quiz, SVD exploration).
|
||||
|
||||
**Requirements:** R3, R8
|
||||
|
||||
**Dependencies:** U2
|
||||
|
||||
**Files:**
|
||||
- Modify: `analysis/tabs/compass.py` (add Overton context expander in the sidebar or below the chart)
|
||||
- Modify: `analysis/tabs/trajectories.py` (add Overton annotation showing 2024 breakpoint)
|
||||
- Create: `analysis/tabs/overton.py` (new tab module — motion browser filtered to right-wing, centrist support trends)
|
||||
- Modify: `analysis/tabs/__init__.py` (register overton tab)
|
||||
- Modify: `explorer.py` (wire the tab into `run_app()`)
|
||||
|
||||
**Approach:**
|
||||
- Add a collapsible "Overton Window Context" expander to the Kompas tab sidebar explaining what the axes show relative to the Overton analysis, with a link to the Quarto narrative. Include a "Try the Stemwijzer quiz" call-to-action linking to the quiz page.
|
||||
- In the Trajectories tab, add a vertical reference line at 2024 with an annotation referencing the breakpoint finding
|
||||
- Create a lightweight "Overton" tab that shows:
|
||||
- Yearly centrist_support_strict trend line (from right_wing_motions)
|
||||
- Right-wing motion count by year
|
||||
- Filterable right-wing motion browser (reusing `browser.py` with a WHERE classified=TRUE filter)
|
||||
- Summary statistics matching the narrative
|
||||
- "Explore further" section linking to Kompas (see party positions), Trajectories (see drift), and SVD Components (see which motions drive the axes)
|
||||
- The Overton tab should make users curious about the underlying data — not present a closed story but an open exploration
|
||||
|
||||
**Test scenarios:**
|
||||
- Happy path: Opening Explorer > Overton tab loads centrist support chart and motion browser
|
||||
- Happy path: Kompas tab shows the Overton context expander
|
||||
- Happy path: Trajectories tab shows the 2024 breakpoint annotation
|
||||
- Edge case: No right-wing motions in database — empty state message
|
||||
|
||||
**Verification:**
|
||||
- `streamlit run Home.py` shows 4 Explorer tabs (Kompas, Trajectories, SVD Components, Overton)
|
||||
- Overton tab shows centrist_support_strict trend line
|
||||
- Kompas sidebar has Overton context expander
|
||||
- Trajectories tab has 2024 reference line
|
||||
|
||||
---
|
||||
|
||||
- U4. **Build master report regeneration script**
|
||||
|
||||
**Goal:** Single script that regenerates all Overton reports in correct dependency order.
|
||||
|
||||
**Requirements:** R6
|
||||
|
||||
**Dependencies:** U1 (cleanup ensures scripts are consistent)
|
||||
|
||||
**Files:**
|
||||
- Create: `analysis/right_wing/build_all_reports.py`
|
||||
|
||||
**Approach:**
|
||||
- Phase 1: Database-dependent scripts (no LLM calls):
|
||||
- `overton_breakpoint_analysis.py`
|
||||
- `temporal_trajectory.py`
|
||||
- `causal_timing.py`
|
||||
- `party_differentiation.py`
|
||||
- `voting_margin.py`
|
||||
- `left_wing_response.py`
|
||||
- `success_correlation.py`
|
||||
- `overton_svd_drift.py`
|
||||
- `svd_trajectory_viz.py`
|
||||
- Phase 2: 2D extremity-dependent scripts (no LLM calls):
|
||||
- `extremity_2d_temporal.py`
|
||||
- `predictive_model.py`
|
||||
- `mechanism_classification.py`
|
||||
- Phase 3: LLM-dependent scripts (optional, skip with --skip-llm):
|
||||
- `derive_categories.py`
|
||||
- `mechanism_classification.py` (LLM classification pass)
|
||||
- Phase 4: Synthesis updates (manual, prints reminder)
|
||||
- CLI: `uv run python analysis/right_wing/build_all_reports.py [--skip-llm]`
|
||||
- Runs each script via `subprocess.run`, checks exit code, logs output paths
|
||||
- Verifies all expected output files exist after each phase
|
||||
|
||||
**Test scenarios:**
|
||||
- Happy path: Running with skip-llm regenerates all DB-dependent reports
|
||||
- Happy path: All expected output files exist after completion
|
||||
- Error path: A sub-script fails — build_all_reports reports which script failed and its stderr
|
||||
|
||||
**Verification:**
|
||||
- `uv run python analysis/right_wing/build_all_reports.py --skip-llm` exits 0
|
||||
- All reports in `reports/overton_window/` have fresh timestamps
|
||||
|
||||
---
|
||||
|
||||
- U5. **Document and cross-reference everything**
|
||||
|
||||
**Goal:** Update README, add reading guide, final compound. Position the Overton analysis within the broader Stemwijzer platform.
|
||||
|
||||
**Requirements:** R5
|
||||
|
||||
**Dependencies:** U1, U2, U3
|
||||
|
||||
**Files:**
|
||||
- Modify: `README.md`
|
||||
- Modify: `AGENTS.md`
|
||||
- Create: `reports/overton_window/README.md` (reading guide)
|
||||
|
||||
**Approach:**
|
||||
- README: Add Quarto article link under a new "Research" section. Reorganize Documentation section to list Overton reports in reading order. Ensure the Overton work is presented as one of Stemwijzer's analytical outputs, not the project's sole purpose. The README should still lead with the platform (voting compass, explorer) and present Overton as a showcase of what the data enables.
|
||||
- AGENTS.md: No changes needed (already has Overton conventions) — verify
|
||||
- Create `reports/overton_window/README.md` as the directory-level reading guide:
|
||||
- First: `overton_window.qmd` (narrative spine)
|
||||
- Then: `overton_window_synthesis.md` (detailed synthesis)
|
||||
- Then: individual appendices with one-sentence descriptions
|
||||
- Also: "Explore live at: Streamlit Explorer > Overton tab"
|
||||
- Mark deprecated: "Historical artifacts: blog_post.html (replaced by Quarto), findings_report.md (removed)"
|
||||
|
||||
**Test expectation:** none — documentation changes
|
||||
|
||||
**Verification:**
|
||||
- `reports/overton_window/README.md` lists all reports in reading order
|
||||
- README.md references the Quarto article and reading guide
|
||||
|
||||
---
|
||||
|
||||
## System-Wide Impact
|
||||
|
||||
- **Interaction graph:** Streamlit Explorer (`explorer.py`, `analysis/tabs/__init__.py`) gains a new tab module. Existing compass/trajectories tabs get minor additions (expander, annotation). No changes to data pipeline, database, or API client.
|
||||
- **Unchanged invariants:** All existing analysis scripts and tests continue to work. The Streamlit app's existing 3 tabs remain functional and unbroken. The Stemwijzer quiz page is untouched.
|
||||
- **Platform alignment (STRATEGY.md):**
|
||||
- Track 1 (Pipeline reliability): U4 master build script improves reproducibility. No pipeline changes.
|
||||
- Track 2 (Analytical depth): This plan IS the track 2 showcase — organizing the deepest analysis the platform has produced into a coherent, explorable narrative.
|
||||
- Track 3 (Agent-native): The Overton tab uses `agent_tools`-compatible data tables. The `build_all_reports.py` script makes the analysis reproducible by agents.
|
||||
|
||||
---
|
||||
|
||||
## Documentation / Operational Notes
|
||||
|
||||
- The Quarto article should be the primary public-facing artifact. It replaces `blog_post.html` and `findings_report.md`.
|
||||
- The Overton analysis is positioned as a Stemwijzer platform showcase — readers should finish the article understanding both the political finding AND what the tool can do.
|
||||
- The live Explorer is the "next step" for engaged readers — the Quarto article and Overton tab both link to it.
|
||||
|
||||
---
|
||||
|
||||
## Risks & Dependencies
|
||||
|
||||
| Risk | Mitigation |
|
||||
|------|------------|
|
||||
| Quarto CLI not available — user needs to install | Check availability early; if not, static HTML with embedded Plotly as fallback |
|
||||
| Explorer tab slows down Streamlit load | Lightweight tab — only queries right_wing_motions and extremity_scores_2d, no SVD computation |
|
||||
| Blog post Regeneration diverges from Quarto narrative | Make Quarto the single source — blog post is rendered from same QMD with different styling |
|
||||
|
||||
---
|
||||
|
||||
## Sources & References
|
||||
|
||||
- **Gap analysis:** `docs/solutions/best-practices/overton-narrative-architecture-2026-06-06.md`
|
||||
- **Methodology:** `docs/solutions/best-practices/overton-window-shift-methodology-2026-05-24.md`
|
||||
- **Synthesis report:** `reports/overton_window/overton_window_synthesis.md`
|
||||
- **HTML report:** `reports/overton_window/overton_report.html`
|
||||
- **Quarto docs:** https://quarto.org/docs/get-started/
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
---
|
||||
title: Large-scale subagent-based 2D extremity scoring
|
||||
date: 2026-06-05
|
||||
category: best-practices
|
||||
module: analysis/right_wing
|
||||
problem_type: best_practice
|
||||
component: development_workflow
|
||||
severity: medium
|
||||
applies_when:
|
||||
- "scaling LLM scoring from hundreds to tens of thousands of items"
|
||||
- "using subagent dispatch as a replacement for API-based batch scoring"
|
||||
- "parallel batch processing with stateful incremental storage"
|
||||
tags:
|
||||
- extremity-scoring
|
||||
- subagent-dispatch
|
||||
- parallelism
|
||||
- duckdb
|
||||
- llm-workflow
|
||||
---
|
||||
|
||||
# Large-scale subagent-based 2D extremity scoring
|
||||
|
||||
## Context
|
||||
|
||||
After scoring 117 right-wing motions with 2D extremity (stijl-extremiteit + materiele impact) using deepseek v4 flash subagents, we needed to scale to all 29,570 motions in the database. The existing OpenRouter-based batch pipeline (`chat_completion_json_parallel`) would be too expensive and slow at this scale. Subagent dispatch via the `task` tool was the alternative.
|
||||
|
||||
## Guidance
|
||||
|
||||
### 1. Batch file generation
|
||||
|
||||
Generate fixed-size batch files (20 motions each) containing filled prompt templates with all motion context upfront. This avoids repeated DB queries per subagent:
|
||||
|
||||
```python
|
||||
for i, chunk in enumerate(chunks):
|
||||
batch_content = ""
|
||||
for motion in chunk:
|
||||
batch_content += f"MOTION_ID: {motion['id']}\n{prompt_template.format(...)}\n\n"
|
||||
write(f"/tmp/all_batch_{i:04d}.txt", batch_content)
|
||||
```
|
||||
|
||||
Always write exact motion IDs in each batch file so results can be matched back without ambiguity.
|
||||
|
||||
### 2. Politically neutral prompt
|
||||
|
||||
When scoring motions across the full political spectrum (not just right-wing), adjust the material impact scale to be politically symmetric:
|
||||
|
||||
- Scale point 5 should describe "fundamentele herstructurering van rechten, instituties of economische systemen" — not only right-wing actions like "inperking van rechten"
|
||||
- Include examples from both left and right: high-impact left motions (nationalization, wealth taxes, climate mandates) and right motions (asylum cessation, EU exit) should both reach the top of the scale
|
||||
|
||||
The SKILL.md file is read at runtime via `load_skill()`, so prompt changes take effect immediately without code changes.
|
||||
|
||||
### 3. Subagent dispatch pattern
|
||||
|
||||
Dispatch subagents in parallel waves of 5-8, each handling 5 batch files (100 motions):
|
||||
|
||||
```
|
||||
For each wave of 5-8 subagents (in parallel):
|
||||
For each subagent (handling 5 batch files):
|
||||
task(score-extremity skill, "Score these motions: {batch_content}")
|
||||
Wait for all to complete
|
||||
Collect results from /tmp/all_result_*.json
|
||||
Validate and store to DB incrementally
|
||||
```
|
||||
|
||||
Key: store results to DB after each wave, not after all waves. /tmp files can be cleaned up by the system, and subagent timeouts can lose data.
|
||||
|
||||
### 4. Anti-scripting guard
|
||||
|
||||
Subagents sometimes write Python scripts to batch-score motions instead of scoring directly in their reasoning. Add explicit instructions:
|
||||
|
||||
```
|
||||
IMPORTANT: Do NOT write Python scripts to score these motions. Score them
|
||||
directly in your reasoning, returning the JSON array. Do not use code
|
||||
to automate this — your reasoning and judgment IS the scoring mechanism.
|
||||
```
|
||||
|
||||
### 5. Incremental storage
|
||||
|
||||
Use `INSERT OR REPLACE` for idempotent writes:
|
||||
|
||||
```sql
|
||||
INSERT OR REPLACE INTO extremity_scores_all
|
||||
(motion_id, stijl_extremiteit, stijl_toelichting, materiele_impact, materiele_toelichting)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
```
|
||||
|
||||
This allows re-running waves without duplicate errors and makes the pipeline resumable.
|
||||
|
||||
### 6. Handling placeholder motions
|
||||
|
||||
Many motions in the database have only an outcome label ("Aangenomen." / "Verworpen.") with no text or layman explanation. These should be scored (1, 1) and the scoring subagent should detect and report this. Do not try to infer scores from metadata like controversy scores — this defeats the purpose of LLM-based scoring.
|
||||
|
||||
## Why This Matters
|
||||
|
||||
- **Cost**: Subagent-based scoring via deepseek v4 flash is ~$2-3 for 30K motions vs. $50-100+ via OpenRouter API at comparable scale
|
||||
- **Resumability**: Wave-by-wave DB storage means a timeout or crash loses at most one wave (~400-500 motions)
|
||||
- **Prompt agility**: SKILL.md changes propagate immediately to the next wave — no pipeline restart needed
|
||||
- **Independence**: Style and material impact dimensions maintain moderate correlation (r ≈ 0.43) even at scale, confirming they capture separable signals
|
||||
|
||||
## Examples
|
||||
|
||||
**Failed approach**: single monolithic subagent scoring all 30K motions. Times out, loses all progress.
|
||||
|
||||
**Working approach**: 1,184 batch files, ~80 waves of 5-8 subagents each, DB stored after each wave. 3-day pipeline, resumable, $3 total cost.
|
||||
|
||||
## Related
|
||||
|
||||
- `.opencode/skills/score-extremity/SKILL.md` — the scoring prompt and subagent workflow
|
||||
- `analysis/right_wing/extremity_score_all.py` — batch generation and orchestrator
|
||||
- `docs/solutions/best-practices/overton-extended-analysis-methodology-2026-05-26.md` — 2D scoring in Overton context
|
||||
@@ -0,0 +1,93 @@
|
||||
---
|
||||
title: Overton window analysis narrative architecture
|
||||
date: 2026-06-06
|
||||
category: best-practices
|
||||
module: analysis/right_wing
|
||||
problem_type: architecture_pattern
|
||||
component: development_workflow
|
||||
severity: medium
|
||||
applies_when:
|
||||
- "organizing multi-report analytical projects into a coherent narrative"
|
||||
- "connecting static reports to live dashboards"
|
||||
- "identifying gaps between parallel analytical tracks"
|
||||
tags:
|
||||
- overton-window
|
||||
- narrative-architecture
|
||||
- report-organization
|
||||
- dashboard-integration
|
||||
- quarto
|
||||
---
|
||||
|
||||
# Overton window analysis narrative architecture
|
||||
|
||||
## Context
|
||||
|
||||
The Overton window analysis produced 17 reports across `reports/overton_window/`, 3 live Streamlit Explorer dashboards, and a project-local scoring skill — but these pieces were built incrementally across sessions and never organized into a coherent narrative. The reports cross-reference each other inconsistently, overlap with dashboard data, and lack a clear reading order.
|
||||
|
||||
## Guidance
|
||||
|
||||
### 1. Three-tier narrative structure
|
||||
|
||||
Organize analytical outputs into three tiers, each with a different audience and purpose:
|
||||
|
||||
| Tier | Audience | Format | Content |
|
||||
|------|----------|--------|---------|
|
||||
| **Narrative spine** | Everyone | Quarto article (`.qmd`) | The coherent story: what happened, why, and what it means |
|
||||
| **Detailed appendices** | Researchers | Markdown reports in `reports/overton_window/` | Per-indicator deep dives with full methodology |
|
||||
| **Live exploration** | Power users | Streamlit Explorer tab | Interactive drill-down into the underlying data |
|
||||
|
||||
The narrative spine references appendices for detail. Appendices reference each other where analyses overlap. The live dashboard links back to the narrative via explanatory text.
|
||||
|
||||
### 2. Centrist definition must be consistent across all outputs
|
||||
|
||||
The strict 4-party definition (D66, CDA, CU, NSC) is the canonical one — it isolates the genuine center and produces cleaner signals. The 6-party definition (adding VVD, BBB) appeared in early iterations and survives in some reports. Every public-facing output must use the strict definition or explicitly note when the wide definition is used for comparison.
|
||||
|
||||
### 3. Live dashboards are part of the story
|
||||
|
||||
The Streamlit Explorer already shows the SVD compass (Tab A), party trajectories (Tab B), and component decomposition (Tab C) — all of which directly visualize Overton window dynamics. The gap is that:
|
||||
|
||||
- No tab explicitly labels itself as "Overton analysis"
|
||||
- No tab shows right-wing motion centrist support trends
|
||||
- No tab shows 2D extremity scoring results
|
||||
- The browser.py/search.py tabs exist but aren't wired
|
||||
|
||||
Adding a dedicated "Overton Window" tab or retrofitting the existing compass tab with an Overton context panel connects the static analysis to the live data surface.
|
||||
|
||||
### 4. Quarto bridges static reports and interactive dashboards
|
||||
|
||||
Static HTML (overton_report.html) is a dead-end artifact — it can't be updated without regeneration and can't be filtered or zoomed. Quarto `.qmd` files with embedded Plotly charts solve this:
|
||||
|
||||
- Interactive centrist support trend lines with hover tooltips
|
||||
- Filterable 2D extremity scatter plots
|
||||
- Linked views between SVD drift and centrist support
|
||||
- Self-contained HTML output with embedded data
|
||||
|
||||
The existing `plotly` dependency (6.6.0) works directly in Quarto's Jupyter engine.
|
||||
|
||||
### 5. Remove, don't accumulate
|
||||
|
||||
Not every report earned its place. Remove:
|
||||
- `findings_report.md` — fully superseded by synthesis
|
||||
- `blog_post.html` — replace with Quarto version
|
||||
- Duplicate analysis between breakpoint and synthesis — keep breakpoint as appendix only
|
||||
|
||||
### 6. Master build script for reproducibility
|
||||
|
||||
A single `analysis/right_wing/build_all_reports.py` that runs every analysis script in dependency order and verifies output existence. This guarantees that any future researcher can regenerate the entire Overton analysis from the same database state.
|
||||
|
||||
## Why This Matters
|
||||
|
||||
Without narrative architecture, a multi-session analytical project produces a fragmented artifact: individual reports are technically correct but nobody can follow the story from question to answer. The three-tier structure (narrative spine → appendices → live dashboard) maps to how different readers consume the work: skim the spine, drill into appendices for detail, explore the dashboard for their own questions.
|
||||
|
||||
## When to Apply
|
||||
|
||||
- Any analytical project that spans multiple sessions and produces more than 5 output files
|
||||
- When static reports overlap with live dashboards
|
||||
- When reports need to survive beyond the session that created them
|
||||
|
||||
## Related
|
||||
|
||||
- `reports/overton_window/overton_window_synthesis.md` — current master synthesis
|
||||
- `reports/overton_window/overton_report.html` — current static HTML deliverable
|
||||
- `.opencode/skills/score-extremity/SKILL.md` — 2D scoring methodology
|
||||
- `docs/solutions/best-practices/overton-window-shift-methodology-2026-05-24.md` — 7-step methodology
|
||||
Reference in New Issue
Block a user