← Back to Interaction Rule Set

Clarity Engine — Constraint Detection Skill

Version: 1.0 | Status: Implementation-Ready — Gear 1

Table of Contents SKILL PURPOSE INVOCATION EXECUTION SEQUENCE SEVERITY TAXONOMY CONSTRAINT REGISTRY — 25 TYPES STAGE 10 — QUANTIFICATION ENGINE STAGE 11 — RESOLUTION MAP STAGE 12 — QUICK WIN IDENTIFICATION STAGE 13 — PROGRESS SCORE STAGE 14 — EMIT CONSTRAINT REPORT WORKED EXAMPLE — MARCUS & DIANA WEBB FORBIDDEN PATTERNS COMPANION SKILLS

Clarity Engine — Constraint Detection Skill

Version: 1.0 | Status: Implementation-Ready — Gear 1

Scope: Receives a validated BorrowerProfile and a ProgramEvaluationQueue and produces a ConstraintReport — a structured, prioritized, and quantified map of every obstacle standing between this borrower and their best mortgage outcome, with a resolution path for each. This is the "Always Approved" engine in executable form.

Confidential: PreFi, Inc. / Purpose Technology, Inc. d/b/a Purlend

SKILL PURPOSE

The Constraint Detection Skill does not approve or deny. It identifies, quantifies, and resolves. For every constraint found it answers three questions:

  1. What is it? Precisely named, categorized, and severity-rated
  2. How bad is it? Quantified in dollars, points, months, or percentage
  3. What fixes it? Ordered resolution paths with estimated impact

The output powers the Explanation Skill (Nova), the Optimization Skill, and the Always Approved state machine. It is the most borrower-facing analytical layer in the Clarity Engine.

This skill produces:

This skill does NOT produce:

INVOCATION

Invoke this skill when:

Required inputs:

If either input is absent: return CONSTRAINT_SKILL_BLOCKED — missing required input and list what is missing.

EXECUTION SEQUENCE


Stage 1  — Validate inputs
Stage 2  — Extract constraint inputs
Stage 3  — Detect CREDIT constraints (C-01 through C-04)
Stage 4  — Detect DTI constraints (D-01 through D-04)
Stage 5  — Detect CASH constraints (K-01 through K-04)
Stage 6  — Detect INCOME constraints (I-01 through I-04)
Stage 7  — Detect PROGRAM constraints (P-01 through P-03)
Stage 8  — Detect PROPERTY / MI constraints (PR-01 through PR-03)
Stage 9  — Detect TIMING opportunities (T-01 through T-03)
Stage 10 — Quantify all quantifiable constraints
Stage 11 — Build ResolutionMap
Stage 12 — Identify QuickWins
Stage 13 — Compute ProgressScore
Stage 14 — Build and emit ConstraintReport

Run all stages in sequence. Do not skip. Every active constraint gets a resolution path. Every quantifiable constraint gets a dollar or point amount.

SEVERITY TAXONOMY

Every constraint is assigned one of five severity levels. Severity drives display order and action priority.

SeverityCodeMeaningDisplay Priority
BLOCKING🔴Prevents qualification for one or more programs right now1 — show first
ELEVATED🟠Does not block today but significantly limits options or cost2
WATCH🟡Monitoring required — may become blocking under adverse conditions3
COST💰No eligibility impact — increases lifetime cost4
OPPORTUNITY🟢Positive unlock available — borrower can improve position5 — show last
INFORMATIONALℹ️Context only — no action requirednot displayed unless requested

CONSTRAINT REGISTRY — 25 TYPES

CREDIT CONSTRAINTS

C-01 — CREDIT_SCORE_BELOW_PROGRAM_MINIMUM 🔴 BLOCKING


Trigger: qualifying_credit_score < minimum for one or more programs
  DSCR minimum:          640
  CONVENTIONAL minimum:  620
  FHA (3.5% down) min:   580
  FHA (10% down) min:    500
  VA minimum:            580 (lender overlay — no official GSE floor)

Detection:
  FOR each program in ProgramEvaluationQueue where eligibility = INELIGIBLE:
    IF gate_failed = GATE_3 AND reason contains "credit score":
      score_gap = program_minimum - qualifying_credit_score
      next_unlock_program = program with smallest score_gap > 0
      next_unlock_points = score_gap for next_unlock_program
      flag C-01 ACTIVE

Quantification:
  points_to_next_program = qualifying_credit_score subtracted from next_unlock_program minimum
  points_to_conventional = MAX(0, 620 - qualifying_credit_score)
  points_to_fha_35 = MAX(0, 580 - qualifying_credit_score)

Resolution paths (ordered by speed):
  1. Revolving utilization paydown → 30-day rescore cycle (fastest lever)
  2. Rapid Rescore via lender → 3–7 business days if error or payoff
  3. Dispute inaccurate derogatory items → 30–45 days
  4. Authorized user tradeline on established account → 30–60 days
  5. Time-based derogatory aging → varies (late pays fade at 24 months, collections at 7 years)

Human review trigger: IF points_to_next_program ≤ 5 → flag NEAR_THRESHOLD — prioritize

C-02 — CREDIT_TIER_RATE_PENALTY 💰 COST


Trigger: qualifying_credit_score < 760 (any tier 2–8)
  Active for every borrower not at Tier 1 pricing.

Rate penalty by tier (midpoint estimates — actual from lender LLPA tables):
  Tier 1 (760+):    0 bps   (0.000%)
  Tier 2 (740–759): 12.5 bps (0.125%)
  Tier 3 (720–739): 25 bps  (0.250%)
  Tier 4 (700–719): 50 bps  (0.500%)
  Tier 5 (680–699): 75 bps  (0.750%)
  Tier 6 (640–679): 100 bps (1.000%)
  Tier 7 (580–639): floor pricing only (no bps estimate)
  Tier 8 (<580):    no standard program

Quantification (per eligible CONVENTIONAL program):
  Step 1: rate_penalty_pct = tier_penalty_bps / 100  (e.g., 75 bps → 0.75%)
  Step 2: par_rate = base_market_rate  (use program Router placeholder rate as proxy)
  Step 3: penalized_rate = par_rate + rate_penalty_pct

  Step 4: Compute pmt_factor at par_rate
    r_par = par_rate / 12
    factor_par = (r_par × (1+r_par)^360) / ((1+r_par)^360 - 1)

  Step 5: Compute pmt_factor at penalized_rate
    r_pen = penalized_rate / 12
    factor_pen = (r_pen × (1+r_pen)^360) / ((1+r_pen)^360 - 1)

  Step 6: monthly_premium = loan_amount × (factor_pen - factor_par)
  Step 7: lifetime_cost = monthly_premium × 360

  NOTE: Use unrounded intermediate values through Steps 4–7.
        Only round monthly_premium and lifetime_cost at final output.

Resolution paths:
  1. Compute cost of score improvement vs lifetime savings
  2. Tier 1 is the target — model savings per tier reached
  3. Rapid Rescore if score is within 10–20 points of next tier boundary

C-03 — HIGH_REVOLVING_UTILIZATION 🟠 ELEVATED


