Measured on real traffic — 2026-08-17 overnight

Honesty Gate — Overnight Numbers

You asked for real data instead of theory, from a real harness, with no simulation and no live side effects. Overnight we built the actual gate (merged, off by default, three PRs), ran it through two real harnesses — the sandboxed conversation-replay harness (real inbound loop, real model, outbound suppressed) and an offline replay of the gate over every real customer turn from the last 30 days — and labeled every flag adversarially (two independent reviewers per flag + a tie-breaker, all with the full conversation record). This page is the numbers, next to each open decision on the redesign page.

489real customer turns, last 30 days, all channels & properties
51turns the gate would touch (11%) — 47 hold, 4 repair, 0 block
19 / 32real catches vs false alarms after adversarial labeling (37%)
5:1catch-to-noise on SMS — the channel where it would enforce first
~$1/mojudge model cost at current volume (Haiku, 235 calls)

What got built and merged tonight (all off by default)

Finding 1 — how often Clara actually says something unsupported

Out of 451 evaluated real turns in 30 days, the gate flagged 51. Adversarial labeling (defaulting to "the gate is wrong" unless the record clearly shows an unsupported claim) split them:

ChannelTurns/moReal catchesFalse alarmsPrecision
SMS795183%
Email924357%
Voice (post-call review only — never in the call path)282102826%
All489193237%

What the 19 real catches look like (each verified against the full record): an invented $6.50 admin fee; a wrong deposit amount contradicting the $500 on file; a wrong tour date stated as fact; a tour "confirmed" with no booking made; a reschedule to 2 PM told to a real customer with the system still showing 1 PM; "I've passed this to the property team" with no escalation ever fired; an invented disability-accommodation detail (fair-housing adjacent); a follow-up promised after the escalation tool had failed.

The sharpest single catch: the "honest" replacement message that August's reverted guard sent to real customers — "I've passed this to the property team and they'll confirm a time with you" — was itself an unsupported claim: no escalation ever fired on those turns. The old guard's safety copy fabricated a handoff. The new gate flags exactly that turn, and pairs it with a repair (fire the real escalation) instead of new canned text.

Both false-alarm causes are identified and fixable, so 37% is a floor, not the ceiling:

What the gate misses (false negatives): re-judging 40 turns the gate passed found 11 with real unsupported claims — almost all voice-call summaries asserting prices/quotes where the record can't confirm what was said. Coverage on voice needs transcript-grade input, not the call summary.

Finding 2 — latency (your constraint: zero added to voice)

MeasurementNumberMeaning
Judge answer time (no cache, offline)p50 3.3s · p95 5.5sToo slow to sit inside an SMS reply as-built (SMS turn is ~7s median today). Zero cache hits tonight — prompt caching and a trimmed evidence pack are the obvious levers, unmeasured.
With the production 2.5s timeout74% of judge calls time out → fail openThe shipped default hides most of the signal. Inline enforcement can't rely on the judge as-built.
End-to-end in the real loop (harness, gate on vs off)+0.7s medianSmall because the judge only runs on claim-bearing turns (~26%) and times out at 2.5s.
Voice0ms added, by constructionVoice is evaluated after the call only. Nothing was added to the call path.

Practical read: the judge fits async shapes today — flag after send for review, or hold-then-send on email where seconds don't matter — and fits inline SMS only after caching/trimming work proves p95 under ~1.5s.

Finding 3 — cost

235 judge calls over 30 days of full traffic ≈ 504k input + 77k output tokens on Haiku ≈ about $1/month at today's volume. The overnight measurement itself ran on the subscription (no metered keys). Cost is not a factor in this decision.

Finding 4 — what a review queue would actually feel like

Bonus findings the harness surfaced (pre-existing, not the gate)

The decisions, now with numbers

1. How often the judge runs

Data says: run it on every claim-bearing turn — it's ~8 calls/day and ~$1/month — but let it enforce nothing yet. 37% precision (and 26% on voice) is not enforcement-grade; SMS at 83% is close. Fix the two named input gaps (transfer-tool semantics, knowledge-base grounding), re-run this same replay, and gate any enforcement on the reading. The rerun is one command now.

