Where you are. Module 0 handed you a map and a toy. The map is the two-tier map: the central bank’s ledger where banks settle in reserves, and the commercial banks’ ledgers where everyone else holds a bank’s IOU. The toy is first_payment.py, fifty lines that pushed one payment across both tiers while two conservation assertions watched. The project that closed module 0 also named the toy’s three softnesses - nothing is typed, the invariants run once at the finish line, and pay cannot say no - and promised that module 1 would harden all three. This module keeps that promise by building the miniledger, a small two-tier ledger library - kept by the paired-entries rule lesson 3 names - that every later module imports. This lesson adds the destination: you meet the finished library before you build a single piece of it.
One command, one green line
At the root of the course, alongside the module folders, sits a directory you have so far walked past: miniledger/. It is the finished form of everything this module teaches, and it ships its own conscience: miniledger/checks.py, a script that exercises every rule the library claims to enforce, including the refusals. Prove it on your own machine. From the course root:
python -m miniledger.checks
One line comes back:
miniledger checks green: postings, tiers, refusals, loans, mismatch alarm
Exit code 0, in well under a second. In the moment that took, a central bank and two commercial banks came into being; customers got accounts and opening balances; one payment crossed inside a bank and another crossed between banks, settling in reserves; an overdraft was refused before anything moved; a loan created a deposit; and a deliberately forged reserve balance set off an alarm. Every clause of that sentence is a module 0 idea, now running as enforced code. That is the module in one gesture: this is the ledger you will build.
The idea in one paragraph
This module builds the miniledger piece by piece, and it shows you the assembled machine first so that every later lesson has a destination. There are six pieces. Lessons 2 to 7 build one each, in your own code/ files; lessons 8 to 10 drive the finished machine through the flows banks actually run; lessons 11 to 14 ask where money rests when nobody is paying anyone; and the milestone project assembles your build into miniledger v1 and checks it against the canonical copy you just exercised. Meeting the end-state first is not a spoiler; it is a contract. python -m miniledger.checks is the executable definition of done, and when your own build passes the same checks, the module owes you nothing further.
Six pieces, six lessons
Paired edits - lesson 2. Money is a list, not a thing. Module 0 said it as a story; lesson 2 says it as code. An Account is a name, a kind and a balance; a Ledger is one institution’s collection of them; and a payment is two edits to two lists. The notched stick from module 0, wearing a class definition.
Balanced postings - lesson 3. Every movement is a posting: a list of (account, change) legs that Ledger.post applies atomically, or not at all. Legs that do not balance raise LedgerError before anything is written. Module 0’s every-debit-finds-its-credit discipline moves from an end-of-run assertion into the write path itself.
The sheet that must always balance - lesson 4. Accounts come in three kinds - asset, liability, equity - and every ledger must keep assets equal to liabilities plus equity. The library re-asserts this after every single posting, where the toy compared totals once at the finish line and let a wrong intermediate state live happily until the end.
The two tiers and their mirror - lesson 5. Bank and CentralBank are ledgers with roles. A bank’s reserves are recorded twice: as an asset line in the bank’s own books and as a matching liability line in the central bank’s - one balance, written on both tiers. World.assert_world() demands the twins agree, and the “mismatch alarm” in the green line is that demand catching a forged balance. The mirror is also why module 0’s count grows: the toy recorded the cross-bank payment as four edits on three ledgers, and the miniledger changes six lines for the very same payment, because each bank also carries its own mirror of its reserve line. Lesson 8 walks that reconciliation leg by leg.
Physical cash - lesson 6. The banknote from the two-tier map, given its place in the machinery: the one form of central-bank money the public can hold. In the library it is not a new class but a new posting: a withdrawal swaps your deposit - the bank’s IOU - for a bearer instrument, and both institutions’ sheets shrink by the amount.
Submit and settle - lesson 7. The toy’s pay committed the instant it was called. The miniledger splits that risky mutation the way you would: World.submit validates a payment and queues it, and refusal happens there, before anything moves, as a raise that names its reason; World.settle then applies the queue atomically, oldest first, re-checking every invariant after each payment. Between the two calls a payment is a promise in motion; after settle it is a fact. Lesson 7 is about the moment in between - the commit point of money.
Wider than the screen; scroll it sideways.
Check yourself
1. The module could have started building piece one immediately. What does meeting the finished library first actually buy?
A destination and a definition of done. Every later lesson slots its piece into a machine you have already watched run, so you always know where the piece clicks in. And because python -m miniledger.checks passes on the canonical library today, “your build passes the same checks” becomes a finish line a machine can judge; no ambiguity is left about what done means.
2. Run as shipped, code/meet_the_ledger.py prints the green line and then fails its own assertion anyway. The library passed; what is the failing assertion testing?
You. The first assertion, on the exit code, established that the library’s checks pass. The second, on WATCHED, records something no library can check about itself: whether you have watched those checks fail. Until you have, the green line is a claim you are taking on faith, and the script refuses to let faith through the gate.
3. The green line ends with “mismatch alarm”. A mismatch between what and what, and why does it need its own alarm?
Between the two records of one balance: a bank’s own reserves line and the central bank’s matching line for that bank - the mirror across the tiers. It needs its own alarm because each ledger can be internally consistent while the two tiers quietly disagree: the checks forge a bank’s reserves in a way that keeps that bank’s own sheet balanced, and only the cross-tier comparison objects.
4. Module 0’s toy could only witness payments. Which word in the green line says the miniledger can do better, and where in the API does it happen?
refusals. It happens in World.submit, before anything moves: a payment that fails validation - an unknown payee, or an amount the payer’s balance cannot cover once already-queued payments are counted - is refused with a raise that names the reason. World.settle only ever applies payments that were accepted, which is why nothing is ever half-applied.
Do this
Ten minutes, standard library only. Work from module-01-money-at-rest.
Open code/meet_the_ledger.py and read it; it is short. It runs the same checks command from the hook, prints the result, and then refuses to pass until you have watched the checks fail. Run it as shipped:
python code/meet_the_ledger.py
The green line prints, then the script dies on watch the checks fail once before trusting them. That is the WATCHED flag holding the gate shut. Earn it:
- Open
miniledger/ledger.py, find the balanced-legs guard inpost, and flip its comparison - one character - so the rule reads backwards. Yes, this touches the one directory the course says never to edit; that is why the break is a single character, and why step 3 is not optional. - Rerun the script. The green line is gone; in its place, the library’s own traceback, surfaced by the exit-code assertion: a
LedgerErrorinsisting the very first posting is unbalanced, while its own message shows the legs cancelling exactly. Read it. This objection is what the green line is wired to. - Restore the character - if you cloned the course with git,
git diff miniledger/printing nothing is your proof - then setWATCHED = Trueincode/meet_the_ledger.pyand rerun.
The green line returns, and the final line prints exactly:
you have watched the conscience object; now you may rely on it
The completed version is in solutions/meet_the_ledger.py; check yours against it after the final line prints, not before.
What you can now do. You can run the finished library’s own checks on demand, and you have watched them object once, deliberately, which is the only reason their green is now worth something to you. You can name the six pieces of the machine and the lesson that builds each one: paired edits, balanced postings, the sheet that must always balance, the two tiers and their mirror, physical cash, and submit and settle. The destination is fixed; next lesson you build the first piece, and the oldest claim in this course - money is a list, not a thing - stops being a story and becomes a class definition.