Qipudata
San Francisco · v0.7.1

San Francisco Board of Supervisors decisions, 1906–2026

decisionsrelease v0.7.1CC0 1.0

About

Every item the San Francisco Board of Supervisors acted on from 1906 to 2026, as printed in its Journal of Proceedings and minutes. One row per item; an item read more than once can have more than one row. Each row links to the scanned page on the Internet Archive it was read from.

Where it comes from
Journal of Proceedings and meeting minutes of the Board of Supervisors, scanned by the San Francisco Public Library and held by the Internet Archive; recent minutes from sfbos.org. 93% of rows link to their archive.org page.
How it was read
The scanned text was split into items by rules. A language model (Claude Haiku) read the pages and wrote the one-line summaries; every model-written line is marked in summary_by.
How far to trust it
The release passed its automatic checks before it was published (what is checked). A hand check by the editor of qipu data is under way: 36 of 38 items checked so far were right, on votes, money, places and the map. A row says what the record states; the scanned page is the authority. Details
Licence
CC0 1.0: use it for anything, no permission needed. The scans and other sources keep their own rights.
Version
v0.7.1, published 21 October 2026. A published release is never changed; corrections come as a new release.
Technical details
Table
decisions, rows where city = 'sf'
Publisher
qipu
Source
SF Board of Supervisors, Journal of Proceedings (1906–1999) and meeting minutes (2000–2026), scanned by the San Francisco Public Library and held by the Internet Archive; recent minutes from sfbos.org
Temporal coverage
1906–2026
Spatial coverage
San Francisco, California
Rows
718,093
Columns
52
Distinct source pages
155,860
Rows citing an archive.org page
669,173 (93.2%)
Page link
exact on 620,576 rows; may be one or two pages off on 7,804; not page-level on 89,713
Instrument number
printed on 75,250 rows
Identifier
qipu:sf/decision/<identifier>|<item>
Version
v0.7.1, 21 October 2026
Licence
CC0 1.0. One-line summaries written by a model are marked in summary_by.
Formats
Parquet, SQLite; one page per decision in the record viewer

Rows

By origin

originRowsShare
v2 read page by page by decisions v2 (claude-haiku-5-5)344,93648.0%
bos_corpus items read from the Journal text by rules161,01522.4%
resweep items re-read by claude-haiku-5-5112,07915.6%
roll_call roll calls with no item text55,6927.8%
site map rows with no item behind them22,0503.1%
map_blocks decisions placed on blocks for qipu's map21,5923.0%
hand written by hand from the cited source7290.1%

By outcome

outcome_bestRowsShare
passed325,07645.3%
(not stated)153,88421.4%
referred80,87111.3%
passed first reading55,6047.7%
pending44,1886.2%
continued25,0443.5%
unknown12,8251.8%
refused10,0541.4%
tabled3,3430.5%
amended2,4890.3%

Rows without an outcome are mostly items the Journal records without a vote: communications, referrals, hearings.

By decade

DecadeRowsShare
1900s21,6653.0%
1910s64,1328.9%
1920s79,87411.1%
1930s47,2996.6%
1940s46,2136.4%
1950s50,3607.0%
1960s36,8605.1%
1970s62,4678.7%
1980s60,7048.5%
1990s58,8788.2%
2000s94,56013.2%
2010s63,5018.8%
2020s31,5804.4%

By author of the summary

Method and accuracy

Method

The Journal text (OCR of the Internet Archive scans) is split into items by rules, and titles are classified by rules with some model labels (run bos-corpus-2026-09). Items from the 1960s to the 2010s were re-read one at a time by claude-haiku-5-5 (runs resweep-d1960-haiku55-2026-10 and later). Decisions v2 (run sf-v21-haiku-1014, claude-haiku-5-5) read the Journal and minutes page by page for 1906–2016; where a v2 row and an earlier row describe the same decision, same_as links them. Roll calls are parsed by rules (20_rollcalls.py). Each item's page is mapped to the archive.org leaf number from the volume's scan data. Names of private people are withheld for 75 years.