Trigger: total_revolving_utilization > 0.30

Quantification:
  target_utilization = 0.30
  paydown_needed = MAX(0, total_revolving_balance − (total_revolving_limit × 0.30))
  
  Rounding: round paydown_needed UP to nearest dollar (conservative — do not undershoot target)

Resolution paths (ordered by impact):
  1. Pay highest-utilization card first (card utilization matters, not just total)
  2. Pay cards above 30% to under 30% each
  3. Request credit limit increase — no hard pull if pre-approved (increases denominator)
  4. Verify all balances as of next statement close before Rapid Rescore
  
Note: Effect on score is fastest of all credit levers — score updates at next statement close
      (~30 days) then lender can request Rapid Rescore within 3–7 business days.

C-04 — DEROGATORY_TRADELINES 🟠 ELEVATED


Trigger: documentation_flags contain derogatory indicators OR
         soft_flags indicate collections, late payments, charge-offs

Quantification: Not directly quantifiable — impact varies by item type, age, and score model

Resolution paths:
  1. Identify all derogatory items from credit report (requires full tri-merge)
  2. Dispute inaccurate items — 30 days FCRA response window
  3. Pay-for-delete: negotiate with collection agencies before payment
  4. Settled accounts: "paid" status improves faster than "unpaid"
  5. Mortgage late payments: most damaging — no shortcut, aging only
  6. Chapter 7 BK: 4-year waiting period (Fannie Mae) from discharge date
  7. Foreclosure: 7-year waiting period (Fannie Mae) from completion date

Human review trigger: ALWAYS — derogatory item strategy requires individual credit analysis

DTI CONSTRAINTS

D-01 — DTI_EXCEEDS_PROGRAM_LIMIT 🔴 BLOCKING


Trigger: preliminary_dti_signal = ELEVATED or CONCERN AND
         (total_obligations + monthly_piti_estimate) / gmi_for_dti > applicable program DTI limit

Program DTI limits:
  CONVENTIONAL DU automated: 0.50 (50%)
  CONVENTIONAL manual:       0.45 (45%)
  FHA AUS automated:         0.57 (57%)
  FHA manual:                0.43 (43%) with compensating factors up to 0.50
  VA:                        0.41 guideline — NO hard stop (residual income governs)
  DSCR:                      NOT APPLICABLE (property income qualifies)

Quantification — compute per applicable program:

  preliminary_dti = (total_monthly_dti_obligations + monthly_piti_estimate) / gmi_for_dti

  max_total_obligations = gmi_for_dti × program_dti_limit
  max_non_housing = max_total_obligations − monthly_piti_estimate
  debt_reduction_needed = MAX(0, total_monthly_dti_obligations − max_non_housing)

  NOTE: Use unrounded gmi_for_dti, monthly_piti_estimate, and total_monthly_dti_obligations.
        Do not round intermediate values. Round debt_reduction_needed at final output.

Resolution paths (ordered by impact):
  1. Pay off highest-payment liability first (credit cards, installment loans)
  2. Time debt exclusion — wait for liability to age past 10 months (see T-01)
  3. Switch programs — FHA AUS tolerates 57% vs Conventional's 50%
  4. Add co-borrower income (increases GMI denominator)
  5. Reduce loan amount / purchase price (reduces PITI numerator)
  6. Student loan IDR adjustment — verify qualifying payment vs 0.5% rule

VA NOTE: If ROUTE_HIGH_DTI AND veteran_flag = true, do not flag D-01 as blocking for VA.
         VA residual income test may override. Flag I-04 instead.

D-02 — DTI_ELEVATED_WATCH 🟡 WATCH


Trigger: preliminary_dti_signal = WATCH (dti 41%–45%)
  Borrower may qualify but margin is thin.

Quantification:
  headroom = (program_dti_limit × gmi_for_dti) − (total_obligations + monthly_piti_estimate)
  headroom expressed in $/month of additional qualifying debt capacity

Resolution paths:
  1. Monitor — may clear at full program evaluation with actual rate
  2. Proactive debt payoff creates margin buffer
  3. Document all income streams to maximize GMI

D-03 — DEBT_TIMING_OPPORTUNITY 🟢 OPPORTUNITY


Trigger: months_to_exclusion_list is non-empty
  A qualifying liability will be excluded from DTI within ≤ 10 months.

Quantification per excluded liability:
  FOR each item in months_to_exclusion_list:
    monthly_payment_freed = that liability's monthly_payment
    dti_improvement = monthly_payment_freed / gmi_for_dti
    new_preliminary_dti = current_dti − dti_improvement
    months_until_exclusion = item.months_remaining

Resolution paths:
  1. Model: can borrower qualify after exclusion date?
     IF new_dti_after_exclusion ≤ program_limit → "qualify by [date]"
  2. Compare: cost of closing now (higher rate, higher payment) vs
              closing after exclusion (better DTI, possibly better terms)
  3. If exclusion unlocks qualification: set AlwaysApproved re-engagement date

Output: "Waiting [N] months eliminates $[X]/month from DTI — new DTI = [Y]%"

D-04 — STUDENT_LOAN_IDR_OVERRIDE ℹ️ INFORMATIONAL


Trigger: student loan IDR payment < 0.5% × outstanding balance
         → qualifying payment uses 0.5% rule (Fannie Mae B3-6-05)

No action required. Document only.
Output: "Student loan qualified at $[X]/month (Fannie Mae 0.5% rule) vs IDR of $[Y]/month.
         Documentation of IDR payment plan required at underwriting."

CASH CONSTRAINTS

K-01 — CASH_TO_CLOSE_SHORTFALL 🔴 BLOCKING


Trigger: funds_available_for_closing < required_cash_to_close (per program)
  Evaluate per program in ProgramEvaluationQueue.

Quantification per program:
  shortfall = MAX(0, required_cash_to_close − funds_available_for_closing)

  IF shortfall = 0: no constraint — skip
  IF shortfall > 0: flag K-01, compute resolution options

Resolution paths (ordered by accessibility):
  1. Gift funds — eligible family member (primary residence: allowed on all programs)
     document: gift letter + donor bank statement + evidence of transfer
  2. Down Payment Assistance (DPA) — check state/county/city programs
     flag ROUTE_CHECK_DPA if first_time_homebuyer_flag = true
  3. Seller concession — negotiate with seller up to program limit:
     Conventional: 3% (LTV > 90%), 6% (LTV 75–90%), 9% (LTV < 75%)
     FHA: 6% of purchase price
     VA: 4% of purchase price (for concessions beyond closing costs)
  4. Lender credit — accept higher rate in exchange for closing cost reduction
     tradeoff: higher monthly payment, lower cash needed
  5. Additional asset liquidation — verify source of funds documentation

Output per program:
  "Program [X]: shortfall $[amount]. Options: [ranked list with dollar amounts]."

K-02 — RESERVE_SHORTFALL 🔴 BLOCKING


Trigger: funds_available_for_reserves < (reserve_months_required × monthly_piti_estimate)

Quantification:
  required_reserves = reserve_months_required × monthly_piti_estimate
  reserve_gap = MAX(0, required_reserves − funds_available_for_reserves)

  reserve_months_required: typically 2 months (primary), 6 months (investment)
  funds_available_for_reserves includes 60% retirement credit