2. Gate tool execution too?

Data says yes, it has real material: the renewal-offer tool's 75% failure rate, and a labeled-real case where Clara promised follow-up right after the escalation tool failed fatally. A tool-outcome-aware gate ("don't let the reply contradict what the tools just did") addresses both; review already forced the design through the same-turn escalation constraint, so the risky interaction is mapped.

3. Voice

Resolved by you (no added call latency) and confirmed by data: voice is where the claims are (10 of 19 real catches, and most of the misses) — but it's all post-call review material. The one build item the data demands: evaluate against the transcript, not the call summary, and teach the judge the transfer tools.

4. Nightly replay job

The economics changed tonight: the full 30-day replay ran in ~10 minutes for ~$1 on the subscription, from an existing script on the mini — no CI credentials problem. A nightly (or weekly) cron on the mini producing this same redacted report is now trivial; the original "multi-week infra project" framing applied to GitHub-CI-hosted replays, not this.

Suggested next step

One increment, fully measurable: fix the two judge input gaps → re-run this replay → if SMS/email precision holds ≥80%, turn on repair-only enforcement (the 0/166 pattern) for text channels at one property, with every fire feeding the Grading Playground. Everything else stays off until its own replay clears the bar. The 19 labeled catches are queued for your 👍/👎 in the Playground to turn model labels into human ground truth.

Method & honesty notes

Sources: three merged PRs (gate; harness extension; offline replay — repo docs/planning/policy-gate-spec.md holds the spec); offline replay over all 489 real-person turns July 18–Aug 17 from production traces (read-only; drafts for guard-blocked turns are the as-sent text); sandboxed harness runs over the 55-conversation/199-turn eligible corpus (real loop, outbound suppressed, writes to the dev table only); labels from two independent adversarial model reviewers per flag + tie-breaker — not yet human-verified; treat precision as an estimate until you grade the 19 in the Playground. Judge ran with a relaxed 15s measurement timeout (the shipped 2.5s default hides 74% of signal — that number is itself a finding). Voice rows judge the call summary, not a full transcript. Harness latency deltas are from the harness environment, not prod. No customer was contacted; nothing is enabled in production; the gate remains off everywhere.

Measurement 2 — Aug 30 to Sep 13

Measured — read-only, nothing shipped

We ran the same check again, three and a half weeks later, this time only on real customer messages and calls (not test traffic): 1,502 turns from Camellia, Yale 25 Station, and Western Slope. We left out the Willows test property's 881 turns — that's our practice property, not real customers.

The rate of Clara saying something made-up dropped from about 4 in every 100 conversation turns (Aug 17) to about 1 in every 200 (Sep 13):

MeasureAug 17Sep 13
Made-up facts per 100 turns3.890.53
Share of turns the checker flagged10.4%1.7%
Of flagged turns, how many were real problems37%16%

We found 8 real problems this time, not 19 — but we also checked far fewer turns by hand, so this is a floor, not the full picture. Most were Western Slope voice calls where Clara said a tour was booked or confirmed when it wasn't; one was a text that quoted a wide rent range instead of the one real price on file. Western Slope's call volume here is almost entirely Fede's own practice calls before go-live, not real prospects, so don't read it as customer traffic yet.

Three reasons this number understates the real rate, not overstates it: the automatic checker timed out on 56–92% of its checks and skipped them entirely, so its "16% real" figure is counting fewer checks than it should; the 0.53 only comes from the turns that got flagged plus a spot-check of 40 "looked fine" turns out of roughly 1,485 — most passed turns were never hand-reviewed; and 12 turns were lost to a technical parsing error and never checked at all.

Source: ~/agents/006/kb-honesty-measurement-2026-09-13.md and the matching redacted .json. Method: real production turns replayed through the same gate as the Aug 17 run, each flagged turn double-reviewed blind by two AI reviewers with a third settling disagreements, plus a 40-turn spot-check of turns the gate passed. No prompt, knowledge base, or code changed; nothing was sent to a customer; the gate remains off everywhere.

PropFlow Docs