Context
Split out from the #24 umbrella (Track C). Implements the bill cluster: populates canonical.bills, canonical.bill_titles, canonical.bill_actions, canonical.bill_sponsorships, canonical.bill_versions from WSL SOAP. Depends on P1a (#23) and benefits from P1b (#27) being in place (sponsorship FK targets).
Spec sketch: docs/specs/2026-06-18-transformation-wsl-soap.md#L189-L206.
WSL operations in scope
LegislationService.GetLegislationByYear(year) + GetLegislation(biennium, bill_id) — bill records.
- Discovery:
GetLegislationIntroducedSince(date) + GetLegislationStatusChanges(date) — the first real discover(since) windows.
GetLegislationTypes — one-off lookup seed.
Open design questions (resolve in the P1c plan before implementation)
bill_type_id lookup seeding. Seed LegislationService.GetLegislationTypes as "P1c step zero" (a one-off bootstrap, like the synthetic anchors) before the bill normalizer runs.
discover(since) shape + cursor state. Bills are the first entity needing change-detection windows. Decide cadence (per-day refresh; per-hour during session) and where "last successful discover" lives — likely a new SyncState-like table in the adapter/canonical schema. This is the main architectural decision of the cut; give it its own spec subsection.
- Sponsorship polymorphism.
BillSponsorship can be by Person or Organization (committee sponsorship). P0.5 hybrid IA already made person_id nullable + added committee_id; the normalizer must populate the correct one.
- Vote scope. Decide: chamber-level vote summary on
Bill only, or full per-legislator detail via LegislationService.GetRollCalls? Recommend deferring full roll-call detail to a separate P1d unless cheap.
Deliverables
Related
Context
Split out from the #24 umbrella (Track C). Implements the bill cluster: populates
canonical.bills,canonical.bill_titles,canonical.bill_actions,canonical.bill_sponsorships,canonical.bill_versionsfrom WSL SOAP. Depends on P1a (#23) and benefits from P1b (#27) being in place (sponsorship FK targets).Spec sketch:
docs/specs/2026-06-18-transformation-wsl-soap.md#L189-L206.WSL operations in scope
LegislationService.GetLegislationByYear(year)+GetLegislation(biennium, bill_id)— bill records.GetLegislationIntroducedSince(date)+GetLegislationStatusChanges(date)— the first realdiscover(since)windows.GetLegislationTypes— one-off lookup seed.Open design questions (resolve in the P1c plan before implementation)
bill_type_idlookup seeding. SeedLegislationService.GetLegislationTypesas "P1c step zero" (a one-off bootstrap, like the synthetic anchors) before the bill normalizer runs.discover(since)shape + cursor state. Bills are the first entity needing change-detection windows. Decide cadence (per-day refresh; per-hour during session) and where "last successful discover" lives — likely a newSyncState-like table in the adapter/canonical schema. This is the main architectural decision of the cut; give it its own spec subsection.BillSponsorshipcan be byPersonorOrganization(committee sponsorship). P0.5 hybrid IA already madeperson_idnullable + addedcommittee_id; the normalizer must populate the correct one.Billonly, or full per-legislator detail viaLegislationService.GetRollCalls? Recommend deferring full roll-call detail to a separate P1d unless cheap.Deliverables
bills,bill_titles,bill_actions,bill_sponsorships,bill_versions.docs/plans/— leads with thediscover(since)cursor design.bill_typelookup seed (step zero).SyncState-like discover-cursor table + migration (if chosen).Related