- name
- legislative-monitoring
- description
- Voting pattern analysis, committee effectiveness, bill tracking, parliamentary oversight for Swedish intelligence operations
- license
- Apache-2.0
# Legislative Monitoring Skill
## 🔴 AI FIRST Quality Principle
> **This skill MUST be applied with the AI FIRST principle: never accept first-pass quality. ALL analysis and content MUST go through minimum 2 complete iterations. After first pass, read ALL output back completely and systematically improve every section — strengthen evidence, deepen analysis, add specific citations, broaden perspectives. Spend ALL allocated time on real work. Single-pass output is NEVER acceptable. NO SHORTCUTS.**
## Purpose
This skill provides comprehensive legislative monitoring capabilities for the Riksdagsmonitor platform, enabling systematic tracking of parliamentary activities, voting patterns, committee effectiveness, bill progression, and oversight mechanisms. It transforms raw parliamentary data into actionable intelligence for understanding legislative dynamics, predicting policy outcomes, and assessing institutional effectiveness within the Swedish Riksdag.
## When to Use This Skill
Apply this skill when:
- ✅ Tracking bill progression through legislative process
- ✅ Analyzing voting deviation patterns within and across parties
- ✅ Assessing committee productivity and effectiveness
- ✅ Monitoring parliamentary oversight activities (questions, interpellations)
- ✅ Predicting legislative outcomes based on historical patterns
- ✅ Identifying cross-party collaboration opportunities
- ✅ Evaluating individual parliamentarian productivity
- ✅ Detecting legislative obstruction or procedural manipulation
- ✅ Measuring government vs. opposition effectiveness
- ✅ Tracking amendment success rates and strategic positioning
- ✅ Tracking Riksrevisionen (RiR) audit findings and constitutional skrivelse deadlines
- ✅ Monitoring government accountability for audit recommendations
- ✅ Generating overdue-deadline alerts for unanswered RiR reports
Do NOT use for:
- ❌ Manipulating legislative processes through intelligence
- ❌ Interfering with democratic parliamentary procedures
- ❌ Undermining legitimate opposition activities
- ❌ Violating parliamentary privilege or confidentiality
## Legislative Monitoring Framework
### Five Core Analytical Dimensions
The Riksdagsmonitor platform monitors Swedish parliamentary activities across five critical dimensions to provide comprehensive legislative intelligence:
```mermaid
graph TB
subgraph "Legislative Data Collection"
A1[🗳️ Voting Records<br/>3.5M+ votes<br/>1971-present]
A2[📄 Bill Tracking<br/>89K+ documents<br/>Full lifecycle]
A3[👥 Committee Activity<br/>15 committees<br/>Productivity metrics]
A4[🔍 Oversight Actions<br/>Questions, interpellations<br/>Accountability measures]
A5[🤝 Cross-Party Collaboration<br/>Co-authorship networks<br/>Coalition patterns]
end
subgraph "Legislative Intelligence Analysis"
A1 --> B1[Deviation Pattern Analysis]
A2 --> B2[Bill Success Prediction]
A3 --> B3[Committee Effectiveness Assessment]
A4 --> B4[Oversight Effectiveness Tracking]
A5 --> B5[Coalition Stability Measurement]
end
subgraph "Intelligence Products"
B1 --> C1[Voting Intelligence]
B2 --> C2[Legislative Forecasts]
B3 --> C3[Institutional Health Reports]
B4 --> C4[Accountability Metrics]
B5 --> C5[Coalition Analysis]
end
subgraph "Strategic Intelligence"
C1 & C2 & C3 & C4 & C5 --> D[📊 Legislative Dashboard]
D --> E[Policy Outcome Predictions]
D --> F[Institutional Risk Assessment]
D --> G[Coalition Stability Forecasts]
end
style A1 fill:#e1f5ff
style A2 fill:#e1f5ff
style A3 fill:#e1f5ff
style A4 fill:#e1f5ff
style A5 fill:#e1f5ff
style D fill:#ffe6cc
style E fill:#ccffcc
style F fill:#ffcccc
style G fill:#fff9cc
```
## 1. Voting Deviation Pattern Analysis
### Party Discipline Measurement
Voting deviation from party lines reveals internal party conflicts, ideological tensions, and coalition instability. The Riksdagsmonitor platform tracks these patterns with temporal granularity.
**Database Views:**
- `view_riksdagen_vote_data_ballot_politician_summary_daily` - Daily voting patterns
- `view_riksdagen_vote_data_ballot_politician_summary_monthly` - Monthly aggregates
- `view_riksdagen_vote_data_ballot_politician_summary_annual` - Annual trends
- `view_riksdagen_politician_ballot_summary` - Career-wide voting statistics
- `view_riksdagen_politician_decision_pattern` - Decision pattern classification
### Deviation Intelligence Framework
```java
@Service
public class VotingDeviationAnalyzer {
/**
* Analyzes voting deviation patterns to understand party discipline.
*
* Intelligence applications:
* - Identify factional splits within parties
* - Predict coalition stability
* - Assess leadership control
* - Detect ideological realignment
* - Forecast party breakaway risks
*/
public DeviationIntelligence analyzePartyDeviation(
String partyId,
LocalDate startDate,
LocalDate endDate
) {
String sql = """
WITH party_voting AS (
SELECT
v.ballot_id,
b.vote_date,
b.issue_category,
b.issue_subcategory,
b.vote_outcome,
-- Party position (mode of party votes)
MODE() WITHIN GROUP (ORDER BY v.vote) as party_position,
-- Deviation metrics
COUNT(*) as party_member_votes,
COUNT(DISTINCT v.vote) as vote_diversity,
-- Rebel identification
COUNT(CASE
WHEN v.vote != (MODE() WITHIN GROUP (ORDER BY v.vote))
THEN 1 END
) as rebel_count,
-- Rebel percentage
COUNT(CASE
WHEN v.vote != (MODE() WITHIN GROUP (ORDER BY v.vote))
THEN 1 END
)::float / NULLIF(COUNT(*), 0) * 100 as rebel_percentage,
-- Identify specific rebels
ARRAY_AGG(
CASE
WHEN v.vote != (MODE() WITHIN GROUP (ORDER BY v.vote))
THEN p.person_id::text
END
) FILTER (WHERE v.vote != (MODE() WITHIN GROUP (ORDER BY v.vote))) as rebel_ids
FROM vote v
JOIN ballot b ON v.ballot_id = b.ballot_id
JOIN person p ON v.person_id = p.person_id
WHERE p.party = :partyId
AND b.vote_date BETWEEN :startDate AND :endDate
GROUP BY v.ballot_id, b.vote_date, b.issue_category,
b.issue_subcategory, b.vote_outcome
),
deviation_patterns AS (
SELECT
issue_category,
COUNT(*) as total_votes,
AVG(rebel_percentage) as avg_deviation_rate,
MAX(rebel_percentage) as max_deviation_rate,
STDDEV(rebel_percentage) as deviation_volatility,
-- High-deviation votes (>15% rebels)
COUNT(CASE WHEN rebel_percentage > 15 THEN 1 END) as high_deviation_votes,
-- Identify consistent rebels
(
SELECT person_id, COUNT(*) as rebel_count
FROM UNNEST(ARRAY_AGG(rebel_ids)) as person_id
GROUP BY person_id
ORDER BY COUNT(*) DESC
LIMIT 10
) as top_rebels
FROM party_voting
GROUP BY issue_category
)
SELECT
p.party as party_id,
p.party_name,
-- Overall deviation metrics
AVG(dp.avg_deviation_rate) as overall_deviation_rate,
MAX(dp.max_deviation_rate) as peak_deviation,
AVG(dp.deviation_volatility) as avg_volatility,
-- High-risk categories (high deviation)
ARRAY_AGG(
dp.issue_category
ORDER BY dp.avg_deviation_rate DESC
) FILTER (WHERE dp.avg_deviation_rate > 10) as high_risk_categories,
-- Discipline classification
CASE
WHEN AVG(dp.avg_deviation_rate) < 3 THEN 'HIGHLY_DISCIPLINED'
WHEN AVG(dp.avg_deviation_rate) < 7 THEN 'MODERATELY_DISCIPLINED'
WHEN AVG(dp.avg_deviation_rate) < 12 THEN 'LOW_DISCIPLINE'
ELSE 'FRACTURED'
END as discipline_classification,
-- Risk assessment
CASE
WHEN AVG(dp.avg_deviation_rate) > 15
OR MAX(dp.max_deviation_rate) > 30
THEN 'CRITICAL_INSTABILITY'
WHEN AVG(dp.avg_deviation_rate) > 10
OR MAX(dp.max_deviation_rate) > 20
THEN 'HIGH_FRACTURE_RISK'
WHEN AVG(dp.avg_deviation_rate) > 5
THEN 'MODERATE_TENSION'
ELSE 'STABLE'
END as stability_risk
FROM party p
JOIN deviation_patterns dp ON 1=1
WHERE p.party = :partyId
GROUP BY p.party, p.party_name
""";
return jdbcTemplate.queryForObject(sql, DeviationIntelligence.class,
Map.of(
"partyId", partyId,
"startDate", startDate,
"endDate", endDate
));
}
}
```
### Deviation Pattern Taxonomy
| Deviation Rate | Discipline Level | Political Implications | Intelligence Assessment |
|----------------|------------------|----------------------|------------------------|
| **< 3%** | HIGHLY_DISCIPLINED | Strong leadership control, unified ideology | Reliable coalition partner |
| **3-7%** | MODERATELY_DISCIPLINED | Occasional dissent, manageable tensions | Generally stable, monitor key issues |
| **7-12%** | LOW_DISCIPLINE | Frequent internal conflicts, weak leadership | Coalition risks, factional monitoring needed |
| **> 12%** | FRACTURED | Severe internal divisions, leadership crisis | High breakaway risk, unstable partner |
### Strategic Intelligence Applications
```python
from typing import Dict, List
import pandas as pd
import numpy as np
class DeviationIntelligenceAnalyzer:
"""
Applies deviation pattern intelligence to strategic assessments.
Intelligence products:
1. Coalition stability forecasts
2. Leadership vulnerability assessment
3. Policy area risk mapping
4. Factional structure identification
"""
def assess_coalition_stability(
self,
coalition_parties: List[str],
date_from: str,
date_to: str
) -> Dict:
"""
Assesses coalition stability through deviation pattern analysis.
Coalition stability factors:
- Intra-party discipline (low deviation = stable)
- Cross-party voting alignment (high alignment = stable)
- Deviation trend (increasing deviation = instability)
"""
query = """
WITH coalition_deviation AS (
SELECT
p.party,
b.vote_date,
b.issue_category,
-- Party deviation rate
COUNT(CASE
WHEN v.vote != (
SELECT MODE() WITHIN GROUP (ORDER BY v2.vote)
FROM vote v2
JOIN person p2 ON v2.person_id = p2.person_id
WHERE p2.party = p.party
AND v2.ballot_id = v.ballot_id
) THEN 1 END
)::float / NULLIF(COUNT(*), 0) * 100 as deviation_rate
FROM vote v
JOIN person p ON v.person_id = p.person_id
JOIN ballot b ON v.ballot_id = b.ballot_id
WHERE p.party = ANY(%s)
AND b.vote_date BETWEEN %s AND %s
GROUP BY p.party, b.vote_date, b.issue_category, v.ballot_id
),
cross_party_alignment AS (
-- Measure voting alignment between coalition parties
SELECT
p1.party as party_a,
p2.party as party_b,
COUNT(CASE WHEN v1.vote = v2.vote THEN 1 END)::float /
NULLIF(COUNT(*), 0) * 100 as alignment_rate
FROM vote v1
JOIN person p1 ON v1.person_id = p1.person_id
JOIN vote v2 ON v1.ballot_id = v2.ballot_id
JOIN person p2 ON v2.person_id = p2.person_id
WHERE p1.party = ANY(%s)
AND p2.party = ANY(%s)
AND p1.party < p2.party -- Avoid duplicates
GROUP BY p1.party, p2.party
)
SELECT
cd.party,
AVG(cd.deviation_rate) as avg_deviation,
STDDEV(cd.deviation_rate) as deviation_volatility,
-- Trend analysis (linear regression slope)
REGR_SLOPE(
cd.deviation_rate,
EXTRACT(EPOCH FROM cd.vote_date)
) as deviation_trend,
-- Cross-party alignment (average with coalition partners)
(SELECT AVG(cpa.alignment_rate)
FROM cross_party_alignment cpa
WHERE cpa.party_a = cd.party OR cpa.party_b = cd.party
) as coalition_alignment
FROM coalition_deviation cd
GROUP BY cd.party
"""
results = pd.read_sql(
query,
self.connection,
params=[coalition_parties, date_from, date_to,
coalition_parties, coalition_parties]
)
# Calculate coalition stability score (0-100)
stability_components = []
for _, party in results.iterrows():
# Component 1: Low deviation (40% weight)
deviation_stability = max(0, (100 - party['avg_deviation']) / 100) * 40
# Component 2: High cross-party alignment (40% weight)
alignment_stability = (party['coalition_alignment'] / 100) * 40
# Component 3: Stable trend (20% weight)
trend_stability = max(0, 20 - abs(party['deviation_trend']) * 10)
party_stability = deviation_stability + alignment_stability + trend_stability
stability_components.append({
'party': party['party'],
'stability_score': round(party_stability, 2),
'deviation': round(party['avg_deviation'], 2),
'alignment': round(party['coalition_alignment'], 2),
'trend': round(party['deviation_trend'], 4)
})
# Overall coalition stability (average weighted by party size)
overall_stability = np.mean([p['stability_score'] for p in stability_components])
return {
'coalition_parties': coalition_parties,
'analysis_period': f"{date_from} to {date_to}",
'overall_stability_score': round(overall_stability, 2),
'party_stability': stability_components,
'stability_classification': self._classify_stability(overall_stability),
'risk_assessment': self._assess_stability_risks(stability_components)
}
def _classify_stability(self, score: float) -> str:
"""Classify coalition stability."""
if score >= 80:
return "HIGHLY_STABLE"
elif score >= 65:
return "MODERATELY_STABLE"
elif score >= 50:
return "UNSTABLE"
else:
return "CRITICAL_INSTABILITY"
def _assess_stability_risks(self, components: List[Dict]) -> List[str]:
"""Identify specific stability risks."""
risks = []
for party in components:
if party['deviation'] > 12:
risks.append(f"{party['party']}: High internal deviation ({party['deviation']}%)")
if party['alignment'] < 70:
risks.append(f"{party['party']}: Low coalition alignment ({party['alignment']}%)")
if party['trend'] > 0.01:
risks.append(f"{party['party']}: Increasing deviation trend")
return risks if risks else ["No significant risks detected"]
```
## 2. Committee Effectiveness Assessment
### Parliamentary Committee Intelligence
Committees are the workhorses of legislative bodies. The Riksdagsmonitor platform measures their productivity, influence, and effectiveness.
**Database Views:**
- `view_riksdagen_committee_decisions` - Committee decision tracking
- `view_riksdagen_committee_document` - Committee-produced documents
- `view_riksdagen_committee_member_activity` - Individual member contributions
- `view_committee_effectiveness_metrics` - Composite effectiveness measures
### Committee Productivity Metrics
```sql
-- Comprehensive Committee Effectiveness Assessment
WITH committee_activity AS (
SELECT
c.org_code,
c.committee_name,
c.policy_area,
-- Document production
COUNT(DISTINCT cd.document_id) as total_documents,
COUNT(DISTINCT CASE WHEN cd.document_type = 'committee_report'
View on GitHub