Methodology · runs

Accuracy

The release passed its automatic checks before it was published (what is checked). A hand check by the editor of qipu data is under way: 36 of 38 items checked so far were right, on votes, money, places and the map. A row says what the record states; the scanned page is the authority.

Decisions v2 (run sf-v21-haiku-1014) against a key written by Opus 5.5 on 40 San Francisco pages, 115 decisions. The key has no record of a hand check; a Wilson 95% interval on 0.95 is about 0.89–0.98. Fields from the earlier runs are not measured.

FieldMetricValue
numberexact1.00
votes (counts)exact0.99
votesconfirmed on the linked page image / checked (Wilson 95% 0.85-0.99)0.97
moneyconfirmed on the linked page image / checked (Wilson 95% 0.85-0.99)0.96
findsrecall0.95
actionexact0.95
number+action+votesall exact0.95
vote namesexact0.95
moverexact0.93
topicsF10.90
placesconfirmed on the linked page image / checked (Wilson 95% 0.70-0.97)0.90
outcomesconfirmed on the linked page image / checked (Wilson 95% 0.73-0.94)0.87
moneyF1 (vs Opus key)0.80
interestSpearman0.78
placesF1 (vs Opus key)0.66
partiesF1 (vs Opus key)0.61
datesF1 (vs Opus key)0.55
relatedF1 (vs Opus key)0.17

Known limitations

  • Rows from decisions v2 and from the earlier runs can describe the same decision: 77,845 earlier rows are linked to their v2 row by same_as. Count distinct decisions with care.
  • Decisions v2 reads the previous page as context: in a 20-claim scan spot check, 18 quotes were on the linked page and 2 on the page before (v0.6 re-points them).
  • Block placement: from v0.5 a decision keeps a block only if a street named in its own text touches it, or a named site is within 400 m; 7.7% of placements moved to a street, a site or the city.
  • Numbers printed in the text are found by pattern; OCR errors (1G2 for 162) are not parsed.
  • The private-name filter is a pattern: it can miss a lone surname and hides some phrases that begin with a first name.

Columns 52

