D4 — qualification
Traced at commit e53d0dc ·
libs/contracts/src/lib/{vector-resolution,extractor,canonicalization,contracts,outbox}.ts ·
libs/temporal/src/{workflows,activities}/call-attempt.ts ·
apps/worker/src/main.ts · live state read 10 September 2026
Summary
- D4 records whether the person meets the criteria of the offer. It holds one value or nothing.
- Three values exist. The model can also answer
UNKNOWN, which the platform discards. QUALIFIEDgivesqualified_no_action.DISQUALIFIEDgivesnot_qualified.- D4 is step 5 of the headline waterfall. It outranks D3.
- The voice provider sets D4 on every call that it marks successful.
- It sets
QUALIFIEDonly when the custom fieldqualifiedis the booleantrue. Otherwise it setsDISQUALIFIED. - No live agent declares a field named
qualified. - In a test, a successful call from the developer test agent became
not_qualified, with no review. - Two of the three agents do not declare
call_successfuleither. No real call yet shows what the provider then sends. - Where step 1 leaves D4 empty, steps 2 and 3 decide it.
- The phrase list and the model prompt describe a home loan. The live agents offer merchant working capital.
Workflow 1 — where the value comes from
Step 1 — the voice provider
- The platform reads
call_successfulfrom the analysis. - It reads
qualifiedfromcustom_analysis_data. It accepts only a boolean. - When
call_successfulis not the booleantrue, step 1 leaves D4 empty. - When
call_successfulistrueandqualifiedistrue, step 1 setsQUALIFIED. It also sets D3INTERESTED. - When
call_successfulistrueandqualifiedis anything else, step 1 setsDISQUALIFIED. - Anything else includes
false, an absent field and the string"yes". - A code comment gives the reason: parity with an older reconciler that returned
not_qualified. - Step 1 cannot set
PENDING_INFO. - If two analysis messages arrive, one
trueforqualifiedwins.
Steps 2 and 3
- The phrase list and the model work as they do for D2. See D2 — who answered.
- Steps 2 and 3 fill D4 only when step 1 left it empty.
- The D4 list holds 29 phrases. Their confidence runs from 0.80 to 0.90.
- Step 2 checks
QUALIFIEDfirst, thenDISQUALIFIED, thenPENDING_INFO. - A qualifying phrase anywhere in the call therefore beats a disqualifying phrase anywhere in the call.
- In a test,
I rent the unit, but yes I have steady income.gaveQUALIFIEDfromyes i have.
Workflow 2 — what each value does
QUALIFIED and DISQUALIFIED reach the headline.- D4 is step 5 of the waterfall. D5, D6, D1 and D2 come first.
QUALIFIEDgivesqualified_no_action.DISQUALIFIEDgivesnot_qualified.PENDING_INFOgives no headline. The waterfall moves on to D3.- Any D4 value except
PENDING_INFOoutranks every D3 value. - A caller who asked for a callback but did not qualify gets
not_qualified. - Outside the headline and the evaluation harness, no code reads D4 today. The outbox and the gauges ignore it.
Workflow 3 — a successful call
- The test ran the real resolver on a call analysis shaped like one from the developer test agent.
- The analysis held
call_successful: trueandqualified_lead: "yes". - The resolver set D4
DISQUALIFIEDand the headlinenot_qualified. - It gave confidence 0.8 and no review. Steps 2 and 3 cannot change that headline.
- A second test sent
qualified: "yes"as a string. The result did not change. - A third test sent
qualified: true. The resolver setQUALIFIED,INTERESTEDandqualified_no_action. - Agents B and C declare neither
call_successfulnorqualified. - A fourth test left out
call_successful. Step 1 left D2, D3 and D4 empty, and the headline atneeds_review. - Steps 2 and 3 then fill all three and derive the headline again.
- For agents B and C, that headline would rest on the home-loan phrase list and prompt.
- The call goes to review if extraction leaves D2, D3 or D4 empty.
- It also goes to review for an
UNKNOWNin D2 or D3, or a score below 0.7. - The rehearsal simulator sends
qualified: trueas a boolean. A rehearsal therefore takes a path that no live agent can take.
The phrase list
Step 2 checks the rows from top to bottom. The first row with a match wins. Dictionary version 1.0.
| Order | Value | Confidence | Phrases |
|---|---|---|---|
| 1 | QUALIFIED | 0.85 | yes i own · i own the property · homeowner · i have equity · my credit is good · i qualify · i meet the requirements · yes i have · currently employed · have income |
| 2 | DISQUALIFIED | 0.90 | i rent · i'm a renter · don't own · no equity · bad credit · bankruptcy · in foreclosure · unemployed · no income · don't qualify · not eligible |
| 3 | PENDING_INFO | 0.80 | not sure · i don't know · let me check · have to look · need to verify · i'll have to find out · maybe · possibly |
The phrases describe another offer. homeowner, i have equity
and my credit is good describe a property loan. The model prompt names homeowners too.
The live agents ask about monthly revenue, time in business and existing advances.
Known defects
- The field name. Step 1 reads
qualified. The developer test agent sendsqualified_lead. Agents B and C send neither. - The field type. Step 1 accepts only a boolean. The provider sends enum fields as strings such as
"yes". Other readers in the same file useasYesNo, which accepts"yes". - Silence gives a definite answer. An absent field produces
DISQUALIFIEDat confidence 0.8. An absent field should leave D4 empty. - Step 1 ties D3 to D4. Only a
QUALIFIEDcall gets a D3 value from step 1. - Value order beats word order. A qualifying phrase beats a disqualifying phrase. The model stub in the renter test answered
DISQUALIFIED. - The wrong offer. The phrase list and the model prompt describe a home loan. The live agents offer merchant working capital. Those decide real D4 values whenever step 1 leaves D4 empty.
- Short phrases match ordinary speech.
maybe,possibly,not sureandi don't knowsetPENDING_INFO. - Rehearsals hide the first defect. The simulator sends the field that no live agent sends.
What rehearsal data can show
- A sample of about 1% of stage attempts held 338 D4 values.
- Step 1 set 138 of them: 107
DISQUALIFIEDand 31QUALIFIED. - The impersonated model set the other 200, all
DISQUALIFIED. The phrase list set none. - Every
QUALIFIEDvalue in the sample came from the simulator’s booleanqualifiedfield. - No real call can produce that value from step 1 today.
D2 — who answered — the gate, and the phrase list reading the agent.
D3 — intent — the value that D4 outranks.
Outcome resolution — how D4 fits among the seven dimensions.