Modification Accounting: ASC 842's Hardest Problem
Lease modifications are the leading source of audit findings in ASC 842 compliance. Not initial measurement, not classification, not even CPI adjustments. Modifications. A tenant gives back 2 of 5 floors, renegotiates rent, extends the term, and pays a penalty to exit early. The accounting standard prescribes a decision tree for how to handle this. Most teams get it wrong.
We built the modification engine at Arvexi to handle every branch of that decision tree in 365 lines of pure calculation code with zero side effects.
The classification decision tree
ASC 842-10-25 defines a precise decision tree. The answers determine radically different accounting treatments. On a $50M headquarters lease where a tenant gives back 40% of the space, the difference between correct and incorrect penalty allocation can be $1.6M.
The code is deliberately simple. The reasoning string is not just for logging; it becomes the accountingTreatment field stored on the modification record and surfaced in the audit trail:
export function testSeparateNewLease(
input: SeparateNewLeaseTestInput
): SeparateNewLeaseTestResult {
if (input.isNewRouAsset && input.isPricingCommensurate) {
return {
isSeparateNewLease: true,
reasoning:
`Modification qualifies as a separate new lease per ASC 842-10-25-8. ` +
`(1) New right-of-use asset: ${input.description}. ` +
`(2) Payment increase is commensurate with standalone price.`,
};
}
// ...falls through to remeasurement
}Partial termination: the hard case
PwC's guidance (Section 11) identifies partial termination penalty allocation as the number one mistake in practice. The penalty must never be expensed immediately. It must be allocated between terminated and retained portions using standalone selling prices. Most teams expense it to P&L on day one. Auditors catch it. Restatements follow.
Gain/loss calculation
Deferred into revised liability
The subtraction approach for penaltyToRetained ensures the two allocations sum exactly to the penalty amount, with no rounding leakage:
const terminatedSSP = toDecimal(terminatedPortion).mul(windDownMonths);
const retainedSSP = toDecimal(retainedPortion).mul(retainedTermMonths);
const totalSSP = terminatedSSP.add(retainedSSP);
const penaltyToTerminated = totalSSP.gt(ZERO)
? round2(terminationPenalty.mul(terminatedSSP.div(totalSSP)))
: ZERO;
const penaltyToRetained = totalSSP.gt(ZERO)
? round2(terminationPenalty.sub(penaltyToTerminated))
: terminationPenalty;Every calculation uses decimal.js with round2 for two-decimal-place precision. We never use JavaScript floats for monetary values. A float multiplication on $4,000,000 can drift by cents. Over thousands of leases, cents become material.
Period locking
Modifications don't exist in a vacuum. A modification that lands in a locked period would corrupt closed financials. We enforce this with a four-state machine.
The assertWritable() guard is called before any write operation. Reopening a locked period requires Controller-or-above role and a mandatory reason string. reopenedById, reopenedAt, and reopenReason create an audit trail. Before any period transitions to LOCKED, 11 validation checks run: 5 blocking (documents reviewed, JEs posted, subledger balanced, leases classified, schedules generated) and 6 warnings. The subledger balance check uses a $0.01 tolerance to absorb floating-point noise from aggregate Prisma sums without masking real imbalances.
Scenario comparison
Before committing a modification, users need to understand the impact. Our model_scenario tool runs the entire calculation pipeline in memory without persisting anything, completely read-only until the user commits.
The partial termination SSP allocation alone, if done manually in a spreadsheet, takes a senior accountant 2-4 hours per modification with a meaningful error rate. In our system it runs in under 100ms and produces an audit-ready narrative explaining exactly how the penalty was allocated and which ASC paragraphs govern the treatment.
The code is the spec. The spec is the code. The auditor reads the accountingTreatment field on the modification record and sees exactly what the system did and why.
See Lease Accounting to learn more about these capabilities.
Next: roll forwards that generate themselves, the AI agent that replaces a 2-person, 2-hour manual process.