Version: 1.2 | Status: Implementation-Ready — Gear 1
Scope: Intake, normalization, and validation of all borrower data into the canonical Borrower Intelligence Ledger schema. The front door of the Clarity Engine. Every other skill receives its input from this skill's output.
Confidential: PreFi, Inc. / Purpose Technology, Inc. d/b/a Purlend
When invoked, this skill:
This skill does NOT underwrite. It does NOT determine eligibility. It does NOT generate scenarios.
It produces one thing: a clean, complete, validated profile object that every downstream skill can trust.
Invoke this skill when:
Trigger phrases:
Run all 9 stages in order. Do not skip stages. Do not pass to downstream skills until Stage 7 clears all blocking fields and handoff_ready = true.
Stage 1 — Intake: accept and extract all raw input
Stage 2 — Identity + Flags + Credit Score normalization
Stage 3 — Co-Borrower collection (if present)
Stage 4 — Income normalization
Stage 5 — Liability normalization
Stage 6 — Asset normalization
Stage 7 — Property + Deal normalization
Stage 8 — Validation + Completeness + Approval Readiness Score
Stage 9 — Output: BorrowerProfile object + Handoff Statement
Accept whatever the user provides. Do not require a specific format. Extract every piece of mortgage-relevant information from the input and map it to one of these entity categories:
ENTITY CATEGORIES:
1. Borrower Identity + Flags + Credit
2. Co-Borrower (if present)
3. Income Sources (one record per stream)
4. Liabilities (one record per debt)
5. Assets (one record per account)
6. Property
7. Deal Intent
8. Goal Weights (borrower priorities)
| Raw Input | Extracted Field(s) | Extracted Value |
|---|---|---|
| "I make $120K a year" | income_type=BASE_SALARY, gross_monthly_amount | 10,000.00 |
| "I get $1,200/month in disability — it's non-taxable" | income_type=DISABILITY, gross_monthly_amount, taxable=false | 1,200.00 |
| "I have a $350 car payment, 26 months left" | liability_type=AUTO, monthly_payment=350, months_remaining=26 | include_in_dti=true |
| "I'm a veteran" | veteran_flag | true |
| "I want to keep my payment under $3,000" | target_monthly_payment | 3,000.00 |
| "I have about $45K in checking and $120K in my 401K" | asset[CHECKING]=45,000 / asset[RETIREMENT_401K]=120,000 | — |
| "I owe $28K across three credit cards" | 3× liability_type=CREDIT_CARD — prompt for individual balances | — |
| "My credit score is 718" | credit_score | 718 |
| "My wife will be on the loan too" | co_borrower_present=true — trigger Stage 3 | — |
| "I've been self-employed for 3 years" | self_employed_flag=true, history_months=36 | — |
After extraction, present a structured summary to the user for confirmation before proceeding to Stage 2.
Map to the Borrower entity. Mark each field: PRESENT | MISSING | INFERRED | ESTIMATED.
borrower_id auto-generate: BORR_[YYYYMMDD_HHMMSS]
first_name string
last_name string
ssn_hash hash on intake — NEVER store plaintext SSN
credit_score integer — see collection protocol below
veteran_flag boolean — ask directly if not stated
first_time_homebuyer_flag boolean — ask if not stated
self_employed_flag boolean — ask if not stated
primary_residence_intent boolean — derive from deal intent
goal_priority_payment integer 1–5
goal_priority_cash integer 1–5
goal_priority_purchase_power integer 1–5
goal_priority_speed integer 1–5
goal_priority_wealth integer 1–5
date_of_birth date — required for age-sensitive programs
citizenship_status US_CITIZEN | PERM_RESIDENT | NON_PERM_RESIDENT
marital_status MARRIED | SINGLE | SEPARATED | DIVORCED
household_size integer — required for USDA and some DPA income limits
disability_flag boolean — VA funding fee waiver trigger
target_monthly_payment decimal
target_cash_to_close decimal
co_borrower_present boolean — if true, execute Stage 3
Ask for credit score if not provided. If the borrower has not pulled credit:
"Do you know your approximate credit score? If not, I can proceed with an estimate, but actual score is needed before any program eligibility can be confirmed."
If score is unknown, set credit_score = null and flag CREDIT_SCORE_MISSING. This is non-blocking — the Program Router will handle it.
If provided, apply the Credit Tier assignment immediately:
| FICO Range | Tier | Rate Adjustment vs Par | PMI Tier | Engine Routing Action |
|---|---|---|---|---|
| 760+ | 1 | Par (best pricing) | Tier 1 (lowest PMI) | No credit optimization needed. Focus other dimensions. |
| 740–759 | 2 | +0.125% to +0.250% | Tier 2 | Calculate cost of reaching 760. Model savings. Flag ROUTE_CREDIT_TIER_UPGRADE. |
| 720–739 | 3 | +0.250% to +0.500% | Tier 3 | Credit optimization high ROI. Flag ROUTE_CREDIT_OPTIMIZATION. |
| 700–719 | 4 | +0.500% to +0.750% | Tier 4 | FHA may be competitive. Model both. Flag ROUTE_CREDIT_OPTIMIZATION. |
| 680–699 | 5 | +0.750% to +1.000% | Tier 5 | FHA often wins on total cost. Rapid Rescore high priority. Flag ROUTE_FHA_COMPETITIVE. |
| 640–679 | 6 | +1.000%+ | Tier 6 (high PMI) | FHA primary. VA if eligible. Utilization paydown fastest path up. Flag ROUTE_FHA_PRIMARY. |
| 580–639 | 7 | Floor only | N/A conventional | FHA 3.5% or VA only. Priority: get to 640 for better access. Flag ROUTE_FHA_PRIMARY + ROUTE_CREDIT_RECOVERY. |
| < 580 | 8 | No standard program | N/A | Non-QM or portfolio only. Action plan required. Flag ROUTE_CREDIT_RECOVERY + ROUTE_NON_QM. |
Assign credit_tier from this table and include in output. The tier is used by the Ranking Skill's rate adjustment logic.
If the borrower has not stated priorities, ask:
"On a scale of 1 to 5, how important is each of the following — 1 being least important, 5 being most:
— Keeping your monthly payment as low as possible
— Minimizing cash needed at closing
— Maximizing the price you can qualify for
— Closing as quickly as possible
— Building long-term wealth (minimizing total interest paid)"
Map responses to goal_priority_[dimension] fields directly.
If borrower declines to prioritize: default all five weights to 3. Set flag GOAL_WEIGHTS_DEFAULT.
Execute this stage only if co_borrower_present = true. Otherwise skip to Stage 4.
Collect a full parallel Borrower entity for the co-borrower. All fields mirror Stage 2 with the following differences:
co_borrower_id auto-generate: COBR_[YYYYMMDD_HHMMSS]
relationship SPOUSE | PARTNER | FAMILY | OTHER
income_combined_flag boolean — true if incomes will be combined for qualification
liabilities_combined_flag boolean — true if co-borrower debts will be included in DTI
When both borrower and co-borrower have credit scores, the qualifying credit score for program eligibility is:
qualifying_credit_score = LOWER of the two MIDDLE scores across both borrowers
Example:
Borrower scores from 3 bureaus: 720 / 715 / 708 → middle = 715
Co-borrower scores: 680 / 672 / 665 → middle = 672
qualifying_credit_score = MIN(715, 672) = 672
Set qualifying_credit_score on the Deal entity. This is the score used for all program eligibility checks — not the primary borrower's score.
gmi_coborrower = SUM(qualifying_monthly_amount) across all co-borrower IncomeSource records
gmi_combined = gmi_total + gmi_coborrower (if income_combined_flag = true)
If income_combined_flag = false: do not add co-borrower income to DTI numerator, but still include co-borrower liabilities if liabilities_combined_flag = true.
Create one IncomeSource record per income stream per borrower. A borrower with salary + bonus + rental = 3 records.
income_id auto-generate: INC_[n]
borrower_id FK — BORR_ or COBR_ as applicable
income_type enum — see table below
gross_monthly_amount decimal — raw amount before any qualifying treatment
qualifying_monthly_amount decimal — after treatment rules applied (calculated in this stage)
income_frequency MONTHLY | BIWEEKLY | WEEKLY | ANNUAL
history_months required for BONUS, COMMISSION, OVERTIME, SELF_EMPLOYMENT
continuance_likely_flag required for pension, alimony, disability
documentation_status STATED | PARTIAL | VERIFIED
add_back_amount SELF_EMPLOYMENT only
gross_up_applied_flag boolean — set true when 1.25× applied
averaging_method CURRENT_ONLY | TWO_YR_AVG | LOWER_OF_TWO_YEARS
taxable_flag boolean — false triggers gross-up eligibility check
Before applying qualifying treatment, normalize all income to monthly:
ANNUAL: gross_monthly_amount = stated_annual / 12
BIWEEKLY: gross_monthly_amount = stated_biweekly × 26 / 12
WEEKLY: gross_monthly_amount = stated_weekly × 52 / 12
MONTHLY: gross_monthly_amount = as stated
| Income Type | Qualifying Treatment | History Required | Averaging Method | Key Rules |
|---|---|---|---|---|
| BASE_SALARY | annual ÷ 12 | None | CURRENT_ONLY | Verify with paystub + W-2 |
| BONUS | 24-month average | 24 months | TWO_YR_AVG | If YoY declining: use LOWER_OF_TWO_YEARS |
| COMMISSION | 24-month average | 24 months | TWO_YR_AVG | If < 24mo: flag CONDITIONAL, use available history |
| OVERTIME | 24-month average | 24 months | TWO_YR_AVG | If YoY declining: use LOWER_OF_TWO_YEARS |
| SELF_EMPLOYMENT | net profit + Schedule C add-backs, 24-month average | 24 months | TWO_YR_AVG | If declining > 10% YoY: use lower year. If < 24mo: CONDITIONAL |
| RENTAL | gross_rent × 0.75 | 12 months | CURRENT_ONLY | Requires executed lease or appraiser market rent. Apply 75% vacancy factor. |
| SOCIAL_SECURITY | gross_monthly × 1.25 if non-taxable | None | CURRENT_ONLY | Set gross_up_applied_flag=true. See VA Gross-Up Guard below. |
| PENSION | as received | None | CURRENT_ONLY | Verify continuance. Set continuance_likely_flag. |
| DISABILITY | gross_monthly × 1.25 if non-taxable | None | CURRENT_ONLY | Set gross_up_applied_flag=true. See VA Gross-Up Guard below. |
| ALIMONY (receiving) | as received if ≥ 3 years continuance remaining | 6 months | CURRENT_ONLY | Require court order |
| BOARDER | up to $200/mo | 12 months | CURRENT_ONLY | FHA only. Set flag NOT_ELIGIBLE_CONVENTIONAL |
| OTHER | case by case | per type | per type | Flag for advisor review |
When taxable_flag = false for SOCIAL_SECURITY or DISABILITY:
qualifying_monthly_amount = gross_monthly_amount × 1.25
gross_up_applied_flag = true
gross_up_amount = gross_monthly_amount × 0.25
Example:
SS income = $1,200/month (non-taxable)
qualifying_monthly_amount = 1,200 × 1.25 = 1,500
gross_up_amount = 1,200 × 0.25 = 300
When any VA loan scenario is in scope (veteran_flag = true), income must be stored on two separate paths. These values will differ whenever gross-up income is present. Failure to separate them is the most dangerous income calculation error in the system.
PATH 1 — DTI (uses grossed-up income):
gmi_for_dti = SUM(qualifying_monthly_amount) for all streams
= includes 1.25× gross-up on non-taxable streams
PATH 2 — VA Residual Income (uses NET received income, NO gross-up):
net_income_for_va_residual = SUM(gross_monthly_amount) for all streams
= 1.00× — never multiply non-taxable streams
VALIDATION RULE:
IF any stream has gross_up_applied_flag = true:
ASSERT gmi_for_dti ≠ net_income_for_va_residual
IF equal → flag INCOME_SPLIT_ERROR — block handoff
qualifying_monthly_amount per stream = result of qualifying treatment above
gmi_total = SUM(qualifying_monthly_amount) — primary borrower all streams
gmi_coborrower = SUM(qualifying_monthly_amount) — co-borrower all streams
gmi_combined = gmi_total + gmi_coborrower (if income_combined_flag = true)
gmi_for_dti = gmi_combined (or gmi_total if no co-borrower)
net_income_for_va_residual = SUM(gross_monthly_amount) — no gross-up, both borrowers
Create one Liability record per debt obligation. Include all debts from credit report and all debts stated by borrower. If credit report shows a debt the borrower did not mention, include it and flag UNDISCLOSED_LIABILITY.
liability_id auto-generate: LIAB_[n]
borrower_id FK — BORR_ or COBR_ as applicable
liability_type enum — CREDIT_CARD | AUTO | STUDENT_LOAN | PERSONAL_LOAN |
MORTGAGE | INSTALLMENT | HELOC | CHILD_SUPPORT |
ALIMONY_PAYING | BUSINESS_DEBT
balance decimal
monthly_payment decimal — minimum payment for revolving; actual for installment
secured_flag boolean
eligible_for_payoff_flag boolean — can the engine propose payoff as an optimization move?
include_in_dti_flag boolean — apply rules below
creditor_name string
interest_rate decimal APR — needed for consolidation ranking
credit_limit decimal — required for all revolving accounts (utilization calc)
months_remaining integer — required for installment exclusion eligibility check
cosigned_flag boolean
business_debt_flag boolean
student_loan_repayment_type STANDARD | DEFERRED | IDR | GRADUATED
Apply in order. First matching rule wins.
| Priority | Condition | include_in_dti_flag | Required Documentation |
|---|---|---|---|
| 1 | GMI = 0 after income processing | BLOCK — ERR-PROFILE-001 | N/A |
| 2 | Installment loan, months_remaining ≤ 10 | FALSE | Document months_remaining |
| 3 | Co-signed, 12+ months third-party payment history | FALSE | Bank statements proving third party pays |
| 4 | Business debt, documented on business return | FALSE | CPA letter |
| 5 | HELOC with $0 drawn balance | FALSE for conventional; TRUE for FHA/VA | Note: program-specific. Default FALSE unless FHA/VA in scope |
| 6 | Child support / alimony paying | TRUE | Always include — no exclusion |
| 7 | Student loan, deferred or $0 payment | TRUE | Use 0.5% of balance as dti_monthly_payment |
| 8 | Student loan, income-driven repayment | TRUE | dti_monthly_payment = MAX(actual_payment, balance × 0.005) |
| 9 | All other standard debts | TRUE | Default |
IF liability_type = STUDENT_LOAN:
IF student_loan_repayment_type = DEFERRED OR monthly_payment = 0:
dti_monthly_payment = balance × 0.005
averaging_note = "Deferred — using 0.5% of balance per Fannie Mae B3-6-05"
ELIF student_loan_repayment_type = IDR:
dti_monthly_payment = MAX(monthly_payment, balance × 0.005)
averaging_note = "IDR — using greater of actual payment or 0.5% of balance"
ELSE:
dti_monthly_payment = monthly_payment
Example:
Student loan balance = $45,000, deferred
dti_monthly_payment = 45,000 × 0.005 = 225.00/month
total_monthly_dti_obligations = SUM(dti_monthly_payment WHERE include_in_dti_flag = true)
total_revolving_balance = SUM(balance WHERE liability_type IN [CREDIT_CARD, HELOC])
total_revolving_credit_limit = SUM(credit_limit WHERE liability_type IN [CREDIT_CARD, HELOC])
total_revolving_utilization = total_revolving_balance / total_revolving_credit_limit
(return 0 if total_revolving_credit_limit = 0)
high_interest_debt_total = SUM(balance WHERE interest_rate >= 15.0%)
months_to_exclusion_list = [liability_id, creditor, months_remaining, monthly_payment]
WHERE months_remaining <= 10 AND include_in_dti_flag = true
(these are debt-timing optimization opportunities)
Create one Asset record per account.
asset_id auto-generate: AST_[n]
borrower_id FK
asset_type enum — CHECKING | SAVINGS | BROKERAGE | RETIREMENT_401K |
RETIREMENT_IRA | CRYPTO | GIFT | REAL_ESTATE_EQUITY |
BUSINESS | OTHER
balance decimal — current balance
liquid_flag boolean
eligible_for_closing_flag boolean
eligible_for_reserves_flag boolean
haircut_pct decimal — see table below
vested_pct decimal — retirement accounts (default 1.00 if not stated)
source_verified_flag boolean — 60-day statement required
seasoning_days integer — days funds have been in account
gift_letter_received_flag boolean — required for GIFT type
| Asset Type | liquid_flag | eligible_for_closing | eligible_for_reserves | haircut_pct | Notes |
|---|---|---|---|---|---|
| CHECKING | true | true | true | 0.00 | Full value |
| SAVINGS | true | true | true | 0.00 | Full value |
| BROKERAGE | true | true | true | 0.30 | 30% haircut per Fannie Mae B3-4.3-09 — use 70% of documented value |
| RETIREMENT_401K | false | false | true | 0.40 | 60% of vested balance for reserves only — never for closing |
| RETIREMENT_IRA | false | false | true | 0.40 | Same as 401K |
| CRYPTO | false | false | false | 1.00 | Must liquidate AND season 60 days post-liquidation — $0 eligible until then |
| GIFT | true | true | false | 0.00 | Requires gift letter. Not eligible for reserves. |
| REAL_ESTATE_EQUITY | false | false | false | varies | Only eligible if cash-out refi proceeds — deal-specific |
| BUSINESS | false | false | false | varies | Requires CPA letter. Rarely eligible. Flag for advisor. |
The engine must reserve a minimum post-close cushion before allocating assets to closing. This prevents the common error of counting all assets as available for closing when part must remain post-close.
reserve_months_required = program.reserve_requirement_months (default 2 if unknown)
estimated_piti_for_reserve = monthly_piti_estimate from Stage 7 (calculated after property/deal)
required_reserves_hold = reserve_months_required × estimated_piti_for_reserve
funds_available_for_closing = net_eligible_assets - required_reserves_hold
(floor at 0 — cannot be negative)
NOTE: required_reserves_hold is recalculated per scenario in downstream skills.
Use 2-month hold as conservative default at profile stage.
net_eligible_assets = SUM(balance × (1 - haircut_pct)) WHERE eligible_for_closing_flag = true
retirement_reserve_credit = SUM(balance × vested_pct × 0.60) WHERE asset_type IN [RETIREMENT_401K, RETIREMENT_IRA]
funds_available_for_closing = net_eligible_assets - required_reserves_hold (floor at 0)
funds_available_for_reserves = net_eligible_assets - funds_available_for_closing + retirement_reserve_credit
total_asset_strength = funds_available_for_closing + funds_available_for_reserves
property_id auto-generate: PROP_[YYYYMMDD_HHMMSS]
address string — full street address
city string
state string — two-letter USPS code
zip_code string
property_type SFR | CONDO | TOWNHOME | 2_UNIT | 3_UNIT | 4_UNIT | PUD | MANUFACTURED
occupancy_type PRIMARY | SECOND_HOME | INVESTMENT
unit_count integer 1–4
county string — derive from zip if not provided
purchase_price decimal — required for PURCHASE deals
estimated_value decimal — required for REFI deals
annual_property_tax decimal — if not provided, estimate below
annual_insurance decimal — if not provided, estimate below
hoa_monthly decimal — 0 if none
flood_zone_flag boolean — default false; set true if known
appraisal_status ESTIMATED | ORDERED | COMPLETED | WAIVED
condo_project_status NOT_APPLICABLE | APPROVED | PENDING_REVIEW | NON_WARRANTABLE
Apply when borrower cannot provide actual amounts. Flag all estimates.
IF annual_property_tax not provided:
annual_property_tax_estimate = purchase_price × 0.0125
monthly_tax = annual_property_tax_estimate / 12
flag: TAX_ESTIMATED
IF annual_insurance not provided:
annual_insurance_estimate = purchase_price × 0.005
monthly_insurance = annual_insurance_estimate / 12
flag: INSURANCE_ESTIMATED
deal_id auto-generate: DEAL_[YYYYMMDD_HHMMSS]
deal_type PURCHASE | RATE_REFI | CASH_OUT_REFI | DEBT_CONSOLIDATION_REFI | TERM_REFI
borrower_id FK
property_id FK
intent_type PURCHASE | REFINANCE | EQUITY_ACCESS | UNCERTAINTY
deal_state ACTIVE (on creation)
qualifying_credit_score from Stage 2 (or Stage 3 if co-borrower present)
created_at ISO 8601 UTC
last_updated_at ISO 8601 UTC
PURCHASE deals:
down_payment_amount decimal — required
requested_loan_amount decimal — if null: loan = purchase_price - down_payment
estimated_closing_costs decimal — if null: estimate = requested_loan_amount × 0.03
seller_concession_amount decimal — default 0
REFI deals:
current_mortgage_balance decimal — required
current_rate decimal — required
current_payment_pi decimal — required for savings calculation
remaining_term_months integer — required
estimated_closing_costs decimal — if null: estimate = current_mortgage_balance × 0.03
CASH-OUT REFI deals:
desired_cash_out_amount decimal — required
(inherits all REFI fields above)
IF PURCHASE:
requested_loan_amount = purchase_price - down_payment_amount
ltv_estimate = requested_loan_amount / purchase_price
cash_to_close_estimate = down_payment_amount + estimated_closing_costs - seller_concession_amount
IF REFI:
ltv_estimate = current_mortgage_balance / estimated_value
cash_to_close_estimate = estimated_closing_costs (no down payment on refi)
IF CASH_OUT_REFI:
requested_loan_amount = current_mortgage_balance + desired_cash_out_amount + estimated_closing_costs
ltv_estimate = requested_loan_amount / estimated_value
monthly_piti_estimate = rough P&I at 7.00% / 30yr on requested_loan_amount
+ monthly_tax + monthly_insurance + hoa_monthly
(7.00% is a neutral placeholder — actual rate computed per scenario)
NOTE on monthly_piti_estimate:
P&I at 7.00% = requested_loan_amount × (0.07/12 × (1+0.07/12)^360) / ((1+0.07/12)^360 - 1)
= requested_loan_amount × 0.006653
Example: loan = $400,000
P&I = 400,000 × 0.006653 = 2,661.20
If tax=$800, ins=$200, hoa=$0: monthly_piti_estimate = 3,661.20
The following fields are BLOCKING — if any are missing, set handoff_ready = false and request them before proceeding.
| Blocking Field | Entity | Reason |
|---|---|---|
| income_type + qualifying_monthly_amount (≥1 stream) | IncomeSource | Cannot compute GMI or DTI |
| credit_score (or qualifying_credit_score) | Borrower / Deal | Cannot run eligibility on any program |
| property_type | Property | Cannot determine eligible programs |
| occupancy_type | Property | Cannot determine eligible programs |
| deal_type | Deal | Cannot route to correct processing path |
| veteran_flag | Borrower | Cannot determine VA eligibility |
| purchase_price (PURCHASE) OR estimated_value (REFI) | Property | Cannot compute LTV |
| down_payment_amount (PURCHASE only) | Deal | Cannot compute LTV or cash to close |
INCOME_HISTORY_SHORT variable income with < 24 months history
SELF_EMPLOYED_SHORT_HISTORY self-employed < 24 months
INCOME_SPLIT_ERROR gmi_for_dti = net_income_for_va_residual when gross-up present — BLOCK
ASSETS_UNVERIFIED no source_verified_flag = true on any asset
TAX_ESTIMATED property tax was estimated at 1.25%
INSURANCE_ESTIMATED insurance was estimated at 0.5%
CLOSING_COSTS_ESTIMATED closing costs estimated at 3%
CO_BORROWER_NOT_EVALUATED co_borrower_present not asked or not confirmed
GOAL_WEIGHTS_DEFAULT borrower declined to state priorities
CREDIT_SCORE_MISSING credit_score = null — non-blocking but limits routing
UNDISCLOSED_LIABILITY debt on credit report not mentioned by borrower
ROUTE_CHECK_VA veteran_flag = true
ROUTE_CHECK_DPA first_time_homebuyer_flag = true
ROUTE_INCOME_COMPLEXITY self_employed_flag = true OR multiple variable income streams
ROUTE_CREDIT_RECOVERY credit_score < 580
ROUTE_FHA_PRIMARY credit_score 580–639 OR (credit_score 640–679 AND ltv > 0.80)
ROUTE_FHA_COMPETITIVE credit_score 680–699
ROUTE_CREDIT_OPTIMIZATION credit_score 700–759 OR total_revolving_utilization > 0.30
ROUTE_CREDIT_TIER_UPGRADE credit_score 740–759 (one tier from par pricing)
ROUTE_DOWN_PAYMENT_CONSTRAINT ltv_estimate > 0.97
ROUTE_DEBT_TIMING_OPPORTUNITY months_to_exclusion_list is non-empty
ROUTE_HIGH_DTI preliminary_dti_signal = ELEVATED or CONCERN
ROUTE_CTC_SHORTFALL funds_available_for_closing < cash_to_close_estimate
Signal only — not a qualifying DTI. Actual DTI computed per program and rate by family skills.
preliminary_dti = (monthly_piti_estimate + total_monthly_dti_obligations) / gmi_for_dti
Signals:
CLEAR < 36% All standard programs viable
WATCH 36%–45% Most programs viable; review carefully
ELEVATED 45%–50% Limited programs; optimization likely needed
CONCERN > 50% Significant constraint; action plan likely required
Example:
monthly_piti_estimate = 3,200
total_monthly_dti_obligations = 750
gmi_for_dti = 9,500
preliminary_dti = (3,200 + 750) / 9,500 = 3,950 / 9,500 = 41.6% → WATCH
A single 0.0–1.0 composite signal summarizing the borrower's current qualification strength. Used for session prioritization and Nova framing. Computed from four components, each scored 0.0–1.0, then weighted.
COMPONENT 1 — Credit Score Margin (weight: 0.30)
credit_margin_score = MIN(1.0, MAX(0.0, (credit_score - 580) / (760 - 580)))
Anchors: 580 = 0.0 (floor), 760 = 1.0 (ceiling), linear between
Example: credit_score = 718
credit_margin_score = (718 - 580) / (760 - 580) = 138 / 180 = 0.767
COMPONENT 2 — DTI Margin (weight: 0.30)
dti_margin = 0.45 - preliminary_dti (positive = room remaining; negative = over limit)
dti_margin_score = MIN(1.0, MAX(0.0, (dti_margin + 0.09) / 0.18))
Anchors: -0.09 (9% over limit) = 0.0, +0.09 (9% under limit) = 1.0, linear between
Example: preliminary_dti = 0.416
dti_margin = 0.45 - 0.416 = 0.034
dti_margin_score = (0.034 + 0.09) / 0.18 = 0.124 / 0.18 = 0.689
COMPONENT 3 — Reserve Depth (weight: 0.20)
reserves_months = funds_available_for_reserves / monthly_piti_estimate
reserve_score = MIN(1.0, MAX(0.0, reserves_months / 6))
Anchors: 0 months = 0.0, 6+ months = 1.0, linear between
Example: funds_available_for_reserves = $28,000, monthly_piti = $3,200
reserves_months = 28,000 / 3,200 = 8.75 months
reserve_score = MIN(1.0, 8.75 / 6) = MIN(1.0, 1.458) = 1.0
COMPONENT 4 — Documentation Completeness (weight: 0.20)
blocking_flags_present = count of BLOCKING fields still missing (0 at handoff)
soft_flags_present = count of soft_missing_fields
doc_score = MAX(0.0, 1.0 - (soft_flags_present × 0.10))
Cap deduction at 1.0 (floor at 0.0)
Example: 2 soft flags (ASSETS_UNVERIFIED, TAX_ESTIMATED)
doc_score = MAX(0.0, 1.0 - (2 × 0.10)) = 0.80
FINAL SCORE:
approval_readiness_score = (credit_margin_score × 0.30)
+ (dti_margin_score × 0.30)
+ (reserve_score × 0.20)
+ (doc_score × 0.20)
Example (continuing above):
= (0.767 × 0.30) + (0.689 × 0.30) + (1.0 × 0.20) + (0.80 × 0.20)
= 0.230 + 0.207 + 0.200 + 0.160
= 0.797
SIGNAL BANDS:
0.85–1.00 STRONG High confidence. Proceed to scenario generation.
0.70–0.84 MODERATE Viable with current profile. Some optimization available.
0.50–0.69 DEVELOPING Constraints present. Optimization moves likely needed.
0.00–0.49 ACTION Significant gap. Constraint detection priority before routing.
completeness_score = count(PRESENT + ESTIMATED + INFERRED fields) / count(total required fields)
Example: 47 of 52 required fields present/estimated → completeness_score = 0.904
{
"schema_version": "clarity_engine_v1.1",
"profile_created_at": "2026-03-08T09:00:00Z",
"last_updated_at": "2026-03-08T09:00:00Z",
"completeness_score": 0.904,
"handoff_ready": true,
"validation": {
"blocking_missing_fields": [],
"soft_missing_fields": ["ASSETS_UNVERIFIED", "TAX_ESTIMATED"],
"documentation_flags": ["TAX_ESTIMATED", "INSURANCE_ESTIMATED"],
"income_split_error": false
},
"routing": {
"routing_flags": ["ROUTE_CHECK_VA", "ROUTE_CHECK_DPA", "ROUTE_CREDIT_OPTIMIZATION"],
"preliminary_dti_value": 0.416,
"preliminary_dti_signal": "WATCH",
"approval_readiness_score": 0.797,
"approval_readiness_signal": "MODERATE"
},
"borrower": {
"borrower_id": "BORR_20260308_090000",
"first_name": "string",
"last_name": "string",
"ssn_hash": "string — hashed only",
"credit_score": 718,
"credit_tier": 4,
"veteran_flag": true,
"disability_flag": false,
"first_time_homebuyer_flag": true,
"self_employed_flag": false,
"primary_residence_intent": true,
"household_size": 3,
"citizenship_status": "US_CITIZEN",
"marital_status": "MARRIED",
"date_of_birth": "YYYY-MM-DD",
"target_monthly_payment": 3000.00,
"target_cash_to_close": 15000.00,
"goal_weights": {
"payment": 5,
"cash": 4,
"purchase_power": 5,
"speed": 3,
"wealth": 4
}
},
"co_borrower": {
"co_borrower_id": "COBR_20260308_090000",
"first_name": "string",
"last_name": "string",
"credit_score": 0,
"income_combined_flag": true,
"liabilities_combined_flag": true,
"relationship": "SPOUSE | PARTNER | FAMILY | OTHER"
},
"income": {
"sources": [
{
"income_id": "INC_1",
"borrower_id": "BORR_20260308_090000",
"income_type": "BASE_SALARY",
"gross_monthly_amount": 0.00,
"qualifying_monthly_amount": 0.00,
"income_frequency": "MONTHLY | BIWEEKLY | WEEKLY | ANNUAL",
"history_months": 0,
"documentation_status": "STATED | PARTIAL | VERIFIED",
"gross_up_applied_flag": false,
"gross_up_amount": 0.00,
"taxable_flag": true,
"averaging_method": "CURRENT_ONLY | TWO_YR_AVG | LOWER_OF_TWO_YEARS",
"continuance_likely_flag": true,
"add_back_amount": 0.00
}
],
"gmi_total": 0.00,
"gmi_coborrower": 0.00,
"gmi_combined": 0.00,
"gmi_for_dti": 0.00,
"net_income_for_va_residual": 0.00,
"gross_up_streams": []
},
"liabilities": {
"accounts": [
{
"liability_id": "LIAB_1",
"borrower_id": "BORR_20260308_090000",
"liability_type": "CREDIT_CARD | AUTO | STUDENT_LOAN | ...",
"creditor_name": "string",
"balance": 0.00,
"monthly_payment": 0.00,
"dti_monthly_payment": 0.00,
"interest_rate": 0.00,
"credit_limit": 0.00,
"months_remaining": 0,
"secured_flag": false,
"include_in_dti_flag": true,
"eligible_for_payoff_flag": true,
"cosigned_flag": false,
"business_debt_flag": false,
"student_loan_repayment_type": "STANDARD | DEFERRED | IDR | GRADUATED"
}
],
"total_monthly_dti_obligations": 0.00,
"total_revolving_balance": 0.00,
"total_revolving_credit_limit": 0.00,
"total_revolving_utilization": 0.00,
"high_interest_debt_total": 0.00,
"months_to_exclusion_list": []
},
"assets": {
"accounts": [
{
"asset_id": "AST_1",
"borrower_id": "BORR_20260308_090000",
"asset_type": "CHECKING | SAVINGS | BROKERAGE | ...",
"balance": 0.00,
"vested_pct": 1.00,
"liquid_flag": true,
"eligible_for_closing_flag": true,
"eligible_for_reserves_flag": true,
"haircut_pct": 0.00,
"net_eligible_balance": 0.00,
"source_verified_flag": false,
"seasoning_days": 0,
"gift_letter_received_flag": false
}
],
"net_eligible_assets": 0.00,
"retirement_reserve_credit": 0.00,
"required_reserves_hold": 0.00,
"funds_available_for_closing": 0.00,
"funds_available_for_reserves": 0.00,
"total_asset_strength": 0.00
},
"property": {
"property_id": "PROP_20260308_090000",
"address": "string",
"city": "string",
"state": "string",
"zip_code": "string",
"county": "string",
"property_type": "SFR | CONDO | TOWNHOME | 2_UNIT | 3_UNIT | 4_UNIT | PUD | MANUFACTURED",
"occupancy_type": "PRIMARY | SECOND_HOME | INVESTMENT",
"unit_count": 1,
"purchase_price": 0.00,
"estimated_value": 0.00,
"annual_property_tax": 0.00,
"monthly_tax": 0.00,
"tax_estimated_flag": false,
"annual_insurance": 0.00,
"monthly_insurance": 0.00,
"insurance_estimated_flag": false,
"hoa_monthly": 0.00,
"flood_zone_flag": false,
"appraisal_status": "ESTIMATED | ORDERED | COMPLETED | WAIVED",
"condo_project_status": "NOT_APPLICABLE | APPROVED | PENDING_REVIEW | NON_WARRANTABLE"
},
"deal": {
"deal_id": "DEAL_20260308_090000",
"deal_type": "PURCHASE | RATE_REFI | CASH_OUT_REFI | DEBT_CONSOLIDATION_REFI | TERM_REFI",
"borrower_id": "BORR_20260308_090000",
"co_borrower_id": "COBR_20260308_090000",
"property_id": "PROP_20260308_090000",
"intent_type": "PURCHASE | REFINANCE | EQUITY_ACCESS | UNCERTAINTY",
"qualifying_credit_score": 0,
"requested_loan_amount": 0.00,
"down_payment_amount": 0.00,
"estimated_closing_costs": 0.00,
"closing_costs_estimated_flag": false,
"seller_concession_amount": 0.00,
"current_mortgage_balance": 0.00,
"current_rate": 0.00,
"current_payment_pi": 0.00,
"remaining_term_months": 0,
"desired_cash_out_amount": 0.00,
"deal_state": "ACTIVE",
"created_at": "ISO 8601 UTC",
"last_updated_at": "ISO 8601 UTC"
},
"preliminary_signals": {
"ltv_estimate": 0.00,
"cash_to_close_estimate": 0.00,
"monthly_piti_estimate": 0.00,
"preliminary_dti_value": 0.00,
"preliminary_dti_signal": "CLEAR | WATCH | ELEVATED | CONCERN",
"approval_readiness_score": 0.00,
"approval_readiness_signal": "STRONG | MODERATE | DEVELOPING | ACTION",
"approval_readiness_components": {
"credit_margin_score": 0.00,
"dti_margin_score": 0.00,
"reserve_score": 0.00,
"doc_score": 0.00
}
}
}
handoff_ready = true only when blocking_missing_fields array is empty AND income_split_error = false.
Emit this summary when handoff_ready = true:
BORROWER PROFILE COMPLETE — v1.1
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Borrower: [Name] (+ Co-Borrower: [Name] if present)
Deal Type: [Type] | Property: [City, State]
Credit Score: [XXX] → Tier [N] ([rate adj description])
Qualifying Score: [XXX] (lowest middle score if co-borrower)
GMI: $[X,XXX]/month (primary)
$[X,XXX]/month (co-borrower, if present)
$[X,XXX]/month (combined)
Total DTI Debts: $[X,XXX]/month
Preliminary DTI: [XX.X%] → [CLEAR / WATCH / ELEVATED / CONCERN]
Available for Closing: $[XX,XXX]
Available for Reserves: $[XX,XXX] ([X.X] months PITI)
LTV Estimate: [XX.X%]
Cash to Close Est.: $[XX,XXX]
Approval Readiness: [0.XXX] → [STRONG / MODERATE / DEVELOPING / ACTION]
Credit margin: [X.XXX] (weight 0.30)
DTI margin: [X.XXX] (weight 0.30)
Reserve depth: [X.XXX] (weight 0.20)
Documentation: [X.XXX] (weight 0.20)
Routing Flags: [list]
Documentation Flags: [list]
Completeness: [XX%] | Blocking Fields: NONE
→ Profile ready for Program Router
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
This example runs a complete borrower through all 9 stages. Validate every number.
"Marcus and Diana Webb. Marcus is a W-2 employee making $85,000/year. Diana gets $1,100/month in VA disability — non-taxable. They're veterans. First-time buyers. Looking to purchase around $425,000, they have $35,000 in checking and $90,000 in Marcus's 401K. Their debts: $380 car payment with 14 months left, $220 credit card minimum on $8,500 balance ($12,000 limit), $185 student loan (IDR, balance $22,000). Marcus's score is 722, Diana's is 698. They want to keep their payment under $3,200 and need to minimize cash at closing. Property is an SFR in Austin, TX — primary."
| Item | Extracted Value |
|---|---|
| Primary borrower | Marcus Webb |
| Co-borrower | Diana Webb |
| Income 1 | BASE_SALARY, $85,000/year, W-2 |
| Income 2 | DISABILITY, $1,100/month, non-taxable |
| veteran_flag | true (both) |
| first_time_homebuyer_flag | true |
| Purchase price | $425,000 |
| Asset 1 | CHECKING $35,000 |
| Asset 2 | RETIREMENT_401K $90,000 |
| Liability 1 | AUTO $380/month, 14 months remaining |
| Liability 2 | CREDIT_CARD $220 minimum, $8,500 balance, $12,000 limit |
| Liability 3 | STUDENT_LOAN IDR, $185/month actual, $22,000 balance |
| Marcus credit score | 722 |
| Diana credit score | 698 |
| target_monthly_payment | $3,200 |
| goal_priority_cash | high (stated "minimize cash at closing") → 5 |
| Property type | SFR, PRIMARY, Austin TX |
borrower_id: BORR_20260308_090000
credit_score (Marcus): 722
credit_tier: 3 (720–739)
credit_tier_note: "+0.25% to +0.50% vs par. Credit optimization high ROI."
veteran_flag: true
first_time_homebuyer_flag: true
self_employed_flag: false
primary_residence_intent: true
target_monthly_payment: 3,200.00
goal_priority_cash: 5 (stated: minimize cash at closing)
remaining goal weights: default 3 (not stated — flag GOAL_WEIGHTS_PARTIAL)
co_borrower_id: COBR_20260308_090000
first_name: Diana
credit_score (Diana): 698
credit_tier (Diana): 5 (680–699)
income_combined_flag: true
liabilities_combined_flag: true
Qualifying Credit Score:
Marcus middle score: 722
Diana middle score: 698
qualifying_credit_score = MIN(722, 698) = 698
→ credit_tier for program eligibility = 5 (Diana's score controls)
→ flag ROUTE_FHA_COMPETITIVE
Stream 1 — Marcus BASE_SALARY
gross_monthly_amount = 85,000 / 12 = 7,083.33
qualifying_monthly_amount = 7,083.33 (no treatment — salary)
income_frequency: ANNUAL → converted to MONTHLY
gross_up_applied_flag: false
taxable_flag: true
Stream 2 — Diana DISABILITY (non-taxable)
gross_monthly_amount = 1,100.00
taxable_flag = false → gross-up applies
qualifying_monthly_amount = 1,100 × 1.25 = 1,375.00
gross_up_applied_flag = true
gross_up_amount = 1,100 × 0.25 = 275.00
GMI Derivation
gmi_total (Marcus): 7,083.33
gmi_coborrower (Diana): 1,375.00 (grossed up for DTI)
gmi_combined: 7,083.33 + 1,375.00 = 8,458.33
gmi_for_dti: 8,458.33
VA Gross-Up Guard (veteran_flag = true — guard must execute):
net_income_for_va_residual = 7,083.33 + 1,100.00 = 8,183.33
(Diana's disability: 1,100.00 — NOT grossed up on residual path)
Validation:
gmi_for_dti (8,458.33) ≠ net_income_for_va_residual (8,183.33) ✓
gross_up_streams: [INC_2 — DISABILITY — gross_up_amount=275.00]
income_split_error: false ✓
Liability 1 — AUTO
balance: not stated — flag BALANCE_UNKNOWN
monthly_payment: 380.00
months_remaining: 14
include_in_dti_flag: FALSE (months_remaining = 14 > 10... wait)
14 > 10 → rule says ≤ 10 for exclusion
14 months remaining → DOES NOT qualify for exclusion
include_in_dti_flag: TRUE
dti_monthly_payment: 380.00
months_to_exclusion: 14 - 10 = 4 months until exclusion eligible
→ flag ROUTE_DEBT_TIMING_OPPORTUNITY (4 months from exclusion)
eligible_for_payoff_flag: true
Liability 2 — CREDIT_CARD
balance: 8,500.00
monthly_payment: 220.00
credit_limit: 12,000.00
interest_rate: not stated
include_in_dti_flag: TRUE
dti_monthly_payment: 220.00
utilization_pct: 8,500 / 12,000 = 70.8% → flag ROUTE_CREDIT_OPTIMIZATION
eligible_for_payoff_flag: true
Liability 3 — STUDENT_LOAN (IDR)
balance: 22,000.00
monthly_payment: 185.00 (actual IDR payment)
student_loan_repayment_type: IDR
dti_monthly_payment: MAX(185.00, 22,000 × 0.005) = MAX(185.00, 110.00) = 185.00
Note: actual payment (185) > 0.5% of balance (110) → use actual
include_in_dti_flag: TRUE
eligible_for_payoff_flag: true
Derived Liability Metrics
total_monthly_dti_obligations = 380.00 + 220.00 + 185.00 = 785.00
total_revolving_balance = 8,500.00
total_revolving_credit_limit = 12,000.00
total_revolving_utilization = 8,500 / 12,000 = 0.708 (70.8%)
high_interest_debt_total = unknown (interest_rate not stated)
months_to_exclusion_list = [{LIAB_1, AUTO, 14 months remaining, $380/month}]
Asset 1 — CHECKING
balance: 35,000.00
liquid_flag: true
eligible_for_closing: true
eligible_for_reserves: true
haircut_pct: 0.00
net_eligible_balance: 35,000.00 × (1 - 0.00) = 35,000.00
Asset 2 — RETIREMENT_401K
balance: 90,000.00
vested_pct: 1.00 (assumed — not stated, flag VESTED_PCT_ASSUMED)
liquid_flag: false
eligible_for_closing: false
eligible_for_reserves: true
haircut_pct: 0.40
net_eligible_balance: 0.00 (not eligible for closing)
Reserve Hold Calculation
reserve_months_required: 2 (default — actual program requirement computed per scenario)
monthly_piti_estimate: 3,447.32 (calculated in Stage 7 — see below)
required_reserves_hold: 2 × 3,447.32 = 6,894.64
NOTE: $3,200 is the borrower's target_monthly_payment — NOT the PITI estimate.
Always use monthly_piti_estimate for the reserve hold, never the target payment.
Derived Asset Metrics
net_eligible_assets: 35,000.00 (CHECKING only — 401K not eligible for closing)
retirement_reserve_credit: 90,000 × 1.00 × 0.60 = 54,000.00
required_reserves_hold: 6,894.64
funds_available_for_closing: 35,000.00 - 6,894.64 = 28,105.36
funds_available_for_reserves: 35,000.00 - 28,105.36 + 54,000.00 = 60,894.64
total_asset_strength: 28,105.36 + 60,894.64 = 89,000.00
Property
property_id: PROP_20260308_090000
address: Austin, TX (full address not provided — flag ADDRESS_INCOMPLETE)
city: Austin
state: TX
zip_code: not provided — flag ZIP_MISSING (non-blocking)
property_type: SFR
occupancy_type: PRIMARY
unit_count: 1
annual_property_tax: not provided
→ estimate: 425,000 × 0.0125 = 5,312.50/year → 442.71/month
→ flag TAX_ESTIMATED
annual_insurance: not provided
→ estimate: 425,000 × 0.005 = 2,125.00/year → 177.08/month
→ flag INSURANCE_ESTIMATED
hoa_monthly: 0.00 (SFR, not stated)
Deal
deal_id: DEAL_20260308_090000
deal_type: PURCHASE
qualifying_credit_score: 698 (Diana's score — lower of two middle scores)
purchase_price: 425,000.00
down_payment_amount: not stated — flag DOWN_PAYMENT_MISSING (BLOCKING)
DOWN_PAYMENT_MISSING is blocking for a PURCHASE deal. Ask before continuing:
"How much are Marcus and Diana planning to put down? If they're considering 0% down (VA loan), I can proceed on that basis."
Assuming borrower confirms 0% down (VA loan, no down payment required):
down_payment_amount: 0.00
requested_loan_amount: 425,000 - 0 = 425,000.00
estimated_closing_costs: 425,000 × 0.03 = 12,750.00 → flag CLOSING_COSTS_ESTIMATED
seller_concession_amount: 0.00
ltv_estimate: 425,000 / 425,000 = 1.000 (100%)
→ VA loan — LTV > 1.00 is normal with funding fee financed
→ flag ROUTE_CHECK_VA
cash_to_close_estimate: 0 + 12,750 - 0 = 12,750.00
→ check vs funds_available_for_closing (28,105.36) → 28,105.36 > 12,750 ✓
Monthly PITI Estimate (7.00% placeholder)
P&I factor at 7.00%/30yr: 0.006653
Formula: (r × (1+r)^n) / ((1+r)^n - 1) where r = 0.07/12, n = 360
Step 1: monthly_rate r = 0.07 / 12 = 0.0058333
Step 2: (1 + r)^360 = (1.0058333)^360 = 8.1161
Step 3: numerator = 0.0058333 × 8.1161 = 0.047344
Step 4: denominator = 8.1161 − 1 = 7.1161
Step 5: factor = 0.047344 / 7.1161 = 0.0066530
P&I: 425,000 × 0.006653 = 2,827.53
monthly_tax: 442.71 (estimated)
monthly_insurance: 177.08 (estimated)
hoa_monthly: 0.00
MI (unknown at profile): 0.00 (calculated per program/scenario)
monthly_piti_estimate: 2,827.53 + 442.71 + 177.08 = 3,447.32
→ note: actual PITI will vary by program, rate, and VA funding fee
8A — Blocking Fields
After collecting 0% down (VA), all blocking fields present:
✓ income (INC_1 + INC_2)
✓ qualifying_credit_score = 698
✓ property_type = SFR
✓ occupancy_type = PRIMARY
✓ deal_type = PURCHASE
✓ veteran_flag = true
✓ purchase_price = 425,000
✓ down_payment_amount = 0
blocking_missing_fields: []
8B — Soft Flags
ASSETS_UNVERIFIED (no source_verified_flag set)
TAX_ESTIMATED
INSURANCE_ESTIMATED
CLOSING_COSTS_ESTIMATED
GOAL_WEIGHTS_PARTIAL (only cash priority stated; rest defaulted to 3)
VESTED_PCT_ASSUMED (401K vesting not confirmed)
ADDRESS_INCOMPLETE (full address not provided)
ZIP_MISSING
8C — Routing Flags
ROUTE_CHECK_VA ✓ veteran_flag = true
ROUTE_CHECK_DPA ✓ first_time_homebuyer_flag = true
ROUTE_FHA_COMPETITIVE ✓ qualifying_credit_score = 698 (Diana controls)
ROUTE_CREDIT_OPTIMIZATION ✓ total_revolving_utilization = 70.8% > 30%
ROUTE_DEBT_TIMING_OPPORTUNITY ✓ AUTO loan excludable in 4 months
8D — Preliminary DTI
preliminary_dti = (monthly_piti_estimate + total_monthly_dti_obligations) / gmi_for_dti
= (3,447.32 + 785.00) / 8,458.33
= 4,232.32 / 8,458.33
= 0.5003 → 50.03% → ELEVATED
Note: This is at 7.00% placeholder. VA actual rate likely lower.
VA has no hard DTI stop — residual income governs.
Routing flag ROUTE_HIGH_DTI set — VA residual income test will likely apply.
8E — Approval Readiness Score
COMPONENT 1 — Credit Score Margin (weight 0.30)
qualifying_credit_score = 698
credit_margin_score = (698 - 580) / (760 - 580) = 118 / 180 = 0.656
COMPONENT 2 — DTI Margin (weight 0.30)
preliminary_dti = 0.5003
dti_margin = 0.45 - 0.5003 = -0.0503 (over limit)
dti_margin_score = MAX(0.0, (-0.0503 + 0.09) / 0.18) = (0.0397) / 0.18 = 0.221
COMPONENT 3 — Reserve Depth (weight 0.20)
reserves_months = funds_available_for_reserves / monthly_piti_estimate
= 60,894.64 / 3,447.32 = 17.66 months
reserve_score = MIN(1.0, 17.66 / 6) = MIN(1.0, 2.944) = 1.000
COMPONENT 4 — Documentation Completeness (weight 0.20)
soft_flags_present = 8
doc_score = MAX(0.0, 1.0 - (8 × 0.10)) = MAX(0.0, 0.20) = 0.200
FINAL:
approval_readiness_score = (0.656 × 0.30) + (0.221 × 0.30) + (1.000 × 0.20) + (0.200 × 0.20)
= 0.197 + 0.066 + 0.200 + 0.040
= 0.503 → DEVELOPING
Interpretation: DTI signal is elevated at placeholder rate — but VA has no hard DTI stop.
Reserve depth is exceptional (17.7 months). Credit is Tier 5 on Diana's score.
VA is the right primary path. Profile is viable, not strong on the generic score —
the score is suppressed by the DTI at a neutral 7% rate.
At a realistic VA rate (~6.5%), DTI will drop and score will improve materially.
BORROWER PROFILE COMPLETE — v1.2
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Borrowers: Marcus Webb + Diana Webb (co-borrower)
Deal Type: PURCHASE | SFR, Austin TX | $425,000
Credit Scores: Marcus 722 (Tier 3) / Diana 698 (Tier 5)
Qualifying Score: 698 (Diana's score controls — lower of two middles)
GMI (Marcus): $7,083.33/month
GMI (Diana): $1,375.00/month (disability grossed up 1.25× for DTI)
GMI Combined: $8,458.33/month
VA Residual Income: $8,183.33/month (Diana: $1,100 — no gross-up on residual path)
Total DTI Debts: $785.00/month
Preliminary DTI: 50.0% → ELEVATED (7% placeholder rate — will improve at VA rate)
Available for Closing: $28,105.36
Available for Reserves: $60,894.64 (17.7 months PITI — exceptional)
LTV Estimate: 100.0% (VA 0% down — normal)
Cash to Close Est.: $12,750.00 (closing costs estimated at 3%)
Approval Readiness: 0.503 → DEVELOPING
Credit margin: 0.656 (weight 0.30)
DTI margin: 0.221 (weight 0.30) ← suppressed by 7% placeholder
Reserve depth: 1.000 (weight 0.20) ← exceptional
Documentation: 0.200 (weight 0.20) ← 8 soft flags
Routing Flags:
ROUTE_CHECK_VA ← primary path
ROUTE_CHECK_DPA ← first-time buyer — check TX DPA programs
ROUTE_FHA_COMPETITIVE ← run FHA comparison (Diana's score 698)
ROUTE_CREDIT_OPTIMIZATION ← CC utilization 70.8% — paydown opportunity
ROUTE_DEBT_TIMING_OPPORTUNITY ← AUTO excludable in 4 months ($380/month freed)
ROUTE_HIGH_DTI ← VA residual income test will apply
Documentation Flags:
ASSETS_UNVERIFIED, TAX_ESTIMATED, INSURANCE_ESTIMATED,
CLOSING_COSTS_ESTIMATED, GOAL_WEIGHTS_PARTIAL,
VESTED_PCT_ASSUMED, ADDRESS_INCOMPLETE, ZIP_MISSING
Completeness: 41/50 = 82% | Blocking Fields: NONE
→ Profile ready for Program Router
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
| Code | Trigger Condition | Blocking? | Response |
|---|---|---|---|
| ERR-PROFILE-001 | GMI = 0 after all income processing | YES | Cannot proceed. Request income information. |
| ERR-PROFILE-002 | income_split_error = true (VA gross-up paths identical) | YES | Flag INCOME_SPLIT_ERROR. Rebuild income stage. |
| ERR-PROFILE-003 | Credit score provided but out of range (< 300 or > 850) | YES | Reject value. Request correction. |
| ERR-PROFILE-004 | Conflicting income values for same stream | NO | Ask borrower to clarify. Do not average without permission. |
| ERR-PROFILE-005 | total_revolving_credit_limit = 0 when revolving balances present | NO | Set utilization = null. Flag UTILIZATION_UNKNOWN. |
| WARN-PROFILE-001 | Debt on record not mentioned by borrower | NO | Include debt. Flag UNDISCLOSED_LIABILITY. |
| WARN-PROFILE-002 | Crypto assets present | NO | Set eligible = $0 until 60-day seasoning confirmed. |
| WARN-PROFILE-003 | HELOC present on refi with $0 balance | NO | Include in CLTV/HCLTV. Note lien position. Default include_in_dti = false for conventional, true for FHA/VA. |
When a user provides updated information mid-session:
1. Identify which entity and field is changing
2. Update that field only — do not rebuild the entire profile
3. Recalculate all derived metrics in the affected stage and all downstream stages
4. Re-run Stage 8 validation
5. Re-emit Handoff Statement showing delta: [field changed: old → new] and new signal values
6. Emit AuditEvent: event_type=PROFILE_UPDATED, fields_changed=[list], timestamp=now
| Skill | Trigger Condition |
|---|---|
Clarity_Engine_Program_Router_SKILL.md | handoff_ready = true — primary handoff |
Clarity_Engine_VA_Module_SKILL.md | ROUTE_CHECK_VA flag set |
Clarity_Engine_Math_SKILL.md | Any computation needed during intake (PMT, DTI preview, etc.) |
Clarity_Engine_Constraint_Detection_SKILL.md | preliminary_dti_signal = ELEVATED or CONCERN |
Clarity Engine — Borrower Profile Skill v1.2 | CONFIDENTIAL — PreFi, Inc. / Purpose Technology, Inc. d/b/a Purlend