Resolution paths:
  1. Verify 401k/IRA balances — 60% credit applies to eligible retirement accounts
  2. Gift funds may be used for reserves on some programs (program-specific)
  3. Accelerate savings — model months to close reserve gap
  4. Reduce required reserves by choosing program with lower reserve requirement

K-03 — CTC_MARGIN_TIGHT 🟡 WATCH


Trigger: 0 < (funds_available_for_closing − required_cash_to_close) < 1,000
  No shortfall today, but margin is less than $1,000.

Quantification:
  margin = funds_available_for_closing − required_cash_to_close

Resolution paths:
  1. Confirm all closing cost estimates — actual costs may differ from estimates
  2. Negotiate seller concession as buffer
  3. Verify no additional escrow holdbacks or prepaids overlooked
  4. Any surprise cost above $[margin] will flip this to K-01

Output: "FHA cash margin: $[margin]. Any closing cost increase exceeds available funds."

K-04 — ASSET_DOCUMENTATION_GAP 🟡 WATCH


Trigger: soft_flags contain ASSETS_UNVERIFIED or TAX_ESTIMATED

No dollar quantification — documentation gap only.

Resolution paths:
  1. Provide 2 most recent bank statements (all pages)
  2. VOD (Verification of Deposit) from financial institution
  3. Brokerage statements for investment accounts (60-day history)
  4. 401k/IRA statements — most recent quarterly
  5. If assets are gifted: gift letter + donor statement + transfer evidence

INCOME CONSTRAINTS

I-01 — INCOME_INSUFFICIENT_FOR_PROGRAM 🔴 BLOCKING


Trigger: gmi_for_dti too low to support housing payment within any program DTI limit
  At maximum DTI for most permissive program (FHA AUS 57%):
    max_housing = gmi_for_dti × 0.57
    IF monthly_piti_estimate > max_housing: income is insufficient

Quantification:
  income_gap = monthly_piti_estimate − (gmi_for_dti × 0.57)  [vs FHA AUS limit]
  additional_gmi_needed = income_gap / 0.57  [income needed to cover payment]
  
  Alternative: loan_amount_at_current_income:
    max_housing_payment = gmi_for_dti × 0.43  [conservative limit]
    r = program_rate / 12
    max_p_and_i = max_housing_payment − monthly_tax − monthly_insurance − hoa_monthly
    max_loan = max_p_and_i / pmt_factor(program_rate)  [if max_p_and_i > 0]

Resolution paths:
  1. Add co-borrower with qualifying income
  2. Reduce purchase price — remodel target payment
  3. Identify additional qualifying income streams (rental, part-time, pension)
  4. Gift of equity from seller to reduce loan amount
  5. DPA to reduce down payment requirement (may free cash for reserves)

I-02 — SELF_EMPLOYED_INCOME_COMPLEXITY 🟡 WATCH


Trigger: self_employed_flag = true

No dollar quantification at router level — actual income TBD at underwriting.

Resolution paths:
  1. 2 years personal tax returns (1040 with all schedules)
  2. 2 years business tax returns (1120S, 1065, Schedule C)
  3. Year-to-date P&L (CPA-prepared preferred)
  4. Business bank statements — 12 or 24 months
  5. CPA letter confirming business viability
  6. Note: declining income trend may require using lower year's income

Human review trigger: ALWAYS — self-employed income requires underwriter analysis

I-03 — VARIABLE_INCOME_AVERAGING_RISK 🟡 WATCH


Trigger: any IncomeSource.income_type IN [COMMISSION, BONUS, OVERTIME, SEASONAL]

No dollar quantification — averaging outcome depends on actual history.

Resolution paths:
  1. Commission/bonus: 24-month average required (Fannie Mae B3-3.1-09)
     If ≥ 2-year history at same employer, average applies
  2. Overtime: 24-month average IF employer confirms likelihood of continuance
  3. Declining income trend: use lower year only (conservative underwrite)
  4. Seasonal: 24-month average across full seasons

Human review trigger: IF commission > 25% of total income

I-04 — VA_RESIDUAL_INCOME_RISK 🟡 WATCH


Trigger: veteran_flag = true AND (preliminary_dti_signal = ELEVATED OR CONCERN)

VA residual income test governs qualification, not DTI hard stop.
Full residual income test computed in VA Module Skill.

This constraint is informational at Router/Constraint level.

Quantification (preliminary only):
  net_income_for_residual = net_income_for_va_residual  [from BorrowerProfile — no gross-up]
  estimated_shelter_expense = monthly_piti_estimate
  estimated_residual = net_income_for_residual − estimated_shelter_expense − total_monthly_dti_obligations

  Compare against VA residual thresholds (VA Pamphlet 26-7, Table 41-1):
  Family of 2, South region:  $738/month
  Family of 3, South region:  $889/month
  Family of 4, South region:  $1,003/month
  Family of 5+, South region: $1,062/month
  (Other regions: Northeast, Midwest, West — higher thresholds. Use correct region.)

  IF estimated_residual ≥ regional_threshold: flag I-04 WATCH — likely passes
  IF estimated_residual < regional_threshold: flag I-04 ELEVATED — residual risk

NOTE: net_income_for_va_residual must NEVER include gross-up adjustments.
      gmi_for_dti (which may include gross-up) is NOT used for residual income.
      ASSERT: if any gross_up_applied_flag = true in BorrowerProfile,
              net_income_for_va_residual ≠ gmi_for_dti. Verify before computing.

PROGRAM CONSTRAINTS

P-01 — NO_ELIGIBLE_PROGRAM 🔴 BLOCKING


Trigger: ProgramEvaluationQueue.no_viable_programs = true
  All programs INELIGIBLE.

This is the highest-severity constraint state. Always triggers full action plan.

Quantification:
  time_to_eligibility: estimated months until a standard program unlocks
  primary_blocking_factor: the single most impactful constraint to resolve

Resolution paths:
  1. Identify nearest program threshold (score, LTV, or DTI)
  2. Build month-by-month improvement timeline
  3. Set AlwaysApproved re-engagement trigger date
  4. Non-QM / portfolio pathway: flag for advisor, document risk premium
  5. FHA manual underwrite: possible for score 500+ with compensating factors

Output: "No standard program available today. Earliest qualification: [date].
         Primary action: [single most impactful step]."

P-02 — SINGLE_PROGRAM_DEPENDENCY 🟠 ELEVATED


Trigger: ProgramEvaluationQueue.programs_eligible = 1

Only one program available — no fallback if that program declines.

Quantification:
  points_to_second_program = gap to next eligible program minimum
  down_payment_to_second_program = additional down to unlock next program (if LTV is the gate)

Resolution paths:
  1. Identify which gate eliminates all other programs
  2. Quantify: what unlocks program #2 (score points, down payment, DTI improvement)
  3. Prioritize actions that create fallback optionality

P-03 — LOAN_AMOUNT_EXCEEDS_CONFORMING_LIMIT 🔴 BLOCKING


