You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
`Motion` has a `belongs_to :agenda_item` association, but `ExtractVotesJob` never populates `agenda_item_id`. All motions currently have `agenda_item_id: nil`.
This means:
Cannot trace votes to topics — the chain `Vote → Motion → AgendaItem → AgendaItemTopic → Topic` is broken, so we can't show "history of votes on a particular topic"
Cannot show vote detail per agenda item — the meeting show page can't render database-backed vote grids per item
Why this matters now
The homepage redesign (Apr 10, 2026) creates a newspaper-style front page linking to topic pages. The topic page needs to be a credible landing page, but Key Decisions being empty for topics with clear votes (e.g., lead service lines has a $2.4M contract mentioned in its Record section but zero Key Decisions) makes the site look broken. This is the #1 blocker for making topic pages the primary homepage destination.
What Works Today
`Vote → Motion → Meeting` — member votes per meeting ✓
`Motion → Meeting → Committee` — which committee ✓
`Vote → Member` — who voted how ✓
What Needs to Change
`ExtractVotesJob` (which calls `Ai::OpenAiService#extract_votes`) needs to:
Include agenda item context in the extraction prompt — pass agenda item IDs and titles alongside the minutes text so the AI can match motions to items
Return `agenda_item_id` in the structured response for each motion
Populate `Motion.agenda_item_id` when creating/updating motion records
The AI already reads minutes text that contains motion descriptions adjacent to agenda item discussions. The matching should be straightforward for most motions. Some motions (like consent agenda batch approvals) may not map cleanly to a single item — those can have `agenda_item_id: nil` and that's fine.
Member voting record by topic: Group a member's votes by topic
Inline vote breakdown on meeting page: Database-backed vote grids per agenda item
Backfill
After fixing `ExtractVotesJob`, re-run for all meetings with minutes to populate `agenda_item_id` on existing motions. The job is idempotent (uses `find_or_create_by`).
Problem
`Motion` has a `belongs_to :agenda_item` association, but `ExtractVotesJob` never populates `agenda_item_id`. All motions currently have `agenda_item_id: nil`.
This means:
Why this matters now
The homepage redesign (Apr 10, 2026) creates a newspaper-style front page linking to topic pages. The topic page needs to be a credible landing page, but Key Decisions being empty for topics with clear votes (e.g., lead service lines has a $2.4M contract mentioned in its Record section but zero Key Decisions) makes the site look broken. This is the #1 blocker for making topic pages the primary homepage destination.
What Works Today
What Needs to Change
`ExtractVotesJob` (which calls `Ai::OpenAiService#extract_votes`) needs to:
The AI already reads minutes text that contains motion descriptions adjacent to agenda item discussions. The matching should be straightforward for most motions. Some motions (like consent agenda batch approvals) may not map cleanly to a single item — those can have `agenda_item_id: nil` and that's fine.
Enables
Backfill
After fixing `ExtractVotesJob`, re-run for all meetings with minutes to populate `agenda_item_id` on existing motions. The job is idempotent (uses `find_or_create_by`).
Not in Scope