> ## Documentation Index
> Fetch the complete documentation index at: https://village-docs.villagelabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Step 5: Update Vesting

> Calculate vested balances and potential forfeitures

## Overview

Step 5 applies the plan's vesting schedule to determine what portion of each participant's account is **vested** (owned by the employee) versus **unvested** (subject to forfeiture if they terminate).

<Info>
  Vesting is a **critical employee retention mechanism** that gradually transfers ownership of ESOP shares to participants based on years of service.
</Info>

## Core Responsibilities

<CardGroup cols={2}>
  <Card title="Vesting Calculation" icon="percent">
    Apply vesting schedule based on service years
  </Card>

  <Card title="Forfeiture Identification" icon="rotate-left">
    Calculate non-vested amounts subject to forfeiture
  </Card>

  <Card title="Multi-Class Support" icon="shapes">
    Track vesting per security in multi-class mode
  </Card>

  <Card title="Cash Vesting" icon="wallet">
    Apply vesting to both shares and cash balances
  </Card>
</CardGroup>

***

## How Vesting Works

### Vesting Schedule Types

<Tabs>
  <Tab title="Graded Vesting">
    Ownership increases gradually over time:

    ```python theme={null}
    vesting_schedule = {
        1: 0.20,  # 20% after 1 year
        2: 0.40,  # 40% after 2 years
        3: 0.60,  # 60% after 3 years
        4: 0.80,  # 80% after 4 years
        5: 1.00   # 100% after 5 years
    }
    ```

    **Example:**

    * Employee has 1,000 allocated shares
    * Service years: 3.5 years
    * Vesting: 60% (based on 3 years, rounded down)
    * **Vested:** 1,000 × 0.60 = 600 shares
    * **Unvested:** 1,000 × 0.40 = 400 shares (potential forfeiture)
  </Tab>

  <Tab title="Cliff Vesting">
    Full ownership after single milestone:

    ```python theme={null}
    vesting_schedule = {
        1: 0.00,  # 0% after 1 year
        2: 0.00,  # 0% after 2 years
        3: 1.00   # 100% after 3 years (cliff)
    }
    ```

    **Example:**

    * Employee A (2.9 years): 0% vested
    * Employee B (3.0 years): 100% vested

    <Warning>
      One day can make the difference between 0% and 100% vested!
    </Warning>
  </Tab>

  <Tab title="Immediate Vesting">
    Full ownership upon allocation (rare for ESOPs):

    ```python theme={null}
    vesting_schedule = {
        0: 1.00   # 100% immediately
    }
    ```

    All shares are vested the moment they're allocated.
  </Tab>
</Tabs>

***

## Processing Logic

### Single-Class Mode

```python theme={null}
for employee in active_employees:
    # 1. Determine vesting percentage
    service_years_int = int(employee.service_years)  # Round down: 3.9 → 3
    
    if service_years_int in vesting_schedule:
        vesting_pct = vesting_schedule[service_years_int]
    else:
        # If beyond max schedule year, assume 100% vested
        max_year = max(vesting_schedule.keys())
        vesting_pct = 1.0 if service_years_int > max_year else 0.0
    
    # 2. Calculate total balances
    total_shares = (
        employee.opening_shares +        # Beginning balance
        employee.allocated_shares -      # This year's allocation
        employee.diversified_shares      # Minus diversification
    )
    
    total_cash = (
        employee.opening_cash +
        employee.allocated_cash -
        employee.diversified_cash
    )
    
    # 3. Apply vesting
    employee.vested_shares = total_shares * vesting_pct
    employee.vested_cash = total_cash * vesting_pct
    
    # 4. Calculate potential forfeitures (if terminated)
    employee.potential_forfeitures = total_shares * (1 - vesting_pct)
    employee.potential_forfeitures_cash = total_cash * (1 - vesting_pct)
```

### Multi-Class Mode

Vesting is applied **per security**:

