Version: 1.0 | Status: Implementation-Ready — Gear 1
Scope: Full Fannie Mae / Freddie Mac conventional loan qualification engine. Executes eligibility gates, income qualification, DTI computation, LLPA rate adjustment, PMI calculation and cancellation, reserve verification, AUS path determination, and final qualification result. Covers purchase, rate/term refinance, and cash-out refinance. Supports PRIMARY, SECOND_HOME, and INVESTMENT occupancy.
Confidential: PreFi, Inc. / Purpose Technology, Inc. d/b/a Purlend
Primary Reference: Fannie Mae Selling Guide (December 2025). All rule citations follow Fannie Mae B-series sections. Freddie Mac LPA mirrors for most standard scenarios — deviations noted explicitly.
This skill takes a validated BorrowerProfile and a ProgramEvaluationQueue entry for CONVENTIONAL and produces a ConventionalQualResult — the definitive conventional mortgage qualification determination, with full computation trail, AUS path, DTI, PMI, rate, payment, cash-to-close, reserve status, and constraint flags.
This skill is the first dependency for the Optimization, Scenario Generation, and Ranking skills. It must be numerically correct on every execution. When in doubt, the more conservative underwriting rule applies.
This skill produces:
ConventionalQualResult — qualification status, amount, payment, rate, DTI, PMIConventionalLineageTrace — step-by-step computation trailConventionalConstraintFlags — constraint signals for Constraint Detection pass-throughThis skill does NOT produce:
Mortgage family scope: CONVENTIONAL only
Forbidden families: Never apply FHA MIP logic, VA residual income rules, or DSCR rental-income qualification in this skill.
Invoke this skill when:
ProgramEvaluationQueue contains a CONVENTIONAL entry with eligibility = ELIGIBLE or CONDITIONALRequired inputs:
BorrowerProfile object (Borrower Profile Skill v1.2+)ProgramEvaluationQueue CONVENTIONAL entry (Program Router Skill v1.0+)If either input is absent: return CONVENTIONAL_SKILL_BLOCKED with missing input listed.
**If CONVENTIONAL entry has eligibility = INELIGIBLE:** return CONVENTIONAL_INELIGIBLE — [ineligible_reason from queue] and stop. Do not proceed.
Stage 1 — Validate inputs
Stage 2 — Extract qualification inputs
Stage 3 — Gate 1: Occupancy eligibility
Stage 4 — Gate 2: Loan amount / conforming limit
Stage 5 — Gate 3: Credit score minimum
Stage 6 — Gate 4: LTV and down payment
Stage 7 — Compute LLPA-adjusted rate
Stage 8 — Compute P&I payment
Stage 9 — Income qualification (GMI verification)
Stage 10 — DTI computation (front-end and back-end)
Stage 11 — AUS path determination
Stage 12 — PMI computation (if LTV > 80%)
Stage 13 — Full PITI / PITIA computation
Stage 14 — Reserve verification
Stage 15 — Cash-to-close computation
Stage 16 — Final qualification determination
Stage 17 — Build and emit ConventionalQualResult
Run all stages in sequence. Do not skip any stage. Every intermediate value must be carried into the lineage trace.
Extract and hold the following from input objects:
From BorrowerProfile:
qualifying_credit_score integer
credit_tier integer (1–8)
gmi_for_dti decimal — grossed-up qualifying income
total_monthly_dti_obligations decimal — all qualifying liabilities
occupancy_type PRIMARY | SECOND_HOME | INVESTMENT
loan_purpose PURCHASE | RATE_TERM_REFI | CASH_OUT_REFI
property_value decimal — MIN(purchase_price, appraised_value)
purchase_price decimal
appraised_value decimal (if refi — use if available)
down_payment_amount decimal (purchase only)
self_employed_flag boolean
income_combined_flag boolean
monthly_tax decimal — property tax / 12
monthly_insurance decimal — hazard insurance / 12
hoa_monthly decimal (0 if none)
funds_available_for_closing decimal
funds_available_for_reserves decimal
income_sources list (for rental income extraction)
liabilities list
From ProgramEvaluationQueue CONVENTIONAL entry:
preliminary_rate decimal (Router placeholder — overridden by Stage 7)
preliminary_loan_amount decimal
preliminary_ltv decimal
preliminary_mi_amount_monthly decimal (Router estimate — verified in Stage 12)
preliminary_ctc decimal
Critical: property_value for LTV computation must always be:
property_value = MIN(purchase_price, appraised_value)
Never use purchase_price alone when an appraisal is available. Appraisal may be lower.
Eligible occupancy types: PRIMARY | SECOND_HOME | INVESTMENT
Ineligible: INVESTMENT_COMMERCIAL | any commercial or mixed-use classification
IF occupancy_type NOT IN [PRIMARY, SECOND_HOME, INVESTMENT]:
return GATE_1_FAIL — "Conventional limited to primary, second home, and investment (residential)"
ELSE:
gate_1 = PASS
conforming_limit_2026 = 806,500 (FHFA baseline — continental US)
IF state IN [AK, HI]:
conforming_limit = 1,209,750 (150% of baseline per statute)
flag HIGH_COST_STATE
IF high_cost_area_flag = true:
flag HIGH_COST_AREA_CHECK
note: "County-level limit may exceed $806,500. Verify FHFA county limit before applying."
conforming_limit = county_limit (if provided) OR 806,500 (conservative)
base_loan_amount = property_value - down_payment_amount (purchase)
= current_payoff_balance (refi)
IF base_loan_amount > conforming_limit:
gate_2 = FAIL — "Loan amount $[X] exceeds 2026 conforming limit of $[conforming_limit]"
flag ROUTE_JUMBO
ELSE:
gate_2 = PASS
IF base_loan_amount > 0.90 × conforming_limit:
flag NEAR_LIMIT_CHECK — "Loan is within 10% of conforming limit. Monitor for appraisal shortfall."
conventional_min_score = 620
IF qualifying_credit_score < 620:
gate_3 = FAIL — "Conventional minimum score is 620. Current score: [qualifying_credit_score]"
ELSE:
gate_3 = PASS
LTV computation:
conv_ltv = base_loan_amount / property_value
NOTE: base_loan_amount includes financed fees if any — for conventional, none.
LTV caps by occupancy:
PRIMARY: conv_ltv ≤ 0.97 (3% down minimum)
SECOND_HOME: conv_ltv ≤ 0.90 (10% down minimum)
INVESTMENT: conv_ltv ≤ 0.80 (20% down minimum)
IF conv_ltv > ltv_cap[occupancy_type]:
gate_4 = FAIL — "LTV [X]% exceeds Conventional [occupancy] maximum of [cap]%"
ELSE:
gate_4 = PASS
Multi-unit LTV caps (if property_type = 2-4 unit):
2-unit PRIMARY: ≤ 0.85 (85%)
2-unit INVESTMENT: ≤ 0.75 (75%)
3-4 unit PRIMARY: ≤ 0.75 (75%)
3-4 unit INVESTMENT: ≤ 0.70 (70%)
flag MULTI_UNIT_LTV_APPLIES if property_unit_count > 1
If any gate fails: stop. Set qualification_status = INELIGIBLE. Emit reason. Do not proceed to income/DTI stages.
The Loan Level Price Adjustment (LLPA) converts a base market rate into the borrower's actual note rate based on credit score and LTV. Additional LLPA surcharges apply for occupancy type and property characteristics.
Use this table to determine the rate adjustment. Values are percentage points added to base market rate.
LTV Band Score 760+ Score 740-759 Score 720-739 Score 700-719 Score 680-699 Score 660-679 Score 640-659 Score 620-639
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
LTV 95.01–97.00% 0.000% 0.250% 0.500% 0.750% 1.000% 1.500% 2.000% 2.500%
LTV 90.01–95.00% 0.000% 0.250% 0.250% 0.500% 0.750% 1.000% 1.500% 2.000%
LTV 80.01–90.00% 0.000% 0.000% 0.250% 0.250% 0.500% 0.750% 1.000% 1.500%
LTV ≤ 80.00% 0.000% 0.000% 0.000% 0.000% 0.000% 0.250% 0.500% 1.000%
qualifying_credit_score ≥ 760: use column "Score 760+"
740 ≤ score < 760: use column "Score 740-759"
720 ≤ score < 740: use column "Score 720-739"
700 ≤ score < 720: use column "Score 700-719"
680 ≤ score < 700: use column "Score 680-699"
660 ≤ score < 680: use column "Score 660-679"
640 ≤ score < 660: use column "Score 640-659"
620 ≤ score < 640: use column "Score 620-639"
score < 620: INELIGIBLE — caught at Gate 3
conv_ltv > 0.9500: use row "LTV 95.01–97.00%"
conv_ltv > 0.9000: use row "LTV 90.01–95.00%"
conv_ltv > 0.8000: use row "LTV 80.01–90.00%"
conv_ltv ≤ 0.8000: use row "LTV ≤ 80.00%"
PRIMARY: +0.000% (no surcharge)
SECOND_HOME: +0.125% to +0.375% depending on LTV
LTV ≤ 75%: +0.125%
LTV 75-85%: +0.250%
LTV > 85%: +0.375%
INVESTMENT: +0.750% for LTV ≤ 75%
+1.000% for LTV > 75%
PURCHASE: +0.000%
RATE_TERM_REFI: +0.000% (standard)
CASH_OUT_REFI: +0.375% to +0.750% depending on LTV and score
LTV ≤ 60%: +0.375%
LTV 60-70%: +0.500%
LTV 70-80%: +0.750%
flag CASH_OUT_LLPA_APPLIES
Step 1: llpa_score_ltv = lookup(conv_ltv_band, score_band)
Step 2: llpa_occupancy = lookup(occupancy_type, conv_ltv)
Step 3: llpa_purpose = lookup(loan_purpose, conv_ltv)
Step 4: total_llpa = llpa_score_ltv + llpa_occupancy + llpa_purpose
Step 5: adjusted_rate = base_market_rate + total_llpa
NOTE: base_market_rate is the current market par rate for a primary 30-year fixed.
Use 6.50% as the system placeholder for Gear 1 (updated from live market data
when rate feed is connected in Gear 2+).
total_llpa is ADDED to this base rate.
Never subtract LLPA. LLPA only adds to rate.
monthly_rate = adjusted_rate / 12
compound = (1 + monthly_rate)^360
numerator = monthly_rate × compound
denominator = compound − 1
pmt_factor = numerator / denominator
pi_payment = base_loan_amount × pmt_factor
CRITICAL RULES:
1. monthly_rate = adjusted_rate / 12 (divide annual rate by 12)
NEVER use adjusted_rate directly in the compound calculation
2. Base of exponent: (1 + monthly_rate) — NOT (1 + adjusted_rate)
3. NEVER round monthly_rate, compound, numerator, or denominator
Round pi_payment only at final output (2 decimal places)
Pre-computed for verification. All factors independently verified.
Rate monthly_r (1+r)^360 factor
6.00% 0.0050000 6.02258 0.0059955
6.25% 0.0052083 6.48917 0.0061572
6.50% 0.0054167 6.99180 0.0063207
6.75% 0.0056250 7.53325 0.0064860
7.00% 0.0058333 8.11650 0.0066530
7.25% 0.0060417 8.74477 0.0068218
7.50% 0.0062500 9.42153 0.0069921
7.75% 0.0064583 10.15051 0.0071641
8.00% 0.0066667 10.93573 0.0073376
The Conventional skill trusts the gmi_for_dti value computed by the Borrower Profile Skill. It does not recompute income from raw sources. It verifies that key income rules are honored and flags any issues.
CHECK 1 — Self-employment documentation:
IF self_employed_flag = true:
Require: 2 years personal tax returns + 2 years business tax returns
Require: CPA letter or P&L for current year
flag SE_DOCS_REQUIRED
IF income history_months < 24: flag SE_INCOME_CONDITIONAL
note: "Self-employment income requires 24-month history per Fannie Mae B3-3.4-01"
CHECK 2 — Variable income history:
FOR each IncomeSource WHERE income_type IN [BONUS, COMMISSION, OVERTIME]:
IF history_months < 24: flag VARIABLE_INCOME_CONDITIONAL
note: "[income_type] requires 24-month history per Fannie Mae B3-3.1-09"
CHECK 3 — Rental income offset for investment properties:
IF occupancy_type = INVESTMENT:
rental_income_gross = SUM(qualifying_monthly_amount) from IncomeSource WHERE income_type = RENTAL
rental_income_net = rental_income_gross × 0.75 (75% gross rent rule, Fannie B3-3.1-08)
IF rental_income_gross > 0:
subject_property_piti = pi_payment + monthly_tax + monthly_insurance + hoa_monthly
net_rental_result = rental_income_net - subject_property_piti
IF net_rental_result ≥ 0:
rental_offset_type = POSITIVE_CASHFLOW
rental_income_for_dti = net_rental_result (added to GMI as income)
gmi_adjusted = gmi_for_dti + rental_income_for_dti
note: "Positive rental cashflow $[net_rental_result] added to qualifying income"
ELSE:
rental_offset_type = NEGATIVE_CASHFLOW
rental_loss_for_dti = ABS(net_rental_result) (added to monthly obligations)
gmi_adjusted = gmi_for_dti (no change to GMI)
note: "Negative rental cashflow $[rental_loss_for_dti] added to monthly obligations"
ELSE:
rental_income_for_dti = 0
gmi_adjusted = gmi_for_dti
CHECK 4 — Income continuance (Fannie Mae B3-3.1-01):
Income must be expected to continue for at least 3 years from note date.
Flag INCOME_CONTINUANCE_RISK if:
- Retirement income or pension ends within 3 years
- Alimony/child support expires within 3 years
- Non-taxable income source lacks documented continuation
For Gear 1: document requirement only — flag for human review
CHECK 5 — Student loan IDR rule (Fannie Mae B3-6-05):
FOR each liability WHERE liability_type = STUDENT_LOAN:
IF repayment_type = IDR AND monthly_payment < loan_balance × 0.005:
qualifying_payment = loan_balance × 0.005
flag STUDENT_LOAN_IDR_OVERRIDE
note: "Student loan IDR: using 0.5% rule ($[qualifying_payment])"
ELSE:
qualifying_payment = actual_monthly_payment
PROHIBITED: Do NOT apply VA gross-up guard rules here.
VA residual income calculation is confined to VA Module Skill.
gmi_for_dti from BorrowerProfile already includes gross-up where applicable.
IF occupancy_type = INVESTMENT AND rental_offset_type = POSITIVE_CASHFLOW:
gmi_qualifying = gmi_adjusted (includes rental positive cashflow)
ELSE:
gmi_qualifying = gmi_for_dti
Round gmi_qualifying to 2 decimal places at final output only.
All DTI computations use unrounded gmi_qualifying.
STEP 1 — Housing expense (front-end):
front_end_housing_expense = pi_payment + monthly_tax + monthly_insurance + hoa_monthly
NOTE: Do NOT include PMI in front-end DTI numerator.
PMI is included in back-end only (it is a housing cost, not a housing payment).
Front-end DTI uses: principal + interest + tax + insurance + HOA
EXCEPTION: Some lenders include PMI in front-end. Flag FRONT_END_PMI_TREATMENT_VARIES
for human review when front-end DTI is close to threshold.
For Clarity Engine Gear 1: exclude PMI from front-end DTI.
front_end_dti = front_end_housing_expense / gmi_qualifying
STEP 2 — Monthly obligations for back-end DTI:
monthly_obligations = total_monthly_dti_obligations (from BorrowerProfile)
NOTE: This already includes student loan override if CHECK 5 was applied.
IF occupancy_type = INVESTMENT AND rental_offset_type = NEGATIVE_CASHFLOW:
monthly_obligations = monthly_obligations + rental_loss_for_dti
flag RENTAL_LOSS_ADDED_TO_DTI
STEP 3 — Back-end DTI:
total_monthly_debt = front_end_housing_expense + monthly_obligations
back_end_dti = total_monthly_debt / gmi_qualifying
STEP 4 — PMI impact on PITIA (for informational display, not DTI):
monthly_pmi = computed in Stage 12 (if LTV > 80%)
pitia = front_end_housing_expense + monthly_pmi
total_with_pmi = pitia + monthly_obligations
back_end_dti_with_pmi = total_with_pmi / gmi_qualifying
NOTE: back_end_dti_with_pmi is the more complete representation.
Report BOTH front_end_dti and back_end_dti_with_pmi in ConventionalQualResult.
CRITICAL ROUNDING RULE:
Use full floating-point precision for gmi_qualifying, front_end_housing_expense,
and monthly_obligations throughout all DTI computations.
Round DTI only at final output (4 decimal places for computation, 2 for display).
DU APPROVE PATH (Fannie Mae Desktop Underwriter):
back_end_dti_with_pmi ≤ 0.50 (50%):
aus_path = DU_APPROVE_ELIGIBLE
note: "Back-end DTI ≤ 50% — eligible for DU Approve/Eligible finding"
DTI_limit_applied = 0.50
NOTE: DU may approve DTIs above 45% with compensating factors:
- 12+ months reserves post-close
- Significant liquid assets (20%+ down payment)
- Minimal DTI increase from prior loan
- Strong residual income (not a formal VA test)
The Clarity Engine flags these compensating factors but does not guarantee DU Approve.
DU REFER PATH:
back_end_dti_with_pmi > 0.50:
aus_path = DU_REFER
note: "Back-end DTI [X]% exceeds DU 50% limit — DU will likely Refer"
MANUAL UNDERWRITE PATH:
IF aus_path = DU_REFER:
manual_eligible = back_end_dti_with_pmi ≤ 0.45
IF manual_eligible:
aus_path = DU_REFER_MANUAL_ELIGIBLE
manual_dti_limit = 0.45
note: "DTI within manual UW limit (45%). Manual underwrite path available."
flag MANUAL_UW_COMPENSATING_FACTORS_REQUIRED
ELSE:
aus_path = DU_REFER_MANUAL_INELIGIBLE
note: "DTI [X]% exceeds both DU 50% and manual 45% limits. Conventional ineligible."
qualification_status = INELIGIBLE_DTI
FREDDIE MAC LPA PATH:
LPA mirrors DU for most scenarios in Gear 1.
Flag LPA_PATH_AVAILABLE for advisor review if:
- DU Refer received
- Back-end DTI ≤ 45%
note: "LPA may return Accept where DU issues Refer. Advisor evaluation required."
PMI required: conv_ltv > 0.80 (80.00%)
PMI not required: conv_ltv ≤ 0.80
If PMI required:
Determine LTV band:
conv_ltv > 0.9000 AND conv_ltv ≤ 0.9700: ltv_band = "90.01-97.00"
conv_ltv > 0.8500 AND conv_ltv ≤ 0.9000: ltv_band = "85.01-90.00"
conv_ltv > 0.8000 AND conv_ltv ≤ 0.8500: ltv_band = "80.01-85.00"
Determine score band:
qualifying_credit_score ≥ 740: pmi_score_band = "740+"
720 ≤ score < 740: pmi_score_band = "720-739"
680 ≤ score < 720: pmi_score_band = "680-719"
620 ≤ score < 680: pmi_score_band = "620-679"
LTV Band Score 740+ Score 720-739 Score 680-719 Score 620-679
────────────────────────────────────────────────────────────────────────────
90.01%–97.00% 0.55% 0.75% 1.00% 1.25%
85.01%–90.00% 0.40% 0.55% 0.80% 1.00%
80.01%–85.00% 0.28% 0.40% 0.60% 0.80%
annual_pmi_rate = pmi_table[ltv_band][pmi_score_band]
monthly_pmi = base_loan_amount × annual_pmi_rate / 12
NOTE: Use unrounded base_loan_amount.
Round monthly_pmi to 2 decimal places at output only.
Per the Homeowners Protection Act (HPA):
TARGET BALANCES:
pmi_cancel_request_target = property_value × 0.80
pmi_auto_cancel_target = property_value × 0.78
AMORTIZATION LOOP:
balance = base_loan_amount
monthly_rate = adjusted_rate / 12
pmt = base_loan_amount × pmt_factor(adjusted_rate)
pmi_cancel_request_month = null
pmi_auto_cancel_month = null
FOR n = 1 TO 360:
interest = balance × monthly_rate [full precision — never round]
principal = pmt − interest [full precision — never round]
balance = balance − principal [full precision — never round]
IF balance ≤ pmi_cancel_request_target AND pmi_cancel_request_month = null:
pmi_cancel_request_month = n
IF balance ≤ pmi_auto_cancel_target AND pmi_auto_cancel_month = null:
pmi_auto_cancel_month = n
BREAK
CRITICAL: monthly_rate = adjusted_rate / 12
Do NOT use adjusted_rate directly in the loop.
Do NOT round balance, interest, or principal at any step.
Round only final presentation output.
lifetime_pmi = monthly_pmi × pmi_auto_cancel_month
pi_payment = base_loan_amount × pmt_factor(adjusted_rate)
monthly_tax = from BorrowerProfile
monthly_insurance = from BorrowerProfile
hoa_monthly = from BorrowerProfile (0 if none)
monthly_pmi = from Stage 12 (0 if LTV ≤ 80%)
piti = pi_payment + monthly_tax + monthly_insurance + hoa_monthly
pitia = piti + monthly_pmi
NOTE: piti = standard housing expense without MI
pitia = total housing expense including MI
DTI uses pitia in the back-end calculation (Stage 10, Step 4)
Display both in ConventionalQualResult
Round piti and pitia to 2 decimal places at output only.
RESERVE REQUIREMENTS BY OCCUPANCY:
PRIMARY: 2 months PITIA (preferred by DU — not hard required on all files)
0 months hard minimum for DU Approve
SECOND_HOME: 2 months PITIA
INVESTMENT: 6 months PITIA
required_reserves = reserve_months[occupancy_type] × pitia
AVAILABLE RESERVES:
funds_available_for_reserves = from BorrowerProfile
(Already net of closing funds and includes 60% retirement credit)
reserve_status:
IF funds_available_for_reserves ≥ required_reserves:
reserve_status = MEETS_REQUIREMENT
reserve_surplus = funds_available_for_reserves - required_reserves
ELSE:
reserve_status = SHORTFALL
reserve_gap = required_reserves - funds_available_for_reserves
flag RESERVE_SHORTFALL
note: "Reserve gap: $[reserve_gap]. Required: $[required_reserves]."
GIFT FUND RULE:
Gift funds may be used for down payment on PRIMARY only.
Gift funds may NOT be used for investment property down payment.
Gift funds may NOT be used for reserves.
IF gift_funds_amount > 0 AND occupancy_type = INVESTMENT:
flag GIFT_NOT_ELIGIBLE_INVESTMENT
note: "Gift funds are not eligible for investment property down payment."
PURCHASE:
cash_to_close = down_payment_amount
+ estimated_closing_costs
+ prepaids_and_escrow
− seller_concession_amount
− lender_credit_amount
Seller concession limits (Fannie Mae B3-4.1-02):
PRIMARY, LTV > 90%: 3% of lesser of purchase price or appraised value
PRIMARY, LTV 75-90%: 6%
PRIMARY, LTV < 75%: 9%
SECOND_HOME, any LTV: 6%
INVESTMENT, any LTV: 2%
flag SELLER_CONCESSION_LIMIT if seller_concession_amount approaches limit
Estimated closing costs (Gear 1 estimate — replaced by actual LE in Gear 2):
1-4% of loan amount depending on state and lender
Use 2.0% of base_loan_amount as system estimate unless actual provided
Prepaids and escrow estimate:
Prepaid interest: (adjusted_rate / 365) × base_loan_amount × 15 days
Escrow setup: typically 2–3 months of taxes and insurance
Use (monthly_tax + monthly_insurance) × 3 as Gear 1 estimate
RATE/TERM REFINANCE:
cash_to_close = estimated_closing_costs + prepaids_and_escrow − lender_credit_amount
(No down payment — existing equity covers LTV requirement)
CASH-OUT REFINANCE:
cash_to_close = estimated_closing_costs + prepaids_and_escrow − lender_credit_amount
cash_received = new_loan_amount − current_payoff_balance − closing_costs
(Borrower receives cash_received at closing)
CTC FEASIBILITY CHECK:
IF funds_available_for_closing ≥ cash_to_close:
ctc_status = MEETS_REQUIREMENT
ctc_surplus = funds_available_for_closing - cash_to_close
ELSE:
ctc_status = SHORTFALL
ctc_shortfall = cash_to_close - funds_available_for_closing
flag CTC_SHORTFALL
daily_rate = adjusted_rate / 365
prepaid_interest = daily_rate × base_loan_amount × days_to_close
(use 15 days as default estimate for Gear 1)
NOTE: Use unrounded daily_rate and base_loan_amount.
Round prepaid_interest to 2 decimal places at output.
qualification_status:
QUALIFIED_DU_APPROVE:
All gates passed AND aus_path = DU_APPROVE_ELIGIBLE
QUALIFIED_MANUAL_UW:
All gates passed AND aus_path = DU_REFER_MANUAL_ELIGIBLE
Requires compensating factors documentation
CONDITIONAL:
All gates passed AND one or more of:
- SE_INCOME_CONDITIONAL
- VARIABLE_INCOME_CONDITIONAL
- LPA_PATH_AVAILABLE (DU Refer, LPA may approve)
INELIGIBLE:
Any gate failed OR aus_path = DU_REFER_MANUAL_INELIGIBLE
If QUALIFIED or CONDITIONAL:
approved_loan_amount = base_loan_amount
note: "Approved at this loan amount subject to full underwrite and appraisal"
{
"schema_version": "clarity_engine_v1.0",
"skill": "CONVENTIONAL",
"skill_version": "1.0",
"deal_id": "string",
"borrower_id": "string",
"created_at": "ISO 8601 UTC",
"qualification_status": "QUALIFIED_DU_APPROVE | QUALIFIED_MANUAL_UW | CONDITIONAL | INELIGIBLE",
"ineligible_reason": "string | null",
"aus_path": "DU_APPROVE_ELIGIBLE | DU_REFER | DU_REFER_MANUAL_ELIGIBLE | DU_REFER_MANUAL_INELIGIBLE",
"loan": {
"base_loan_amount": 0.00,
"occupancy_type": "PRIMARY | SECOND_HOME | INVESTMENT",
"loan_purpose": "PURCHASE | RATE_TERM_REFI | CASH_OUT_REFI",
"property_value": 0.00,
"conv_ltv": 0.0000,
"down_payment_amount": 0.00
},
"rate": {
"base_market_rate": 0.0000,
"llpa_score_ltv": 0.0000,
"llpa_occupancy": 0.0000,
"llpa_purpose": 0.0000,
"total_llpa": 0.0000,
"adjusted_rate": 0.0000
},
"payment": {
"pi_payment": 0.00,
"monthly_tax": 0.00,
"monthly_insurance": 0.00,
"hoa_monthly": 0.00,
"monthly_pmi": 0.00,
"piti": 0.00,
"pitia": 0.00
},
"pmi": {
"pmi_required": false,
"annual_pmi_rate": 0.0000,
"monthly_pmi": 0.00,
"pmi_cancel_request_month": null,
"pmi_auto_cancel_month": null,
"lifetime_pmi": 0.00
},
"dti": {
"gmi_qualifying": 0.00,
"front_end_dti": 0.0000,
"back_end_dti": 0.0000,
"back_end_dti_with_pmi": 0.0000,
"dtu_limit": 0.50,
"manual_limit": 0.45,
"dti_status": "WITHIN_DU | WITHIN_MANUAL | EXCEEDS_ALL"
},
"cash_to_close": {
"down_payment": 0.00,
"estimated_closing_costs": 0.00,
"prepaids_and_escrow": 0.00,
"seller_concession": 0.00,
"lender_credit": 0.00,
"total_cash_to_close": 0.00,
"funds_available": 0.00,
"ctc_status": "MEETS_REQUIREMENT | SHORTFALL",
"ctc_surplus_or_gap": 0.00
},
"reserves": {
"reserve_months_required": 0,
"pitia_for_reserve": 0.00,
"required_reserves": 0.00,
"funds_available_for_reserves": 0.00,
"reserve_status": "MEETS_REQUIREMENT | SHORTFALL",
"reserve_surplus_or_gap": 0.00
},
"flags": [],
"constraint_signals": [],
"human_review_required": false,
"human_review_reasons": [],
"lineage_trace": {
"gate_1_result": "string",
"gate_2_result": "string",
"gate_3_result": "string",
"gate_4_result": "string",
"llpa_computation": {},
"dti_computation": {},
"pmi_computation": {},
"reserve_computation": {},
"ctc_computation": {}
}
}
Inputs from BorrowerProfile and ProgramEvaluationQueue:
qualifying_credit_score: 698
credit_tier: 5
occupancy_type: PRIMARY
loan_purpose: PURCHASE
purchase_price: 425,000
appraised_value: 425,000 (assume = purchase price)
down_payment_amount: 12,750 (3%)
gmi_for_dti: 8,458.33
total_monthly_dti_obligations: 785.00
monthly_tax: 531.25
monthly_insurance: 100.00
hoa_monthly: 0.00
funds_available_for_closing: 28,105.36
funds_available_for_reserves: 60,894.64
Stage 4 — Gate 4: LTV
property_value = MIN(425,000, 425,000) = 425,000
base_loan_amount = 425,000 - 12,750 = 412,250
conv_ltv = 412,250 / 425,000 = 0.9700 = 97.00%
LTV cap (PRIMARY) = 97.00% → gate_4 = PASS (exactly at limit)
Stage 7 — LLPA Rate
conv_ltv = 97.00% → LTV band: 95.01–97.00%
score = 698 → score band: 680-699
llpa_score_ltv = table[95.01-97.00][680-699] = 1.000%
llpa_occupancy = 0.000% (primary)
llpa_purpose = 0.000% (purchase)
total_llpa = 1.000%
adjusted_rate = 6.50% + 1.00% = 7.50%
Stage 8 — P&I Payment
monthly_rate = 0.075 / 12 = 0.0062500
compound = (1.0062500)^360 = 9.42153
numerator = 0.0062500 × 9.42153 = 0.058885
denominator = 9.42153 - 1 = 8.42153
pmt_factor = 0.058885 / 8.42153 = 0.0069921
pi_payment = 412,250 × 0.0069921 = 2,882.51
Stage 12 — PMI
conv_ltv = 97.00% > 80% → PMI required
ltv_band = 90.01–97.00%
pmi_score_band = 680-719 (score 698)
annual_pmi_rate = pmi_table[90.01-97.00][680-719] = 1.00%
monthly_pmi = 412,250 × 0.0100 / 12 = 343.54
PMI cancellation loop (rate 7.50%, loan 412,250, property 425,000):
pmi_cancel_request_target = 425,000 × 0.80 = 340,000
pmi_auto_cancel_target = 425,000 × 0.78 = 331,500
monthly_rate = 0.075 / 12 = 0.0062500
pmt = 412,250 × 0.0069921 = 2,882.51
Amortization loop:
Month 146: balance crosses below 340,000 → pmi_cancel_request_month = 146
Month 157: balance crosses below 331,500 → pmi_auto_cancel_month = 157
[verified by Python: cancel_80 = 146, cancel_78 = 157]
lifetime_pmi = 343.54 × 157 = 53,935.78
Stage 13 — PITI / PITIA
piti = 2,882.51 + 531.25 + 100.00 + 0.00 = 3,513.76
pitia = 3,513.76 + 343.54 = 3,857.30
Stage 10 — DTI
front_end_dti = (pi_payment + tax + ins + HOA) / gmi
= (2,882.51 + 531.25 + 100 + 0) / 8,458.33
= 3,513.76 / 8,458.33
= 0.4154 = 41.54%
back_end_dti_with_pmi = (pitia + obligations) / gmi
total = 3,857.30 + 785.00 = 4,642.30
back_end_dti_with_pmi = 4,642.30 / 8,458.33 = 0.5489 = 54.89%
DU limit (50%): 54.89% > 50% → DU REFER
Manual limit (45%): 54.89% > 45% → MANUAL INELIGIBLE
dti_status = EXCEEDS_ALL
aus_path = DU_REFER_MANUAL_INELIGIBLE
qualification_status = INELIGIBLE_DTI
Stage 15 — Cash to Close
closing_costs_estimate = 412,250 × 0.020 = 8,245.00
daily_rate = 0.075 / 365 = 0.00020548
prepaid_interest = 0.00020548 × 412,250 × 15 = 1,270.63
escrow_setup = (531.25 + 100.00) × 3 = 1,893.75
prepaids = 1,270.63 + 1,893.75 = 3,164.38
cash_to_close = 12,750.00 + 8,245.00 + 3,164.38 - 0 - 0 = 24,159.38
funds_available = 28,105.36
ctc_status = MEETS_REQUIREMENT (surplus $3,946.00)
Stage 16 — Final Result
qualification_status: INELIGIBLE_DTI
reason: Back-end DTI 54.89% exceeds DU 50% limit and manual 45% limit.
Conventional is not viable at this configuration without DTI reduction.
Constraint signals emitted:
CONV_DTI_BLOCKING — back-end DTI 54.89% (DU 50%, Manual 45%)
CONV_PMI_COST — $343.54/month, $53,935.78 lifetime, cancels month 157
CONV_RATE_PENALTY — LLPA 1.00% → 7.50% rate (vs 6.50% base)
Inputs:
qualifying_credit_score: 755
occupancy_type: PRIMARY
loan_purpose: PURCHASE
purchase_price: 550,000
down_payment_amount: 55,000 (10%)
gmi_for_dti: 12,500.00
total_monthly_dti_obligations: 650.00
monthly_tax: 687.50
monthly_insurance: 120.00
hoa_monthly: 0.00
funds_available_for_closing: 80,000.00
funds_available_for_reserves: 50,000.00
Gate 2: loan = 495,000 < 806,500 ✓
Gate 3: score 755 ≥ 620 ✓
Gate 4:
conv_ltv = 495,000 / 550,000 = 0.9000 = 90.00%
LTV cap (PRIMARY) = 97% → PASS (90% ≤ 97%)
Stage 7 — LLPA Rate
conv_ltv = 90.00% → LTV band: 80.01–90.00%
score = 755 → score band: 740-759
llpa_score_ltv = table[80.01-90.00][740-759] = 0.000%
llpa_occupancy = 0.000% (primary)
llpa_purpose = 0.000% (purchase)
total_llpa = 0.000%
adjusted_rate = 6.50% + 0.00% = 6.50%
Stage 8 — P&I
monthly_rate = 0.065 / 12 = 0.0054167
compound = (1.0054167)^360 = 6.99180
numerator = 0.0054167 × 6.99180 = 0.037872
denominator = 6.99180 - 1 = 5.99180
pmt_factor = 0.037872 / 5.99180 = 0.0063207
pi_payment = 495,000 × 0.0063207 = 3,128.74
Stage 12 — PMI
conv_ltv = 90.00% → PMI required (> 80%)
ltv_band = 85.01–90.00% (90.00% ≤ 90.00% → use 85.01-90.00 band)
BOUNDARY RULE: LTV exactly 90.00% — use band 85.01-90.00% (≤ 90.00)
pmi_score_band = 740+ (score 755)
annual_pmi_rate = pmi_table[85.01-90.00][740+] = 0.40%
monthly_pmi = 495,000 × 0.0040 / 12 = 165.00
PMI cancellation (rate 6.50%, loan 495,000, property 550,000):
pmi_cancel_request_target = 550,000 × 0.80 = 440,000
pmi_auto_cancel_target = 550,000 × 0.78 = 429,000
monthly_rate = 0.065 / 12 = 0.0054167
pmt = 495,000 × 0.0063207 = 3,128.74
Amortization loop:
Month 95: balance crosses below 440,000 → pmi_cancel_request_month = 95
Month 109: balance crosses below 429,000 → pmi_auto_cancel_month = 109
[verified by Python]
lifetime_pmi = 165.00 × 109 = 17,985.00
Stage 13 — PITI / PITIA
piti = 3,128.74 + 687.50 + 120.00 + 0.00 = 3,936.24
pitia = 3,936.24 + 165.00 = 4,101.24
Stage 10 — DTI
front_end_dti = 3,936.24 / 12,500.00 = 0.3149 = 31.49%
back_end_dti_with_pmi = (4,101.24 + 650.00) / 12,500.00
= 4,751.24 / 12,500.00
= 0.3801 = 38.01%
DU limit (50%): 38.01% ≤ 50% → DU APPROVE ELIGIBLE ✓
Manual limit (45%): 38.01% ≤ 45% → MANUAL ELIGIBLE ✓
aus_path = DU_APPROVE_ELIGIBLE
Stage 15 — Cash to Close
closing_costs_estimate = 495,000 × 0.020 = 9,900.00
daily_rate = 0.065 / 365 = 0.00017808
prepaid_interest = 0.00017808 × 495,000 × 15 = 1,322.26
escrow_setup = (687.50 + 120.00) × 3 = 2,422.50
prepaids = 1,322.26 + 2,422.50 = 3,744.76
cash_to_close = 55,000 + 9,900 + 3,744.76 = 68,644.76
funds_available = 80,000.00
ctc_status = MEETS_REQUIREMENT (surplus $11,355.24)
Stage 16 — Final Result
qualification_status: QUALIFIED_DU_APPROVE
approved_loan_amount: 495,000
adjusted_rate: 6.50%
pi_payment: 3,128.74
pitia: 4,101.24
front_end_dti: 31.49%
back_end_dti: 38.01%
monthly_pmi: $165.00 (cancels month 109, lifetime $17,985.00)
cash_to_close: 68,644.76
reserve_status: MEETS_REQUIREMENT
Inputs:
qualifying_credit_score: 720
occupancy_type: INVESTMENT
loan_purpose: PURCHASE
purchase_price: 380,000
down_payment_amount: 95,000 (25%)
gmi_for_dti: 9,000.00
total_monthly_dti_obligations: 500.00
monthly_tax: 475.00
monthly_insurance: 90.00
hoa_monthly: 0.00
rental_income_gross: 2,400.00
funds_available_for_closing: 115,000.00
funds_available_for_reserves: 60,000.00
Gate 4:
conv_ltv = 285,000 / 380,000 = 0.7500 = 75.00%
LTV cap (INVESTMENT) = 80% → PASS (75% ≤ 80%)
Stage 7 — LLPA Rate
conv_ltv = 75.00% → LTV band: ≤ 80.00%
score = 720 → score band: 720-739
llpa_score_ltv = table[≤80.00][720-739] = 0.000%
llpa_occupancy = +0.750% (investment, LTV ≤ 75%)
llpa_purpose = 0.000% (purchase)
total_llpa = 0.750%
adjusted_rate = 6.50% + 0.75% = 7.25%
Stage 8 — P&I
monthly_rate = 0.0725 / 12 = 0.0060417
compound = (1.0060417)^360 = 8.74477
numerator = 0.0060417 × 8.74477 = 0.052833
denominator = 8.74477 - 1 = 7.74477
pmt_factor = 0.052833 / 7.74477 = 0.0068218
pi_payment = 285,000 × 0.0068218 = 1,944.20
Stage 9 — Rental Income
rental_income_gross = 2,400.00
rental_income_net = 2,400 × 0.75 = 1,800.00
subject_piti = 1,944.20 + 475 + 90 + 0 = 2,509.20
net_rental_result = 1,800.00 - 2,509.20 = -709.20
rental_offset_type = NEGATIVE_CASHFLOW
rental_loss_for_dti = 709.20 (added to monthly obligations)
gmi_adjusted = 9,000.00 (no change)
Stage 12 — PMI
conv_ltv = 75.00% ≤ 80% → PMI NOT required
monthly_pmi = 0.00
Stage 13 — PITI
piti = 1,944.20 + 475.00 + 90.00 + 0.00 = 2,509.20
pitia = 2,509.20 + 0.00 = 2,509.20 (no PMI)
Stage 10 — DTI
front_end_dti = piti / gmi = 2,509.20 / 9,000.00 = 0.2788 = 27.88%
monthly_obligations_adjusted = 500.00 + 709.20 = 1,209.20
(rental loss added per Stage 9)
back_end_dti = (piti + monthly_obligations_adjusted) / gmi
= (2,509.20 + 1,209.20) / 9,000.00
= 3,718.40 / 9,000.00
= 0.4132 = 41.32%
DU limit (50%): 41.32% ≤ 50% → DU APPROVE ELIGIBLE ✓
Manual limit (45%): 41.32% ≤ 45% ✓
aus_path = DU_APPROVE_ELIGIBLE
Stage 14 — Reserves
reserve_months (INVESTMENT) = 6
required_reserves = 6 × 2,509.20 = 15,055.20
funds_available_for_reserves = 60,000.00
reserve_status = MEETS_REQUIREMENT (surplus $44,944.80)
Stage 15 — CTC
closing_costs_estimate = 285,000 × 0.020 = 5,700.00
daily_rate = 0.0725 / 365 = 0.00019863
prepaid_interest = 0.00019863 × 285,000 × 15 = 849.14
escrow_setup = (475.00 + 90.00) × 3 = 1,695.00
prepaids = 849.14 + 1,695.00 = 2,544.14
cash_to_close = 95,000 + 5,700 + 2,544.14 = 103,244.14
funds_available = 115,000.00
ctc_status = MEETS_REQUIREMENT (surplus $11,755.86)
Stage 16 — Final Result
qualification_status: QUALIFIED_DU_APPROVE
approved_loan_amount: 285,000
adjusted_rate: 7.25%
pi_payment: 1,944.20
pitia: 2,509.20
front_end_dti: 27.88%
back_end_dti: 41.32% (with rental loss)
monthly_pmi: $0 (not required at 75% LTV)
cash_to_close: 103,244.14
reserve_status: MEETS_REQUIREMENT
flags: [RENTAL_LOSS_ADDED_TO_DTI]
CF-01: Applying FHA MIP to conventional loans
FHA UFMIP and annual MIP are FHA-specific. PMI is conventional-specific.
Never use FHA MIP rates, duration rules, or UFMIP in this skill.
CF-02: Using VA residual income for conventional qualification
VA residual income is a VA-only test. Not applicable here.
Back-end DTI governs conventional qualification.
CF-03: Rounding intermediate values before final output
All intermediate values (balance, interest, principal, factors, rates)
use full floating-point precision throughout computation.
Round only final presentation outputs (2 decimal places for dollars,
4 decimal places for rates, 4 for DTI computation, 2 for display).
CF-04: Applying DSCR logic to conventional investment
DSCR uses property income only and has no borrower DTI.
Conventional investment uses borrower GMI + rental offset.
These are fundamentally different qualification methods.
CF-05: Using annual rate directly in amortization loop
monthly_rate = annual_rate / 12.
Never use annual_rate in the balance computation loop.
CF-06: Using purchase_price as LTV denominator when appraisal is lower
property_value = MIN(purchase_price, appraised_value).
Always apply this comparison before computing LTV.
CF-07: PMI not required check off-by-one
PMI required when conv_ltv > 0.80 (strictly greater than).
LTV exactly 80.00% does NOT require PMI.
Apply as > 0.80, not ≥ 0.80.
CF-08: Gift funds for investment down payment
Gift funds are NOT eligible for investment property down payment.
Primary and second home only (Fannie Mae B3-4.3-04).
Flag GIFT_NOT_ELIGIBLE_INVESTMENT and block if investment + gift.
CF-09: Seller concessions exceeding program limits
Seller concessions have LTV-based caps. Excess concessions are subtracted
from purchase price or returned — not applied dollar-for-dollar.
Flag SELLER_CONCESSION_LIMIT if approaching cap.
| Skill | Relationship |
|---|---|
Clarity_Engine_Borrower_Profile_SKILL.md | Required input — provides BorrowerProfile |
Clarity_Engine_Program_Router_SKILL.md | Required input — provides ProgramEvaluationQueue CONVENTIONAL entry |
Clarity_Engine_Math_SKILL.md | Reference — PMT factor computation |
Clarity_Engine_Constraint_Detection_SKILL.md | Receives ConventionalConstraintFlags |
Clarity_Engine_FHA_SKILL.md | Sibling skill — runs in parallel for FHA comparison |
Clarity_Engine_Optimization_SKILL.md | Downstream — receives ConventionalQualResult as baseline |
Clarity_Engine_Audit_Trace_SKILL.md | Downstream — receives ConventionalLineageTrace |
Clarity Engine — Conventional Mortgage Skill v1.0 | CONFIDENTIAL — PreFi, Inc. / Purpose Technology, Inc. d/b/a Purlend