Post-transfer tour extraction: incident fix & eval proof

2026-07-29 · Fix shipped in #4861 (merged) · Eval runner in #4870 · Author: Fede + Claude

The incident (2026-07-28)

A prospect called Camellia, was transferred to a human, and agreed to a same-day tour ("maybe this afternoon… around three thirty"). The post-transfer transcript extractor — which had no idea what day the call happened — invented the date 2024-01-16. That past-dated tour was auto-confirmed and calendar-synced, but was invisible to every "upcoming tour" filter, so:

Same bug class as the July 17 email-pipeline RCA — "the AI never decides the calendar, code does" — whose doctrine never reached this extractor.

The fix (#4861, merged + prod-verified)

Eval: replay of every real prod post-transfer transcript

All 17 usable human-leg transcripts in prod (of 193 rows with a transcript stamp; the rest are empty), replayed through the extraction prompt on the subscription runner, graded against hand-labeled gold. 4 are tour-relevant, 13 are negatives (vendor calls, voicemails, delinquency, availability).

ArmPromptModelResultNotes
old-haikupre-#4861 (no anchor)claude-haiku-4-515/17Reproduced both prod past-date hallucinations (2024-01-16, 2024-07-19). Window guard blocks both.
new-haiku (prod)#4861 (anchored)claude-haiku-4-517/17Both incident dates resolved correctly; zero false tours on negatives.
new-sonnet#4861 (anchored)claude-sonnet-4-617/17Clean with the byte-exact prod prompt (see the prompt-fidelity finding below).

Findings

Decision: no architecture change now

The proposed fold of leasing post-transfer into the maintenance-style gather/judge Temporal workflow is shelved — the simple fix is proven on real data. The ladder, if evidence ever changes:

  1. This eval is the standing measuring stick (scripts/eval-post-transfer-extraction-subscription.ts, --mine refreshes the corpus from prod).
  2. If within-window date misses appear: emit spans from the LLM and resolve dates deterministically via tour-date-decision.ts (small change).
  3. Only if that fails: the gather/judge workflow fold.

Corpus is not in git (real caller PII) — mine fresh with --mine; durable copies belong in the private training-data bucket.

PropFlow Docs