```python theme={null}
for employee in active_employees:
    # Determine vesting %
    vesting_pct = get_vesting_percentage(employee.service_years)
    
    total_vested_shares = 0
    total_potential_forfeitures = 0
    
    # Apply to each security holding
    for security_id, holding in employee.holdings.items():
        # Total shares in this security
        shares_in_security = holding.shares
        
        # Vested amount
        vested_in_security = shares_in_security * vesting_pct
        total_vested_shares += vested_in_security
        
        # Potential forfeitures
        forfeitures_in_security = shares_in_security * (1 - vesting_pct)
        total_potential_forfeitures += forfeitures_in_security
    
    # Set aggregate amounts
    employee.vested_shares = total_vested_shares
    employee.potential_forfeitures = total_potential_forfeitures
    
    # Cash vesting (aggregate, not per-security)
    total_cash = employee.opening_cash + employee.allocated_cash - employee.diversified_cash
    employee.vested_cash = total_cash * vesting_pct
    employee.potential_forfeitures_cash = total_cash * (1 - vesting_pct)
```

***

## Vesting Examples

<Tabs>
  <Tab title="Example 1: Fully Vested">
    **Scenario:**

    * Service years: 5.2 years
    * Vesting schedule: 100% at year 5
    * Allocated shares: 1,000
    * Opening shares: 4,000
    * Total: 5,000 shares

    **Calculation:**

    * Vesting %: 100%
    * Vested shares: 5,000 × 1.0 = **5,000 shares**
    * Potential forfeitures: 5,000 × 0.0 = **0 shares**

    ✅ Employee owns entire account
  </Tab>

  <Tab title="Example 2: Partially Vested">
    **Scenario:**

    * Service years: 2.8 years
    * Vesting schedule: 40% at year 2, 60% at year 3
    * Allocated shares: 500
    * Opening shares: 1,500
    * Total: 2,000 shares

    **Calculation:**

    * Service (rounded): 2 years → 40% vested
    * Vested shares: 2,000 × 0.40 = **800 shares**
    * Potential forfeitures: 2,000 × 0.60 = **1,200 shares**

    ⚠️ If employee terminates, they forfeit 1,200 shares
  </Tab>

  <Tab title="Example 3: Not Vested">
    **Scenario:**

    * Service years: 0.9 years
    * Vesting schedule: 20% at year 1
    * Allocated shares: 200
    * Opening shares: 0
    * Total: 200 shares

    **Calculation:**

    * Service (rounded): 0 years → 0% vested
    * Vested shares: 200 × 0.0 = **0 shares**
    * Potential forfeitures: 200 × 1.0 = **200 shares**

    ❌ If employee terminates, they get nothing
  </Tab>

  <Tab title="Example 4: Multi-Class">
    **Scenario:**

    * Service years: 3.2 years → 60% vested
    * Holdings:
      * Class A: 800 shares
      * Class B: 1,200 shares
    * Total: 2,000 shares

    **Calculation:**

    **Class A:**

    * Vested: 800 × 0.60 = 480 shares
    * Forfeitures: 800 × 0.40 = 320 shares

    **Class B:**

    * Vested: 1,200 × 0.60 = 720 shares
    * Forfeitures: 1,200 × 0.40 = 480 shares

    **Aggregates:**

    * Total vested: 480 + 720 = **1,200 shares**
    * Total forfeitures: 320 + 480 = **800 shares**
  </Tab>
</Tabs>

***

## Cash Vesting

<Info>
  **New in v0.2:** Cash balances are vested using the **same schedule** as shares.
</Info>

Participants may have cash from:

* Company cash contributions
* Diversification elections (converted from stock to cash)
* Dividends or interest
* Opening cash balances

**Cash vesting mirrors share vesting:**

```python theme={null}
total_cash = opening_cash + allocated_cash - diversified_cash
vested_cash = total_cash * vesting_percentage
potential_forfeitures_cash = total_cash * (1 - vesting_percentage)
```

**Example:**

* Employee has \$10,000 cash in account
* Service: 2 years → 40% vested
* Vested cash: $10,000 × 0.40 = $4,000
* Potential forfeiture: $10,000 × 0.60 = $6,000

***

## Potential Forfeitures

<Warning>
  **"Potential forfeitures"** are NOT actual forfeitures yet. They become **actual forfeitures** only if the employee terminates before becoming fully vested.
</Warning>

### When Forfeitures Occur

Forfeitures are realized in **Step 7** when:

1. Employee terminates
2. Employee has `potential_forfeitures > 0`
3. Forfeiture policy is applied

**The Flow:**

* **Step 5:** Calculate `potential_forfeitures`
* **Step 7:** If terminated → convert to `forfeited_shares`
* **Step 2 (next year):** Reallocate forfeited shares

### Forfeiture vs. Vested

| Metric        | Vested              | Unvested (Potential Forfeiture) |
| ------------- | ------------------- | ------------------------------- |
| Ownership     | Employee owns       | Company owns                    |
| If terminated | Employee keeps      | Company reclaims                |
| If continues  | Stays with employee | May vest later                  |
| Distribution  | Must be distributed | Never distributed               |

***

## Service Year Rounding

<Note>
  Service years are **rounded down** (floor) to determine vesting schedule lookup.
</Note>

**Examples:**

* 1.0 years → Lookup year 1
* 1.9 years → Lookup year 1 (not 2!)
* 2.0 years → Lookup year 2
* 2.999 years → Lookup year 2
* 5.1 years → Lookup year 5

```python theme={null}
service_years_int = int(employee.service_years)  # Floor function
vesting_pct = vesting_schedule.get(service_years_int, default)
```

This protects the company from prematurely vesting employees who haven't yet completed a full service year.

***

## Data Flow

### Inputs

<Tabs>
  <Tab title="Plan Rules">
    ```python theme={null}
    {
      "vesting_schedule": {
        1: 0.20,
        2: 0.40,
        3: 0.60,
        4: 0.80,
        5: 1.00
      }
    }
    ```
  </Tab>

  <Tab title="Employee Data">
    ```python theme={null}
    {
      "employee_id": "EMP001",
      "service_years": 3.2,
      "opening_shares": 1500.0,      # Beginning balance
      "allocated_shares": 500.0,     # This year's allocation (from Step 3)
      "diversified_shares": 0.0,     # Diversification (from Step 6)
      "opening_cash": 5000.0,
      "allocated_cash": 0.0,
      "diversified_cash": 0.0,
      "holdings": {                   # Multi-class mode
        "CLASS_A": {"shares": 1200.0},
        "CLASS_B": {"shares": 800.0}
      }
    }
    ```
  </Tab>
</Tabs>

### Outputs

<Tabs>
  <Tab title="Employee Updates">
    ```python theme={null}
    {
      "vested_shares": 1200.0,             # 60% of 2,000
      "vested_cash": 3000.0,               # 60% of 5,000
      "potential_forfeitures": 800.0,      # 40% of 2,000
      "potential_forfeitures_cash": 2000.0 # 40% of 5,000
    }
    ```
  </Tab>

  <Tab title="Compliance Events">
    Per employee:

    ```json theme={null}
    {
      "year": 2025,
      "phase": "vesting",
      "event": "vesting_updated",
      "entity_type": "employee",
      "entity_id": "EMP001",
      "details": {
        "vest_pct": 0.60,
        "vested_shares": 1200.0,
        "vested_cash": 3000.0,
        "potential_forfeitures": 800.0,
        "potential_forfeitures_cash": 2000.0
      }
    }
    ```
  </Tab>
</Tabs>

***

## Edge Cases

<AccordionGroup>
  <Accordion title="Service Years Exceed Max Schedule" icon="calendar-plus">
    If employee service exceeds the max year in vesting schedule:

    ```python theme={null}
    max_year = max(vesting_schedule.keys())  # e.g., 5
    if service_years_int > max_year:
        vesting_pct = 1.0  # Assume 100% vested
    ```

    **Example:**

    * Schedule ends at year 5
    * Employee has 12 years service
    * Vesting: 100% (fully vested)
  </Accordion>

  <Accordion title="Service Years Below Min Schedule" icon="calendar-minus">
    If employee service is less than first schedule year:

    ```python theme={null}
    if service_years_int < min(vesting_schedule.keys()):
        vesting_pct = 0.0  # Not yet vested
    ```

    **Example:**

    * Schedule starts at year 1
    * Employee has 0.5 years service
    * Vesting: 0% (not vested)
  </Accordion>

  <Accordion title="Negative Balances Protection" icon="shield">
    In rare cases, diversification or corrections might cause negative balance:

    ```python theme={null}
    total_shares = max(0, opening + allocated - diversified)
    ```

    Prevents negative vesting calculations.
  </Accordion>

  <Accordion title="Newly Allocated Shares" icon="gift">
    Shares allocated this year are **immediately subject to vesting**:

    * Allocated in Step 3: 500 shares
    * Vesting in Step 5: 40%
    * Vested: 500 × 0.40 = 200 shares
    * Unvested: 500 × 0.60 = 300 shares

    New allocations don't get special treatment—same vesting % applies.
  </Accordion>