ColumnTypeCan be emptyPrivacyPublic copyDescription
decision_idVARCHARnononeas isqipu:sf/decision/<item id>: corpus items <volume>|<n>, re-swept items <volume>|g<n>, hand-built hand:<slug>, map/site-only rows map:..., su:..., sd:....
Values e.g. qipu:sf/decision/journalofproceed30sanfrich|1
Can be empty no · Privacy none · Public copy as is
item_idVARCHARyesnoneas isThe item inside its volume: <volume>|<n> (corpus), <volume>|g<n> (re-sweep), or a hand/map/site key.
Can be empty yes · Privacy none · Public copy as is
originVARCHARyesnoneas isHow the row came in: bos_corpus (rules over the Journal text), resweep (re-read by a model), roll_call (a roll call with no item text), map_blocks, site, hand, v2.
Values bos_corpus, hand, map_blocks, resweep, roll_call, site, v2
Can be empty yes · Privacy none · Public copy as is
yearBIGINTyesnoneas isThe year of the meeting.
Can be empty yes · Privacy none · Public copy as is
dateVARCHARyesnoneas isThe meeting date (YYYY-MM-DD) when known.
Can be empty yes · Privacy none · Public copy as is
date_fromVARCHARyesnoneas isWhere the date comes from (v0.6.1): record (the pass's own record), page: running head / page: page heading / page: meeting heading (the Journal page's printed meeting date before the item), page: heading of an earlier page / page: previous page heading (the last printed meeting date before the page), page: dated claims on the page.
Can be empty yes · Privacy none · Public copy as is
rollcall_idVARCHARyesnoneas isv0.6.1: the roll call of this decision's item (its last; it may be printed on the next page).
Can be empty yes · Privacy none · Public copy as is
decision_groupVARCHARyesnoneas isOne id per printed item (v0.6.1): rows of different passes over the same item (v1 corpus, resweep, v2, map, site, roll call) share it; it is the decision_id of the group's first row by pass. Count distinct decision_group for "how many decisions".
Can be empty yes · Privacy none · Public copy as is
kindVARCHARyesnoneas isresolution, ordinance, motion, bill, hearing, report ... as classified.
Can be empty yes · Privacy none · Public copy as is
headingVARCHARyesfree textprivate people's names withheld under the embargoThe item heading as printed (OCR).
Can be empty yes · Privacy free text · Public copy private people's names withheld under the embargo
plainVARCHARyesfree textprivate people's names withheld under the embargoThe run's one-line plain summary (model-written; see summary_by).
Can be empty yes · Privacy free text · Public copy private people's names withheld under the embargo
record_typeVARCHARyesnoneas isWhat the row records: decision, vote-outcome-only, report ...
Values cut-in-half, decision, departmental-work, index-row, page-furniture, public-comment, too-damaged, vote-outcome-only
Can be empty yes · Privacy none · Public copy as is
topicVARCHARyesnoneas isTopic label.
Can be empty yes · Privacy none · Public copy as is
subtopicVARCHARyesnoneas isFiner topic label.
Can be empty yes · Privacy none · Public copy as is
actionVARCHARyesnoneas isThe last action on the item (adopted, passed first reading, referred ...).
Values accepted, amended, appointed, appropriated, commended, granted, ordered, other, paid, refused, settled, voted-or-scheduled
Can be empty yes · Privacy none · Public copy as is
outcomeVARCHARyesnoneas isThe run's outcome (passed / refused / rejected / vetoed / pending / unknown).
Values amended, approved by voters, continued, passed, passed first reading, pending, referred, refused, rejected, rejected by voters, submitted_to_voters, tabled ...
Can be empty yes · Privacy none · Public copy as is
source_urlVARCHARyesnoneas isThe archive.org page of the item.
Can be empty yes · Privacy none · Public copy as is
blockVARCHARyesnoneas isAssessor block the item names, when it names one.
Can be empty yes · Privacy none · Public copy as is
streetsVARCHARyesfree textprivate people's names withheld under the embargoStreets the item names ("|"-separated).
Can be empty yes · Privacy free text · Public copy private people's names withheld under the embargo
amountsVARCHARyesnoneas isDollar amounts printed in the item (text).
Can be empty yes · Privacy none · Public copy as is
how_placedVARCHARyesnoneas isHow the item was placed on the map (block, street, no place given ...).
Values between two streets, names its own block, no place given, street address, street corner, street only
Can be empty yes · Privacy none · Public copy as is
classified_byVARCHARyesnoneas isWhat classified it: rule, form, model.
Values form, fund, near-duplicate, purpose-clause, record, rule, title
Can be empty yes · Privacy none · Public copy as is
hocr_leafBIGINTyesnoneas isPage index in the OCR (before the leaf map).
Can be empty yes · Privacy none · Public copy as is
page_exactBOOLEANyesnoneas isTrue when the page link was converted from the OCR leaf with the per-volume leaf map; false = may be a page or two off.
Can be empty yes · Privacy none · Public copy as is
whoVARCHARyesfree textprivate people's names withheld under the embargoWho the item concerns, in words (model-written).
Can be empty yes · Privacy free text · Public copy private people's names withheld under the embargo
place_textVARCHARyesfree textprivate people's names withheld under the embargoThe place as written in the item.
Can be empty yes · Privacy free text · Public copy private people's names withheld under the embargo
run_idVARCHARyesnoneas isThe run that read it (see runs).
Values resweep-d1960-haiku55-2026-10, resweep-d1970-haiku55-2026-10, resweep-d1980-haiku55-2026-10, resweep-d1990-haiku55-2026-10, resweep-d2000-haiku55-2026-10, resweep-d2010-haiku55-2026-10, sf-v21-haiku-1014, van-v21-haiku-1014
Can be empty yes · Privacy none · Public copy as is
addressVARCHARyesfree textprivate people's names withheld under the embargoThe street address the item names, if any.
Can be empty yes · Privacy free text · Public copy private people's names withheld under the embargo
amountBIGINTyesnoneas isThe main dollar amount, as a number.
Can be empty yes · Privacy none · Public copy as is
quoteVARCHARyesraw textleft out under the embargoRaw OCR text of the item. Not published for records under the embargo.
Can be empty yes · Privacy raw text · Public copy left out under the embargo
site_plainVARCHARyesfree textprivate people's names withheld under the embargoThe map's corrected one-line summary.
Can be empty yes · Privacy free text · Public copy private people's names withheld under the embargo
site_outcomeVARCHARyesnoneas isThe map's outcome value.
Values approved by voters, passed, refused, rejected, rejected by voters, vetoed
Can be empty yes · Privacy none · Public copy as is
site_idsVARCHARyesnoneas isThe map's row ids for this decision.
Can be empty yes · Privacy none · Public copy as is
outcome_bestVARCHARyesnoneas ispassed / refused / rejected / vetoed / pending / unknown (the map's value first, then the run's).
Values amended, approved by voters, continued, passed, passed first reading, pending, referred, refused, rejected, rejected by voters, submitted_to_voters, tabled ...
Can be empty yes · Privacy none · Public copy as is
plain_bestVARCHARyesfree textprivate people's names withheld under the embargoThe best one-line summary (the map's corrected line first).
Can be empty yes · Privacy free text · Public copy private people's names withheld under the embargo
instrument_idVARCHARyesnoneas isOrdinance/resolution number printed in the item (see instruments).
Can be empty yes · Privacy none · Public copy as is
outcome_fromVARCHARyesnoneas isWhere outcome_best came from (site, run, roll call ...).
Can be empty yes · Privacy none · Public copy as is
same_asVARCHARyesnoneas isAudit: the id this row was merged from (decisions v2 attached to v1).
Can be empty yes · Privacy none · Public copy as is
cityVARCHARnononeas issf or van.
Values sf, van
Can be empty no · Privacy none · Public copy as is
privacy_flagVARCHARyesnoneas ismay_name_private_person_after_1950 on Board text from 1952 on (records up to 1951 are open: the one cutoff, qipu_data/cutoff.py).
Values may_name_private_person_after_1950
Can be empty yes · Privacy none · Public copy as is
summary_byVARCHARyesnoneas isWho wrote the plain line (model name, "model-written; check the scan").
Values a model in the 2026-09 pipeline (model-written; check the scan), claude-haiku-5-5 (model-written; check the scan), qipu (hand-written from the cited source)
Can be empty yes · Privacy none · Public copy as is
statusVARCHARnononeas isWhat the Board did with this item at this reading, from the first rule that applies (status_from); never blank: not_recorded when nothing says (qipu_data/status.py, usability audit 19/10).
Values introduced, proposed, referred, continued, amended, hearing_held, first_reading, submitted_to_voters, recommended, claim_filed, demand_listed, reported ...
Can be empty no · Privacy none · Public copy as is
status_wordVARCHARnononeas isThe status in the word people see (proposed, referred, first reading, passed, adopted, vetoed, failed, withdrawn, claimed, listed for payment, recommended, reported, no status on record ...).
Can be empty no · Privacy none · Public copy as is
status_plainVARCHARnononeas isThe status in one plain sentence, e.g. "Sent to committee; no final vote found"; says when the matter went further later.
Can be empty no · Privacy none · Public copy as is
happenedVARCHARnononeas isdecided (finally passed, adopted, voters approved, veto overridden) / not_decided (proposed, referred, continued, first reading only, claim, recommendation) / failed (refused, tabled, withdrawn, vetoed) / unknown (no status on record).
Values decided, not_decided, failed, unknown
Can be empty no · Privacy none · Public copy as is
carried_outVARCHARnononeas isWhether what was decided was carried out (paid, built, demolished): only with its own evidence (carried_out_evidence); unknown = not confirmed. A decision to pay is not a payment.
Values True, False, unknown
Can be empty no · Privacy none · Public copy as is
carried_out_evidenceVARCHARyesnoneas isThe statement or record that shows it was carried out.
Can be empty yes · Privacy none · Public copy as is
status_fromVARCHARnononeas isWhere the status comes from: the instrument lifecycle stage of this reading, outcome_best, the v2 extraction, another reading of the same printed item, the printed roll call, a wording rule on the heading/summary/printed text, or none.
Values instrument_lifecycle, outcome_best, x_decisions, other_reading, roll_call, wording_rule, none
Can be empty no · Privacy none · Public copy as is
matter_statusVARCHARnononeas isThe furthest status of the whole matter (instrument lifecycle; else the same printed item; else the same title decided within 120 days; else this reading's own).
Can be empty no · Privacy none · Public copy as is
matter_happenedVARCHARnononeas ishappened, for the whole matter.
Values decided, not_decided, failed, unknown
Can be empty no · Privacy none · Public copy as is
matter_status_fromVARCHARnononeas isWhere matter_status comes from.
Values instrument_lifecycle, printed_item, same_title_120d, this_reading
Can be empty no · Privacy none · Public copy as is
plain_fixVARCHARyesnoneas isSet when plain_best was rewritten because it stated an open matter as done (rule_* = wording rule, model_haiku = rewritten by Claude Haiku and checked); plain keeps the original.
Can be empty yes · Privacy none · Public copy as is

Privacy: what kind of text the column holds. Public copy: what the published file does with it; the embargo covers records after 1951.

Preview

DateKindOutcomeSummaryPrinted page
8 November 1906resolutionpassedBoard tells Ocean Shore Railway to finish its stalled Potrero Avenue roadbed work at once, without further delay.page ↗
8 January 1908resolutionpassedPayment of $2,000 (≈ $74,876 in 2026 dollars) to Annie Galloway approved for a small lot added to the Jean Parker School site.page ↗
8 July 1940ordinancereferredTerms for leasing City airport land by competitive bid were referred to the Finance Committee.page ↗
23 September 1940resolutionpassedSupervisor Arthur M. Brown, Jr. granted a leave of absence from September 28 to October 12, 1940, with permission to leave the State.page ↗
11 March 1943otherreferredJack Smith requested higher pay for Rammer; Board moved to fix it at $11 (≈ $214 in 2026 dollars) per day and referred it to Civil Service.page ↗
19 May 1943otherpassedBoard approved $3,686 (≈ $71,790 in 2026 dollars) for War Memorial overtime payments.page ↗
26 May 1945ordinancenot readThe annual salary ordinance fixing city positions and pay for the fiscal year ending June 30, 1946 was taken up for second reading.page ↗
16 July 1945motionreferredSupervisor MacPhee's push for a new Juvenile Court Building was referred to the Public Health and Welfare Committee.page ↗

Five of 52 columns, for eight rows from 1906–1951 sampled at build time. The date opens the record; every column is in the Columns list above and in SQL.

Download

FormatFileSize
Parquetdecisions.parquet ↗89.2 MB
SQLite (all tables)qipu_sf.db ↗6.44 GB

SQL

SELECT year, date, plain_best, outcome_best, source_url FROM decisions WHERE city = 'sf' AND plain_best ILIKE '%Hunters Point%' ORDER BY date

Run in the SQL console (DuckDB in the browser, over the Parquet file).

Python

import duckdb duckdb.sql("SELECT * FROM 'https://tiles.qipu.org/data/releases/v0.7.1/parquet/decisions.parquet' LIMIT 5").show()