class AEChair(BaseModel):
"""An AE Chair with chairing history, pipeline status, and cross-conference service."""
name: str = Field(
description="Full name, e.g. 'Mathias Payer'. May include DBLP disambiguation suffix.",
examples=["Mathias Payer"],
)
display_name: str = Field(
description="Human-readable name without disambiguation suffix.",
examples=["Mathias Payer"],
)
affiliation: str = Field(
description="Current institutional affiliation, e.g. 'EPFL', 'MIT'.",
examples=["ETH Zurich"],
)
country: str | None = Field(
default=None,
description="Country of the institution, e.g. 'Switzerland'. Null if unresolved.",
examples=["Switzerland"],
)
continent: str | None = Field(
default=None,
description="Continent of the institution, e.g. 'Europe'. Null if unresolved.",
examples=["Europe"],
)
total_memberships: int = Field(
ge=0,
description="Total AE roles (chair + member) across all conferences and years.",
examples=[7],
)
chair_count: int = Field(
ge=1,
description="Number of conference-years served as AE chair.",
examples=[3],
)
member_count: int = Field(
ge=0,
description="Number of conference-years served as regular AE member (total_memberships - chair_count).",
examples=[4],
)
conferences: list[AEMembership] = Field(
description="All AE committee memberships (both chair and member roles).",
)
area: str = Field(
description="Research area: 'systems', 'security', or 'both'.",
examples=["systems"],
)
years: dict[str, int] = Field(
description="Year (string key) → number of AE roles that year.",
examples=[{"2023": 2, "2024": 1}],
)
first_year: int | None = Field(
default=None,
description="Earliest year of any AE service (chair or member).",
examples=[2019],
)
last_year: int | None = Field(
default=None,
description="Most recent year of any AE service.",
examples=[2025],
)
first_chair_year: int | None = Field(
default=None,
description="Year of first chairing role.",
examples=[2021],
)
chaired_series: list[str] = Field(
description="Conference series chaired, e.g. ['OSDI', 'EUROSYS'].",
examples=[["OSDI", "ATC"]],
)
chaired_conferences: list[AEMembership] = Field(
description="Only the chair-role entries from conferences list.",
)
promoted_from_member: bool = Field(
description="True if this person served as regular AE member before first chairing.",
examples=[True],
)
years_to_chair: int | None = Field(
default=None,
description="Years between first member role and first chair role. Null if not promoted from member.",
examples=[2],
)
model_config = {"extra": "forbid"}