LedgerLoom Chapter 07 — Adjusting entries as “late-arriving data”

Chapter 06 introduced periods and the idea that timing changes what “profit” means. Chapter 07 makes that operational: it shows how real closes work when information arrives after period end.

In accounting language, these are adjusting entries (accruals, deferrals, estimates). In software language, they are late-arriving events that we ingest after the period boundary.

The key engineering principle: Never overwrite history. Append new events, record provenance, and rebuild derived views.

Why this matters (accountants + engineers + data people)

Accountants get: - a clean “unadjusted” close vs. an “adjusted” close - a documented audit trail for who posted what and why - repeatable evidence that the trial balance and equation still hold

Software developers get: - an event-sourced model: adjustments are separate events - deterministic compilation: same inputs → same postings → same reports - testable invariants as constraints (double-entry + equation)

Data professionals get: - a reproducible pipeline: append-only facts + derived views - explicit handling of late data (cutoff diagnostics) - stable artifacts for downstream analysis and monitoring

What you will build

This chapter emits two close snapshots for the same period:

  1. Unadjusted close: what was recorded by the deadline.

  2. Adjusted close: unadjusted + adjusting entries dated at period end, with provenance.

The example adjustments include:

  • Deferring unearned revenue (customer prepayment)

  • Reclassifying prepaid rent

  • Accruing a utility bill received after month-end

  • Recognizing supplies used based on a month-end count

Outputs (artifacts)

The runner writes artifacts under outputs/ledgerloom/ch07:

  • postings_unadjusted.csv and postings_adjusted.csv

  • trial_balance_unadjusted.csv and trial_balance_adjusted.csv

  • income_statement_unadjusted.csv and income_statement_adjusted.csv

  • balance_sheet_unadjusted.csv and balance_sheet_adjusted.csv

  • entry_register.csv (all events) and adjustments_register.csv (adjustments only)

  • cutoff_audit.csv (late-arrival diagnostics: effective period vs posted period)

  • adjustment_deltas_by_account.csv (what changed, by account)

  • invariants.json (engine invariants for both snapshots + equation checks)

  • manifest.json (run metadata + SHA256 checksums)

Run it

make ll-ch07

Or directly:

python -m ledgerloom.chapters.ch07_adjusting_entries_late_arriving_data \
  --outdir outputs/ledgerloom \
  --seed 123

How to read the outputs

Start with these three files:

  1. trial_balance_unadjusted.csv vs trial_balance_adjusted.csv shows the account-level impact of the adjustments.

  2. income_statement_* shows how timing changes profit.

  3. cutoff_audit.csv explains why the adjustments exist: the entry effective date is period-end, but the posted_at date is later.

Engineering takeaway: append-only + provenance + deterministic rebuild

LedgerLoom treats adjustments as first-class events. That lets you:

  • reproduce any close (unadjusted or adjusted) from the event log

  • audit “who/why/when/source” without guessing

  • enforce constraints with tests, not tribal knowledge

This is the same workflow you want in production accounting software: trust comes from invariants, provenance, and reproducibility.