# How must an instance pin the accrual cutoff instant so cash and accrual ledgers agree? **Date of Record:** 2026 November 2 **Scope:** Applies to period-end close where a cash ledger and an accrual ledger must reconcile, and both must agree on which transactions fall in which period. Does not apply to perpetual systems with continuous close, or systems with a single ledger. ## Core Distinction Cash accounting recognises revenue and expense when money moves; accrual accounting recognises when the obligation is incurred. The two ledgers only reconcile if they agree on a cutoff instant and on whether the cutoff is inclusive or exclusive. A transaction that posts at exactly the cutoff is either in the period or not, and a comparison operator mismatch produces a one-transaction difference at every period boundary. **Invariant.** Cash and accrual ledgers agree at period end if and only if `cutoff_instant` is identical and `cutoff_operator ∈ {<=, <}` is identical across both ledgers. **Violation.** The **Cutoff Straddle**. The cash ledger closes at `period_end <` and the accrual ledger closes at `period_end <=`. Any transaction at exactly `period_end` appears in one ledger's period and not the other's, and the reconciliation difference is one transaction per boundary — non-zero, unexplained, and small enough to be tolerated. **Asymmetry.** Each ledger is internally consistent and reports its own period total. The straddle only appears in the cross-ledger reconciliation, where the difference is small and is repeatedly explained as "timing" without being examined. **Recorded elements.** The `cutoff-instant-receipt` (the exact instant), the `cutoff-operator-receipt` (inclusive or exclusive), and the `straddle-transaction-signature` (any transaction at the exact cutoff instant) together make the agreement checkable. ## What Was Observed **Signature.** Period-end reconciliation difference equal to the value of any transaction posting at exactly the boundary instant. The difference is one transaction per boundary per account, appears at every period end, and disappears when the boundary transaction is reclassified. **Trace.** Period closes at 2026-11-02T23:59:59Z. Cash ledger cutoff: `< 2026-11-02T23:59:59Z` (exclusive). Accrual ledger cutoff: `<= 2026-11-02T23:59:59Z` (inclusive). A payment posting at exactly 23:59:59Z appears in the accrual period, not the cash period. Reconciliation difference equals that payment, every period. **Why monitoring stays green.** Each ledger reports its total correctly. The reconciliation is run at period end with a tolerance band, and a one-transaction difference is typically inside the tolerance, so it is accepted and rolled forward. **Why the defect compounds.** The rolled-forward difference accumulates. By year end, the cumulative difference is the sum of boundary transactions, which can be material, and it is attributed to "timing" in every period. ## Condition of Validity The instance must ensure at least one holds before it treats period-end ledgers as reconciled: 1. **Must pin the cutoff instant.** The cutoff is stored as an exact instant (ISO 8601 with timezone), not as "end of day" or "period close", which mean different things in different systems. 2. **Must share the operator.** Both ledgers use the same inclusion rule (`<` or `<=`) and the same operator is stored with the cutoff, so it cannot be defaulted independently. 3. **Must surface boundary transactions.** Any transaction posting at exactly the cutoff instant is logged as a boundary transaction, so straddles are visible in the period they occur, not in aggregate at year end. ## Decision Boundary - Same instant and same operator: ledgers agree at the boundary. - Same instant, different operator: one transaction per period per account will straddle; treat as defect. - Different instants (even by a second): the boundary shifts and the difference is undefined; treat as unreconcilable. - Cutoff stored as date without time or timezone: ambiguous; boundary is not a point in time, and straddles are guaranteed. ## Operational Effect The invariant couples two accounting models to a single instant and a single comparison. The instance's correct posture is to store cutoff as an exact instant plus operator, and to surface boundary transactions rather than letting them accumulate. **Trap.** Set both cutoffs to "end of day". "End of day" is not an instant — it is a locale-dependent convention, and different systems interpret it differently (midnight local, midnight UTC, 23:59:59, etc.). The instant must be stored explicitly. ```python from dataclasses import dataclass class CutoffStraddleError(RuntimeError): """Raised when cash and accrual ledgers use different cutoff instants or operators.""" @dataclass(frozen=True) class AccrualCutoffGate: cash_cutoff_instant: str cash_operator: str # "<" or "<=" accrual_cutoff_instant: str accrual_operator: str def verify(self) -> bool: if not (self.cash_cutoff_instant and self.accrual_cutoff_instant): raise CutoffStraddleError("cutoff instant missing: boundary is undefined") if self.cash_cutoff_instant != self.accrual_cutoff_instant: raise CutoffStraddleError( f"instant mismatch cash={self.cash_cutoff_instant} " f"accrual={self.accrual_cutoff_instant}" ) if self.cash_operator != self.accrual_operator: raise CutoffStraddleError( f"operator mismatch cash={self.cash_operator} accrual={self.accrual_operator}" ) return True def dispatch_cutoff_mode(gate: AccrualCutoffGate) -> str: try: gate.verify() except CutoffStraddleError: return "pin-instant-and-operator" return "cutoff-sound" ```