Trigger: base_loan_amount > 806,500 AND program = FHA or CONVENTIONAL
  (VA exempt — no conforming limit with full entitlement)

Quantification:
  excess = base_loan_amount − 806,500
  additional_down_to_bring_in_conforming = excess (must pay down loan by this amount)

Resolution paths:
  1. Increase down payment by [excess amount] to bring loan under limit
  2. VA loan if eligible — no conforming limit (flag ROUTE_CHECK_VA)
  3. Negotiate lower purchase price
  4. High-balance / jumbo loan — outside current skill scope, flag for advisor
  5. Flag HIGH_COST_AREA_CHECK — county limits may be higher than $806,500

Output: "Loan $[amount] exceeds 2026 conforming limit of $806,500 by $[excess].
         Additional down payment of $[excess] brings loan under limit."

PROPERTY / MI CONSTRAINTS

PR-01 — LTV_EXCEEDS_PROGRAM_MAXIMUM 🔴 BLOCKING


Trigger: ltv_estimate > program LTV cap for all programs borrower is eligible for
  AND down_payment_amount < program minimum

Quantification:
  required_down = property_value × (1 − program_ltv_cap)
  additional_down_needed = MAX(0, required_down − down_payment_amount)

  Per program:
    FHA (score ≥ 580): ltv_cap = 0.965 → required_down = property_value × 0.035
    CONVENTIONAL:      ltv_cap = 0.97  → required_down = property_value × 0.03
    DSCR:              ltv_cap = 0.80  → required_down = property_value × 0.20
    VA:                no ltv cap (with full entitlement) — PR-01 does not apply

Resolution paths:
  1. Increase down payment by [additional_down_needed]
  2. VA loan if eligible
  3. Gift funds for down payment
  4. Negotiate lower purchase price — recalculate LTV at new price

PR-02 — PMI_COST_DRAG 💰 COST


Trigger: CONVENTIONAL eligible AND conv_ltv > 0.80

Quantification:
  monthly_pmi = conv_base_loan × annual_pmi_rate / 12
    (annual_pmi_rate from Router PMI estimate table)

  immediate_paydown_to_eliminate = MAX(0, conv_base_loan − property_value × 0.80)

  Months to automatic PMI cancellation via amortization:
    Amortization loop: compute balance each month until balance ≤ property_value × 0.78
    (78% LTV triggers automatic cancellation per Homeowners Protection Act)
    Borrower may REQUEST cancellation at 80% LTV

    For each month n = 1 to 360:
      interest_n = balance_{n-1} × monthly_rate
      principal_n = monthly_pmt − interest_n
      balance_n = balance_{n-1} − principal_n
      IF balance_n ≤ property_value × 0.80:
        months_to_cancel_request = n
        BREAK
      IF balance_n ≤ property_value × 0.78:
        months_to_auto_cancel = n
        BREAK

    NOTE: monthly_rate = penalized_rate / 12  (use actual program rate, not par)
          Do not use annual_rate directly. Convert to monthly first.

  lifetime_pmi_cost = monthly_pmi × months_to_auto_cancel

Resolution paths:
  1. Immediate paydown of $[immediate_paydown] eliminates PMI now
  2. VA loan eliminates PMI entirely (if eligible)
  3. Lender-paid PMI (LPMI): no monthly PMI, but rate is permanently higher
     — compare: LPMI lifetime cost vs monthly PMI until cancellation
  4. At 80% LTV via appreciation: request cancellation (requires appraisal)
  5. FHA comparison: MIP persists longer but rate may be lower at Tier 5–6 credit

PR-03 — FHA_MIP_LIFETIME_DRAG 💰 COST


Trigger: FHA eligible AND fha_ltv > 0.90 at origination
  → MIP assessed for life of loan (360 months)
  → If fha_ltv ≤ 0.90: MIP only 132 months (11 years) — less severe

Quantification (for life-of-loan case — LTV > 90%):
  monthly_mip_365 = fha_base_loan × annual_mip_rate / 12
    annual_mip_rate = 0.0055 (LTV > 95%), 0.0050 (LTV 90.01%–95%)

  additional_down_for_11yr_mip = property_value × 0.10 − down_payment_amount
    (bring LTV to exactly 90.00% to unlock 11-year MIP)

  IF additional_down_for_11yr_mip > 0:
    new_fha_base = property_value × 0.90
    new_monthly_mip = new_fha_base × 0.0050 / 12

    savings_during_11yr_mip = (monthly_mip_365 − new_monthly_mip) × 132
    savings_after_11yr_mip = monthly_mip_365 × 228  (MIP eliminated after 11 years)
    total_mip_savings = savings_during_11yr_mip + savings_after_11yr_mip

    net_benefit = total_mip_savings − additional_down_for_11yr_mip
    (simplified: ignores time value of money)

BOUNDARY RULE — LTV exactly 90.00%:
  IF fha_ltv = 0.9000 exactly: MIP duration = 11 years (≤ 0.90 → 11 years)
  IF fha_ltv = 0.9001 or higher: MIP duration = life of loan (> 0.90 → life)
  Apply as ≤ 0.90, not < 0.90.

Resolution paths:
  1. Bring LTV to ≤ 90% — unlock 11-year MIP limit
  2. VA loan if eligible — eliminates MIP entirely
  3. Build conventional comparison — PMI cancelable at 80% LTV
  4. Refinance into conventional when equity reaches 20% (future path)

TIMING OPPORTUNITIES

T-01 — DEBT_EXCLUSION_OPPORTUNITY 🟢 OPPORTUNITY


Trigger: months_to_exclusion_list is non-empty in BorrowerProfile

Detection:
  FOR each item in months_to_exclusion_list:
    months_remaining = item.months_remaining
    monthly_payment = item.monthly_payment
    liability_name = item.description

Quantification per item:
  dti_improvement = monthly_payment / gmi_for_dti
  new_dti_after_exclusion = current_dti − dti_improvement
  
  IF new_dti_after_exclusion ≤ program_dti_limit:
    exclusion_unlocks_program = true
    qualify_date = today + months_remaining

Resolution:
  "Waiting [N] months until [Month Year] removes $[payment]/month from DTI.
   New DTI: [X]%. [Program] becomes eligible on [date]."

AlwaysApproved trigger: IF exclusion_unlocks_program = true
  → set re_engagement_date = qualify_date − 30 days (30-day advance notice)

T-02 — CREDIT_IMPROVEMENT_TIMELINE 🟢 OPPORTUNITY


Trigger: qualifying_credit_score < 760 AND resolution path identified
  (C-01, C-02, or C-03 is active)

Quantification — estimate improvement timelines:
  Utilization paydown (C-03):
    IF paydown_needed ≤ available_cash:
      timeline = "30–60 days (next statement close + Rapid Rescore)"
      estimated_score_improvement = "15–40 points" (range — exact depends on scoring model)
    NOTE: Score improvement is estimated only. Credit score models are proprietary.
          Do not state a specific point improvement as guaranteed.

  Dispute resolution:
    timeline = "30–45 days"
    improvement: varies by item

  Authorized user tradeline:
    timeline = "30–60 days"
    improvement: 10–30 points estimated (thin file borrowers benefit most)

