Decisions (Fede, 2026-08-03): Q1 = A, schema-derived injected knowledge block. Q2 = no output guard — rely on injection + generated evals (risk accepted: no runtime check stands between a small model's bad day and an outbox; the gauntlet and replay corpus are the containment). Q3 = straight to general — the narrow deposit-fix worktree is retired.
Ship gate (Fede): hard proof that the new solution is better than current prod — on all eligible real past conversations plus synthetic data — before anything ships. Protocol below; nothing merges until the proof artifacts are attached and reviewed.
The ask (Fede, 2026-08-03): stop fixing this one deposit field. Make Clara able to answer anything that's in the property knowledge base on email/SMS — and route anything that isn't — without hand-writing every fact into a tool description. Three premises are taken as direction, not open questions:
| Block | Shape | Examples | Reaches email today? |
|---|---|---|---|
pricingDetails | ~19 structured fields + customFees |
securityDeposit, petFee/Deposit/Rent, adminFee, applicationFee, parking, storageFee, holdingDeposit, transferFee, mtmFee, earlyTerminationMultiplier, nsfFee, utilitySetupFee, unauthorizedPetFee, keyFobDeposit, lateFee | No — only via tools the model may not call |
sections | free-text policy cards (doc-ingested, human-confirmed) | Pet Policy, Smoking, Laundry, Lease Terms | Yes — rendered as PROPERTY POLICIES |
concessions | free text | "1 month free on 12-mo leases" | Yes — LEASING SPECIALS |
| hours / links / phones | structured | office hours, application link | Yes |
So the gap is precisely the structured facts block — the one with the dollar amounts,
where being wrong hurts most. Voice already injects it ({{pricing_fees}}, INJECT-4);
email deliberately excludes it from the prompt and reaches it only through tool selection.
Clara's email brain already gets handed the property's policies, specials, and office hours on a card. The fee sheet — the thing prospects ask about most — was left off the card, and she was told "go look it up if you think you need to," with a catalog whose labels didn't say where the deposit was. The fix is to put the whole fee sheet on the card, generated from the database so it can never go stale, and mark every blank line as "not on file" so she knows when to hand off to a human instead of guessing.
Injection makes correct answers possible; it doesn't stop a small model from inventing a number anyway (Haiku fabricated "$1,350 = one month's rent" under the always-route rule). The hallucination guard already verifies dollar amounts against renewal offers — the same pattern can verify leasing replies: any dollar amount / numeric fact in an outbound email/SMS leasing reply must trace to the injected knowledge block or a tool result from this turn.
The narrow fix (RULE 7.0 deposit clause + tool description + eval cases 13/13b) sits proven but
unshipped in worktree propflowai-deposit-quote, with one Haiku tour-pushiness regression
open. The general fix replaces most of it: the injection block supersedes the description edit, and a
general "answer what's on file, route what isn't" rule supersedes the deposit-specific clause.
"Deposit ON FILE → quote it" was one hand-authored case; the general fix gets a generated knowledge-grounding gauntlet:
pricingDetails schema, two cases are generated
automatically: value on file → the reply must cite it; value absent → the reply must
route, and must not contain any invented figure. Add a field to the schema and its test cases
exist the same day — the eval can no longer lag the data model.evals/replay-harness/ (real prod
conversations through the real loop, parity + judge) runs baseline-vs-candidate over the 117-conversation
corpus before the cutover PR merges — the strongest available evidence that nothing else moved.Two arms, both run against the candidate build and current prod (baseline), same inputs, same graders. The PR does not merge until both pass and Fede has reviewed the artifacts.
evals/replay-harness/ runs the full eligible corpus — 117 real
customer email/SMS conversations, 291 inbound turns — through the real inbound loop, baseline vs
candidate (~640 model calls per arm).pricingDetails field × on-file
("must cite it") and absent ("must route, must not invent") × Sonnet and Haiku × 3 repeats —
roughly 230 graded runs, on the subscription runner.Proof artifacts (parity report, divergence review, gauntlet JSONs both arms) attach to the cutover PR. This PR does not auto-merge regardless of green — Fede reviews the proof.
conversation-manager.ts:3160/3348, voice injection leasing-context-injection.ts:371,
no forced tool_choice or fee router anywhere in the conversation loop). Corpus and replay figures from
evals/replay-harness/ README census 2026-08-02. Token-cost figure is an estimate until
measured.