joey.hersh

systems / secondhome

SecondHome

Source-to-score qualification with a reason on every record

A score without a reason is just a guess with confidence.

Period
July 2026
My role
Product lead and sole author. 223 commits in a twelve-day sprint, working with a real-estate operator as the intended user.
State
Working MVP with a demo, an acceptance packet, and a thousand passing tests.
  • 20+County connectorsscraped portals and open-data feeds
  • 1,039Tests passingreal fixtures from captured portal payloads
  • 23Schema migrations
  • 2Independent signals before a contact counts
  • Python
  • Postgres
  • FastAPI
  • Windmill
  • Next.js
  • MCP
  • Anthropic API
  • Playwright
an isometric county map tile with property parcels outlined, a magnifying glass hovering, small pins with tiny glow
Twenty county sources, one schema, a written reason on every score.
source-to-score.flow: architecture flowadjustmentsCounty recordsforeclosure · tax · evictionforeclosure · tax · evict…Normalizeone schemaone schemaEnrichmentownership · equity · skip traceownership · equity · skip…Agent skills17 bounded tasks17 bounded tasksContact confidenceidentity · authority · reachabilityidentity · authority · re…Scoring engineversioned weightsversioned weightsCall rationalefrom evidencefrom evidenceCaller briefsources · confidence · whysources · confidence · whyOperator reviewcapturedcaptured

Diagram nodes, in flow order: County records (foreclosure · tax · eviction); Normalize (one schema); Enrichment (ownership · equity · skip trace); Agent skills (17 bounded tasks); Contact confidence (identity · authority · reachability); Scoring engine (versioned weights); Call rationale (from evidence); Caller brief (sources · confidence · why); Operator review (captured).

deterministic code model judgment human durable state tool / API

The problem

Distressed-property leads are cheap to list and expensive to qualify. A broker can't research eight hundred foreclosure filings a month. The economics only work if a machine does an unreasonable amount of work per lead and then tells a human, honestly, which ones deserve a phone call and why.

The architecture

Public records come in through county-specific connectors, twenty-plus of them, some of which reverse-engineer ancient government web portals and work around their bugs. Everything is normalized into one schema that keeps the original source on every field. Enrichment providers add ownership, equity, event timing, and contact data behind a shared interface, so a vendor can be swapped without touching the scoring.

Seventeen bounded agent skills do the fuzzy parts: extraction, maturity inference, decision-maker ranking, street-view condition, contradiction detection, and the caller brief itself. Each skill is a versioned task spec loaded by content hash, and the agent's system prompt has hard rules against foreclosure-rescue language.

Every distress signal carries a source class, official or vendor or agent, and every field carries an epistemic label: hard, inferred, estimated, or agent judgment. Contact channels are scored on identity, authority, reachability, and eligibility with named floors, and a channel needs at least two independent signals before it's promoted to primary.

The score is a deterministic, versioned formula over persisted evidence: opportunity value times distress severity times urgency, adjusted by confidence, contactability, and freshness decay. It does no I/O, so the number on the screen composes exactly from the components you can inspect. Then a model writes a plain-language rationale from that evidence, and the whole thing lands in a caller brief served to the operator's app and, through an MCP server, to their agent.

I set three boundaries early. Downstream access is read-only. Scoring is client-specific, not a universal number. Nothing transfers a score without its provenance.

What happened

The product existed. Twelve days, 223 commits, a Next.js review app, a demo script, and an acceptance packet. A thousand tests pass against captured portal payloads. The commercial partnership didn't close, and I'd rather show a good system that didn't sell than hide it.

What I kept

Every scoring system I've built since carries a written reason. It's the cheapest form of explainability there is, and it's the one users actually read.

SecondHome, in twenty-five seconds

SecondHome reads twenty county sources, keeps the source on every field, scores each lead with a formula you can inspect, and writes the reason to call before anyone dials.