Resolution output:
  "Score is [X]. Target is [Y] (+[Z] points).
   Fastest path: [action] → estimated [N] days → [program] unlocks."

AlwaysApproved trigger: IF improvement_within_90_days = true
  → set re_engagement_date = today + estimated_days

T-03 — RATE_LOCK_URGENCY ℹ️ INFORMATIONAL


Trigger: Market rate information available AND (rate_trend = RISING OR deal_expiry_approaching)
  Note: Rate data requires external input — not computed from BorrowerProfile.
        Flag as INFORMATIONAL only. Do not assert rate direction without source.

Output (if triggered):
  "Rate environment context: [provided context]. Consider timing tradeoffs between
   immediate qualification and optimization path."

STAGE 10 — QUANTIFICATION ENGINE

Apply quantification formulas for all active constraints marked quantifiable = true.

PMT Factor Reference (for use in I-01 max loan calculation and C-02)


For any annual_rate and 360-month term:

  Step 1: r = annual_rate / 12
  Step 2: compound = (1 + r)^360
  Step 3: numerator = r × compound
  Step 4: denominator = compound − 1
  Step 5: pmt_factor = numerator / denominator

Pre-computed factors:
  6.00% → r=0.005000, (1+r)^360=6.02258, factor=0.0059955
  6.25% → r=0.005208, (1+r)^360=6.48917, factor=0.0061572
  6.50% → r=0.005417, (1+r)^360=6.99180, factor=0.0063207
  6.75% → r=0.005625, (1+r)^360=7.53325, factor=0.0064860
  7.00% → r=0.005833, (1+r)^360=8.11650, factor=0.0066530
  7.25% → r=0.006042, (1+r)^360=8.74477, factor=0.0068218
  7.50% → r=0.006250, (1+r)^360=9.42153, factor=0.0069921

CRITICAL: r = annual_rate / 12. Base of exponent is (1 + r), not (1 + annual_rate).
          Never compute as annual_rate^360 or (annual_rate/12)^360.

PMI Amortization Loop


For PR-02 months_to_cancel computation:
  balance = conv_base_loan
  monthly_rate = penalized_rate / 12
  monthly_pmt = conv_base_loan × pmt_factor(penalized_rate)
  pmi_cancel_request_month = null
  pmi_auto_cancel_month = null

  FOR n = 1 TO 360:
    interest = balance × monthly_rate    [use full precision — do not round interest]
    principal = monthly_pmt − interest   [do not round principal]
    balance = balance − principal        [do not round running balance]
    
    IF balance ≤ property_value × 0.80 AND pmi_cancel_request_month = null:
      pmi_cancel_request_month = n
    
    IF balance ≤ property_value × 0.78 AND pmi_auto_cancel_month = null:
      pmi_auto_cancel_month = n
      BREAK

  lifetime_pmi_cost = monthly_pmi × pmi_auto_cancel_month

Rounding Policy


Round ONLY final presentation outputs — never intermediate values.
  Dollar amounts: round to nearest cent (2 decimal places)
  Percentages: round to 2 decimal places (e.g., 70.83%)
  Points: round to nearest integer (credit score gaps)
  Months: round UP to nearest integer (always conservative for timelines)
  Factors: use 7 decimal places internally, round to 2 decimal places for display only

STAGE 11 — RESOLUTION MAP

For every BLOCKING constraint, build a complete resolution object:


{
  "constraint_id": "C-01",
  "constraint_name": "CREDIT_SCORE_BELOW_PROGRAM_MINIMUM",
  "severity": "BLOCKING",
  "quantification": {
    "points_to_conventional": 22,
    "points_to_fha_35": 0,
    "next_unlock": "CONVENTIONAL",
    "next_unlock_points": 22
  },
  "resolution_paths": [
    {
      "rank": 1,
      "action": "Pay down revolving balances to below 30% utilization",
      "estimated_impact": "$4,900 paydown → utilization 70.83% → 30.00%",
      "estimated_timeline": "30–60 days",
      "estimated_score_gain": "15–40 points (model-dependent)",
      "blocks_cleared_if_successful": ["C-01", "C-03"]
    },
    {
      "rank": 2,
      "action": "Rapid Rescore via lender after paydown",
      "estimated_impact": "Score update in 3–7 business days post-paydown",
      "estimated_timeline": "3–7 business days",
      "prerequisite": "Must complete paydown first"
    }
  ],
  "human_review_required": false,
  "always_approved_trigger": {
    "active": true,
    "re_engagement_event": "Score reaches 620",
    "estimated_date": "30–60 days if utilization path taken"
  }
}

STAGE 12 — QUICK WIN IDENTIFICATION

Identify constraints where:

Label these as QUICK_WIN = true in the ConstraintReport.


Quick Win criteria:
  1. C-03 (HIGH_REVOLVING_UTILIZATION): paydown_needed ≤ available_funds → QUICK_WIN
  2. K-03 (CTC_MARGIN_TIGHT): seller concession negotiable → QUICK_WIN
  3. K-04 (ASSET_DOCUMENTATION_GAP): documents collectible → QUICK_WIN
  4. D-01 small debt payoff: single small liability eliminates DTI block → QUICK_WIN
     Threshold: IF single liability payoff ≤ available_funds AND eliminates D-01 → QUICK_WIN

STAGE 13 — PROGRESS SCORE

The Progress Score measures how close the borrower is to an optimal approval state. It is directional — not a credit score, not an approval probability. It signals momentum.


Component weights:

  W1: Program Access (0.30)
    IF programs_eligible ≥ 2:  1.00
    IF programs_eligible = 1:  0.60
    IF programs_eligible = 0:  0.00

  W2: Credit Health (0.25)
    credit_health = MIN(1.0, (qualifying_credit_score − 580) / (760 − 580))
    Floor at 0.00 if score < 580

  W3: Cash Sufficiency (0.25)
    FOR best_eligible_program (Priority 1 in queue):
      IF funds_available_for_closing ≥ required_cash_to_close:
        cash_ratio = MIN(1.0, funds_available_for_closing / required_cash_to_close)
      ELSE:
        cash_ratio = funds_available_for_closing / required_cash_to_close  (will be < 1.0)
    cash_health = MAX(0.0, MIN(1.0, cash_ratio))

  W4: DTI Margin (0.20)
    best_dti_margin = MAX(0, MIN(1, (0.50 − preliminary_dti) / 0.20))
    Note: scaled so 50% DTI = 0 margin, 30% DTI = full margin
    Floor at 0.00 if dti > 0.50

  progress_score = (W1 × 0.30) + (W2 × 0.25) + (W3 × 0.25) + (W4 × 0.20)

Signal bands:
  0.85–1.00: STRONG    — ready to proceed, minimal constraints
  0.65–0.84: MODERATE  — viable path forward, targeted actions needed
  0.40–0.64: DEVELOPING — meaningful work required, path exists
  0.00–0.39: ACTION    — significant constraints, structured plan needed

NOTE: progress_score is directional and additive — it goes up as constraints resolve.
      It is NOT a probability of approval. Do not represent it as such.

