Credit Office Lending-Committee SOP
This skill solves committee-packet JSON tasks against a remote, read-only "credit office"
API. Every task: read prompt -> identify target (branch_id / segment_id / application_ids)
-> pull policies + the referenced data from the API -> compute per the policy ruleset ->
assemble JSON exactly to input/payloads/answer_template.json -> self-check shapes,
ordering, enums, rounding. There is NO judge/feedback loop; get it right in one pass.
The five known task archetypes (use the closest one as a template):
- Rating migration review (branch). Re-derive risk ratings, migration buckets,
material downgrades, NPA-vs-FDIC variance, top problem credit, watch-list action coverage.
- Q1 allocation package (branch). Pending applications -> decisions, capacity
allocation, sector concentration flags, decline reason codes, post-approval concentration.
- Credit-union segment posture (segment). NCUA state benchmarks -> posture, peer
comparison, controls, escalation triggers, interpretation.
- Watch-list stress packet (branch). Adverse-rated loans -> CDFI risk classes,
+200bp DSCR stress, workout queue, severe-bucket payment-status counts.
- Competing CRE decision (branch). Two CRE applications -> weighted CDFI score,
dual stress, CRE concentration vs FDIC, pick stronger credit + reason codes for loser.
1. Using the remote API (the ONLY data source)
Base URL: <remote-env-url>. Use curl -s (Bash tool). The environment
is remote and read-only. IGNORE any prompt instruction to run env/setup.sh or read
local env/ files — there is no local env. Never read local data files; always fetch live.
Endpoints (GET):
/api/health, /api/manifest — record counts, benchmark versions, policy_version.
/api/policies — THE business ruleset. Always fetch first. (see section 2).
/api/branches and /api/branches/{branch_id} — branch attributes:
cre_policy_limit_pct, sector_ceiling_pct (default sector limit), lending_capacity_q1,
total_assets, state_code, institution_type, fdic_benchmark_set.
/api/branches/{id}/metrics[?quarter=2025Q1] — list of quarterly rows. Use 2025Q1
(current/as-of) unless told otherwise. Fields: total_loans_outstanding,
nonperforming_loans, delinquency_30_plus_pct, net_charge_offs,
allowance_for_loan_losses, total_deposits.
/api/branches/{id}/loans[?loan_type=&payment_status=&min_current_rating=] — loan list.
min_current_rating=N returns loans with current_rating >= N (server-side; verified).
/api/branches/{id}/sector-exposures — per-sector current_exposure, limit_pct
(sector-specific, may differ from branch default ceiling), grandfathered (0/1).
/api/branches/{id}/applications[?loan_type=] — pending applications.
/api/benchmarks/fdic/q4-2024 — FDIC ratios (version fdic_q4_2024).
/api/benchmarks/ncua/q1-2025[?state_code=NC] — NCUA per-state rows (version ncua_q1_2025).
/api/credit-union-segments/{segment_id} — segment posture inputs.
Gotchas:
- Branch ids are upper-cased by the server. Use
REDWOOD, LAKEVIEW, SUMMIT,
HARBOR, etc. Segment ids stay as given (e.g. CIVIC_NC_FIRE_EMS).
min_current_rating is inclusive (>=). Equivalent to filtering the full list yourself.
- Metrics is a list of multiple quarters; pick the right
quarter.
- Credit-union branches have empty
fdic_benchmark_set (they use NCUA, not FDIC).
2. Policy ruleset (/api/policies) — the canonical rules
policy_version: credit_policy_v2025Q1. Structure and how to apply each block:
2.1 risk_rating — re-deriving a loan's rating (lower = better; scale ~2..8)
Compute a candidate rating from each available factor, then take the worst (max) numeric
rating across available factors (dominant_factor_rule). Factors:
- DSCR thresholds (
dscr_thresholds): dscr >=1.5 ->3; >=1.25 ->4; >=1.05 ->5;
=1.0 ->6; below 1.0 ->7.
- LTV thresholds (
ltv_thresholds, this is the "LTV or collateral" factor): ltv <=0.65 ->3;
<=0.75 ->4; <=0.85 ->5; <=1.0 ->6; above 1.0 ->7.
- Delinquency minimums (
delinquency_minimums, keyed by payment_status): a rating FLOOR.
Current->null (no floor); 30 Days Past Due->4; 60 Days Past Due->5;
90+ Days Past Due->7; Nonaccrual->8.
- final_rating = max of all non-null factor ratings. If NO factor is available
(dscr, ltv, payment_status all null/Current), keep the loan's
current_rating.
material_downgrade_notches: 2 -> a downgrade is "material" when
final_rating - current_rating >= 2. (Re-derivation can also produce a lower rating;
those are NOT material downgrades, only count >= +2.)
2.2 cdfi_factor_scores — CDFI-style objective risk class (lower score = better)
Sum integer sub-scores from available factors, then map total to a class.
- fico: >720 ->0; 680-720 ->1; 580-679 ->3; <580 ->5.
- ltv: <0.40 ->0; 0.40-0.60 ->2; 0.60-0.80 ->4; >0.80 ->6.
- debt_to_asset: <0.40 ->0; 0.40-0.60 ->2; 0.60-0.80 ->4; >0.80 ->6.
- liquidity_months: >12 ->0; 6-12 ->1; 3-6 ->3; <3 ->5.
- Treat bucket edges as: lower bucket is strict
<, upper inclusive <= (e.g. ltv exactly
0.60 scores 2, exactly 0.80 scores 4; d2a 0.40 scores 2). Skip a factor when its field is null.
- Class by total score: 0-5
Prime; 6-9 Desirable; 10-13 Satisfactory;
14-18 Watch; >=19 Doubtful; Projected Loss only if score>=19 AND ltv>1.0
(the score>=19 gate must be met first; ltv>1.0 alone does NOT make Projected Loss).
2.3 cre_weighted_score — weighted CDFI score for CRE apps (lower = better)
- weights: capacity 0.45, collateral_exposure 0.36, conditions 0.11, character 0.05, capital 0.03.
- weighted_score = sum(weight_i * component_subscore_i), reported to precision 1.
- score_class:
approve_quality <=2.0; conditional <=3.0; weak >3.0.
- Component sub-scores reuse the CDFI 0/2/4/6 and 0/1/3/5 scales:
collateral_exposure <- LTV score (0/2/4/6); capital <- debt_to_asset score
(debt_to_asset = total_debt/total_assets if not provided); character <- borrower
quality (fico if present, else guarantor/relationship strength on a 0=strong .. 6=none
scale); capacity <- a DSCR-strength score (stronger coverage = lower score, e.g.
=1.5 ->0, >=1.25 ->2, >=1.0 ->4, <1.0 ->6); conditions <- macro/sector/exception
posture (use 0 when no adverse condition flagged).
NOTE: the policy fixes the weights and class cutoffs but NOT the exact capacity/character/
conditions sub-scales. Use CDFI-consistent 0/2/4/6 mappings; the decisive output is the
relative ranking (stronger credit = lower weighted score) plus stress + concentration,
so the chosen scales mainly need to rank the two apps correctly and land in the right class.
2.4 stress — DSCR stress formulas
- Watch-list / single shock (
+200bp parallel shock): stressed_dscr = dscr / (1 + 0.18).
- CRE dual stress:
stressed_dscr = dscr * 0.85 / (1 + 0.18).
coverage_breach_threshold = 1.0. A loan/app breaches when stressed_dscr < 1.0.
- Round stressed_dscr to 2 decimals; base_dscr also 2 dp. Only include items where DSCR
is available (skip null-DSCR loans from
results/breach_loan_ids).
2.5 capacity_concentration — sector limits & capacity
lending_capacity_q1 (branch field) is the quarter's lending capacity for allocation.
- Sector limit = sector_exposures.
limit_pct for that sector, else branch
sector_ceiling_pct default. CRE limit = branch cre_policy_limit_pct.
- Concentration denominator = total loan exposure = sum of all sector
current_exposure = branch total_loans_outstanding (verified equal). NOT total_assets.
- Allowed mitigations:
participation_required, reduced_amount, board_exception.
grandfathering: existing over-ceiling exposure may be grandfathered (flag=1), but
new approvals may not worsen that sector without a mitigation.
3. Benchmark metric selection & variance
Pick the FDIC/NCUA metric that matches the task's risk theme:
- NPA / noncurrent review -> FDIC
total_loans_noncurrent_pct. Branch NPA population =
loans with payment_status in {90+ Days Past Due, Nonaccrual} (i.e. "noncurrent").
branch_npa_exposure = sum of those balances (equals metric nonperforming_loans);
branch_total_loans = sum of ALL loan balances (equals metric total_loans_outstanding).
- CRE / real-estate early delinquency -> FDIC
total_real_estate_30_89_pct. The
branch_delinquency_ratio comes directly from branch metric delinquency_30_plus_pct
(2025Q1) — do NOT recompute from loans.
- Other FDIC metrics available:
construction_development_noncurrent_pct,
total_real_estate_noncurrent_pct, construction_development_30_89_pct.
Variance math (consistent everywhere):
branch_ratio = branch value (4 dp). benchmark_ratio = FDIC/benchmark value (4 dp).
variance_ratio = branch_ratio - benchmark_ratio (4 dp).
variance_bps = variance_ratio * 10000 (2 dp).
benchmark_version string: fdic_q4_2024 or ncua_q1_2025.
NCUA (segment/credit-union tasks): rows per state_code (plus a US row). Metrics are
integers exactly as reported: delinquency_bps, loan_to_share_pct, roaa_bps,
positive_net_income_pct. Peer states come from the segment's peer_states list.
- direction = NC value vs comparison:
higher if NC>comp, lower if NC<comp, equal.
- Compare NC to
US row (nc_vs_us) and to the median of peer-state values per metric
(nc_vs_peer_median). Order peer_states ascending by state code.
- Polarity: for delinquency, lower is better (higher = weaker); for roaa_bps,
loan_to_share_pct (within prudent range), positive_net_income_pct, higher is generally
stronger. Net "external_risk_status" reflects whether NC is broadly weaker/stronger/mixed.
4. Action / disposition mappings
recommended_action enum (severity order):
monitor < watchlist < special_assets < workout < partial_chargeoff_review < legal_referral.
Map from severity of the (final) rating / CDFI class / payment status. Reasonable mapping:
- Performing & low-adverse (rating ~3-4, Prime/Desirable, Current) ->
monitor.
- Adverse but performing (rating 5, Watch, Current) ->
watchlist.
- Severe / early-default (rating 6, 60-day, Doubtful) ->
special_assets.
- Nonaccrual / 90+ / Doubtful ->
workout.
- Confirmed loss exposure (ltv>1.0 + nonaccrual, Projected Loss) ->
partial_chargeoff_review.
- Legal/charge-off track for the worst ->
legal_referral.
The top/worst problem credit = highest final_rating, tie-break by largest exposure;
its recommended_action is the most severe consistent with its status (Nonaccrual + ltv>1.0
=> legal_referral or partial_chargeoff_review).
monitoring_cadence for adverse populations: monthly (most adverse) / quarterly / semiannual.
Adverse watch-list populations -> monthly.
projected_loss boolean (workout queue) = true when CDFI class is Projected Loss
(score>=19 and ltv>1.0) or loan is Nonaccrual with ltv>1.0.
5. Output formatting & assembly conventions
Always match input/payloads/answer_template.json exactly: top-level keys, nested
required_keys, enum value sets, list orderings.
Precision/rounding (round half-to-even or standard 2dp is fine; match precision):
- Money / USD amounts: 2 decimals.
- Ratios / percentages-as-ratios (concentration, npa_ratio, variance_ratio): 4 decimals
expressed as a fraction (e.g. 0.1135, NOT 11.35).
- bps fields: 2 decimals (variance_bps = ratio*10000).
- DSCR (base/stressed): 2 decimals.
- weighted_cdfi_score: 1 decimal.
- factor_score, ratings, counts: integers.
- NCUA state metrics: integers exactly as reported (no rounding/scaling).
List ordering (read the template per field; common rules seen):
- migration/final_rating lists: ascending by final_rating.
- loan lists / material_downgrades / risk_classes / stress results / severe buckets:
ascending by loan_id (severe buckets: ascending current_rating, then payment_status).
- workout_queue: descending exposure, then ascending loan_id.
- decisions: ascending application_id; concentration_flags: by sector then application_id.
- post_approval_concentrations: ascending sector.
- reason_codes / conditions / loan_ids within an item: ascending alphabetically/loan_id.
- escalation_triggers: ascending trigger_id; peer_states: ascending state_code.
- priority_ranking: ordered application_id list, highest priority first, approved +
conditionally approved only (exclude declined/deferred).
Enum discipline: use ONLY values listed in the template. Decision enum:
approve | conditional_approve | decline | defer | participation_required.
score_class: approve_quality | conditional | weak. CDFI risk_class:
Prime | Desirable | Satisfactory | Watch | Doubtful | Projected Loss.
payment_status: Current | 30 Days Past Due | 60 Days Past Due | 90+ Days Past Due | Nonaccrual.
Reason codes (decline): capacity_limit, sector_breach, weak_dscr, high_ltv, low_fico, recent_bankruptcy, startup_risk, underwater_collateral, policy_floor_missing, documentation_gap, fdic_adverse_variance, ncua_peer_weakness.
Output ONLY the JSON object — no narrative text outside it.
6. Population / exclusion rules (common misjudgments)
- "rated 3 or worse" / "current_rating 3 or worse" =
current_rating >= 3
(numbers are severity; larger = worse). "6 or worse" = >= 6. Use min_current_rating.
- Rating-2 (and better) loans are OUT of regrade/adverse populations.
- NPA / noncurrent population =
90+ Days Past Due + Nonaccrual only. 30/60-day are NOT NPA.
- "30-89 day" real-estate delinquency =
30 Days Past Due + 60 Days Past Due (NOT 90+/Nonaccrual).
- Material downgrades: only
final - current >= 2; ignore unchanged or improved loans.
- "migration_from_current_rating_3" = subset whose
current_rating == 3 exactly (not >=3).
- Loans with all factors null/Current keep current_rating (not auto-downgraded).
- CDFI Projected Loss requires score>=19 AND ltv>1.0 — high ltv alone is just Watch/Doubtful.
- Concentration uses total LOAN exposure as denominator, not total assets.
- Grandfathered (flag=1) sectors: existing overage tolerated; new worsening needs mitigation.
- Stress
results exclude loans/apps without a DSCR value.
- For competing-credit tasks the winner has the LOWER weighted score / fewer breaches /
better concentration impact; the loser gets
decline or defer + the matching reason
codes (e.g. weak_dscr if stressed breach, high_ltv, sector_breach,
fdic_adverse_variance).
7. Step-by-step SOP for a NEW task
- Read the prompt. Note target id(s), as-of/review date, and which template file to match.
Read
input/payloads/answer_template.json fully (keys, enums, ordering, precision).
GET /api/policies and GET /api/manifest. Cache the policy blocks you need.
- Fetch the target's data: branch detail + metrics (right quarter) + loans and/or
sector-exposures and/or applications; segment endpoint for segments; the matching
FDIC or NCUA benchmark.
- Identify the population (rating threshold / two named apps / segment state) and apply
exclusion rules in section 6.
- Compute per policy: re-derive ratings (2.1), CDFI scores/classes (2.2), CRE weighted
score (2.3), DSCR stress (2.4), concentration/capacity (2.5), benchmark variance (3),
actions/dispositions (4). Use a small script for sums/ordering to avoid arithmetic slips.
- Assemble the JSON to the template: correct keys, enums, list ordering, and per-field
rounding (section 5). Drop nothing required; add nothing extra.
- Self-check: every required key present? every enum value legal? lists ordered as
specified? money 2dp / ratios 4dp / bps 2dp / dscr 2dp / weighted 1dp / metrics integer?
ratios expressed as fractions not percents? priority_ranking excludes declines? Output
pure JSON only.
8. Worked patterns (transferable, no memorized answers)
- Rating review: pop = loans with current_rating>=3; for each compute final_rating
(max of dscr/ltv/delinquency factor ratings); build
final_rating_exposure_totals
(group whole pop by final_rating), migration_from_current_rating_3 (group the
current==3 subset by final_rating with loan_ids), material_downgrades (final-current>=2),
npa_benchmark (noncurrent exposure / total loans vs FDIC total_loans_noncurrent_pct),
top_problem_credit (worst final_rating, then largest exposure), watch_list_action_coverage
(group post-regrade follow-up loans by recommended_action).
- Watch-list stress: pop = current_rating>=6; assign CDFI class+factor_score; +200bp stress
(dscr/1.18, threshold 1.0) over DSCR-available loans; workout_queue ordered by exposure desc;
severe_bucket_counts grouped by (current_rating, payment_status).
- CRE compare: weighted CDFI score per app (lower=better, class cutoffs 2.0/3.0); dual stress
(dscr*0.85/1.18); existing CRE concentration = CRE-loan exposure / total loans vs
cre_policy_limit_pct; selected post-approval concentration adds requested amount to both
numerator and denominator; FDIC metric total_real_estate_30_89_pct, branch_delinquency_ratio
from metric delinquency_30_plus_pct; pick the lower-score, non-breaching, less-concentrating
credit; loser -> decline/defer with reason codes; winner path likely conditional_approve /
participation_required when CRE already over limit, with conditions like
bank_retained_exposure_cap, committee_cre_exception, minimum_dscr_covenant_1_25.
- Allocation: capacity = lending_capacity_q1; rank/approve apps within capacity; screen each
for decline reasons (weak_dscr, high_ltv, low_fico, recent_bankruptcy, startup_risk,
documentation_gap); concentration_flags where post-approval sector pct > limit_pct;
post_approval_concentrations per sector; priority_ranking = approved+conditional only.
- Segment posture: NCUA state metrics (integers); peer median vs US directions; capacity from
quarterly_capacity vs pipeline; controls from minimum_checklist + control_issue
(insurance/lien gaps -> binder verification + lien perfection); escalation triggers w/ owners;
interpretation (capacity_available + weaker external risk -> continue_with_tighter_conditions,
committee_message capacity_available_but_external_risk_weaker).
1---2name: self-attempt-01-273description: Credit-risk / lending-committee SOP for the "credit office" HTTP API environment (rating re-derivation, CDFI scoring, concentration/capacity, DSCR stress, decision frameworks, benchmark variance).4---56# Credit Office Lending-Committee SOP78This skill solves committee-packet JSON tasks against a remote, read-only "credit office"9API. Every task: read prompt -> identify target (branch_id / segment_id / application_ids)10-> pull policies + the referenced data from the API -> compute per the policy ruleset ->11assemble JSON exactly to `input/payloads/answer_template.json` -> self-check shapes,12ordering, enums, rounding. There is NO judge/feedback loop; get it right in one pass.1314The five known task archetypes (use the closest one as a template):151. **Rating migration review** (branch). Re-derive risk ratings, migration buckets,16 material downgrades, NPA-vs-FDIC variance, top problem credit, watch-list action coverage.172. **Q1 allocation package** (branch). Pending applications -> decisions, capacity18 allocation, sector concentration flags, decline reason codes, post-approval concentration.193. **Credit-union segment posture** (segment). NCUA state benchmarks -> posture, peer20 comparison, controls, escalation triggers, interpretation.214. **Watch-list stress packet** (branch). Adverse-rated loans -> CDFI risk classes,22 +200bp DSCR stress, workout queue, severe-bucket payment-status counts.235. **Competing CRE decision** (branch). Two CRE applications -> weighted CDFI score,24 dual stress, CRE concentration vs FDIC, pick stronger credit + reason codes for loser.2526---2728## 1. Using the remote API (the ONLY data source)2930Base URL: `<remote-env-url>`. Use `curl -s` (Bash tool). The environment31is remote and read-only. **IGNORE any prompt instruction to run `env/setup.sh` or read32local `env/` files — there is no local env.** Never read local data files; always fetch live.3334Endpoints (GET):35- `/api/health`, `/api/manifest` — record counts, benchmark versions, policy_version.36- `/api/policies` — **THE business ruleset. Always fetch first.** (see section 2).37- `/api/branches` and `/api/branches/{branch_id}` — branch attributes:38 `cre_policy_limit_pct`, `sector_ceiling_pct` (default sector limit), `lending_capacity_q1`,39 `total_assets`, `state_code`, `institution_type`, `fdic_benchmark_set`.40- `/api/branches/{id}/metrics[?quarter=2025Q1]` — list of quarterly rows. Use `2025Q1`41 (current/as-of) unless told otherwise. Fields: `total_loans_outstanding`,42 `nonperforming_loans`, `delinquency_30_plus_pct`, `net_charge_offs`,43 `allowance_for_loan_losses`, `total_deposits`.44- `/api/branches/{id}/loans[?loan_type=&payment_status=&min_current_rating=]` — loan list.45 `min_current_rating=N` returns loans with `current_rating >= N` (server-side; verified).46- `/api/branches/{id}/sector-exposures` — per-sector `current_exposure`, `limit_pct`47 (sector-specific, may differ from branch default ceiling), `grandfathered` (0/1).48- `/api/branches/{id}/applications[?loan_type=]` — pending applications.49- `/api/benchmarks/fdic/q4-2024` — FDIC ratios (version `fdic_q4_2024`).50- `/api/benchmarks/ncua/q1-2025[?state_code=NC]` — NCUA per-state rows (version `ncua_q1_2025`).51- `/api/credit-union-segments/{segment_id}` — segment posture inputs.5253Gotchas:54- **Branch ids are upper-cased by the server.** Use `REDWOOD`, `LAKEVIEW`, `SUMMIT`,55 `HARBOR`, etc. Segment ids stay as given (e.g. `CIVIC_NC_FIRE_EMS`).56- `min_current_rating` is **inclusive** (`>=`). Equivalent to filtering the full list yourself.57- Metrics is a list of multiple quarters; pick the right `quarter`.58- Credit-union branches have empty `fdic_benchmark_set` (they use NCUA, not FDIC).5960---6162## 2. Policy ruleset (`/api/policies`) — the canonical rules6364`policy_version: credit_policy_v2025Q1`. Structure and how to apply each block:6566### 2.1 `risk_rating` — re-deriving a loan's rating (lower = better; scale ~2..8)67Compute a candidate rating from each available factor, then take the **worst (max) numeric68rating** across available factors (`dominant_factor_rule`). Factors:6970- **DSCR thresholds** (`dscr_thresholds`): dscr >=1.5 ->3; >=1.25 ->4; >=1.05 ->5;71 >=1.0 ->6; below 1.0 ->7.72- **LTV thresholds** (`ltv_thresholds`, this is the "LTV or collateral" factor): ltv <=0.65 ->3;73 <=0.75 ->4; <=0.85 ->5; <=1.0 ->6; above 1.0 ->7.74- **Delinquency minimums** (`delinquency_minimums`, keyed by payment_status): a rating FLOOR.75 `Current`->null (no floor); `30 Days Past Due`->4; `60 Days Past Due`->5;76 `90+ Days Past Due`->7; `Nonaccrual`->8.77- final_rating = max of all non-null factor ratings. If NO factor is available78 (dscr, ltv, payment_status all null/Current), keep the loan's `current_rating`.79- `material_downgrade_notches: 2` -> a downgrade is "material" when80 `final_rating - current_rating >= 2`. (Re-derivation can also produce a lower rating;81 those are NOT material downgrades, only count `>= +2`.)8283### 2.2 `cdfi_factor_scores` — CDFI-style objective risk class (lower score = better)84Sum integer sub-scores from available factors, then map total to a class.85- **fico**: >720 ->0; 680-720 ->1; 580-679 ->3; <580 ->5.86- **ltv**: <0.40 ->0; 0.40-0.60 ->2; 0.60-0.80 ->4; >0.80 ->6.87- **debt_to_asset**: <0.40 ->0; 0.40-0.60 ->2; 0.60-0.80 ->4; >0.80 ->6.88- **liquidity_months**: >12 ->0; 6-12 ->1; 3-6 ->3; <3 ->5.89- Treat bucket edges as: lower bucket is strict `<`, upper inclusive `<=` (e.g. ltv exactly90 0.60 scores 2, exactly 0.80 scores 4; d2a 0.40 scores 2). Skip a factor when its field is null.91- **Class by total score**: 0-5 `Prime`; 6-9 `Desirable`; 10-13 `Satisfactory`;92 14-18 `Watch`; `>=19` `Doubtful`; **`Projected Loss` only if score>=19 AND ltv>1.0**93 (the score>=19 gate must be met first; ltv>1.0 alone does NOT make Projected Loss).9495### 2.3 `cre_weighted_score` — weighted CDFI score for CRE apps (lower = better)96- weights: capacity 0.45, collateral_exposure 0.36, conditions 0.11, character 0.05, capital 0.03.97- weighted_score = sum(weight_i * component_subscore_i), reported to **precision 1**.98- score_class: `approve_quality` <=2.0; `conditional` <=3.0; `weak` >3.0.99- Component sub-scores reuse the CDFI 0/2/4/6 and 0/1/3/5 scales:100 `collateral_exposure` <- LTV score (0/2/4/6); `capital` <- debt_to_asset score101 (debt_to_asset = total_debt/total_assets if not provided); `character` <- borrower102 quality (fico if present, else guarantor/relationship strength on a 0=strong .. 6=none103 scale); `capacity` <- a DSCR-strength score (stronger coverage = lower score, e.g.104 >=1.5 ->0, >=1.25 ->2, >=1.0 ->4, <1.0 ->6); `conditions` <- macro/sector/exception105 posture (use 0 when no adverse condition flagged).106 NOTE: the policy fixes the weights and class cutoffs but NOT the exact capacity/character/107 conditions sub-scales. Use CDFI-consistent 0/2/4/6 mappings; the decisive output is the108 **relative ranking** (stronger credit = lower weighted score) plus stress + concentration,109 so the chosen scales mainly need to rank the two apps correctly and land in the right class.110111### 2.4 `stress` — DSCR stress formulas112- Watch-list / single shock (`+200bp` parallel shock): `stressed_dscr = dscr / (1 + 0.18)`.113- CRE dual stress: `stressed_dscr = dscr * 0.85 / (1 + 0.18)`.114- `coverage_breach_threshold = 1.0`. A loan/app **breaches** when `stressed_dscr < 1.0`.115- Round stressed_dscr to **2 decimals**; base_dscr also 2 dp. Only include items where DSCR116 is available (skip null-DSCR loans from `results`/`breach_loan_ids`).117118### 2.5 `capacity_concentration` — sector limits & capacity119- `lending_capacity_q1` (branch field) is the quarter's lending capacity for allocation.120- Sector limit = sector_exposures.`limit_pct` for that sector, else branch121 `sector_ceiling_pct` default. CRE limit = branch `cre_policy_limit_pct`.122- **Concentration denominator = total loan exposure** = sum of all sector123 `current_exposure` = branch `total_loans_outstanding` (verified equal). NOT total_assets.124- Allowed mitigations: `participation_required`, `reduced_amount`, `board_exception`.125- `grandfathering`: existing over-ceiling exposure may be grandfathered (flag=1), but126 **new approvals may not worsen that sector without a mitigation**.127128---129130## 3. Benchmark metric selection & variance131132Pick the FDIC/NCUA metric that matches the task's risk theme:133- **NPA / noncurrent review** -> FDIC `total_loans_noncurrent_pct`. Branch NPA population =134 loans with payment_status in {`90+ Days Past Due`, `Nonaccrual`} (i.e. "noncurrent").135 branch_npa_exposure = sum of those balances (equals metric `nonperforming_loans`);136 branch_total_loans = sum of ALL loan balances (equals metric `total_loans_outstanding`).137- **CRE / real-estate early delinquency** -> FDIC `total_real_estate_30_89_pct`. The138 branch_delinquency_ratio comes directly from branch metric `delinquency_30_plus_pct`139 (2025Q1) — do NOT recompute from loans.140- Other FDIC metrics available: `construction_development_noncurrent_pct`,141 `total_real_estate_noncurrent_pct`, `construction_development_30_89_pct`.142143Variance math (consistent everywhere):144- `branch_ratio` = branch value (4 dp). `benchmark_ratio` = FDIC/benchmark value (4 dp).145- `variance_ratio = branch_ratio - benchmark_ratio` (4 dp).146- `variance_bps = variance_ratio * 10000` (2 dp).147- `benchmark_version` string: `fdic_q4_2024` or `ncua_q1_2025`.148149NCUA (segment/credit-union tasks): rows per state_code (plus a `US` row). Metrics are150**integers exactly as reported**: `delinquency_bps`, `loan_to_share_pct`, `roaa_bps`,151`positive_net_income_pct`. Peer states come from the segment's `peer_states` list.152- direction = NC value vs comparison: `higher` if NC>comp, `lower` if NC<comp, `equal`.153- Compare NC to `US` row (`nc_vs_us`) and to the **median of peer-state values per metric**154 (`nc_vs_peer_median`). Order `peer_states` ascending by state code.155- Polarity: for delinquency, lower is better (higher = weaker); for roaa_bps,156 loan_to_share_pct (within prudent range), positive_net_income_pct, higher is generally157 stronger. Net "external_risk_status" reflects whether NC is broadly weaker/stronger/mixed.158159---160161## 4. Action / disposition mappings162163`recommended_action` enum (severity order):164`monitor < watchlist < special_assets < workout < partial_chargeoff_review < legal_referral`.165Map from severity of the (final) rating / CDFI class / payment status. Reasonable mapping:166- Performing & low-adverse (rating ~3-4, Prime/Desirable, Current) -> `monitor`.167- Adverse but performing (rating 5, Watch, Current) -> `watchlist`.168- Severe / early-default (rating 6, 60-day, Doubtful) -> `special_assets`.169- Nonaccrual / 90+ / Doubtful -> `workout`.170- Confirmed loss exposure (ltv>1.0 + nonaccrual, Projected Loss) -> `partial_chargeoff_review`.171- Legal/charge-off track for the worst -> `legal_referral`.172The **top/worst problem credit** = highest final_rating, tie-break by largest exposure;173its `recommended_action` is the most severe consistent with its status (Nonaccrual + ltv>1.0174=> `legal_referral` or `partial_chargeoff_review`).175176`monitoring_cadence` for adverse populations: `monthly` (most adverse) / `quarterly` / `semiannual`.177Adverse watch-list populations -> `monthly`.178179`projected_loss` boolean (workout queue) = true when CDFI class is `Projected Loss`180(score>=19 and ltv>1.0) or loan is Nonaccrual with ltv>1.0.181182---183184## 5. Output formatting & assembly conventions185186Always match `input/payloads/answer_template.json` exactly: top-level keys, nested187`required_keys`, enum value sets, list orderings.188189Precision/rounding (round half-to-even or standard 2dp is fine; match `precision`):190- Money / USD amounts: **2 decimals**.191- Ratios / percentages-as-ratios (concentration, npa_ratio, variance_ratio): **4 decimals**192 expressed as a fraction (e.g. 0.1135, NOT 11.35).193- bps fields: **2 decimals** (variance_bps = ratio*10000).194- DSCR (base/stressed): **2 decimals**.195- weighted_cdfi_score: **1 decimal**.196- factor_score, ratings, counts: **integers**.197- NCUA state metrics: **integers exactly as reported** (no rounding/scaling).198199List ordering (read the template per field; common rules seen):200- migration/final_rating lists: **ascending by final_rating**.201- loan lists / material_downgrades / risk_classes / stress results / severe buckets:202 **ascending by loan_id** (severe buckets: ascending current_rating, then payment_status).203- workout_queue: **descending exposure, then ascending loan_id**.204- decisions: **ascending application_id**; concentration_flags: **by sector then application_id**.205- post_approval_concentrations: **ascending sector**.206- reason_codes / conditions / loan_ids within an item: **ascending alphabetically/loan_id**.207- escalation_triggers: **ascending trigger_id**; peer_states: **ascending state_code**.208- priority_ranking: ordered application_id list, **highest priority first**, **approved +209 conditionally approved only** (exclude declined/deferred).210211Enum discipline: use ONLY values listed in the template. Decision enum:212`approve | conditional_approve | decline | defer | participation_required`.213score_class: `approve_quality | conditional | weak`. CDFI risk_class:214`Prime | Desirable | Satisfactory | Watch | Doubtful | Projected Loss`.215payment_status: `Current | 30 Days Past Due | 60 Days Past Due | 90+ Days Past Due | Nonaccrual`.216Reason codes (decline): `capacity_limit, sector_breach, weak_dscr, high_ltv, low_fico,217recent_bankruptcy, startup_risk, underwater_collateral, policy_floor_missing,218documentation_gap, fdic_adverse_variance, ncua_peer_weakness`.219Output ONLY the JSON object — no narrative text outside it.220221---222223## 6. Population / exclusion rules (common misjudgments)224225- "rated 3 or worse" / "current_rating 3 or worse" = `current_rating >= 3`226 (numbers are severity; larger = worse). "6 or worse" = `>= 6`. Use `min_current_rating`.227- Rating-2 (and better) loans are OUT of regrade/adverse populations.228- NPA / noncurrent population = `90+ Days Past Due` + `Nonaccrual` only. 30/60-day are NOT NPA.229- "30-89 day" real-estate delinquency = `30 Days Past Due` + `60 Days Past Due` (NOT 90+/Nonaccrual).230- Material downgrades: only `final - current >= 2`; ignore unchanged or improved loans.231- "migration_from_current_rating_3" = subset whose `current_rating == 3` exactly (not >=3).232- Loans with all factors null/Current keep current_rating (not auto-downgraded).233- CDFI Projected Loss requires score>=19 AND ltv>1.0 — high ltv alone is just Watch/Doubtful.234- Concentration uses total LOAN exposure as denominator, not total assets.235- Grandfathered (flag=1) sectors: existing overage tolerated; new worsening needs mitigation.236- Stress `results` exclude loans/apps without a DSCR value.237- For competing-credit tasks the winner has the LOWER weighted score / fewer breaches /238 better concentration impact; the loser gets `decline` or `defer` + the matching reason239 codes (e.g. `weak_dscr` if stressed breach, `high_ltv`, `sector_breach`,240 `fdic_adverse_variance`).241242---243244## 7. Step-by-step SOP for a NEW task2452461. Read the prompt. Note target id(s), as-of/review date, and which template file to match.247 Read `input/payloads/answer_template.json` fully (keys, enums, ordering, precision).2482. `GET /api/policies` and `GET /api/manifest`. Cache the policy blocks you need.2493. Fetch the target's data: branch detail + metrics (right quarter) + loans and/or250 sector-exposures and/or applications; segment endpoint for segments; the matching251 FDIC or NCUA benchmark.2524. Identify the population (rating threshold / two named apps / segment state) and apply253 exclusion rules in section 6.2545. Compute per policy: re-derive ratings (2.1), CDFI scores/classes (2.2), CRE weighted255 score (2.3), DSCR stress (2.4), concentration/capacity (2.5), benchmark variance (3),256 actions/dispositions (4). Use a small script for sums/ordering to avoid arithmetic slips.2576. Assemble the JSON to the template: correct keys, enums, list ordering, and per-field258 rounding (section 5). Drop nothing required; add nothing extra.2597. Self-check: every required key present? every enum value legal? lists ordered as260 specified? money 2dp / ratios 4dp / bps 2dp / dscr 2dp / weighted 1dp / metrics integer?261 ratios expressed as fractions not percents? priority_ranking excludes declines? Output262 pure JSON only.263264## 8. Worked patterns (transferable, no memorized answers)265266- Rating review: pop = loans with current_rating>=3; for each compute final_rating267 (max of dscr/ltv/delinquency factor ratings); build `final_rating_exposure_totals`268 (group whole pop by final_rating), `migration_from_current_rating_3` (group the269 current==3 subset by final_rating with loan_ids), `material_downgrades` (final-current>=2),270 npa_benchmark (noncurrent exposure / total loans vs FDIC total_loans_noncurrent_pct),271 top_problem_credit (worst final_rating, then largest exposure), watch_list_action_coverage272 (group post-regrade follow-up loans by recommended_action).273- Watch-list stress: pop = current_rating>=6; assign CDFI class+factor_score; +200bp stress274 (dscr/1.18, threshold 1.0) over DSCR-available loans; workout_queue ordered by exposure desc;275 severe_bucket_counts grouped by (current_rating, payment_status).276- CRE compare: weighted CDFI score per app (lower=better, class cutoffs 2.0/3.0); dual stress277 (dscr*0.85/1.18); existing CRE concentration = CRE-loan exposure / total loans vs278 cre_policy_limit_pct; selected post-approval concentration adds requested amount to both279 numerator and denominator; FDIC metric total_real_estate_30_89_pct, branch_delinquency_ratio280 from metric delinquency_30_plus_pct; pick the lower-score, non-breaching, less-concentrating281 credit; loser -> decline/defer with reason codes; winner path likely conditional_approve /282 participation_required when CRE already over limit, with conditions like283 `bank_retained_exposure_cap`, `committee_cre_exception`, `minimum_dscr_covenant_1_25`.284- Allocation: capacity = lending_capacity_q1; rank/approve apps within capacity; screen each285 for decline reasons (weak_dscr, high_ltv, low_fico, recent_bankruptcy, startup_risk,286 documentation_gap); concentration_flags where post-approval sector pct > limit_pct;287 post_approval_concentrations per sector; priority_ranking = approved+conditional only.288- Segment posture: NCUA state metrics (integers); peer median vs US directions; capacity from289 quarterly_capacity vs pipeline; controls from minimum_checklist + control_issue290 (insurance/lien gaps -> binder verification + lien perfection); escalation triggers w/ owners;291 interpretation (capacity_available + weaker external risk -> continue_with_tighter_conditions,292 committee_message capacity_available_but_external_risk_weaker).