Private Wealth Advisory — Structured Planning Skill
Environment
Base URL: use the GDPEVO_ENV_BASE_URL supplied by the harness (HTTP). All endpoints are under /api/ and use kebab-case naming. The API is a plain JSON REST service over HTTP; no authentication is required within the staging environment. Use curl or equivalent. Responses are JSON arrays or objects.
Endpoint Reference
| Endpoint |
Returns |
Use |
GET /api/clients |
Array of client objects |
Look up client by client_id |
GET /api/clients/{client_id} |
Single client object |
Verify or pull a specific client |
GET /api/retirement-accounts |
Array of IRA account objects |
Get traditional/Roth balances, expected return, RMD start age, recommended conversion years |
GET /api/rmd-factors |
Object mapping age→factor |
IRS Uniform Lifetime Table; divisor for RMD = balance / factor |
GET /api/life-insurance |
Array of policy objects |
Death benefit, annual premium, proposed owner, contribution date, existing-policy-transfer flag |
GET /api/trust-candidates |
Array of trust objects |
Asset value, growth rate, GRAT term/annuity rate, CRAT term/payout rate |
GET /api/source-documents |
Array of document objects |
CRM_NOTE, ATTORNEY_MEMO, SIGNED_PROFILE with facts payloads |
GET /api/policies/tax |
Tax constants object |
Gift exclusion, estate exemption, estate rate, conversion bracket targets, CRAT max term, charitable deduction rate |
No other endpoints exist. Query parameters are not supported. Client sub-resource paths return "error":"client not found" — always list the full collection and filter on client_id client-side.
Source Document Resolution (Critical for Every Task)
Every client has up to three source documents keyed by source_type:
| Source |
Typical Date |
Authority |
SIGNED_PROFILE |
2026-02-06 |
Highest — most recent, signed by client |
ATTORNEY_MEMO |
2026-01-18 |
Middle — attorney notes, may reflect stated intent |
CRM_NOTE |
2025-11-20 |
Lowest — stale CRM import, often conflicts |
Rule: When facts conflict across sources, the SIGNED_PROFILE always controls. Use the ATTORNEY_MEMO only when SIGNED_PROFILE omits a field. Never prefer CRM_NOTE values over SIGNED_PROFILE or ATTORNEY_MEMO values.
Key conflicts to expect:
beneficiary_count — CRM_NOTE often shows a different number than SIGNED_PROFILE
annual_non_ira_income — CRM_NOTE vs SIGNED_PROFILE can differ by $20K–$50K
philanthropic_intent and family_transfer_priority — CRM_NOTE often shows "moderate" while SIGNED_PROFILE shows "high" / "low" pairings
marginal_tax_rate — only present in SIGNED_PROFILE
estate_value — ATTORNEY_MEMO and SIGNED_PROFILE should agree; CRM_NOTE lacks this field
For source_resolution fields:
- The controlling profile source is
SIGNED_PROFILE whenever it provides the deciding fact values.
- The controlling account source is always
CUSTODIAN_EXPORT (retirement account data).
- The controlling beneficiary source is
SIGNED_PROFILE (it has the beneficiary_count).
- The controlling policy source is
SIGNED_PROFILE by default (life insurance keyed by client, not from documents).
- The controlling goal source is
SIGNED_PROFILE (has philanthropic_intent and family_transfer_priority).
- The controlling asset source is
ATTORNEY_MEMO (estate_value used for trust asset sizing).
Note: The enum STALE_MARKETING_INTAKE is defined but CRM_NOTE is almost never the controlling source.
Tax Policy Constants (GET /api/policies/tax)
These are the advisory-internal 2026 planning constants:
annual_gift_exclusion.2026 = $20,000
estate_tax_exemption.2026 = $13,610,000
estate_tax_rate = 0.40
conversion_bracket_targets.MFJ = $394,600
conversion_bracket_targets.SINGLE = $197,300
conversion_bracket_targets.HOH = $263,500
max_crat_term_years = 20
charitable_deduction_rate = 0.35
How to Use Each Constant
- Annual gift exclusion: Multiply by beneficiary count to get
annual_exclusion_capacity. Compare with annual_premium to compute premium_gap.
- Estate tax exemption: Subtract from
estate_value to get taxable estate; multiply by 40% for estate_tax_exposure.
- Conversion bracket targets: These are the top-line ceiling (gross income before deduction) used to determine how much Roth conversion fits within the client's current marginal bracket. Convert up to this ceiling, not beyond it.
- Max CRAT term: CRATs are capped at 20 years. Use the
crat_term_years from trust-candidates if ≤ 20, otherwise cap at 20.
- Charitable deduction rate: Used for CRAT income-tax deduction estimate:
crat.projected_charitable_remainder × charitable_deduction_rate.
Income Tax Brackets (Standard 2026)
The API provides bracket ceiling targets, but full 2026 marginal brackets are standardized:
| Rate |
MFJ |
SINGLE |
| 10% |
$0–$23,200 |
$0–$11,600 |
| 12% |
$23,201–$94,300 |
$11,601–$47,150 |
| 22% |
$94,301–$201,050 |
$47,151–$100,525 |
| 24% |
$201,051–$394,600 |
$100,526–$197,300 |
| 32% |
$394,601–$501,050 |
$197,301–$250,525 |
| 35% |
$501,051–$751,600 |
$250,526–$626,350 |
| 37% |
$751,601+ |
$626,351+ |
The conversion_bracket_targets values correspond to the top of 24% bracket. Use the client's marginal_tax_rate from SIGNED_PROFILE as the rate applied to conversion amounts.
Analysis Type 1: Roth Conversion + RMD (roth_conversion_rmd)
Tasks: Mercer (train_001), Patel (train_005). Horizon is provided in the request memo.
Key Data Sources
- Client record:
age, filing_status, liquid_assets
- Retirement account:
traditional_balance, roth_balance, expected_return, rmd_start_age, recommended_conversion_years
- RMD factors: mapping age→divisor
- SIGNED_PROFILE:
annual_non_ira_income, marginal_tax_rate, beneficiary_count
- Tax policy:
conversion_bracket_targets for the filing status
Conversion Plan Calculation
first_conversion_year = planning_year (2026) — conversions begin immediately.
conversion_years = recommended_conversion_years from the retirement account (integer from the CUSTODIAN_EXPORT). This is the number of years to stage the conversion.
conversion_years_positive = same as conversion_years — it is the positive (non-zero) count of conversion years. Set it equal to conversion_years.
annual_conversion_amount = fill-up-to-ceiling logic:
Determine remaining room in the target bracket:
room = conversion_bracket_target - annual_non_ira_income
annual_conversion_amount = min(traditional_balance / conversion_years, room)
Cap at zero if no room (income already above target).
For near-RMD clients (age ≥ 72): if traditional_balance can be fully converted within the bracket room over the available years before RMDs start, use that amount. Otherwise, convert up to the bracket ceiling each year.
total_converted = annual_conversion_amount × conversion_years (capped at traditional_balance).
total_conversion_tax = total_converted × marginal_tax_rate.
RMD Projection
first_rmd_year = planning_year + (rmd_start_age - age). RMD start age is always 73 in this environment.
horizon_year = from memo (e.g., 2046, 2042).
Baseline (no conversion):
- Grow
traditional_balance at expected_return each year.
- From
first_rmd_year through horizon_year: RMD = balance / rmd_factor_for_age, taxed at marginal_tax_rate.
baseline_rmd_tax_through_horizon = sum of all RMD taxes over the RMD window.
Conversion scenario:
- Subtract converted amounts during conversion years. Grow remaining traditional balance.
- Grow Roth balance (starting + converted) at
expected_return.
- From
first_rmd_year through horizon_year: RMD on remaining traditional only.
conversion_rmd_tax_through_horizon = sum of reduced RMD taxes.
rmd_tax_savings_through_horizon = baseline − conversion (always non-negative if conversion makes sense).
rmd_tax_savings_through_horizon = baseline_rmd_tax_through_horizon - conversion_rmd_tax_through_horizon.
Legacy Projection
projected_roth_balance_horizon = Roth balance at horizon after growing at expected_return for horizon−planning_year years.
projected_traditional_balance_horizon = Remaining traditional balance at horizon after conversions and RMDs.
heir_tax_profile:
MOSTLY_TAX_FREE if projected Roth > 67% of total IRA assets
MOSTLY_TAXABLE if projected traditional > 67%
MIXED_TAXABLE_AND_TAX_FREE otherwise
Recommendation Logic
primary_action: STAGED_ROTH_CONVERSION if rmd_tax_savings_through_horizon > 0 and annual_conversion_amount > 0. DEFER if RMDs start within 2 years and bracket room is minimal. NO_CONVERSION if age already past RMD start or no tax savings.
suitability: SUITABLE when clear savings and adequate liquid assets. BORDERLINE when RMD near-term or small savings. DEFER when no meaningful benefit.
risk_flag: TAX_BRACKET_MANAGEMENT (standard cases), RMD_NEAR_TERM (age ≥ 71), LIQUIDITY_CONSTRAINT (conversion tax > liquid_assets).
Analysis Type 2: ILIT Crummey (ilit_crummey_implementation)
Task: Keating (train_002).
Key Data Sources
- Client: age, filing_status, liquid_assets, estate_value
- Life insurance: death_benefit, annual_premium, planned_contribution_date, is_existing_policy_transfer
- SIGNED_PROFILE: beneficiary_count, marginal_tax_rate
- Tax policy: annual_gift_exclusion.2026
Gift Plan Calculations
planning_year = 2026 (from client record).
annual_exclusion_per_beneficiary = annual_gift_exclusion.2026 = $20,000.
beneficiary_count = from SIGNED_PROFILE (not CRM_NOTE).
annual_exclusion_capacity = beneficiary_count × annual_exclusion_per_beneficiary.
annual_premium = from life insurance policy.
premium_gap = annual_premium - annual_exclusion_capacity. If positive, the premium exceeds the exclusion capacity.
Administration Dates
All derived from planned_contribution_date:
contribution_date = planned_contribution_date (from life insurance record).
notice_due_date = contribution_date + 30 days (Crummey notice must be sent within 30 days of contribution).
withdrawal_window_end = notice_due_date + 30 days (beneficiaries have 30 days from notice to exercise withdrawal rights).
earliest_premium_payment_date = withdrawal_window_end + 1 day (premium can be paid only after withdrawal window closes).
notices_required = beneficiary_count (one Crummey notice per beneficiary).
dedicated_bank_account_required = true (best practice for ILIT administration).
Estate Result
death_benefit = from life insurance policy.
estate_inclusion_risk:
LOW_IF_FORMALITIES_MET when premium_gap ≤ 0 and is_existing_policy_transfer = false
EXCLUSION_SHORTFALL when premium_gap > 0
THREE_YEAR_LOOKBACK when is_existing_policy_transfer = true
THREE_YEAR_LOOKBACK_AND_EXCLUSION_SHORTFALL when both conditions hold
projected_outside_estate_if_implemented = death_benefit (if properly structured, ILIT keeps death benefit outside taxable estate).
tax_liquidity_support = death_benefit - (estate_value - estate_tax_exemption.2026) × estate_tax_rate. Represents how much of the death benefit would cover estate tax. Floor at 0.
Recommendation Logic
FUND_WITH_CRUMMEY_NOTICES when premium_gap ≤ 0 and no lookback — standard Crummey path.
USE_LIFETIME_EXEMPTION_FOR_SHORTFALL when premium_gap > 0 — gap exceeds exclusion capacity.
USE_NEW_POLICY_OR_ACCEPT_LOOKBACK when is_existing_policy_transfer = true — three-year lookback issue.
DISCLOSE_LOOKBACK_AND_USE_EXEMPTION when both lookback AND shortfall.
Analysis Type 3: GRAT vs CRAT (trust_comparison)
Task: Alvarez (train_003).
Key Data Sources
- Client: estate_value, liquid_assets, filing_status
- Trust candidate: asset_value, expected_growth_rate, grat_term_years, grat_annuity_rate, crat_term_years, crat_payout_rate
- SIGNED_PROFILE: philanthropic_intent, family_transfer_priority, marginal_tax_rate
- Tax policy: estate_tax_exemption, estate_tax_rate, charitable_deduction_rate, max_crat_term_years
Estate Context
taxable_estate = estate_value (total gross estate for this analysis).
estate_tax_exposure = max(0, (estate_value - estate_tax_exemption.2026) × estate_tax_rate).
liquidity_gap_before_planning = max(0, estate_tax_exposure - liquid_assets).
GRAT Analysis
term_years = grat_term_years from trust candidate.
projected_remainder_to_heirs: GRAT remainder calculation:
- The grantor receives annuity payments =
asset_value × grat_annuity_rate for grat_term_years.
- Assets grow at
expected_growth_rate inside the GRAT.
- Remainder = final asset value after annuity payments minus the "hurdle" (return of the §7520-rate-adjusted present value). In the simplified model:
asset_value × (1 + expected_growth_rate)^grat_term_years - (annuity_payments accumulated at the hurdle rate).
Simplified approximation: asset_value × ((1 + expected_growth_rate)^grat_term_years - 1) × (expected_growth_rate - grat_annuity_rate) / expected_growth_rate. When expected_growth_rate > grat_annuity_rate, there is a positive remainder.
A more direct model: growth exceeds annuity rate → remainder exists. Compute as:
future_value = asset_value × (1 + expected_growth_rate)^grat_term_years
total_annuity = asset_value × grat_annuity_rate × grat_term_years
remainder = max(0, future_value - total_annuity)
estimated_estate_tax_reduction = remainder × estate_tax_rate (the portion of the remainder that would have been taxed at 40%).
mortality_inclusion_risk = TERM_SURVIVAL_REQUIRED (always; GRAT requires grantor survival through term for tax benefit).
CRAT Analysis
Recommendation Logic
preferred_strategy: GRAT when family_transfer_priority = "high". CRAT when philanthropic_intent = "high" AND family_transfer_priority ≠ "high".
rationale_code: CHILDREN_TRANSFER_PRIORITY when GRAT chosen. PHILANTHROPIC_PRIORITY when CRAT chosen.
alternate_role: SECONDARY_CHARITABLE_TOOL (when GRAT preferred — CRAT as backup for charity). SECONDARY_FAMILY_TRANSFER_TOOL (when CRAT preferred — GRAT as backup for family).
Analysis Type 4: Estate Liquidity Action Plan (estate_liquidity_action_plan)
Task: Chen (train_004). Combines ILIT analysis + trust comparison into an integrated plan.
Key Data Sources
- Client: estate_value, liquid_assets, filing_status, age
- Life insurance: death_benefit, annual_premium, planned_contribution_date, is_existing_policy_transfer
- Trust candidate: asset_value, expected_growth_rate, grat_term_years, grat_annuity_rate
- SIGNED_PROFILE: beneficiary_count, philanthropic_intent, family_transfer_priority, annual_non_ira_income
Estate Context (same as trust_comparison)
taxable_estate = estate_value
estate_tax_exposure = max(0, (estate_value − estate_tax_exemption.2026) × 0.40)
liquidity_gap_before_planning = max(0, estate_tax_exposure − liquid_assets)
ILIT Section (same as ilit_crummey_implementation)
Same calculations. Note that annual_exclusion_capacity uses beneficiary_count from SIGNED_PROFILE.
Trust Transfer Section
preferred_strategy: GRAT when family_transfer_priority = "high". CRAT otherwise.
projected_remainder_to_heirs: GRAT remainder calculation (same as trust_comparison).
estimated_estate_tax_reduction: projected_remainder_to_heirs × 0.40.
projected_charitable_remainder: CRAT charitable remainder (same as trust_comparison). If GRAT preferred, this is the fallback scenario value.
Action Set
Choose from: ATTORNEY_DRAFT_REVIEW, CRAT_FOR_CHARITABLE_REMAINDER, GRAT_FOR_APPRECIATING_SHARES, ILIT_CRUMMEY_NOTICE_CYCLE, LIFETIME_EXEMPTION_ALLOCATION.
ILIT_CRUMMEY_NOTICE_CYCLE — always included when there's a life insurance policy.
GRAT_FOR_APPRECIATING_SHARES — included when GRAT is preferred strategy.
CRAT_FOR_CHARITABLE_REMAINDER — included when CRAT is preferred strategy OR as secondary tool.
LIFETIME_EXEMPTION_ALLOCATION — included when premium_gap > 0.
ATTORNEY_DRAFT_REVIEW — always included (drafting required for any trust strategy).
Must be sorted alphabetically in the output array.
Recommendation
primary_action: COMBINE_ILIT_AND_GRAT when both ILIT and GRAT applicable; CRAT_WITH_LIQUIDITY_REVIEW when CRAT preferred; ILIT_WITH_EXEMPTION_REVIEW when premium gap necessitates exemption.
sequencing: ILIT_FIRST_THEN_GRAT (standard order — ILIT first for estate tax liquidity, then GRAT for wealth transfer). TRUST_DECISION_FIRST when CRAT is preferred. ILIT_FIRST_THEN_ATTORNEY_REVIEW when only ILIT applies.
risk_flag: same logic as ILIT Crummey task.
General Conventions
Monetary Values
- All USD amounts must be JSON numbers (not strings), rounded to cents (2 decimal places).
- Use 2 decimal places consistently even for whole-dollar amounts (e.g.,
20000.00 not 20000).
Dates
- All dates must be ISO 8601
YYYY-MM-DD format as strings.
- Planning year is always 2026.
Enums
- Use exact enum values as specified in each answer template. Do not invent new values.
- Multiple-choice fields: copy the enum string exactly, including underscores and capitalization.
Task ID
- Set
task_id to the exact task identifier (e.g., train_001, test_001).
- Set
client_id to the client ID from the engagement memo (e.g., CLT-1001).
Output Format
- Return only a JSON object. No markdown fences, no prose.
- The JSON must include all
required_top_level_keys from the answer template.
- Nested keys use dot-notation in the template (e.g.,
recommendation.primary_action means {"recommendation": {"primary_action": "..."}}).
Data Filtering Pattern
- Always fetch the full collection endpoint, then filter client-side by
client_id.
- Do NOT try nested paths like
/api/clients/{id}/accounts — they return errors.
- When filtering, match
client_id exactly (case-sensitive, e.g., CLT-1001).
Common Pitfalls
- Using CRM_NOTE values over SIGNED_PROFILE: Always prefer SIGNED_PROFILE. CRM_NOTE is stale.
- Wrong beneficiary count: CRM_NOTE often disagrees with SIGNED_PROFILE. Use SIGNED_PROFILE.
- Forgetting to cap conversion amount at bracket ceiling: Converting above the ceiling pushes income into a higher bracket, eroding tax savings.
- RMD factor lookup: Use the client's age at each projection year, not current age. RMD = balance at end of prior year / factor for age in distribution year.
- Estate tax exposure floor at zero:
max(0, ...) — negative exposure means no estate tax.
- CRAT term cap: Always cap CRAT term at 20 years regardless of trust-candidate data.
- action_set ordering: Must be alphabetically sorted for
estate_liquidity_action_plan.
conversion_years_positive vs conversion_years: They are typically the same value — both equal to recommended_conversion_years. Do not set one to zero.
- Premium gap sign: Positive means shortfall (premium > exclusion capacity). This drives ILIT risk flags.
- Date arithmetic: Crummey dates cascade: contribution → +30d notice → +30d withdrawal → +1d premium payment.
1---2name: self-attempt-02-493description: Private Wealth Advisory — Structured Planning Skill4---5# Private Wealth Advisory — Structured Planning Skill67## Environment89Base URL: use the `GDPEVO_ENV_BASE_URL` supplied by the harness (HTTP). All endpoints are under `/api/` and use kebab-case naming. The API is a plain JSON REST service over HTTP; no authentication is required within the staging environment. Use `curl` or equivalent. Responses are JSON arrays or objects.1011### Endpoint Reference1213| Endpoint | Returns | Use |14|---|---|---|15| `GET /api/clients` | Array of client objects | Look up client by `client_id` |16| `GET /api/clients/{client_id}` | Single client object | Verify or pull a specific client |17| `GET /api/retirement-accounts` | Array of IRA account objects | Get traditional/Roth balances, expected return, RMD start age, recommended conversion years |18| `GET /api/rmd-factors` | Object mapping age→factor | IRS Uniform Lifetime Table; divisor for RMD = balance / factor |19| `GET /api/life-insurance` | Array of policy objects | Death benefit, annual premium, proposed owner, contribution date, existing-policy-transfer flag |20| `GET /api/trust-candidates` | Array of trust objects | Asset value, growth rate, GRAT term/annuity rate, CRAT term/payout rate |21| `GET /api/source-documents` | Array of document objects | CRM_NOTE, ATTORNEY_MEMO, SIGNED_PROFILE with `facts` payloads |22| `GET /api/policies/tax` | Tax constants object | Gift exclusion, estate exemption, estate rate, conversion bracket targets, CRAT max term, charitable deduction rate |2324No other endpoints exist. Query parameters are not supported. Client sub-resource paths return `"error":"client not found"` — always list the full collection and filter on `client_id` client-side.2526---2728## Source Document Resolution (Critical for Every Task)2930Every client has up to three source documents keyed by `source_type`:3132| Source | Typical Date | Authority |33|---|---|---|34| `SIGNED_PROFILE` | 2026-02-06 | **Highest** — most recent, signed by client |35| `ATTORNEY_MEMO` | 2026-01-18 | Middle — attorney notes, may reflect stated intent |36| `CRM_NOTE` | 2025-11-20 | **Lowest** — stale CRM import, often conflicts |3738**Rule**: When facts conflict across sources, the SIGNED_PROFILE always controls. Use the ATTORNEY_MEMO only when SIGNED_PROFILE omits a field. Never prefer CRM_NOTE values over SIGNED_PROFILE or ATTORNEY_MEMO values.3940Key conflicts to expect:41- `beneficiary_count` — CRM_NOTE often shows a different number than SIGNED_PROFILE42- `annual_non_ira_income` — CRM_NOTE vs SIGNED_PROFILE can differ by $20K–$50K43- `philanthropic_intent` and `family_transfer_priority` — CRM_NOTE often shows "moderate" while SIGNED_PROFILE shows "high" / "low" pairings44- `marginal_tax_rate` — only present in SIGNED_PROFILE45- `estate_value` — ATTORNEY_MEMO and SIGNED_PROFILE should agree; CRM_NOTE lacks this field4647For `source_resolution` fields:48- The **controlling profile source** is `SIGNED_PROFILE` whenever it provides the deciding fact values.49- The **controlling account source** is always `CUSTODIAN_EXPORT` (retirement account data).50- The **controlling beneficiary source** is `SIGNED_PROFILE` (it has the beneficiary_count).51- The **controlling policy source** is `SIGNED_PROFILE` by default (life insurance keyed by client, not from documents).52- The **controlling goal source** is `SIGNED_PROFILE` (has philanthropic_intent and family_transfer_priority).53- The **controlling asset source** is `ATTORNEY_MEMO` (estate_value used for trust asset sizing).5455Note: The enum `STALE_MARKETING_INTAKE` is defined but CRM_NOTE is almost never the controlling source.5657---5859## Tax Policy Constants (`GET /api/policies/tax`)6061These are the advisory-internal 2026 planning constants:6263```64annual_gift_exclusion.2026 = $20,00065estate_tax_exemption.2026 = $13,610,00066estate_tax_rate = 0.4067conversion_bracket_targets.MFJ = $394,60068conversion_bracket_targets.SINGLE = $197,30069conversion_bracket_targets.HOH = $263,50070max_crat_term_years = 2071charitable_deduction_rate = 0.3572```7374### How to Use Each Constant7576- **Annual gift exclusion**: Multiply by beneficiary count to get `annual_exclusion_capacity`. Compare with `annual_premium` to compute `premium_gap`.77- **Estate tax exemption**: Subtract from `estate_value` to get taxable estate; multiply by 40% for `estate_tax_exposure`.78- **Conversion bracket targets**: These are the **top-line ceiling** (gross income before deduction) used to determine how much Roth conversion fits within the client's current marginal bracket. Convert up to this ceiling, not beyond it.79- **Max CRAT term**: CRATs are capped at 20 years. Use the `crat_term_years` from trust-candidates if ≤ 20, otherwise cap at 20.80- **Charitable deduction rate**: Used for CRAT income-tax deduction estimate: `crat.projected_charitable_remainder × charitable_deduction_rate`.8182### Income Tax Brackets (Standard 2026)8384The API provides bracket **ceiling** targets, but full 2026 marginal brackets are standardized:8586| Rate | MFJ | SINGLE |87|---|---|---|88| 10% | $0–$23,200 | $0–$11,600 |89| 12% | $23,201–$94,300 | $11,601–$47,150 |90| 22% | $94,301–$201,050 | $47,151–$100,525 |91| 24% | $201,051–$394,600 | $100,526–$197,300 |92| 32% | $394,601–$501,050 | $197,301–$250,525 |93| 35% | $501,051–$751,600 | $250,526–$626,350 |94| 37% | $751,601+ | $626,351+ |9596The `conversion_bracket_targets` values correspond to the **top of 24%** bracket. Use the client's `marginal_tax_rate` from SIGNED_PROFILE as the rate applied to conversion amounts.9798---99100## Analysis Type 1: Roth Conversion + RMD (`roth_conversion_rmd`)101102Tasks: Mercer (train_001), Patel (train_005). Horizon is provided in the request memo.103104### Key Data Sources105- Client record: `age`, `filing_status`, `liquid_assets`106- Retirement account: `traditional_balance`, `roth_balance`, `expected_return`, `rmd_start_age`, `recommended_conversion_years`107- RMD factors: mapping age→divisor108- SIGNED_PROFILE: `annual_non_ira_income`, `marginal_tax_rate`, `beneficiary_count`109- Tax policy: `conversion_bracket_targets` for the filing status110111### Conversion Plan Calculation1121131. **`first_conversion_year`** = `planning_year` (2026) — conversions begin immediately.1142. **`conversion_years`** = `recommended_conversion_years` from the retirement account (integer from the CUSTODIAN_EXPORT). This is the number of years to stage the conversion.1153. **`conversion_years_positive`** = same as `conversion_years` — it is the positive (non-zero) count of conversion years. Set it equal to `conversion_years`.1164. **`annual_conversion_amount`** = fill-up-to-ceiling logic:117118 Determine remaining room in the target bracket:119 ```120 room = conversion_bracket_target - annual_non_ira_income121 annual_conversion_amount = min(traditional_balance / conversion_years, room)122 ```123 Cap at zero if no room (income already above target).124125 For near-RMD clients (age ≥ 72): if `traditional_balance` can be fully converted within the bracket room over the available years before RMDs start, use that amount. Otherwise, convert up to the bracket ceiling each year.1261275. **`total_converted`** = `annual_conversion_amount × conversion_years` (capped at `traditional_balance`).1286. **`total_conversion_tax`** = `total_converted × marginal_tax_rate`.129130### RMD Projection1311321. **`first_rmd_year`** = `planning_year + (rmd_start_age - age)`. RMD start age is always 73 in this environment.1332. **`horizon_year`** = from memo (e.g., 2046, 2042).134135Baseline (no conversion):136- Grow `traditional_balance` at `expected_return` each year.137- From `first_rmd_year` through `horizon_year`: RMD = balance / rmd_factor_for_age, taxed at `marginal_tax_rate`.138- `baseline_rmd_tax_through_horizon` = sum of all RMD taxes over the RMD window.139140Conversion scenario:141- Subtract converted amounts during conversion years. Grow remaining traditional balance.142- Grow Roth balance (starting + converted) at `expected_return`.143- From `first_rmd_year` through `horizon_year`: RMD on remaining traditional only.144- `conversion_rmd_tax_through_horizon` = sum of reduced RMD taxes.145- `rmd_tax_savings_through_horizon` = baseline − conversion (always non-negative if conversion makes sense).1461473. **`rmd_tax_savings_through_horizon`** = `baseline_rmd_tax_through_horizon - conversion_rmd_tax_through_horizon`.148149### Legacy Projection150151- `projected_roth_balance_horizon` = Roth balance at horizon after growing at `expected_return` for horizon−planning_year years.152- `projected_traditional_balance_horizon` = Remaining traditional balance at horizon after conversions and RMDs.153- `heir_tax_profile`:154 - `MOSTLY_TAX_FREE` if projected Roth > 67% of total IRA assets155 - `MOSTLY_TAXABLE` if projected traditional > 67%156 - `MIXED_TAXABLE_AND_TAX_FREE` otherwise157158### Recommendation Logic159160- **`primary_action`**: `STAGED_ROTH_CONVERSION` if `rmd_tax_savings_through_horizon > 0` and `annual_conversion_amount > 0`. `DEFER` if RMDs start within 2 years and bracket room is minimal. `NO_CONVERSION` if age already past RMD start or no tax savings.161- **`suitability`**: `SUITABLE` when clear savings and adequate liquid assets. `BORDERLINE` when RMD near-term or small savings. `DEFER` when no meaningful benefit.162- **`risk_flag`**: `TAX_BRACKET_MANAGEMENT` (standard cases), `RMD_NEAR_TERM` (age ≥ 71), `LIQUIDITY_CONSTRAINT` (conversion tax > liquid_assets).163164---165166## Analysis Type 2: ILIT Crummey (`ilit_crummey_implementation`)167168Task: Keating (train_002).169170### Key Data Sources171- Client: age, filing_status, liquid_assets, estate_value172- Life insurance: death_benefit, annual_premium, planned_contribution_date, is_existing_policy_transfer173- SIGNED_PROFILE: beneficiary_count, marginal_tax_rate174- Tax policy: annual_gift_exclusion.2026175176### Gift Plan Calculations1771781. **`planning_year`** = 2026 (from client record).1792. **`annual_exclusion_per_beneficiary`** = `annual_gift_exclusion.2026` = $20,000.1803. **`beneficiary_count`** = from SIGNED_PROFILE (not CRM_NOTE).1814. **`annual_exclusion_capacity`** = `beneficiary_count × annual_exclusion_per_beneficiary`.1825. **`annual_premium`** = from life insurance policy.1836. **`premium_gap`** = `annual_premium - annual_exclusion_capacity`. If positive, the premium exceeds the exclusion capacity.184185### Administration Dates186187All derived from `planned_contribution_date`:188- **`contribution_date`** = `planned_contribution_date` (from life insurance record).189- **`notice_due_date`** = `contribution_date + 30 days` (Crummey notice must be sent within 30 days of contribution).190- **`withdrawal_window_end`** = `notice_due_date + 30 days` (beneficiaries have 30 days from notice to exercise withdrawal rights).191- **`earliest_premium_payment_date`** = `withdrawal_window_end + 1 day` (premium can be paid only after withdrawal window closes).192- **`notices_required`** = `beneficiary_count` (one Crummey notice per beneficiary).193- **`dedicated_bank_account_required`** = `true` (best practice for ILIT administration).194195### Estate Result196197- **`death_benefit`** = from life insurance policy.198- **`estate_inclusion_risk`**:199 - `LOW_IF_FORMALITIES_MET` when `premium_gap ≤ 0` and `is_existing_policy_transfer = false`200 - `EXCLUSION_SHORTFALL` when `premium_gap > 0`201 - `THREE_YEAR_LOOKBACK` when `is_existing_policy_transfer = true`202 - `THREE_YEAR_LOOKBACK_AND_EXCLUSION_SHORTFALL` when both conditions hold203- **`projected_outside_estate_if_implemented`** = `death_benefit` (if properly structured, ILIT keeps death benefit outside taxable estate).204- **`tax_liquidity_support`** = `death_benefit - (estate_value - estate_tax_exemption.2026) × estate_tax_rate`. Represents how much of the death benefit would cover estate tax. Floor at 0.205206### Recommendation Logic207208- `FUND_WITH_CRUMMEY_NOTICES` when `premium_gap ≤ 0` and no lookback — standard Crummey path.209- `USE_LIFETIME_EXEMPTION_FOR_SHORTFALL` when `premium_gap > 0` — gap exceeds exclusion capacity.210- `USE_NEW_POLICY_OR_ACCEPT_LOOKBACK` when `is_existing_policy_transfer = true` — three-year lookback issue.211- `DISCLOSE_LOOKBACK_AND_USE_EXEMPTION` when both lookback AND shortfall.212213---214215## Analysis Type 3: GRAT vs CRAT (`trust_comparison`)216217Task: Alvarez (train_003).218219### Key Data Sources220- Client: estate_value, liquid_assets, filing_status221- Trust candidate: asset_value, expected_growth_rate, grat_term_years, grat_annuity_rate, crat_term_years, crat_payout_rate222- SIGNED_PROFILE: philanthropic_intent, family_transfer_priority, marginal_tax_rate223- Tax policy: estate_tax_exemption, estate_tax_rate, charitable_deduction_rate, max_crat_term_years224225### Estate Context2262271. **`taxable_estate`** = `estate_value` (total gross estate for this analysis).2282. **`estate_tax_exposure`** = `max(0, (estate_value - estate_tax_exemption.2026) × estate_tax_rate)`.2293. **`liquidity_gap_before_planning`** = `max(0, estate_tax_exposure - liquid_assets)`.230231### GRAT Analysis232233- **`term_years`** = `grat_term_years` from trust candidate.234- **`projected_remainder_to_heirs`**: GRAT remainder calculation:235 - The grantor receives annuity payments = `asset_value × grat_annuity_rate` for `grat_term_years`.236 - Assets grow at `expected_growth_rate` inside the GRAT.237 - Remainder = final asset value after annuity payments minus the "hurdle" (return of the §7520-rate-adjusted present value). In the simplified model: `asset_value × (1 + expected_growth_rate)^grat_term_years - (annuity_payments accumulated at the hurdle rate)`.238 239 Simplified approximation: `asset_value × ((1 + expected_growth_rate)^grat_term_years - 1) × (expected_growth_rate - grat_annuity_rate) / expected_growth_rate`. When `expected_growth_rate > grat_annuity_rate`, there is a positive remainder.240 241 A more direct model: growth exceeds annuity rate → remainder exists. Compute as:242 ```243 future_value = asset_value × (1 + expected_growth_rate)^grat_term_years244 total_annuity = asset_value × grat_annuity_rate × grat_term_years245 remainder = max(0, future_value - total_annuity)246 ```247- **`estimated_estate_tax_reduction`** = `remainder × estate_tax_rate` (the portion of the remainder that would have been taxed at 40%).248- **`mortality_inclusion_risk`** = `TERM_SURVIVAL_REQUIRED` (always; GRAT requires grantor survival through term for tax benefit).249250### CRAT Analysis251252- **`term_years`** = `min(crat_term_years, max_crat_term_years)` — cap at 20 years.253- **`projected_charitable_remainder`**: 254 ```255 future_value = asset_value × (1 + expected_growth_rate)^crat_term_years256 annual_payout = asset_value × crat_payout_rate257 total_payouts = annual_payout × crat_term_years258 charitable_remainder = max(0, future_value - total_payouts)259 ```260- **`estimated_income_tax_deduction`** = `projected_charitable_remainder × charitable_deduction_rate`. This is the present value of the charitable remainder interest deduction.261- **`family_transfer_fit`**: `LOW` by default (CRAT primarily benefits charity). `MODERATE` if `philanthropic_intent = "high"`. `HIGH` only if both charitable and family priorities are strong.262263### Recommendation Logic264265- **`preferred_strategy`**: `GRAT` when `family_transfer_priority = "high"`. `CRAT` when `philanthropic_intent = "high"` AND `family_transfer_priority ≠ "high"`.266- **`rationale_code`**: `CHILDREN_TRANSFER_PRIORITY` when GRAT chosen. `PHILANTHROPIC_PRIORITY` when CRAT chosen.267- **`alternate_role`**: `SECONDARY_CHARITABLE_TOOL` (when GRAT preferred — CRAT as backup for charity). `SECONDARY_FAMILY_TRANSFER_TOOL` (when CRAT preferred — GRAT as backup for family).268269---270271## Analysis Type 4: Estate Liquidity Action Plan (`estate_liquidity_action_plan`)272273Task: Chen (train_004). Combines ILIT analysis + trust comparison into an integrated plan.274275### Key Data Sources276- Client: estate_value, liquid_assets, filing_status, age277- Life insurance: death_benefit, annual_premium, planned_contribution_date, is_existing_policy_transfer278- Trust candidate: asset_value, expected_growth_rate, grat_term_years, grat_annuity_rate279- SIGNED_PROFILE: beneficiary_count, philanthropic_intent, family_transfer_priority, annual_non_ira_income280281### Estate Context (same as trust_comparison)2822831. `taxable_estate` = estate_value2842. `estate_tax_exposure` = max(0, (estate_value − estate_tax_exemption.2026) × 0.40)2853. `liquidity_gap_before_planning` = max(0, estate_tax_exposure − liquid_assets)286287### ILIT Section (same as ilit_crummey_implementation)288289Same calculations. Note that `annual_exclusion_capacity` uses beneficiary_count from SIGNED_PROFILE.290291### Trust Transfer Section292293- `preferred_strategy`: `GRAT` when `family_transfer_priority = "high"`. `CRAT` otherwise.294- `projected_remainder_to_heirs`: GRAT remainder calculation (same as trust_comparison).295- `estimated_estate_tax_reduction`: `projected_remainder_to_heirs × 0.40`.296- `projected_charitable_remainder`: CRAT charitable remainder (same as trust_comparison). If GRAT preferred, this is the fallback scenario value.297298### Action Set299300Choose from: `ATTORNEY_DRAFT_REVIEW`, `CRAT_FOR_CHARITABLE_REMAINDER`, `GRAT_FOR_APPRECIATING_SHARES`, `ILIT_CRUMMEY_NOTICE_CYCLE`, `LIFETIME_EXEMPTION_ALLOCATION`.301302- `ILIT_CRUMMEY_NOTICE_CYCLE` — always included when there's a life insurance policy.303- `GRAT_FOR_APPRECIATING_SHARES` — included when GRAT is preferred strategy.304- `CRAT_FOR_CHARITABLE_REMAINDER` — included when CRAT is preferred strategy OR as secondary tool.305- `LIFETIME_EXEMPTION_ALLOCATION` — included when premium_gap > 0.306- `ATTORNEY_DRAFT_REVIEW` — always included (drafting required for any trust strategy).307308**Must be sorted alphabetically** in the output array.309310### Recommendation311312- `primary_action`: `COMBINE_ILIT_AND_GRAT` when both ILIT and GRAT applicable; `CRAT_WITH_LIQUIDITY_REVIEW` when CRAT preferred; `ILIT_WITH_EXEMPTION_REVIEW` when premium gap necessitates exemption.313- `sequencing`: `ILIT_FIRST_THEN_GRAT` (standard order — ILIT first for estate tax liquidity, then GRAT for wealth transfer). `TRUST_DECISION_FIRST` when CRAT is preferred. `ILIT_FIRST_THEN_ATTORNEY_REVIEW` when only ILIT applies.314- `risk_flag`: same logic as ILIT Crummey task.315316---317318## General Conventions319320### Monetary Values321- All USD amounts must be JSON numbers (not strings), rounded to cents (2 decimal places).322- Use 2 decimal places consistently even for whole-dollar amounts (e.g., `20000.00` not `20000`).323324### Dates325- All dates must be ISO 8601 `YYYY-MM-DD` format as strings.326- Planning year is always 2026.327328### Enums329- Use exact enum values as specified in each answer template. Do not invent new values.330- Multiple-choice fields: copy the enum string exactly, including underscores and capitalization.331332### Task ID333- Set `task_id` to the exact task identifier (e.g., `train_001`, `test_001`).334- Set `client_id` to the client ID from the engagement memo (e.g., `CLT-1001`).335336### Output Format337- Return **only** a JSON object. No markdown fences, no prose.338- The JSON must include all `required_top_level_keys` from the answer template.339- Nested keys use dot-notation in the template (e.g., `recommendation.primary_action` means `{"recommendation": {"primary_action": "..."}}`).340341### Data Filtering Pattern342- Always fetch the full collection endpoint, then filter client-side by `client_id`.343- Do NOT try nested paths like `/api/clients/{id}/accounts` — they return errors.344- When filtering, match `client_id` exactly (case-sensitive, e.g., `CLT-1001`).345346### Common Pitfalls3471. **Using CRM_NOTE values over SIGNED_PROFILE**: Always prefer SIGNED_PROFILE. CRM_NOTE is stale.3482. **Wrong beneficiary count**: CRM_NOTE often disagrees with SIGNED_PROFILE. Use SIGNED_PROFILE.3493. **Forgetting to cap conversion amount at bracket ceiling**: Converting above the ceiling pushes income into a higher bracket, eroding tax savings.3504. **RMD factor lookup**: Use the client's age at each projection year, not current age. RMD = balance at end of prior year / factor for age in distribution year.3515. **Estate tax exposure floor at zero**: `max(0, ...)` — negative exposure means no estate tax.3526. **CRAT term cap**: Always cap CRAT term at 20 years regardless of trust-candidate data.3537. **action_set ordering**: Must be alphabetically sorted for `estate_liquidity_action_plan`.3548. **`conversion_years_positive` vs `conversion_years`**: They are typically the same value — both equal to `recommended_conversion_years`. Do not set one to zero.3559. **Premium gap sign**: Positive means shortfall (premium > exclusion capacity). This drives ILIT risk flags.35610. **Date arithmetic**: Crummey dates cascade: contribution → +30d notice → +30d withdrawal → +1d premium payment.