STAGE 14 — EMIT CONSTRAINT REPORT

ConstraintReport JSON Schema


{
  "schema_version": "clarity_engine_v1.0",
  "report_id": "CR_[YYYYMMDD_HHMMSS]",
  "deal_id": "DEAL_[from BorrowerProfile]",
  "borrower_id": "BORR_[from BorrowerProfile]",
  "created_at": "ISO 8601 UTC",
  "skill_version": "1.0",

  "summary": {
    "blocking_count": 0,
    "elevated_count": 0,
    "watch_count": 0,
    "cost_count": 0,
    "opportunity_count": 0,
    "quick_wins": [],
    "progress_score": 0.00,
    "progress_signal": "STRONG | MODERATE | DEVELOPING | ACTION",
    "earliest_qualification_date": "ISO 8601 | null",
    "always_approved_triggers": []
  },

  "constraints": [
    {
      "constraint_id": "string",
      "constraint_name": "string",
      "category": "CREDIT | DTI | CASH | INCOME | PROGRAM | PROPERTY | TIMING",
      "severity": "BLOCKING | ELEVATED | WATCH | COST | OPPORTUNITY | INFORMATIONAL",
      "quick_win": false,
      "applies_to_programs": ["VA", "FHA", "CONVENTIONAL", "DSCR", "ALL"],
      "quantification": {},
      "resolution_paths": [],
      "human_review_required": false,
      "always_approved_trigger": {}
    }
  ],

  "opportunity_register": [
    {
      "opportunity_id": "T-01 | T-02 | T-03",
      "description": "string",
      "unlock_date": "ISO 8601 | null",
      "unlock_condition": "string",
      "programs_unlocked": [],
      "re_engagement_date": "ISO 8601 | null"
    }
  ],

  "cost_map": [
    {
      "constraint_id": "C-02 | PR-02 | PR-03",
      "description": "string",
      "monthly_cost": 0.00,
      "lifetime_cost": 0.00,
      "resolution_savings": 0.00
    }
  ],

  "progress_components": {
    "program_access_score": 0.00,
    "credit_health_score": 0.00,
    "cash_sufficiency_score": 0.00,
    "dti_margin_score": 0.00,
    "progress_score": 0.00,
    "progress_signal": "string"
  }
}

WORKED EXAMPLE — MARCUS & DIANA WEBB

Inputs: BorrowerProfile (v1.2) + ProgramEvaluationQueue (Router v1.0)


qualifying_credit_score:       698  (Diana — lower of two middles)
credit_tier:                   5
veteran_flag:                  true
gmi_for_dti:                   8,458.33
net_income_for_va_residual:    8,183.33  (no gross-up — Marcus 7,083.33 + Diana 1,100)
total_monthly_dti_obligations: 785.00
monthly_piti_estimate:         3,447.32
preliminary_dti:               0.5004  (50.04%)
preliminary_dti_signal:        ELEVATED
total_revolving_balance:       8,500
total_revolving_limit:         12,000
total_revolving_utilization:   0.7083  (70.83%)
funds_available_for_closing:   28,105.36
funds_available_for_reserves:  60,894.64
routing_flags:                 [ROUTE_CHECK_VA, ROUTE_CHECK_DPA, ROUTE_FHA_COMPETITIVE,
                                ROUTE_CREDIT_OPTIMIZATION, ROUTE_DEBT_TIMING_OPPORTUNITY,
                                ROUTE_HIGH_DTI]

From ProgramEvaluationQueue:
  VA:           ELIGIBLE  priority=1  loan=434,137.50  monthly=3,363.83  ctc=12,750.00
  FHA:          ELIGIBLE  priority=2  loan=417,302.19  monthly=3,445.39  ctc=27,625.00
  CONVENTIONAL: ELIGIBLE  priority=3  loan=412,250.00  monthly=3,706.05  ctc=25,500.00
  DSCR:         INELIGIBLE (primary occupancy)
  programs_eligible: 3

Stage 3 — CREDIT CONSTRAINTS:


C-01: CREDIT_SCORE_BELOW_PROGRAM_MINIMUM
  qualifying_credit_score = 698
  DSCR minimum = 640 → 698 ≥ 640 → no C-01 for DSCR (also INELIGIBLE on occupancy)
  CONVENTIONAL minimum = 620 → 698 ≥ 620 → no C-01
  FHA minimum = 580 → 698 ≥ 580 → no C-01
  VA minimum = 580 → 698 ≥ 580 → no C-01
  → C-01: NOT ACTIVE

C-02: CREDIT_TIER_RATE_PENALTY
  credit_tier = 5 → rate_penalty = 75 bps = 0.75%
  Applies to CONVENTIONAL (Tier 5 pricing penalty)
  
  par_rate = 6.25%  (Tier 1 conventional benchmark)
  penalized_rate = 6.25% + 0.75% = 7.00%
  
  Step 1: r_par = 0.0625 / 12 = 0.0052083
  Step 2: compound_par = (1.0052083)^360 = 6.48917
  Step 3: numerator_par = 0.0052083 × 6.48917 = 0.033798
  Step 4: denominator_par = 6.48917 − 1 = 5.48917
  Step 5: factor_par = 0.033798 / 5.48917 = 0.0061572
  
  Step 1: r_pen = 0.07 / 12 = 0.0058333
  Step 2: compound_pen = (1.0058333)^360 = 8.11650
  Step 3: numerator_pen = 0.0058333 × 8.11650 = 0.047346
  Step 4: denominator_pen = 8.11650 − 1 = 7.11650
  Step 5: factor_pen = 0.047346 / 7.11650 = 0.0066530
  
  monthly_premium = 412,250 × (0.0066530 − 0.0061572)
                  = 412,250 × 0.0004958
                  = 204.42
  lifetime_cost = 204.42 × 360 = 73,591.20
  
  → C-02: ACTIVE — 💰 COST — $204.42/month, $73,591.20 lifetime (Conventional)

C-03: HIGH_REVOLVING_UTILIZATION
  total_revolving_utilization = 8,500 / 12,000 = 70.83% > 30%
  paydown_needed = MAX(0, 8,500 − 12,000 × 0.30)
                 = MAX(0, 8,500 − 3,600)
                 = 4,900.00
  → C-03: ACTIVE — 🟠 ELEVATED — paydown $4,900 → utilization 30%

C-04: DEROGATORY_TRADELINES — soft flags show TAX_ESTIMATED, INSURANCE_ESTIMATED — no derogatory. NOT ACTIVE.

Stage 4 — DTI CONSTRAINTS:


