Baseline units (per habitat row)
baselineUnits = distinctiveness x condition x area_ha x strategicSignificance
Post-development units (per habitat row)
postDevUnits = distinctiveness x condition x area_ha x strategicSignificance
x temporalRiskMultiplier
x spatialRiskMultiplier
x difficultyMultiplier10% uplift requirement
requiredDelta = max(0, sum(baselineUnits) * 1.10 - sum(postDevUnits))
Open-source TypeScript reference
// JP039 v4.0 core arithmetic
export function unitsForRow(row: HabitatRow): number {
const d = DISTINCTIVENESS_SCORE[row.band]; // 0,2,4,6,8
const c = CONDITION_SCORE[row.condition]; // 1,2,3
const s = STRATEGIC_SIGNIFICANCE[row.ss]; // 1.0,1.1,1.15
return d * c * row.areaHa * s;
}
export function postDevUnits(row, years, difficulty) {
return unitsForRow(row)
* temporalRiskMultiplier(years)
* difficultyMultiplier(difficulty);
}Divergence from the bound JP039 spreadsheet
The bound spreadsheet adds: per-habitat trading-rule enforcement; module-level summation (area, hedgerow, watercourse); and condition-card guidance baked into validation cells. This implementation reproduces the core arithmetic and surfaces the trading-rule check as a boolean; for formal submission the bound spreadsheet remains the authoritative output.[S2]