# offer-calculator

Job offer, compensation and total-comp capability pack for recruiters, hiring managers and candidates negotiating salary: compute total compensation (totalComp) from base salary, target bonus...


Job offer & compensation intelligence pack. Deterministic comp math for recruiters, hiring managers
and candidates, with an optional AI negotiation-advice layer that activates only when a model is
reachable (and silently falls back to the heuristic core otherwise).

**Not financial, tax or legal advice.** Cost-of-living and band figures are estimates for negotiation
framing.

## Tools

| Tool | Args | Does |
|---|---|---|
| `totalComp` | `{base, bonus, equity, benefits, options?}` | Sum annual comp; `bonus`/`equity`/`benefits` accept numbers or objects (`{percent}`, `{shares,price,vesting}`, `{health:…}`). `options.advise:true` adds AI tips when a model is up. |
| `equityValue` | `{shares, price, vesting}` | Value a grant; `vesting` is years or `{years,cliffMonths,frequency}`. Returns per-year/per-month + a vesting schedule. |
| `compBand` | `{role, level, options?}` | Salary range for a role at a level (intern→director). `options.city` returns a COL-adjusted band too. |
| `colAdjust` | `{salary, fromCity, toCity}` | Cost-of-living-equivalent salary between two cities + purchasing-power ratio. |
| `compare` | `{offers:[…], options?}` | Rank 2+ offers by total comp; `options.baselineCity` ranks by COL-adjusted comp; `options.advise` adds an AI recommendation. |
| `listCities` | `{}` | The built-in COL index (100 = US national average). |
| `listRoles` | `{}` | The known role bands + the level-multiplier ladder. |

Every result of a tool with an AI path is tagged `{ mode: 'heuristic' | 'llm' }`.

## Example

```js
import pack from './index.js';
await pack.adapters.totalComp({ base: 150000, bonus: { percent: 15 }, equity: { shares: 4000, price: 40, vesting: 4 }, benefits: { health: 12000 } });
// { mode:'heuristic', base:150000, bonus:22500, equityAnnualized:40000, benefits:12000, cashComp:172500, totalComp:224500, breakdown:{…} }

await pack.adapters.colAdjust({ salary: 150000, fromCity: 'austin', toCity: 'san francisco' });
// equivalentSalary ≈ 242017, deltaPct, purchasingPowerRatio, verdict
```

## DRY boundaries

- **`numbers`** owns generic scalar math and unit conversion; **`finance`** owns NPV/loan/interest;
  **`tax`** owns income-tax withholding. This pack does compensation-domain *composition* (band lookup,
  offer comparison, cost-of-living relocation) that none of those own.
- Self-contained: the only cross-pack import is `../_shared/llm.js` for the optional AI layer.

## Hybrid intelligence

Deterministic cores run offline with no model. `totalComp` and `compare` accept `options.advise:true`
to request LLM-generated negotiation advice; if no model is configured/reachable they return the exact
same numbers with `mode:'heuristic'`. A down model never throws.


---
Source: shared/engines/adapters/domain/offer-calculator/README.md
Canonical: https://docs.leumas.tech/p/adapters/domain/offer-calculator