D-01: DTI_EXCEEDS_PROGRAM_LIMIT
  preliminary_dti = (785.00 + 3,447.32) / 8,458.33 = 4,232.32 / 8,458.33 = 0.5004 = 50.04%
  
  CONVENTIONAL DU limit = 50.00%:
    max_total = 8,458.33 × 0.50 = 4,229.17
    max_non_housing = 4,229.17 − 3,447.32 = 781.85
    debt_reduction = MAX(0, 785.00 − 781.85) = 3.15
    → D-01 ACTIVE for CONVENTIONAL — barely over by 0.04%
    → debt_reduction_needed = $3.15/month (smallest eligible liability payoff clears this)
  
  FHA AUS limit = 57.00%:
    max_total = 8,458.33 × 0.57 = 4,821.25
    max_non_housing = 4,821.25 − 3,447.32 = 1,373.93
    debt_reduction = MAX(0, 785.00 − 1,373.93) = 0 (well under)
    → D-01 NOT ACTIVE for FHA
  
  VA: ROUTE_HIGH_DTI flagged BUT veteran_flag = true
    → Do NOT flag D-01 for VA. Flag I-04 instead. VA residual income governs.
  
  → D-01: ACTIVE for CONVENTIONAL only — 🔴 BLOCKING (Conventional DU manual path)
    → QUICK_WIN candidate: $3.15/month reduction clears Conventional DU path

D-02: DTI_ELEVATED_WATCH
  preliminary_dti_signal = ELEVATED
  headroom_vs_fha = (0.57 × 8,458.33) − 4,232.32 = 4,821.25 − 4,232.32 = 588.93/month
  → D-02: ACTIVE — 🟡 WATCH — $588.93/month headroom vs FHA AUS

D-03: DEBT_TIMING_OPPORTUNITY
  months_to_exclusion_list: AUTO loan, 4 months remaining, $380/month
  dti_improvement = 380 / 8,458.33 = 0.0449 = 4.49%
  new_dti_after_exclusion = 50.04% − 4.49% = 45.55%
  45.55% ≤ 50% → qualifies Conventional DU after exclusion
  qualify_date = today + 4 months
  → D-03: ACTIVE — 🟢 OPPORTUNITY — wait 4 months, DTI drops to 45.55%, Conventional unlocked
  → AlwaysApproved trigger: re_engagement_date = today + 3 months (30 days advance)

D-04: STUDENT_LOAN_IDR — IDR override documented. NOT ACTIVE as constraint.

Stage 5 — CASH CONSTRAINTS:


K-01: CASH_TO_CLOSE_SHORTFALL
  VA:   required_ctc = 12,750.00, funds = 28,105.36 → shortfall = 0 ✓
  FHA:  required_ctc = 27,625.00, funds = 28,105.36 → shortfall = 0 ✓
  CONV: required_ctc = 25,500.00, funds = 28,105.36 → shortfall = 0 ✓
  → K-01: NOT ACTIVE

K-02: RESERVE SHORTFALL
  required_reserves = 2 × 3,447.32 = 6,894.64
  funds_available_for_reserves = 60,894.64
  reserve_gap = MAX(0, 6,894.64 − 60,894.64) = 0 ✓
  → K-02: NOT ACTIVE

K-03: CTC_MARGIN_TIGHT
  FHA margin = 28,105.36 − 27,625.00 = 480.36 < $1,000
  → K-03: ACTIVE — 🟡 WATCH — FHA margin $480.36

K-04: ASSET_DOCUMENTATION_GAP
  soft_flags include ASSETS_UNVERIFIED, TAX_ESTIMATED
  → K-04: ACTIVE — 🟡 WATCH — asset documentation required

Stage 6 — INCOME CONSTRAINTS:


I-01: NOT ACTIVE — income supports payment at FHA AUS limits
I-02: NOT ACTIVE — self_employed_flag = false for both borrowers
I-03: ACTIVE — Diana's gross-up income (nontaxable disability) is variable-adjacent
      → 🟡 WATCH — document VA benefit letter for continuance

I-04: VA_RESIDUAL_INCOME_RISK
  veteran_flag = true AND preliminary_dti_signal = ELEVATED
  net_income_for_va_residual = 8,183.33  (NO gross-up)
  estimated_shelter = 3,447.32
  estimated_residual = 8,183.33 − 3,447.32 − 785.00 = 3,951.01
  
  VA South region, family of 2: threshold = $738
  estimated_residual $3,951.01 >> $738 → substantial surplus
  → I-04: ACTIVE — 🟡 WATCH → likely PASSES residual test with significant margin
  Note: Full test in VA Module Skill. Preliminary result strongly favorable.

Stage 7 — PROGRAM CONSTRAINTS:


P-01: NOT ACTIVE — 3 programs eligible
P-02: NOT ACTIVE — 3 programs eligible (not single dependency)
P-03: NOT ACTIVE — loan amount $425,000 < $806,500 conforming limit

Stage 8 — PROPERTY / MI CONSTRAINTS:


PR-01: NOT ACTIVE — VA eligible with 0% down (no LTV cap)

PR-02: PMI_COST_DRAG (CONVENTIONAL)
  conv_base_loan = 412,250, conv_ltv = 97.00% > 80% → PMI required
  monthly_pmi = 343.54 (from Router)
  
  immediate_paydown_to_eliminate = 412,250 − 425,000 × 0.80
                                 = 412,250 − 340,000
                                 = 72,250.00
  
  Amortization loop for months_to_cancel (7.00%, $412,250 loan):
    [computed via amortization loop — see Stage 10 formula]
    At month 140: balance ≤ 340,000 (80% LTV) → pmi_cancel_request_month = 140
    At month 151: balance ≤ 331,500 (78% LTV) → pmi_auto_cancel_month = 151
    
  lifetime_pmi_cost = 343.54 × 151 = 51,874.54
  
  VA comparison: VA eliminates PMI entirely → $343.54/month savings from day 1
  → PR-02: ACTIVE — 💰 COST — $343.54/month PMI for 151 months = $51,874.54 lifetime (Conventional)

PR-03: FHA_MIP_LIFETIME_DRAG
  fha_ltv = 96.50% > 90% → MIP for life of loan (360 months)
  monthly_mip = 187.97
  
  additional_down_for_11yr_mip = 425,000 × 0.10 − 0 = 42,500.00 (currently 0 down for FHA)
  Wait — FHA example uses 3.5% down ($14,875).
  additional_down = 425,000 × 0.10 − 14,875 = 42,500 − 14,875 = 27,625.00
  
  new_fha_base = 425,000 × 0.90 = 382,500
  new_monthly_mip = 382,500 × 0.0050 / 12 = 1,912.50 / 12 = 159.38
  
  savings_first_132mo = (187.97 − 159.38) × 132 = 28.59 × 132 = 3,773.88

  NOTE: The exact (unrounded) calculation is: (187.973958 − 159.375000) × 132 = 3,775.06
        Per skill rounding policy, intermediate values must NOT be rounded before multiplication.
        Correct value: sav_first = 3,775.06

  savings_next_228mo = 187.97 × 228 = 42,857.16

  NOTE: Exact: 187.973958 × 228 = 42,858.06. Use exact value.
        Correct value: sav_rest = 42,858.06

  total_mip_savings = 3,775.06 + 42,858.06 = 46,633.12
  net_benefit = 46,633.12 − 27,625.00 = 19,008.12

  → PR-03: ACTIVE — 💰 COST — $187.97/month MIP for life of loan (FHA)
             additional $27,625 down saves $46,633.12 MIP over loan life (net $19,008.12 benefit)

Stage 9 — TIMING:


