console: Quote Presented is two situations, not one

The page said "Waiting for the customer to reply on WhatsApp" directly
above a panel saying "Accepted by the customer, over WhatsApp. KYC and
underwriting are running." Both rendered from the same instant; only one
was true.

Quote Presented has the same shape as Document Pending — the state holds
still while the situation underneath it changes completely. Before the
customer answers, the lead is genuinely with them and nothing is running.
After they accept, KYC and the underwriting screen run inside the SAME
state, because the lead does not move until underwriting clears. phaseOf
splits it, so the strip now says "Verifying KYC" and then "Screening the
risk for underwriting", and the Next step line records only the fact of
the acceptance rather than repeating what is running.

That also puts this stretch under the stall detector for the first time,
which matters: the KYC agent talked itself out of the underwriting screen
earlier today and the lead sat in Quote Presented with a passed KYC and
nothing happening. With this it would have said so after five minutes and
offered "Run the underwriting screen" — both steps ops_admin can perform,
so the recovery needs nobody's help.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Yashas 2026-09-08 16:48:25 +05:30
parent 93baba3fa1
commit cb94e2417f
2 changed files with 33 additions and 1 deletions

View File

@ -375,6 +375,26 @@ export function fieldApplies(fieldId, lead) {
*/
export function phaseOf(stage, lead) {
if (!stage || !lead) return stage
// Quote Presented has the same shape as Document Pending: the state holds
// still while the situation underneath it changes completely.
//
// Before the customer answers, the lead is genuinely with them and nothing
// is running. After they accept, KYC and the underwriting screen run inside
// the SAME state — the lead does not move until underwriting clears — so a
// page saying "waiting for the customer to reply" sat directly above a panel
// saying "accepted by the customer, KYC and underwriting are running". Both
// were rendered from the same instant; only one was true.
if (stage.uid === 'zk-state-quoted' && lead.acceptance_ref && !lead.uw_outcome) {
return {
...stage,
kind: 'auto',
doing: lead.kyc_outcome ? 'Screening the risk for underwriting' : 'Verifying KYC',
by: 'KYC & Evidence',
after: 'customer accepted',
}
}
if (stage.uid === 'zk-state-docs' && lead.documents_status === 'complete') {
return {
...stage,
@ -476,6 +496,15 @@ export function nudgeFor(stage, lead) {
return null
}
case 'zk-state-quoted': {
// Only after an acceptance — before that nothing is running and there is
// nothing to wake; the lead is with the customer.
if (!lead.acceptance_ref) return null
if (!lead.kyc_outcome) return { uid: 'zk-act-kyc', label: 'Run KYC again', by: 'KYC & Evidence' }
if (!lead.uw_outcome) return { uid: 'zk-act-uw-screen', label: 'Run the underwriting screen', by: 'KYC & Evidence' }
return null
}
case 'zk-state-issued':
return { uid: 'zk-act-onboard', label: 'Close the file', by: 'Engage' }

View File

@ -536,7 +536,10 @@ export default function Lead() {
: blocked
? 'The chain has stopped. The fix is above.'
: accepted && stage?.uid === 'zk-state-quoted'
? `Accepted by the customer${row.accepted_at ? ' on ' + row.accepted_at : ''}${row.acceptance_ref === 'whatsapp' ? ', over WhatsApp' : ''}. KYC and underwriting are running.`
/* What is RUNNING is the strip's job now, so this
records only the fact otherwise the two lines
said the same thing twice, one above the other. */
? `Accepted by the customer${row.accepted_at ? ' on ' + row.accepted_at : ''}${row.acceptance_ref === 'whatsapp' ? ', over WhatsApp' : ''}. Nothing is waiting on you.`
: `Nothing is waiting on you — ${stage?.by ?? 'someone else'} has this one.`}
</p>
</div>