</AccordionGroup>

***

## Compliance Events

<Tabs>
  <Tab title="vesting_updated">
    Legacy compliance log format:

    ```json theme={null}
    {
      "year": 2025,
      "phase": "vesting",
      "event": "vesting_updated",
      "entity_type": "employee",
      "entity_id": "EMP042",
      "details": {
        "vest_pct": 0.80,
        "vested_shares": 4800.0,
        "vested_cash": 12000.0,
        "potential_forfeitures": 1200.0,
        "potential_forfeitures_cash": 3000.0
      }
    }
    ```
  </Tab>

  <Tab title="vesting_computed (structured)">
    Structured event format:

    ```json theme={null}
    {
      "year": 2025,
      "phase": "vesting",
      "event": "vesting_computed",
      "entity_type": "employee",
      "entity_id": "EMP042",
      "inputs": {
        "vesting_percent": 0.80
      },
      "outputs": {
        "vested_shares": 4800.0,
        "vested_cash": 12000.0,
        "potential_forfeitures": 1200.0,
        "potential_forfeitures_cash": 3000.0
      }
    }
    ```
  </Tab>
</Tabs>

***

## Related Steps

<CardGroup cols={2}>
  <Card title="Step 3: Allocation" icon="divide" href="/simulation/step-3-allocation">
    Provides allocated shares that get vested
  </Card>

  <Card title="Step 6: Diversification" icon="chart-pie" href="/simulation/step-6-diversification">
    Reduces share balance before vesting calculation
  </Card>

  <Card title="Step 7: Repurchase" icon="money-bill-transfer" href="/simulation/step-7-repurchase">
    Converts potential forfeitures to actual forfeitures
  </Card>

  <Card title="Plan Rules" icon="gavel" href="/models/plan-rules">
    Defines vesting schedule
  </Card>
</CardGroup>

***

## Vesting Strategy Considerations

<AccordionGroup>
  <Accordion title="Why Use Graded Vesting?" icon="stairs">
    **Advantages:**

    * Gradual ownership transfer
    * Reduces forfeiture shock
    * Better retention over time
    * Employees see progress annually

    **Disadvantages:**

    * More complex to administer
    * Partial forfeitures common
  </Accordion>

  <Accordion title="Why Use Cliff Vesting?" icon="mountain">
    **Advantages:**

    * Simpler to administer
    * Strong retention at cliff point
    * Clear ownership threshold

    **Disadvantages:**

    * "All or nothing" can be demotivating
    * High forfeiture if employees leave before cliff
    * May violate DOL regulations if cliff > 3 years for ESOPs
  </Accordion>

  <Accordion title="Accelerated Vesting Triggers" icon="bolt">
    Some plans include **accelerated vesting** for:

    * Death
    * Disability
    * Retirement (age 65)
    * Plan termination
    * Change of control

    These triggers can override the normal vesting schedule and grant immediate 100% vesting.
  </Accordion>
</AccordionGroup>

***

## Summary

Step 5 is the **vesting calculator** that:

* ✅ Applies vesting schedule based on service years
* ✅ Calculates vested shares and cash balances
* ✅ Identifies potential forfeitures (unvested amounts)
* ✅ Supports multi-class securities with per-security tracking
* ✅ Handles edge cases (service beyond schedule, negative balances)
* ✅ Emits compliance events for audit trail

**Key Insight:** Vesting is a **powerful retention tool**. Employees who leave before fully vested forfeit unvested amounts, which are then reallocated to remaining participants—creating an incentive to stay with the company.

<Note>
  Vesting calculations in Step 5 are **forward-looking** estimates. Actual forfeitures only occur in Step 7 if the employee terminates.
</Note>