T-01: DEBT_EXCLUSION_OPPORTUNITY
  AUTO loan: 4 months remaining, $380/month
  new_dti = 50.04% − (380/8,458.33) = 50.04% − 4.49% = 45.55%
  45.55% ≤ 50% → Conventional DU unlocked after exclusion
  → T-01: ACTIVE — 🟢 OPPORTUNITY — 4 months to Conventional DTI compliance

T-02: CREDIT_IMPROVEMENT_TIMELINE
  paydown_needed = $4,900, funds available = $28,105.36 → QUICK_WIN
  timeline: 30–60 days
  estimated_impact: 15–40 point score improvement (model-dependent)
  → T-02: ACTIVE — 🟢 OPPORTUNITY

T-03: NOT ACTIVE — no rate data provided

Stage 13 — PROGRESS SCORE:


W1: Program Access (0.30)
  programs_eligible = 3 → score = 1.00
  W1_contribution = 1.00 × 0.30 = 0.300

W2: Credit Health (0.25)
  credit_health = MIN(1.0, (698 − 580) / (760 − 580))
               = MIN(1.0, 118 / 180)
               = MIN(1.0, 0.6556)
               = 0.6556
  W2_contribution = 0.6556 × 0.25 = 0.1639

W3: Cash Sufficiency (0.25) — vs best eligible program (VA, priority 1)
  VA required_ctc = 12,750.00
  funds = 28,105.36
  cash_ratio = MIN(1.0, 28,105.36 / 12,750.00) = MIN(1.0, 2.2043) = 1.00
  W3_contribution = 1.00 × 0.25 = 0.2500

W4: DTI Margin (0.20)
  preliminary_dti = 0.5004
  dti_margin = MAX(0, MIN(1, (0.50 − 0.5004) / 0.20))
             = MAX(0, MIN(1, −0.0004 / 0.20))
             = MAX(0, MIN(1, −0.002))
             = MAX(0, −0.002)
             = 0.00
  W4_contribution = 0.00 × 0.20 = 0.000

progress_score = 0.300 + 0.1639 + 0.2500 + 0.000 = 0.7139

Signal: 0.65–0.84 → MODERATE

NOTE ON VA: DTI at 50.04% marginally exceeds the 50% DTI scale boundary,
yielding W4=0. However, VA is Priority 1 program and VA has no hard DTI limit
(residual income governs). The progress score is conservative — VA qualification
is likely stronger than the score indicates. This is intentional: the score is
a floor estimate, not a ceiling.

Stage 14 — Constraint Report Summary:


CONSTRAINT REPORT — Marcus & Diana Webb
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Progress Score: 0.714  →  MODERATE
Programs eligible: 3 (VA, FHA, Conventional)

BLOCKING (1):
  🔴 D-01 — DTI over Conventional DU limit by 0.04%
     → $3.15/month reduction clears this  [QUICK WIN]
     → Wait 4 months (AUTO exclusion) → 45.55% DTI, fully clear

ELEVATED (1):
  🟠 C-03 — Revolving utilization 70.83%
     → Pay down $4,900 → 30% utilization  [QUICK WIN]
     → Estimated 15–40 point score improvement within 60 days

WATCH (4):
  🟡 D-02 — DTI elevated, $588.93/month headroom vs FHA AUS
  🟡 K-03 — FHA cash margin $480.36 — tight
  🟡 K-04 — Asset documentation required
  🟡 I-04 — VA residual: estimated $3,951.01/month — well above $738 threshold

COST (2):
  💰 C-02 — Conventional rate penalty (Tier 5): $204.42/month, $73,591.20 lifetime
  💰 PR-02 — PMI on Conventional: $343.54/month, ~$51,874.54 lifetime (~151 months)
  💰 PR-03 — FHA MIP life-of-loan: $187.97/month, $67,670.62 lifetime (360 months)
             [VA eliminates both PMI and MIP entirely]

OPPORTUNITIES (2):
  🟢 T-01 — Wait 4 months → AUTO excludes → DTI drops to 45.55% → Conventional clears
  🟢 T-02 — $4,900 utilization paydown → score improvement → rate tier upgrade possible

QUICK WINS (2):
  1. $3.15/month debt payoff → clears Conventional DU DTI (smallest qualifying liability)
  2. $4,900 revolving paydown → 30% utilization → 15–40 point score improvement

ALWAYS APPROVED TRIGGERS:
  Re-engagement: [today + 3 months] — 30-day advance of AUTO exclusion date
  Condition: verify DTI improvement; initiate Conventional evaluation

ADVISORY NOTE:
  VA is Priority 1 and eliminates both PMI ($343.54/month) and MIP.
  VA residual income estimate ($3,951/month) far exceeds VA South threshold ($738).
  The single highest-value action for this borrower is closing the VA loan now.
  All other constraints are cost-based or program-optimization opportunities —
  none block VA eligibility.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

FORBIDDEN PATTERNS

The following are prohibited and must never appear in any ConstraintReport output:


FORBIDDEN-01: Applying DTI hard stop to VA programs
  VA has no hard DTI stop. Residual income governs. Do not flag D-01 as BLOCKING for VA.

FORBIDDEN-02: Using gmi_for_dti (which may include gross-up) for VA residual income
  net_income_for_va_residual must never include gross-up adjustments.
  Assert: if gross_up_applied_flag = true for any income stream,
  net_income_for_va_residual ≠ gmi_for_dti. Verify before computing I-04.

FORBIDDEN-03: Rounding intermediate values before final output
  All intermediate calculations use full floating-point precision.
  Round only at the moment of presentation.

FORBIDDEN-04: Mixing DSCR and borrower income
  DSCR qualification uses property income only. Never reference gmi_for_dti in DSCR constraints.

FORBIDDEN-05: Asserting exact credit score improvement amounts
  Score improvement from any action is estimated only. Score models are proprietary.
  Always express as a range: "estimated 15–40 points" — never "will improve by exactly 30 points."

FORBIDDEN-06: Using annual interest rate directly in amortization loop
  monthly_rate = annual_rate / 12. Never use annual_rate directly in the loop.

FORBIDDEN-07: Representing progress_score as an approval probability
  progress_score is a directional improvement metric. It is not a probability of approval.
  Do not say "71% chance of approval" — say "progress score 0.714 — MODERATE."

COMPANION SKILLS

SkillRelationship
Clarity_Engine_Borrower_Profile_SKILL.mdRequired input — provides BorrowerProfile object
Clarity_Engine_Program_Router_SKILL.mdRequired input — provides ProgramEvaluationQueue
Clarity_Engine_VA_Module_SKILL.mdDownstream — receives I-04 for full residual income test
Clarity_Engine_Math_SKILL.mdReference — all PMT factor computations
Clarity_Engine_Optimization_SKILL.mdDownstream — receives ConstraintReport to generate scenarios
Clarity_Engine_Explanation_SKILL.mdDownstream — receives ConstraintReport for borrower-facing output
Clarity_Engine_Always_Approved_SKILL.mdDownstream — receives re-engagement triggers from opportunity register

Clarity Engine — Constraint Detection Skill v1.0 | CONFIDENTIAL — PreFi, Inc. / Purpose Technology, Inc. d/b/a Purlend