Implementation Appendix
Complete V3.1 implementation reference. All thresholds match score.ts, synthetic-roles.ts, and validate.ts.
Core Formula
net_risk = exposure × (1 − bottleneck) × market_modifier
Where exposure and bottleneck are percentile-ranked (0–1) across all 562 occupations.
Risk Band Boundaries
| Band | Threshold | Meaning |
|---|---|---|
| very_low | < 0.05 | Negligible displacement pressure |
| low | 0.05 – 0.15 | Limited pressure; AI likely augments |
| moderate | 0.15 – 0.30 | Mixed; bottlenecks or market provide buffer |
| high | 0.30 – 0.50 | Significant pressure; weaker buffers |
| very_high | ≥ 0.50 | Strong pressure across multiple signals |
Impact Type Classification
Based on displacement (net_risk) × augmentation 2×2 matrix. Demand signal override: high displacement + SOL/JiD match → mixed (not at_risk).
| Type | Rule | Description |
|---|---|---|
| ai_leveraged | net_risk < 0.25 AND augmentation ≥ 0.12 | Low displacement with meaningful augmentation potential |
| at_risk | net_risk ≥ 0.25 AND augmentation < 0.12 AND no demand signal | High displacement, low augmentation, no market buffer |
| mixed | net_risk ≥ 0.25 AND (augmentation ≥ 0.12 OR demand signal) | High displacement but offset by augmentation or demand |
| stable | net_risk < 0.25 AND augmentation < 0.12 | Low displacement, low augmentation — minimal AI impact |
Augmentation Score
augmentation = exposure × bottleneck × (1 + market_resilience × 0.3)
| Band | Threshold |
|---|---|
| very_high | ≥ 0.8 |
| high | ≥ 0.6 |
| moderate | ≥ 0.4 |
| low | ≥ 0.2 |
| very_low | < 0.2 |
Market Modifier
market_resilience = 0.6 × market_momentum + 0.4 × occupation_scarcity
market_modifier = 1 − 0.35 × market_resilience
Singapore demand signal bonuses:
| Source | Match | Bonus |
|---|---|---|
| SOL 2026 | exact | +0.15 |
| SOL 2026 | prefix | +0.08 |
| Jobs in Demand 2025 | exact | +0.10 |
| Jobs in Demand 2025 | prefix | +0.05 |
Confidence Scoring
confidence = mean(crosswalk_quality, market_data_granularity, source_freshness)
| Level | Score |
|---|---|
| high | ≥ 0.7 |
| medium | 0.4 – 0.7 |
| low | < 0.4 |
Stability Stress Test
Each layer is perturbed by ±5 percentile points. Net risk is recomputed for all combinations.
| Label | Condition |
|---|---|
| stable | Band unchanged under all perturbations |
| watch | ±1 band shift |
| sensitive | ±2+ band shifts |
Seniority Modifiers (V3.1)
Applied in the Outlook engine. Adjustments scale with the occupation's variant_sensitivity (0–1), derived from institutional knowledge, relationship intensity, regulatory weight, and coordination requirements.
| Level | Exposure | Bottleneck |
|---|---|---|
| Entry-level | +0.12 × sensitivity | −0.10 × sensitivity |
| Mid-career | 0 | 0 |
| Senior / Lead | −0.10 × sensitivity | +0.12 × sensitivity |
Synthetic Role Rules
- Scores = weighted average of 2–4 component SSOC occupation scores
- All component SSOC codes validated against occupations.json at build time
- Confidence capped at Medium
- High-dispersion roles (stddev > 0.08) show risk range visualization
- Low-dispersion roles (< 3pp from primary) link to closest official occupation
- Always labeled "Estimated modern role" in the UI
Validation Checks (48 total)
- Record completeness (562 occupations, all fields present)
- Crosswalk coverage and evidence signals
- Distribution sanity (band counts, impact type ratios)
- Anchor occupation directional checks (5 occupations)
- Labour monitor data integrity
- Synthetic role SSOC validity (all components must exist)
- Alias SSOC validity (all references must exist)
- Archetype classification coverage (no professional/manager gets field_manual)
- Workflow overlay completeness (17 archetypes)
- Transition capacity sanity checks