Expanded candidate data contracts, version 1.0.0
These additive contracts describe research candidates and reviewed canonical expanded
records. They do not modify the legacy inventory or state-policy CSVs. The existing codebook's
moratorium grain and exclusion of permanent bans remain unchanged. A successful
validation is structural consistency, not proof of legal effect, source accuracy,
identity, completeness, or permission to publish. An initial reviewed snapshot writer now supplies separate
identity, evidence, field-review and atomic-publication gates; reviewed canonical
records currently cover 57 reviewed proposal and measure records: 53 mapped frozen-cohort publications, Jay's separately reviewed solar ballot, Wilmington's litigated initiative, Bethel's town-meeting question and an Augusta notice-only question. Three frozen candidate payloads remain withheld; the Augusta record may overlap one of them, so those payloads are not additional disjoint contests. Its sector, result, ordinance linkage and final wording remain unresolved. Result supersession remains explicit. The restriction/link migration now includes Edgewater’s proposed charter restriction with unknown legal status and an accepted proposes relationship. For Edgewater, no adoption/effect event or current force is inferred. The Coachella history migration adds a separate adopted prohibition and qualified policy-predecessor relation without establishing effectiveness, formal termination or present force; broader migration remains incomplete. See the
generated results view. Identity decisions have a separate
append-only registry.
Authoritative paths and CSV projections
The path decision is now explicit:
| Path | Authority and purpose |
|---|---|
data/moratorium_inventory.csv |
Authoritative legacy local-instrument inventory; its existing IDs and denominator remain separate from ballots. |
data/state_legislation.csv |
Authoritative legacy state-policy inventory. |
data/expanded/<table>.jsonl |
Current reviewed expanded records, reached through one relative snapshot pointer. Resolve the pointer once for a multi-table read. |
data/expanded-snapshots/<generation>/<table>.jsonl |
Immutable expanded generation retained with its publication receipt; generation fingerprint covers the complete JSONL table set. |
data/identities/expanded.jsonl |
Append-only identity allocation and lineage, not automatic acceptance of domain facts. |
data/expanded-csv/<table>.csv |
Derived convenience projection selected by an atomic relative pointer; never an import or editing authority. |
data/expanded-csv-snapshots/<projection>/ |
Immutable CSV generation. Its manifest pins the source JSONL generation, publication receipt, schema, exporter and each output hash. |
work/ candidate and review packets |
Research/provenance inputs; publication requires separate identity, evidence and field-review gates. |
Every one of the fifteen schema tables has a same-named CSV projection, including
header-only tables when no records are published. measure_results.csv retains
all historical observations. The additional measure_results_current.csv view
removes only observations named in explicit supersession chains. It preserves
multiple current county parts or other reporting scopes for the same measure.
No vote categories, turnout, certification or legal outcome are inferred.
CSV columns follow the published schema and preserve original field names/IDs. Strings use ordinary CSV quoting, including multiline text. Numbers and booleans use JSON scalar spelling; arrays/objects remain compact JSON in one cell. Null or absent values become empty cells rather than zero. This convenience projection cannot distinguish an absent value, null and an empty string; JSONL is the exact typed authority for that distinction and for restore/import. The manifest includes column lists, record counts and hashes, not a claim of completed research coverage.
CSV downloads and manifest are generated
from a single pinned source. scripts/build_expanded_csv.py --check verifies every
byte, file set, selected generation and download link. make data regenerates;
make check detects drift. Release bundles include both relative pointers and
both selected generation trees. Projection publication does not renew the source
facts, certification or legal-force review.
Files and validation
The canonical publication selects validation profile 1.0.4
for the unchanged schema_version: "1.0.0" record format. The event contract
and validity publication protocol bind exact event claims,
review validity, retained history and source/legal limits. Bound publication readers dispatch
from the authenticated receipt. For standalone candidate validation select --profile 1.0.4
explicitly; its retained default is 1.0.1. The original schemas remain retained for
frozen fixtures and historical receipts.
The compound-condition contract supports nested clause logic introduced under 1.0.3 and retained by 1.0.4. A source-reviewed publication adds twelve proposed clauses to two existing provisions; absent clauses leave legacy flat grouping unspecified. No legal force or extraction accuracy is inferred.
JSON Schema 2020-12 contains a named
$defs schema for each JSONL table. Every record has schema_version: "1.0.0".
Use UTF-8, one object per line, in files named <table>.jsonl. Missing tables are
allowed and mean no records supplied, not that the universe was searched. Unknown
JSONL filenames and duplicate IDs within a table fail. Examples in
synthetic jurisdiction fixture are entirely
invented; ZZ and example.invalid are deliberately fictitious.
~/projects/bc/bc-modules/.venv/bin/python scripts/expanded_data.py \
work/schemas/expanded/fixtures/synthetic
~/projects/bc/bc-modules/.venv/bin/python -m unittest discover -s tests -p test_expanded_data.py -v
Use --moratoria data/moratorium_inventory.csv and/or --state-actions
data/state_legislation.csv when tagged references use those legacy types. The
validator reads these CSVs only to resolve their ID columns; missing files,
columns, or IDs fail. Restrictions resolve to the supplied JSONL records. The CLI
is read-only and returns 0 for valid input and 1 for invalid input. Its certified
count is current explicitly certified result observations, not measures or
legal instruments; independent observations may describe the same measure. Only
explicit supersession removes an observation from that count. It is a diagnostic,
not a public tally. Missing rows and unresolved references cannot establish absence.
Grains and semantics
The classification definitions specify the development-relative advisory axis, contest-count reporting scope, statutory roles and actor/electorate/territory distinctions. A mechanism describes the proposition, not its winning side. These definitions do not renew source review or silently relabel historical observations.
An election link may identify an intended event. The Clarksville proposals provisionally group matching city referendum calls, with joint final administration explicitly unconfirmed in election type, measure notes and field decisions. Their unknown date bounds retain the exact conditional call in original text; neither alternative is selected. The link establishes neither final placement nor an actually held joint ballot. Later evidence may require registry identity reconciliation. Petition-only proposed voting effects remain source observations while final effect fields are unresolved.
The table definitions are jurisdictions, elections, ballot_measures,
measure_provisions, measure_results, local_restrictions, instrument_events,
measure_instrument_links, source_documents, claims, review_decisions,
search_runs, search_attempts, search_sightings, and coverage_observations.
Each table's singular ID field is its key. IDs are opaque and must be allocated
from a reviewed, collision-checked registry; the
identity registry now supplies explicit UUID allocation,
observation aliases and merge/split lineage. It performs no identity inference and
does not promote domain records. Names and titles
are not keys. Distinct same-name governments must have distinct IDs. This first
validator requires a measure and its election to use the same jurisdiction ID;
overlapping administrative and electoral jurisdictions need a future explicit
relationship contract rather than a guessed equivalence.
A measure record may describe a proposed initiative linked to its intended election,
including a proposal whose placement was litigated or refused. The election foreign
key alone does not establish ballot appearance or voting. litigated records a
source-qualified litigation history; dated claims and the scope note retain any
reported placement refusal and judicial disposition without asserting later status.
No placeholder result is created for a proposal with no reviewed vote observation.
Count all proposal/measure records, recorded lifecycles, voted measures and current
result observations separately. A source-supported placement refusal or writ denial
is not an electoral defeat or an operative restriction.
A source-backed measure can have unresolved sector attribution: an empty sectors
array means unknown, not no infrastructure relevance. It remains in the overall
proposal/measure count, while sector-specific counts require an explicit reviewed
sector label. A general zoning title does not establish a data-center restriction.
Missing full wording or an unproved result/instrument crosswalk may leave those
fields and links unresolved without automatically excluding the independently
identified measure. Scope inclusion and identity still require substantive review;
schema validity alone does not establish either.
A measure has independent lifecycle, bindingness, yes-direction and referendum
polarity. Provisions capture mechanisms, covered uses, exemptions, and thresholds
with original unit, measurement basis, aggregation and scope. An election result
is an observation with separate reported and calculated outcomes and explicit
certification. A complete precinct count does not certify a result. For a
mechanically calculated outcome this version uses the stated denominator, threshold
and strict or inclusive comparison. It reverses restricts/facilitates for a defeated
question; mixed, neutral and unresolved remain as stated. A direction is not a
legal-effect assertion. Unspecified totals stay null, never zero. The validator
allows optional outcome_direction_basis to distinguish calculated (the default
for legacy candidates), reported, and unresolved. A reported basis requires a
source_reported value method for reported_outcome and a matching claim scoped
to that exact result observation. It does not invent a passage rule, certify the
result, establish legal effect, or override contradictory calculable arithmetic.
The validator
checks arithmetic only when inputs are available, and compares reported percentages
to the chosen denominator with 0.11 percentage point rounding tolerance.
Optional yes_no_votes records the arithmetic sum without inventing total valid
votes or turnout; blank_votes remains distinct from overvotes and undervotes.
Optional source_vote_categories preserve original labels/counts such as VOIDS,
without mapping them to blanks, other votes, undervotes or overvotes. Optional
source_vote_totals preserve printed totals with their original label and an
explicit scope. Neither field supplies a denominator or changes standard counts.
Each item requires nonnegative count and supporting claim IDs. Every claim must
match the exact result, source document, predicate (source_vote_category or
source_vote_total) and complete label/count/scope value. Duplicate label/scope
entries and forced mapping keys are rejected. Absent fields remain compatible
with earlier snapshots. Public summaries display these observations separately.
Optional result reporting_scope records geographic coverage with a kind
(jurisdiction_total, jurisdiction_part, or unknown) and a nonblank
description. A county portion of a village is a separate observation from
another county portion; neither is a village-wide result. Public summaries label
the scope and preserve separate rows without summing them. Missing legacy scope
is displayed as scope not recorded, not inferred to be the whole electorate.
New scope fields require the same evidence and field-level publication review as
other result assertions. Historical snapshot bytes are unchanged.
Supersession cannot change a known whole/part kind, drop known scope, or replace one named jurisdiction part with another. A fresh county-part return can supersede an older observation for that same named part; a different part or whole-jurisdiction return needs its own observation. These rules prevent a later county release from silently replacing a village-wide result. This field does not establish certification, derive a combined result, or determine the source's vote-percentage denominator.
value_methods identifies text, OCR, visual review, source reporting or derivation
per result field with supporting claim IDs. Optional provision/restriction
duration distinguishes enactment, adoption, effectiveness and applicability anchors;
no dates are equated without source/legal review. It retains calendar months/years
versus days, the legal anchor and its
uncertain date; it does not automatically calculate an operative expiration.
Complicated passage rules should remain unknown and be described in evidence;
they cannot be represented or calculated completely by this first increment.
instrument is a tagged reference (moratorium, restriction, or state_action)
so legacy identifiers do not collide. Accepted measure-to-instrument relations
require a current accepted decision scoped to that exact relation, and each
supporting claim needs its own current accepted decision scoped to its predicate.
Claims identify the document version and their subject. Accepted decisions require
supporting claim IDs, and those claims must address the target. A claim decision
uses that claim itself as its supporting ID; this records review of the source
assertion, not independent corroboration. Superseded decisions do not count as
current; competing successors fail. An advisory measure cannot itself enact or
uphold an instrument through an accepted link. Independent subsequent adoption
requires its own event and evidence. An advisory result never creates an active
moratorium: this validator generates no instrument or status at all.
Source records distinguish payload and extracted-text hashes and retain retrieval, access and publication classification. Create a new document ID when bytes change; old claims keep their original document reference. Search ledgers retain attempts, errors, retries, sightings, run scope and spend; null spend means unknown, not free. Coverage observations describe a bounded search, not proof of absence. These contracts do not check URL bodies, quote spans, rights, reviewer competence or whether the cited source actually supports a claim.
scripts/audit_refresh_returns.py adds a separate pre-review check against retained
bounded-client artifacts: declared source hashes, independently located excerpts,
and candidate seed coverage against the frozen discovery list. A payload-only
document with null text hash can pass payload accounting but cannot prove a text
claim. Visual claims require their own reviewed source/page/render provenance;
an unlocated text quote is not automatically a visual claim. The audit does not
promote candidates or establish legal effect, and its success cannot substitute
for substantive review. Frozen seeds describe that source list, not a full census.
Earlier pilot evidence is reusable only through its pinned input manifest and
fresh body/text hash checks. The audit explicitly records universal newline
decoding where required to reproduce the original pilot text hash; it does not
silently replace source bytes. Additional omission leads have their own frozen
registry and bounded recovery jobs, distinct from the initial 50-seed list.
scripts/build_ballot_census.py compiles terminal ballot packets into a separate
review snapshot. Every packet gets its own ID namespace, including claim subjects,
result revisions and value-method claim references; external legacy instrument IDs
and free-form source values remain unchanged. Explicit identity decisions pin both
measure records before grouping aliases. Grouping does not delete observations or
accept legal effect. A reviewed input overlay must match its review receipt's
output hashes. The builder refuses to overwrite snapshots and records input and
expanded-output hashes. Combined unreviewed claims remain private until excerpt
and evidence review; the public census manifest is not canonical ballot promotion.
Visual transcription reviews require a pinned claim, values, source PDF hash,
page and rendering parameters. visual_claim_review.py rehashes the retained PDF
and reproduces the approved page-image hash. This verifies the reviewed rendering
chain, not the reviewer judgement, election certification or legal effect. The
return audit reports visual verification separately from located text evidence.
Reviewed overlays are audited separately from unmodified worker returns. Each
overlay must match its receipt's output hashes; accepted claim decisions are
checked against verified evidence. An accepted result transcription does not
accept the measure's bindingness or legal implementation.
Dates and limitations
date_bounds has inclusive earliest/latest possible dates, precision and
original text. day requires equal non-null bounds; unknown precision requires
null bounds. Jurisdiction validity and coverage periods use [start, end);
convert source-inclusive end dates only with evidence and retain original wording.
Full timestamps require a UTC offset and are kept distinct from date-only facts.
Adoption, effective date and applicability start are separate. When known bounds
establish retroactivity, require an explanation and an applicability-start claim;
validation does not adjudicate that claim. Null or overlapping bounds do not imply
chronology. Duration remains source text; calendar months and years are not
converted into 30/365-day terms, and expiry is not calculated. The legacy
duration_days field has historical conversion assumptions described in the
codebook and is not reinterpreted here.
The schema/fixture increment does not itself complete the P1 pilot review or validate legal chronology, certification evidence, external instrument status, independent result revisions or all passage rules. Identity allocation, scoped reviewed publication and the derived CSV projections now have separate working gates. Broader pilot-case review and migration remain open. Certification and active-status counts must come from reviewed, scoped evidence and a declared cutoff, not merely from structural validation.
Durable citations and acquisition identity
Source documents may carry an optional HTTP(S) citation_url for a reviewed,
durable public citation, such as the parent post of a CDN-hosted image. Public
summaries prefer it for navigation. The original url and body/text hashes still
identify the acquired version; a citation URL never supplies substitute evidence
or authenticates its publisher. Earlier snapshots without this field retain their
existing URLs and remain unchanged.
Optional event validity profile
Profile 1.0.2 adds explicit event review validity and typed correction evidence without rewriting existing event records. A source generation selecting it gains separate retained, current-accepted and status CSV views. The five-event migration introduced profile 1.0.2 after source review; the compound-clause publication selected 1.0.3, and current profile 1.0.4 preserves those safeguards while adding qualified policy succession. Event validity means acceptance of a historical source-supported action, not current legal force.
Qualified policy succession
Profile 1.0.4 adds a typed successor-adoption event and predecessor reference, with a mandatory qualification that policy succession does not establish formal termination, overlap or current force. It preserves the earlier profiles and their receipts. The current publication receipt identifies which profile its data actually uses; the Coachella migration now selects it, with ten total historical events and two restriction records. These counts do not establish current legal force. Source and field review remain mandatory, and automatic extraction stays pinned to the earlier supported candidate schema.