Harmony Union School District is a small elementary district in west Sonoma County. Like every other small district in California, it hit 2026 with the COVID money gone and special ed costs climbing, which is a polite way of saying people were about to lose their jobs.
I was on the board until mid-2025. After that I did what private citizens do, which is show up at meetings and talk. I said a parcel tax was the only real way out. People nodded. Nothing happened.
Talk is free, so I wrote the thing instead: parcel-level revenue model, an audit of what §50079 actually lets a district do, and a precinct-by-precinct read on whether this could clear two-thirds. Districts normally buy this from a consultant. I did it in my kitchen, for free, out of civic feeling and spite in roughly equal proportion.
The board called the election on July 28, 2026. Voters decide November 3, 2026.
Posted in downtown Occidental. $75/parcel, four years, 65+ exemption, ~$177,600/year.
Model and memos are live at harmony-parcel-tax.netlify.app.
Mostly, with one honest loose end.
The notice projects $177,600/year, which at $75 is 2,368 parcels. That figure comes from CalMuni, the assessed-value and parcel data vendor used by Isom Advisors, the district's consultant — confirmed by their staff after I asked. Their series for Harmony:
| Fiscal year | Total secured parcels | Taxable parcels |
|---|---|---|
| 2021-22 | 2,687 | 2,353 |
| 2022-23 | 2,688 | 2,360 |
| 2023-24 | 2,693 | 2,361 |
| 2024-25 | 2,693 | 2,360 |
| 2025-26 | 2,565 | 2,368 |
I derive 2,354 taxable parcels for the same year. Fourteen parcels apart, and I can't fully account for it.
Three of the fourteen I can: parcels coded NON-TAXABLE (SONOMA COUNTY) that nonetheless carry real assessed value, which I exclude and a value-based count would keep. The remaining eleven are unexplained. For scale, CalMuni's own taxable count moves 15 parcels across their five years, and my 2,354 sits inside that band — so this may be definitional rather than an error by either of us. Resolving it needs their parcel list, which I've asked for. Working: diagnostics/diagnose_parcel_count_gap.py.
The drop in total parcels for 2025-26 has a clean explanation, and it exposes a limitation in my data. The assessor collapsed 100-plus legacy micro-lots at the St. Dorothy's Rest campground in Camp Meeker into a few consolidated parcels. My May 2026 shapefile still carries the pre-consolidation lots — 174 of my Harmony parcels are under 0.05 acres in Camp Meeker, and my total is 2,739 against their 2,565. Those lots are fully exempt, so nothing about taxable value changes, but my parcel universe is stale where I'd assumed it wasn't.
A note on how I got here, since the method is the point of this repo. Before learning the source, I reconstructed 2,368 as the county's WSCUHSD billable roll (2,398) less 30 senior exemptions. It matched to the parcel, and I treated the exactness as evidence. It was a coincidence — CalMuni's number is a straight taxable-parcel count with no exemption arithmetic in it. An exact match on a number you were aiming at is worth far less than it feels like — which is the same lesson I'd already written down two sections from here about my own feasibility memo, and then walked straight into again.
The disagreement about 14 parcels is worth $1,050/year. This is worth more, and it isn't a disagreement at all.
Neither count nets out the parcel tax's own exemption. CalMuni sells assessed-value data; the 65+/SSI/SSDI exemption is district-administered and application-based, so it cannot be in their number by construction. About 30 parcels in Harmony already hold that exemption against WSCUHSD's Measure B and would presumably file again — roughly $2,250/year off the top before a dollar of administration.
Then the administration itself. $177,600 is a levy, not a budget:
| Annual | |
|---|---|
| 2,324 paying parcels × $75 | $174,300 |
| County collection fee (0.85%) | −$1,482 |
| Exemption admin, §50075.3 reporting, oversight | −$2,662 |
| Election cost over the 4-year term ($25,000 ÷ 4) | −$6,250 |
| What the district can actually spend | $163,906 |
7.7% under the headline, about $13,700/year. On a measure this size that's a real person's hours.
And the 30 exemptions are a floor, not a forecast. Those are the people who filed against a tax nobody campaigned on; publicize a new one and more show up.
Two caveats on the record. The 0.85% collection fee is lifted from a Graton CSD direct-charge agreement, not confirmed with the ACTTC, and the $25,000 election cost is a guess — both are flagged as unverified in docs/model-notes.md and both should be nailed down with the county before anyone budgets against them. And the four-year term (Measure B got eight) doubles the annual election drag and puts a renewal fight on the 2030 ballot.
Gov. Code §50079 says a school parcel tax has to "apply uniformly to all taxpayers or all real property" and can't be "imposed on a particular class of property or taxpayers." That one sentence kills most of the clever things a spreadsheet is happy to do. Full audit in docs/legal-memo.md. Four things changed the model:
SB 1021 is not law. It would have expressly blessed per-square-foot, per-acre, class-based, and contiguous-common-ownership taxes. It passed the Senate and died in Assembly Revenue and Taxation on June 25, 2014. It is nonetheless cited all over the place as if it were on the books, including — this is the embarrassing part — by an earlier draft of my own legal page. Catching it flipped the risk ranking on three of the four structures I was modeling. Anyone who tells you per-acre is fine is probably citing a bill that died before their intern was born.
A residential-only or habitable-only square-footage base is a trap. That is precisely the class-based formula Borikas v. Alameda USD (2013) 214 Cal.App.4th 135 threw out. What makes it a trap is that the data supports it beautifully — the assessor hands you a dwelling-unit count field, so restricting to "just houses" is about four lines of code. I built it, then deleted it.
Uniform square footage with a per-parcel cap is fine, per Traiman v. Alameda USD (2023) 94 Cal.App.5th 89, review denied. With AB 2954 (2018) allowing a lower rate on unimproved land, that's the one variable structure with actual appellate cover: one formula for every improved parcel, flat rate for vacant.
Per-acre has no home in the statute. Its only authority was the bill that failed. Deleted too.
Measure B lets contiguous parcels under one owner get charged once. The naive way to model that is to zero those parcels out. That's wrong, and wrong in the direction that makes you underestimate revenue.
The contiguity rule is really a rule about what counts as a parcel. It fuses adjacent commonly-owned parcels into one taxable unit, so it cancels the per-parcel flat charge once for the group. But a per-square-foot charge attaches to buildings, and buildings don't merge when parcels do. Under a hybrid structure a contiguous group still owes square footage on every barn it owns.
Both implementations compute liability twice, once with the flat rate zeroed, and take the difference. That also handles a binding per-parcel cap, which is the case that bites you.
Modeling common ownership requires knowing who owns what. Gov. Code §7928.200 strips owner names and mailing addresses out of public assessor data, so the public file is useless for this.
So: CPRA the high school district for its full roll, which carries owner mailing addresses. Confirm they're mailing and not situs addresses (they differ on 59.7% of parcels, so yes). Normalize them into ownership keys. Then throw geometry at it, because a shared mailing address proves nothing — 53 parcels in the district share PO Box 48 in Graton, and they are not a contiguous estate, they're a property manager. Buffer every polygon 75 feet in EPSG:2226, build a graph, take connected components. That leaves 263 groups that are genuinely adjacent and 113 parcels that would actually qualify.
Which parcel is the "main" one? The homeowner's exemption flag is the best available proxy for "the owner sleeps here," ties broken on assessed value. It's a proxy. I've said so everywhere it matters.
My first feasibility pass was tidy and depressing: Harmony's 2024 bond passed with 56.6% against a 55% bar, a parcel tax needs 66.67%, so we're ten points short. Every North Bay pattern agreed — bonds sail, parcel taxes don't.
It was also comparing a bond to a parcel tax and a 55% threshold to a 66.67% one, which is not analysis, it's vibes with a citation. There was a much better comparator sitting right there: WSCUHSD's Measure B, a real $79 school parcel tax, on a real ballot, in front of substantially these same voters.
So I pulled the March 2020 precinct returns:
| Precinct | Yes | No | Total | Yes % |
|---|---|---|---|---|
| 7504 | 1,071 | 371 | 1,442 | 74.27% |
| 7506 | 412 | 163 | 575 | 71.65% |
| 5063 MB (mail) | 117 | 36 | 153 | 76.47% |
| 5070 MB (mail, n=23) | 9 | 14 | 23 | 39.13% |
| The two real Harmony precincts | 1,483 | 534 | 2,017 | 73.52% |
Not ten points short. About 6.8 points over. That turned the recommendation from "possible but risky" into "yours to lose," which is a very different conversation to have with a board.
Caveats stay: a March 2020 primary is not a November 2026 general, precinct lines don't sit exactly on district lines, and six points evaporates if someone organizes against you. Plan on ~73% with no opposition and ~70% as the floor.
Three parcels the current assessor shapefile calls NON-TAXABLE (SONOMA COUNTY) show up in the high school district's clean direct-charge roll under tax code 75301. They may be getting billed for a tax they don't owe.
They're sitting in docs/wscuhsd-billing-notices.md with APNs and values, and I have deliberately not made noise about it. A public assessor snapshot is not proof of a billing error, and the correct move is a polite question to the Auditor-Controller, not an accusation from a guy with a shapefile.
I pushed for the Traiman split: per-square-foot on improved parcels with a cap, flat rate on vacant land. The board went with flat $75.
Fine. It's the most bulletproof structure in California law and it fits on a mailer. I'm not on the board. I'll take it.
But I'm going to write down what it cost, because that's the whole point of having a model. Solve for the per-square-foot rate that raises identical revenue — $0.0298/sqft improved, $75 vacant:
| Flat $75 | Same money, sqft split | |
|---|---|---|
| Gross levy | $174,300 | $174,300 |
| Improved parcels paying under $75 | 0 | 1,212 (63.8%) |
| Median bill | $75 | $60 |
| 25th percentile | $75 | $38 |
| 90th percentile | $75 | $136 |
| Biggest single bill | $75 | $891 |
| Share of the improved levy paid by the top 10% | 10.0% | 28.7% |
Computed over the 2,324 parcels expected to pay: 1,900 improved, 424 vacant.
Same dollars in the door, and almost two-thirds of improved parcels pay less — which is to say every small cottage and every fixed-income household in the district. The flat tax buys its simplicity by charging a 900 square foot cabin exactly what it charges a 10,000 square foot second home with a view.
On a measure that needs two-thirds, that isn't only a fairness question. The median voter's bill is a campaign variable.
Anyway. The surface is already modeled for whoever runs the 2030 renewal: /sensitivity.
├── run_pipeline.py # runs the four below, stops on the first failure
├── harmony_classify.py # parcels → billing status, ownership groups, contiguity roles
├── generate_js_data.py # parcel attributes → JSON for the browser model
├── revenue_model.py # structure × exemption regime → gross and net
├── check_model_parity.py # proves the Python and JS models agree to the cent
├── export_parcel_lists.py # the taxable and exempt APN lists, with reasons
│
├── src/, public/ # Astro app: explorer, tax tables, legal, overhead, feasibility
│
├── docs/
│ ├── methodology.md # scope, structures, exemption categories, why
│ ├── legal-memo.md # §50079 audit: Borikas, Traiman, Dondlinger, SB 1021
│ ├── feasibility-memo.md # North Bay ballot record 2018–2025 and what it means
│ ├── data-notes.md # data dictionary, join keys, every trap I stepped in
│ ├── model-notes.md # implementation, invariants, development log
│ ├── wscuhsd-billing-notices.md
│ └── resolution-20260728B-parcel-tax-election.pdf
│
└── diagnostics/ # one script per question I had to actually answer
Source data isn't committed. County extracts are huge and the district rolls came in through CPRA. docs/data-notes.md says what every file is and where to ask for it.
conda env create -f environment.yml && conda activate parcel_tax
python run_pipeline.py
npm install && npm run buildThe parity check exists because the explorer needs the tax formula in JavaScript and the sweeps need it in Python, and two copies of the same formula always drift eventually. It runs both across six structures and three exemption regimes — 36 comparisons on gross and net — and kills the pipeline if any pair differs by more than a penny.
Heavy LLM assistance, throughout, for the code and the research and the prose. I'm saying that up front because pretending otherwise is both dishonest and beside the point. The tools are fine. The question is what you did to check their work, and that's where the hours went.
Things checking caught: the SB 1021 citation my own page was leaning on. A file whose preamble described its own filters incorrectly, which I only found by taking the 332 excluded parcels and the 2,398 included ones and comparing them field by field until the real discriminator fell out. A CPRA response that Excel had quietly mangled into scientific notation on half its assessment numbers — I reconstructed it to about 93% confidence and then threw the reconstruction away and asked for a clean file, which is what you should do with a 93% reconstruction. DBF column names truncated to ten characters, so that Building_2 means BuildingPrimaryUnitCount, and guessing wrong gets you a tax base that's confidently incorrect. And a feasibility memo that was internally consistent and built on the wrong comparison.
Cleaning this up for publication meant running the pipeline instead of believing the docs about the pipeline, which turned up three more: the parity check had been silently dead for months (importing from a directory I'd retired, passing two parameters the model no longer takes), the projection sweep crashed on one of those same dead parameters so the CSVs couldn't be regenerated at all, and the data step was writing into the old web/ folder, meaning the deployed site wasn't getting refreshed by the pipeline that claimed to refresh it. Fixed, all three. That's what rot looks like in a repo nobody's run in three months, and it's why "the docs say it works" isn't a claim about anything.
Every load-bearing number in docs/ traces to a script in diagnostics/ or to a primary source — statute, published opinion, Auditor-Controller report, or certified election return. Anything a model produced and nobody checked isn't in here.
Under 300 students: free. Small districts can't justify a consultant, and small districts are exactly where a parcel tax is the last lever available. I watched that from the inside for a few years.
Over 300 students: $5,000 flat. Which includes:
- 10 hours of my actual time with your staff or board — on the front end to scope it and pressure-test the assumptions, on the back end to sit with the board and explain what the numbers do and don't say. Not a PDF over the transom.
- My own research into your political and demographic situation. Your precinct returns on comparable measures, your local ballot history, who's actually in your electorate, and where your real threshold sits. Not a national average.
Either way you get what's in this repo, built on your data:
- Your tax base, rebuilt from assessor and Auditor-Controller records, with zero-value, non-taxable and exemption-eligible parcels pulled out and every classification traceable to why.
- A revenue model across structures and exemption regimes, reported net of realistic collection and admin overhead, because the gross number is what gets a district embarrassed at the second board meeting.
- A legal read on which structures you can actually put on a ballot under §50079 and current case law, cited to primary sources rather than to whatever a bond firm's brochure says.
- A feasibility read off your own precinct returns and your county's ballot record.
- The interactive model, so when a trustee asks "what if we capped it at $2,000," somebody can answer in ten seconds instead of buying another engagement.
One practical limit: §50079 parcel taxes are a California thing, and the legal analysis is California-specific. The data engineering travels anywhere. The case law does not.
This is not legal advice. It's research and arithmetic. Have your counsel read any measure language before it goes anywhere near a ballot, and confirm collection fees and election costs with your own county before you budget against them.
Andrew Cone — andrewpcone@gmail.com
Method questions and district inquiries both welcome. Email, or open an issue.
