P3: the cash flow statement by ASC 230 (defect 1, D-35, D-42)
check / check (push) Canceled after 0s

Direct method with the operating reconciliation and noncash schedules; it
foots by construction (Lean and Kani). Every non-cash account belongs to
one section; reversals net; a member or lender paying for the company is
cash borrowed and spent (D-42, constructive receipt and disbursement);
property a member contributes stays noncash. The bookspec seed: one loader
checks every example.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T3gXMVt7XJPi6ens1or9Dj
This commit is contained in:
swaitsandClaude Opus 5.5 committed 2026-10-21 09:35:32 -06:00
1 parent 2c29d48ab9
commit eb4329bb2a
64 files changed
+12128 -1567

No files matched your search

+1 -1
View File
@@ -16,7 +16,7 @@ Statuses: `covered` (built and tested), `partial` (built, known gaps listed),
| 2 | Chart of accounts | engine + `books.chart` (with live balances) | covered |
| 3 | Live P&L tab | engine + `books.profit_and_loss` | covered |
| 4 | Live Balance Sheet tab | engine + `books.balance_sheet` | covered |
| 5 | Live Cash Flow tab | engine `cash_flow` (indirect) + `books.cash_flow` | covered |
| 5 | Live Cash Flow tab | engine `cash_flow` (direct, with the reconciliation schedule) + `books.cash_flow` | covered |
| 6 | Transaction Journal as append-only log | engine posting log + `books.search_entries` | covered |
| 7 | Receipt storage in Drive | blob store + `books.attach_receipt` / `link_receipt` / `unlink_receipt` / `withdraw_attachment` | covered |
| 8 | Document filing by category (01 Formation / 02 Legal / 03 Tax / 04 Accounting) | `books.file_document` | covered |
+65 -7
View File
@@ -453,10 +453,58 @@ every tool over every book in ledger-store's `tests/fixtures/old-books`.
`revenue_accounts` and `expense_accounts` for the range. `end` defaults to
today, `start` to the first posted entry. Closing entries are excluded, so
a closed period still shows what it earned.
- `books.cash_flow { start?, end?, cash_accounts?, financing_accounts?, investing_accounts? }` (each defaults to `[books]` in wanderbooks.toml; cash is required one way or the other)
→ indirect-method cash flow statement. `cash_accounts` are the reconciling
accounts (required); the three sections always sum to their net change.
Disposal gains/losses move from operating to investing automatically.
- `books.cash_flow { start?, end?, cash_accounts?, financing_accounts?, investing_accounts? }` (each defaults to the books' settings, `books.cash_accounts` and so on; cash is required one way or the other)
→ the statement of cash flows, direct method (rules.md B-14, P3 defect
1): `{ method: "direct", start, end, operating_by_class, operating,
cash_from_operations, investing_by_kind, investing, cash_from_investing,
financing_by_kind, financing, cash_from_financing, net_change_in_cash,
cash_beginning, cash_ending, noncash_disclosures,
operating_reconciliation, reconciles, warnings }`.
- Lines (`operating`, `investing`, `financing`) are one per entry, section
and kind: `{ entry, date, label, kind, amount, on_behalf?, accounts,
reverses?, class? }`; every transaction is listed (D-35), each under its
kind. An entry's interest is its own operating class, (b) or (e), apart
from the rest of its operating cash. What a member or a lender paid or
received for the company with no cash account moving is cash borrowed
(or contributed) and spent, on the entry's date (D-42, rules.md B-14
rule 11): an expense a member paid personally through Due to Members
is a "Proceeds from borrowing — <account>" line and an operating
line, each with `on_behalf`, the part of its amount so handled (absent
when none; an entry's `on_behalf` parts net to zero).
Labels never come from a reversal's sign: "Reversal of #N — …",
"Reinstatement of #A (reverses #B)". An entry and its reversal in the
same period drop out together.
- `operating_by_class`, `investing_by_kind`, `financing_by_kind`:
`{ kind, class?, amount, entries }`, how the printed statement shows the
sections: operating by ASC 230-10-45-25 class (`from_customers`,
`interest_and_dividends_received`, `other_receipts`,
`to_suppliers_and_employees`, `interest_paid`, `income_taxes_paid`,
`other_payments`), investing and financing by kind ("Contributions from
members — <member>", "Repayments of borrowing — <account>", "Purchases
of property and equipment", …).
- `noncash_disclosures`: `{ entry, date, label, amount, operating,
investing, financing, exchanged, reverses? }`, the investing and
financing activities no cash settled (ASC 230-10-50-3): property
contributed, debt converted to equity, a purchase on the seller's
credit, interest charged into a loan, the noncash part of a part-cash
purchase.
- `operating_reconciliation`: `{ net_income, lines: [{ kind, label,
amount, account?, entries }], net_cash_from_operating }`, net income
reconciled to operating cash (ASC 230-10-45-30), kinds `depreciation`,
`investing_gain_loss`, `noncash_through`, `other_noncash`,
`operating_balance_change`.
- `reconciles`: `{ sections_sum, net_change, difference }`; `difference`
is always `"0.00"`: a statement that wouldn't foot is an engine error,
never output.
- `warnings`: `{ entry, kind, message }` for an entry whose later payment
or collection the books can't classify (`asset_on_operating_payable`,
`asset_sold_on_operating_receivable`), with the fix.
- Refused, naming the setting, when the roles contradict the chart or
each other (cash and investing accounts must be assets, financing
accounts liabilities or equity; no account in two lists or twice in
one; no registered asset's account as cash).
- Changed in P3 (breaking): `net_income`, `depreciation` and
`working_capital` are gone (net income is in `operating_reconciliation`).
- `books.digest { since: "2026-10-01" }`
→ `{ entries_posted: [...], totals_by_account: [...], stale_rules: [...] }`.
The human review surface: "what did the AI do with my books lately." The
@@ -1133,8 +1181,15 @@ posting.
- `books.export { format, report, start?, end?, as_of?, cash_accounts?,
financing_accounts?, investing_accounts? }` → `{ content,
content_encoding?, warnings? }`.
- Reports: `profit_and_loss`, `balance_sheet`, `cash_flow` (needs
`cash_accounts`), `trial_balance`, `members_equity` (statement of
- Reports: `profit_and_loss`, `balance_sheet`, `cash_flow` (direct
method; needs `cash_accounts`; json is `books.cash_flow`'s answer, csv
is `section,kind,class,entry,date,label,amount,on_behalf` (`on_behalf`
on a section's lines only) with sections
`operating`, `investing`, `financing`, `reconciliation`, `noncash`,
`footing` and `warning` (its kind, entry and message; no amount); xlsx
and pdf are the printed statement, operating by class and investing
and financing by kind with each kind's transactions under it, with its
two schedules), `trial_balance`, `members_equity` (statement of
changes in members' equity; members from `wanderbooks.toml`; earnings
not yet closed are split the way the next members close will split
them, so a member's capital on a day never changes when its month is
@@ -1506,7 +1561,10 @@ entries.
README says which. With TINs it adds `party_id, tin_last4, tin,
tin_type, tin_note`. A zip with the full set, each
statement as PDF and XLSX: `profit-and-loss`, `balance-sheet`,
`cash-flow` (reconciled to `cash_accounts`), `members-equity`
`cash-flow` (the direct method, as `books.export` prints it: operating
by class, investing and financing by kind with each member named, and
its two schedules; reconciled to the package's cash accounts),
`members-equity`
(multi-member LLCs), `trial-balance`; plus `general-ledger.xlsx` and
`general-journal.xlsx`. Period reports cover the fiscal year to date.
What the CPA needs; they never log into the system.
+1 -1
View File
@@ -28,7 +28,7 @@ No other statuses.
| Reversing entries | Reverse transaction | done | linked via `reversal_of` |
| Canonical report snapshots (JSON) | — (our oracle format) | done | `reports::snapshot` |
| Fixed-asset register + straight-line depreciation | Fixed Asset register | done | `assets.rs`; golden-covered schedule; idempotent runs; disposal with gain/loss |
| Cash flow statement (indirect) | Reports → Cash Flow | done | R-FUTURE-3 |
| Cash flow statement (direct, with the reconciliation schedule and noncash disclosures) | Reports → Cash Flow | done | R-FUTURE-3; rules.md B-14 (P3 defect 1) |
| Foreign-currency lines (base + foreign stored) | Multi-currency accts | done | R-FUTURE-1 |
| Period close (closing entry to Retained Earnings) | Close books | done | R-FUTURE-2 |
| Bank reconciliation (cleared flags + report) | Reconcile | done | — |
+3 -1
View File
@@ -113,7 +113,9 @@ requirement conflict, the requirement wins.
## Promoted from future (done)
- **R-? — Cash flow statement** (indirect method). Was R-FUTURE-3.
- **R-? — Cash flow statement** (direct method, with the reconciliation
of net income to operating cash and the noncash investing and financing
activities; rules.md B-14, P3 defect 1). Was R-FUTURE-3.
`ledger-core::reports::cash_flow` + `books.cash_flow`.
- **R-? — QuickBooks-compatible import/export.** Was R-FUTURE-4.
`ledger-import` crate: CSV bank/chart import, IIF and XLSX export.
+10 -1
View File
@@ -63,4 +63,13 @@ Read on 2026-10-13 through Deloitte's free DART roadmaps, which reproduce
ASC text: ASC 230-10-45-16 and -28, 326-20-55-37/38, 606-10-25-23, 45-2,
55-37/38, 830-20-30-1. Read directly in the ASC basic view on 2026-10-14
(`sources/fasb-asc.md`): 360-10-35-4, 340-10-05-2/4/5, 210-10-45-1/2/5,
230-10-45-7/10/12/13/14/15, 606-10-55-36 through 55-38. None left open.
230-10-45-7/10/12/13/14/15, 606-10-55-36 through 55-38. Read on
2026-10-20 where public sources reproduce the Codification (EY's FRD on
the statement of cash flows, July 2026; FASB ASUs 2016-15 and 2016-18;
Deloitte's public DART Roadmap): ASC 230-10-10-1, 45-1, 45-4, 45-5,
45-8, 45-9, 45-12(c), 45-13(c), 45-14(a), 45-15(a)/(c), 45-16(a)/(b),
45-17, 45-24 to 45-26, 45-28 to 45-31, 50-3 to 50-8, and 830-230-45-1;
each checked again against the same sources in the P3 review (numbers,
pages and wording hold). Open: 105-10-05-1 to 05-3, read only in their
2009 text (ASU 2009-01, and as Wiley GAAP 2020 quotes them); their
current wording is unconfirmed.
+305 -45
View File
@@ -356,51 +356,309 @@ earnings the same running way, D-38, 2026-10-20)
`a_yen_members_page_splits_in_whole_yen`; the bookspec examples
`members-close.*`.
## B-14 Statements: P&L for a period; cash flow by the indirect method
## B-14 Statements: P&L for a period; cash flows by the direct method
**Status:** AUTHORITY
**Status:** AUTHORITY, except where marked CONVENTION or DECISION
ASC 230-10-45-28 (cited): an entity not using the direct method "shall
determine and report the same amount for net cash flow from operating
activities indirectly by adjusting net income … (the indirect or
reconciliation method)." ASC 230-10-45-16: "All of the following are cash
inflows from operating activities: Cash receipts from sales of goods or
services…". A closing entry is not income or spending (B-11), so period
statements exclude it.
The P&L covers a period; a closing entry is not income or spending
(B-11), so period statements exclude it.
Investing and financing are gross (ASC 230-10-45-7, read directly
2026-10-14, `sources/fasb-asc.md`:
"information about the gross amounts of cash receipts and cash payments
during a period is more relevant than information about the net
amounts"; 45-8 allows netting only where "the turnover is quick, the
amounts are large, and the maturities are short"). Financing inflows
include "Proceeds from issuing equity instruments" and "other short- or
long-term borrowing" (45-14(a), (b)); outflows include "distributions to
owners" and "Repayments of amounts borrowed" (45-15(a), (b)). Every cash
flow is investing, financing, or operating (45-10). Investing
"include[s] making and collecting loans and acquiring and disposing of
debt or equity instruments and property, plant, and equipment" (ASC
230-10-20). Which accounts hold loans made, investments, and debt is a
fact of each company's chart, so it is a setting: `[books]
financing_accounts` and `investing_accounts` in wanderbooks.toml (with
`cash_accounts`), read by the MCP tools and the viewer alike.
The statement of cash flows (P3 defect 1, D-35, D-42; the paragraphs were read
in public sources that reproduce the Codification, `sources/fasb-asc.md`):
Money an owner advances, by paying a company expense personally (a
"Due to owners" liability), is borrowing: PwC Viewpoint, Financial
statement presentation 6.9.3.1 (constructive receipts and
disbursements) presents cash a third party pays on the entity's behalf
"as though the transaction took place through the bank accounts of the
reporting entity": a financing inflow and an operating outflow. Listing
that liability in `financing_accounts` gives exactly that; repaying the
owner is then a repayment of amounts borrowed. "Judgment is required"
(PwC), so it is the company's setting, not a fixed rule.
1. **Cash receipts and payments.** The statement reports "the cash
effects" of operations, investing and financing (ASC 230-10-45-1; its
objective, 10-1: "cash receipts and cash payments"). An entry
contributes to the body only its net movement of the cash accounts,
and what a member or a lender paid or received for it (rule 11, which
nets to zero within the entry); an entry that moves neither
contributes nothing; a transfer between two cash accounts is no flow. The period is [start, end], inclusive. The
cash accounts are every account holding cash, cash equivalents or
restricted cash: the statement explains the change in their total
(45-4, as ASU 2016-18 amended it), and transfers among them "are not
reported as cash flow activities" (45-5). Which accounts those are is
the books' `books.cash_accounts`.
2. **Partition.** Every receipt and payment is investing, financing or
operating (45-10), so every non-cash account is in exactly one section:
investing (the cost and accumulated-depreciation accounts of every
registered fixed asset, and `books.investing_accounts`); financing
(equity, and `books.financing_accounts`); operating (every other
balance-sheet account, and revenue and expense, but see rule 4). The
roles must agree with the chart and each other, or the statement is
refused with the setting to change: cash and investing accounts are
assets; financing accounts are liabilities (equity listed is accepted:
it is financing anyway); no code twice in a list or in two lists; no
registered asset's account as cash; at least one cash account. One
check (`cashflow::role_problems`) is behind both the refusal and
`books.settings`' problems.
3. **Only the cash portion** of a part-cash transaction is reported
(50-5). An entry's cash `c` is applied to the sections moving against
it, in the order operating, investing, financing, each up to its own
movement; what is left of a section's movement is the entry's noncash
part, disclosed (rule 7). CONVENTION: the order (the ASC is silent on
allocating within one entry); it matters only for an entry with a
noncash source and two or more sections paid by cash, and is disclosed.
Within a section the same order splits the cash among its kinds (rule
5).
4. **Gains and losses on investing assets are investing**: receipts from
sales of PP&E are investing (45-12(c)), so the whole proceeds are, and
the gain or loss is taken out of net income (45-28(b)). In an entry that
credits a registered cost account or an investing account, the revenue
and expense lines are investing, except interest, received or paid (tax
categories `interest_income` and `interest_expense`): interest is
operating in any entry (45-16(b), 45-17(d)). The trigger is broad (a
return, a reclass or an impairment credits the cost account too), so the
reconciling line reads "(Gain) loss and other noncash changes in
investing assets".
5. **Gross lines by kind** (45-7; investing and financing inflows and
outflows "reported separately", 45-26). One line per entry, section and
kind, with the entry, date, label and the kind's accounts. Operating
lines carry the class 45-25 requires "at a minimum" (a)-(g), kind by
kind within the entry, by the direction of the cash: the cash an
entry's `interest_income` lines take is (b) interest received, and its
`interest_expense` lines' (e) interest paid, whatever else the entry
settles (a loan payment on an operating payable is (d) for the
principal and (e) for the interest, never all (e)); the rest of its
operating cash, by its other operating lines: a receipt is (a) if a
line is revenue or the receivables control, or the entry's party is a
customer, else (c); a payment is (g) if every such line is on an
account whose tax category is `taxes_licenses` (payments to
governments for taxes and fees are 45-17(c), apart from suppliers'
45-17(b); 45-25 names only income taxes, (f)), else (d) if a line is
an expense, a liability or a non-receivables asset, else (g). (Interest paid back out
is (g); interest refunded to the company, (c).) The operating cash is
split among these kinds as a section's among its kinds (rule 3), in
the order: the rest, interest received, interest paid (CONVENTION).
Class (f) stays empty until a tax category marks an entity-level income
tax (a
partnership pays none "as such", IRC §701, but can under §6225 or a
state pass-through election). Investing and financing kinds (D-35):
purchases and sales of property and equipment, payments for and
collections on each investing account, contributions from and
distributions to each member (by name; equity not a member's by
account), proceeds of and repayments of each financing liability. An
original's direction is its nature (45-15(a): cash out of equity is a
distribution). The printed statement and the viewer show operating one
row per class, and investing and financing one row per kind with its
total, each transaction listed under it (D-35); `books.cash_flow` and
the exports carry every line. Known limits: an entry's other operating
lines take one class, so its mixed receipts and payments other than
interest net within it; class (b) relies on portfolio interest being
categorized `interest_income` (interest receivable collected is (c)).
6. **Reversals.** A reversal takes its chain root's sections, class and
kind, with its own sign (`Ledger::reversal_chain`). Pairing walks each
chain from its root: an entry and its reversal both in the period drop
out of every line and disclosure, when their flows are exact negatives
(proved, and checked at runtime), so a reversal of a reversal whose
partner is paired is shown. A reversal shown alone is labelled
"Reversal of #N — <N's description>", a reinstatement "Reinstatement
of #A (reverses #B)", listed under the original's kind: never a label
from a reversal's sign (D1-c).
7. **Noncash investing and financing activities are disclosed** (50-3,
50-4; placement, 50-6). Disclosed: every entry not netted whose noncash
part moves financing, or moves investing through an account that is
neither accumulated depreciation nor a rule-4 P&L line, or that
exchanges inside investing and financing without cash (50-4's
"converting debt to equity", a note for equipment, a trade-in): `x =
max(0, min(D - out, C - in))` over the net debits `D` and credits `C`
of its investing and financing balance-sheet accounts, `in` and `out`
the cash those two sections took in and paid out, what a member or
lender handled for the entry included (rule 11: equipment a bank paid
for is 1,000 in and 1,000 out, nothing exchanged). Amount: `max(Σ
max(r_k, 0), x)`. Depreciation is a
reconciling item, not an activity. Limit: a trade-in within one cost
account nets away.
8. **Net income reconciled to operating cash**, a separate schedule with
the direct method (45-30; major classes of reconciling items, 45-29;
what is removed, 45-28): operating = NI + G + X + W, over the period's
non-closing entries. NI, net income; G, the rule-4 P&L lines; X, each
entry's operating noncash part, as "Depreciation" (its investing and
financing balance-sheet lines all accumulated depreciation), "Noncash:
through <A>" (those lines, accumulated depreciation aside, all on A),
or "Other noncash items"; W, minus each
operating balance-sheet account's movement ("Increase in" / "Decrease
in"). An identity over balanced entries (Lean
`operating_reconciliation_ties`), checked at runtime.
9. **The sections foot** (45-24: the statement reconciles beginning and
ending cash). `reconciles {sections_sum, net_change, difference}`; any
difference, a section unequal to its lines, or a reconciliation unequal
to operating is `CashFlowDoesNotFoot`, an engine error: nothing is
produced. It can't happen on posted entries (Lean
`cashflow_sections_sum_to_cash_change`, `Reachable.cashflow_foots`).
10. **Closing entries are never in the statement** (B-11). A close moves
only revenue, expense and equity, and cash accounts are assets, so a
close has no cash line.
11. **What a member or a lender pays, or receives, for the company is
cash the company borrowed (or a member contributed) and spent**
(DECISION, D-42, the owner, 2026-10-20, revising D-35's first point;
bookspec's CHOICE: the standard leaves it open).
*Source.* The Codification does not address a payment a third party
makes on the entity's behalf (PwC Viewpoint FSP 6.9.3: "ASC 230 does
not address these situations"; BDO Blueprint 3.4: "While ASC 230 is
silent"; EY FRD 4.6.2: "judgment will be needed"; KPMG Handbook
Q8.3.10), so 105-10-05-2 sends the question to nonauthoritative
guidance. There the firms present it by substance, as constructive
receipt and disbursement: PwC 6.9.3.1, "a reporting entity should
include cash flows received or paid by a third party on behalf of the
reporting entity" (a bank paying a vendor: "a financing inflow ... and
an operating outflow"); DART Roadmap 7.2 (third-party financing,
Example 7-2: a lender paying an insurance premium, an operating outflow
and a financing inflow; the contrast, a supplier's own finance arm, is
AICPA TQA 1300.16 and the SEC staff's 2005 view: noncash); BDO 3.4
(Example 3-5: a bank paying for equipment, an investing outflow and a
financing inflow; it names "a parent might pay on behalf of a
subsidiary expenses"); EY 5.2.4 and 5.3.1 (third-party financing,
unlike the seller's, is a financing inflow and an operating or
investing outflow). KPMG Q8.3.10 also accepts a noncash presentation
for equipment a lender pays for. A CPA would present it as the firms
do; the change in cash is the same either way. The rule, entry by
entry, after its own cash (rule 3; `kernel::constructive`):
- **Paid for the company.** A financing liability
(`books.financing_accounts`: the members' financing account such as
Due to Members, a loan, a card listed as financing) credited against
operating or investing lines debited paid for them: a financing
inflow under the liability's kind ("Proceeds from borrowing — 2100
Due to Members", 45-14(b)) and the operating outflow (its class by
rule 5) or the investing outflow (45-13(c)), both on the entry's
date. A member's capital credited against revenue or expense debited
paid for them likewise, a contribution ("Contributions from members
— <member>", 45-14(a)): the expense-to-capital case below.
- **Received for the company.** A financing liability or a member's
capital debited against revenue, expense or the receivables control
credited (a customer paying a member, a vendor refunding to a
member's card): an operating inflow, and a repayment or a
distribution (PwC 6.9.3.1: cash "received or paid").
- Each line's `on_behalf` is the part of its cash so handled. The parts
net to zero within the entry, so the sections still sum to the
change in cash (rule 9; Kani `constructive_nets_to_zero`). Kinds take
it in order, operating before investing and, within operating,
balance-sheet lines before revenue and expense (CONVENTION, as rule
3's: it matters only for an entry whose sources cover part of its
uses, and then leaves capital the revenue and expense it can pay
for). A reversal mirrors its root (rule 6; Kani
`constructive_mirrors`), so a payment and its reversal net out, and
a reimbursement is the repayment it is (45-15(b)).
- **Stays noncash**, disclosed (rule 7): property a member contributes
that it already owned (capital credited against an asset, a prepaid
included: no cash moved, to anyone, 50-4); property handed over in
kind (an asset credited against a financing liability or capital
debited); a debt exchanged for another or for equity (50-4's
"converting debt to equity"); interest and guaranteed payments
charged into what the company owes the lender or member (tax
categories `interest_expense`, `interest_income`,
`guaranteed_payments`: their own charges, accrued, paid to no one;
"interest paid", 45-25(e), is cash paid); and a purchase on the
seller's own credit, an operating payable (50-4, "acquiring assets by
assuming directly related liabilities"; EY 5.3.1), flagged
`asset_on_operating_payable` (rule 12).
- **An expense a member pays into capital** (Dr expense / Cr the
member's capital, no cash) is a constructive contribution and an
operating outflow. The member paid cash to a vendor for the company;
whether the company owes it back (Due to Members) or not (capital)
is only the form of the financing, not the substance of the payment,
which the guides follow ("the same economic result", DART 7.2). BDO
3.4 lists a parent paying a subsidiary's expenses among the cases
for constructive cash flows without asking how the subsidiary
records what it owes back (a parent's payment is often booked as a
contribution), and none of the guides read presents an expense
someone paid on the entity's behalf as noncash. The books' own K-1
worksheet already counts it as a cash contribution (`k1.rs`
INVARIANT 3, DECISION 2026-10-15), so the two agree.
- **Card purchases** follow the card's classification (D-35,
unchanged): on a card listed as financing, the issuer is a lender
that paid the merchant, so the purchase is borrowed and spent and the
card payment a repayment; on a card that is an operating payable, the
purchase is an accrual and its payment operating (d).
- *Limits* (the books can't tell who was paid). A lender's or member's
own charge credited to what the company owes them, other than
interest and guaranteed payments (a card's annual fee, rent a member
charges), reads as paid for the company: its operating outflow shows
when charged, its repayment as financing (each section's total over
the charge and its payment is right; the timing is the charge's).
Post what the company owes a member for their own goods or services
to a payable, not to the members' financing account. A note to the
seller listed in `books.financing_accounts` reads as a lender's loan
(borrowed and invested, where 50-4 makes it noncash): keep a seller's
note out of it (its principal payments then show as operating, where
45-13(c) makes them financing; flagged). An expense a member
contributes in kind (an item already owned, expensed at once) reads
as paid: post it to an asset first. A debt a member or a new lender
pays off directly is a noncash exchange (disclosed), where PwC
6.9.3.1 and BDO Example 3-6 would gross it up. Debt issue costs, a
financing outflow (45-15(f)), posted to an expense account read as
operating: post them to a contra-liability listed as financing, so a
fee the lender withholds is a noncash exchange inside financing and
the loan reads as its net proceeds. An entry that moves revenue or
expense straight to capital by hand, as a close does, reads as paid
or received for the company: close periods with `books.close_period`,
whose entries are never in the statement (rule 10).
12. **Equipment paid for, or sold, later** (D-35; 45-12(c), 45-13(c)). A
bill payment carries its bill's split, equipment part first: the
payables line's equipment part is investing, so its payment is an
investing outflow, the reconciliation's payables change leaves it out,
and the purchase is disclosed only for what is unpaid at the period's
end (a payment reversed by then is unpaid again; EY FRD 5.3.3; DART
6.1.3; bills post to the general-expenses
control today, so this waits for bills with account lines). A card
purchase follows the card's classification: on an operating payable it
is disclosed and flagged (`asset_on_operating_payable`), on a financing
one it is borrowed and invested (rule 11) and its payment a repayment. A sale for an amount owed on an
operating receivable is disclosed and flagged with the fix
(`asset_sold_on_operating_receivable`: post it to an investing
account). The flags are the statement's `warnings`, and items in the
viewer's Needs attention. Limits: payments more than "soon after" purchase are
financing by 45-13(c) when the seller financed it, which the books
can't tell from a bill; unregistered equipment is operating (the asset
register's `unregistered_cost` flags it).
**Enforced:** `profit_and_loss_for_period`, `cash_flow`. **Checked:** Lean
`statements_add_up`; `prop_period_pnl_partitions`;
`cash_flow_reconciles_to_change_in_cash`;
`financing_is_gross_borrowing_apart_from_repayment`,
`a_loan_the_entity_makes_is_investing_gross`,
`an_expense_the_owner_paid_is_borrowing_then_operating`.
Scope: single-currency books (R-5). A foreign-currency cash account's
exchange effect would be a separate reconciling line (830-230-45-1); a
hand-posted revaluation of a cash account shows as an operating receipt.
**Enforced:** `profit_and_loss_for_period`; `cashflow::cash_flow` (with
`kernel::entry_flows`, `apply_cash`, `constructive`, `exchanged`),
`role_problems`, `foot`; `ledger_package::cash_flow_for` (the server, the
package and the viewer). **Checked:** Lean `statements_add_up`,
`cashflow_sections_sum_to_cash_change`, `entry_flows_sum`,
`flows_reversal`, `constructive_nets`, `constructive_neg`,
`constructive_sections_net`, `stmt_flows_sum`, `stmt_flows_reversal`,
`operating_reconciliation_ties`, `cashflow_reversal_nets`,
`Reachable.cashflow_foots`, `Reachable.cashflow_is_change_in_cash`; Kani
`entry_flows_*`, `no_cash_no_flow`, `take_is_odd_and_bounded`,
`apply_cash_mirrors`, `apply_cash_spends_exactly`,
`exchanged_is_bounded`, `constructive_nets_to_zero`,
`constructive_mirrors`; `prop_period_pnl_partitions`,
`prop_cash_flow_laws` (5,000 cases, reversals of reversals, rule 11's
shapes), `prop_pure_entries_sections_are_movements`; regressions
`defect1_reversed_contributions_foot_regression`,
`defect1_two_member_llc_first_year_regression`,
`defect1_two_member_llc_as_of_march_18_regression` (and bookspec
`cash-flow.*`, `cash-flow.paid-on-the-companys-behalf` for rule 11);
`disposal_proceeds_all_investing`,
`an_expense_a_member_paid_is_borrowed_and_spent`,
`reimbursing_a_member_is_a_repayment_of_borrowing`,
`equipment_a_lender_paid_for_is_borrowed_and_invested`,
`an_expense_a_member_paid_into_capital_is_contributed_and_spent`,
`property_a_member_contributes_stays_noncash`,
`equipment_on_the_sellers_credit_stays_noncash_and_flagged`,
`a_payment_made_for_the_company_and_its_reversal_net`,
`part_paid_by_a_member_and_a_refund_a_member_received`,
`a_lender_pays_balance_sheet_lines_first_and_a_customer_pays_a_member`,
`interest_and_guaranteed_payments_charged_to_a_creditor_stay_noncash`,
`a_fee_withheld_from_a_loan_follows_its_account`,
`odd_shapes_foot_and_net`, `operating_classes_follow_asc_230_10_45_25`,
`a_reversal_of_a_reversal_is_shown_and_foots`,
`a_reversal_three_levels_down_is_labelled_a_reversal`,
`operating_cash_is_classed_kind_by_kind`,
`two_kinds_of_one_class_are_one_line`,
`interest_paid_in_a_disposal_stays_operating`,
`a_loss_on_disposal_on_a_revenue_or_expense_account_is_investing`,
`an_investments_gain_is_investing`, `cash_goes_to_the_sections_in_order`,
`cash_goes_to_a_sections_kinds_in_order`,
`converting_member_debt_to_capital_is_disclosed`,
`a_bill_payment_carries_its_bills_split`,
`a_reversed_bill_payment_leaves_the_purchase_unpaid`, the role refusals,
`foot_refuses_any_difference` (`crates/ledger-core/tests/spec_cash_flow.rs`).
## B-15 Depreciation: straight line, salvage never depreciated, partial months by days
@@ -491,10 +749,11 @@ Attorneys' gross proceeds stay at $600 (not modeled).
What counts as paid: payments made in the calendar year (§6041(a)), so a
prepayment counts when made. A worksheet as of a day (the CPA package's,
B-33) counts the year's payments from January 1 through that day. The engine counts credits minus debits to the
payment sources on a vendor's tagged entries: `[books] cash_accounts` and
`financing_accounts` (a member or lender paying on the company's behalf;
the company is still the payer). A card charge leaves neither (1099-K); a
B-33) counts the year's payments from January 1 through that day. The
engine counts credits minus debits to the payment sources on a vendor's
tagged entries: `[books] cash_accounts` and `financing_accounts` (a
member or lender paying on the company's behalf; the company is still the
payer). A card charge leaves neither (1099-K); a
bill is not paid until it is (`form1099::vendor_1099_report_with`,
checked by `payments_come_from_cash_and_financing_only`). A W-9 is on
file by the vendor's flag or its party's W-9 facts.
@@ -1067,7 +1326,8 @@ fixed asset register, mid-year and at year end; `as_of_package_iif_stops_at_as_o
`iif_ties_to_the_trial_balance_as_of`, 2,000 cases); `ledger-mcp`
`oracle_mcp.rs` (`cpa_package_holds_the_year_and_its_evidence`); the
bookspec examples `bookspec/examples/as-of-package-stops-at-as-of.toml`
and `bookspec/examples/1099-worksheet-through-as-of.toml`.
and `bookspec/examples/1099-worksheet-through-as-of.toml` (`ledger-core`
`tests/bookspec.rs`).
## B-34 The QuickBooks Desktop file (IIF): plain ASCII, every entry through as_of, closes left out
+193 -1
View File
@@ -1,6 +1,7 @@
# FASB Accounting Standards Codification: paragraphs read directly
Read 2026-10-14 in the ASC's basic view (asc.fasb.org, the owner's login).
Read 2026-10-14 in the ASC's basic view (asc.fasb.org, the owner's login),
except the ASC 230 section added 2026-10-20, which says where it was read.
The Codification is copyrighted by the Financial Accounting Foundation,
so this file keeps only short quotes and paraphrase, with the paragraph
numbers to look up. Earlier ASC paragraphs were read through Deloitte's
@@ -49,6 +50,197 @@ loans the entity makes are investing (45-12(a), 45-13(a)). Proceeds of
→ B-14: money owners advance (Due to Shareholders) is borrowing, so
financing, gross; a loan the company makes is investing, gross.
## ASC 230 for the direct method (rules.md B-14, P3 defect 1)
Read 2026-10-20, not in the ASC basic view: DART's Codification pages
need a login, and its public Roadmap on the statement of cash flows
quotes only some of these paragraphs. So they were read where public
sources reproduce the Codification's text: EY's Financial reporting
developments guide "Statement of cash flows" (July 2026,
https://www.ey.com/content/dam/ey-unified-site/ey-com/en-us/technical/accountinglink/documents/ey-frd42856-07-29-2026.pdf,
which quotes ASC 230 and 830-230 in full; page numbers its own), the
FASB's ASUs that last amended them (ASU 2016-15,
https://storage.fasb.org/ASU%202016-15.pdf; ASU 2016-18,
https://storage.fasb.org/ASU%202016-18.pdf), and Deloitte's public DART
Roadmap where it quotes them
(https://dart.deloitte.com/USDART/home/codification/presentation/asc230-10/roadmap-statement-cash-flow,
no trailing slash: with one the page is "Tree node not found").
Quotes are short; the rest is paraphrase.
- **230-10-10-1** (EY p. 1): the statement's primary objective is "to
provide relevant information about the cash receipts and cash payments
of an entity during a period." → B-14 rule 1.
- **230-10-45-1** (EY p. 1): the statement "shall report the cash effects
during a period of an entity's operations, its investing transactions,
and its financing transactions." (It says nothing of reconciling
beginning and ending cash: that is 45-24.)
- **230-10-45-4** (EY p. 5): the statement explains the change in the
total of cash, cash equivalents and restricted cash. ASU 2016-18 struck
its old sentence on the totals at the beginning and end of the period
(gone from the current text). → rule 1: the cash accounts are all of
them. (50-7 and 50-8, EY pp. 5-6, 30: the nature of restrictions, and
the balance-sheet lines that hold the total when there are several.)
- **230-10-45-5** (EY p. 5): purchases and sales of cash equivalents are
cash management, and transfers among cash, cash equivalents and
restricted cash "are not reported as cash flow activities". → rule 1: a
transfer between two cash accounts is no flow.
- **230-10-45-12(c)** (EY p. 41; ASU 2016-15 p. 25): investing inflows
include "Receipts from sales of property, plant, and equipment and other
productive assets". → rule 4.
- **230-10-45-13(c)** (EY p. 41; ASU 2016-15 p. 12): investing outflows
include payments "at the time of purchase or soon before or after
purchase" for PP&E; generally only those are investing, and incurring
debt directly to the seller is a financing transaction whose later
principal payments are financing. → rule 12 (the bill split), and the
limit B-14 records.
- **230-10-45-14(a)** (EY p. 42): financing inflows include "Proceeds from
issuing equity instruments". **45-15(a)**: financing outflows include
"Payments of dividends or other distributions to owners"; **45-15(c)**:
most principal payments on seller-financed debt for PP&E are financing.
(45-14(b) and 45-15(b): above, read directly.)
- **230-10-45-16(a), (b)** (EY p. 43): operating inflows include "Cash
receipts from sales of goods or services", including collections of
receivables from customers arising from those sales; and interest and
dividends received. 45-16(c): all other operating receipts. → rule 5,
rule 4's exception.
- **230-10-45-17** (EY pp. 43-44): operating outflows: payments for goods
for resale (a), to "other suppliers and employees" (b), to governments
for taxes, duties, fines and other fees (c), interest to lenders and
other creditors (d), and others ((e), (ee), (f)). (Income taxes fall
under (c); 45-25 names them a class.)
- **230-10-45-8, 45-9** (EY p. 12): only items whose "turnover is quick,
the amounts are large, and the maturities are short" (original maturity
"three months or less"; amounts due on demand count) may be reported
net, and even then need not be. **230-10-45-26** (EY p. 13): otherwise
investing and financing inflows and outflows are reported separately,
"proceeds of borrowings ... separately from repayments of debt". → rule
5: gross lines, members' advances and their repayments apart.
- **230-10-45-24** (EY p. 15; ASU 2016-18 pp. 4-5): the statement reports
net cash from operating, investing and financing activities and "the
net effect of those flows" on cash, "in a manner that reconciles
beginning and ending totals". → rule 9, the footing.
- **230-10-45-25** (EY p. 8; ASU 2016-15 p. 10): entities "are encouraged
to report major classes of gross cash receipts and gross cash payments";
those that do "shall, at a minimum, separately report" (a) cash
collected from customers, (b) interest and dividends received, (c) other
operating cash receipts, (d) cash paid to employees and other suppliers,
(e) interest paid, (f) income taxes paid, (g) other operating cash
payments. → rule 5, the operating classes; the direct method is a
choice the standard encourages, not one it requires.
- **230-10-45-28** (EY p. 10; DART 3.1): the indirect method adjusts net
income to remove (a) deferrals and accruals of operating receipts and
payments, such as changes in receivables and payables, and (b) items
with no operating cash effect, including those "whose cash effects are
related to investing or financing cash flows, such as gains or losses on
sales of property, plant, and equipment". → rule 8's G and W.
- **230-10-45-29** (EY p. 7; DART 3.1): the reconciliation of net income
to operating cash is required with either method; it "shall separately
report all major classes of reconciling items", at a minimum the
changes in operating receivables, inventory and payables.
- **230-10-45-30** (EY p. 8; DART 3.1): with the direct method, that
reconciliation "shall be provided in a separate schedule." → rule 8.
- **230-10-50-3** (EY p. 47): investing and financing activities that
"affect recognized assets or liabilities but that do not result in cash
receipts or cash payments in the period shall be disclosed", narrative
or in a schedule. → rule 7.
- **230-10-50-4** (EY p. 47): its examples, among them: "converting debt to equity";
acquiring assets by assuming directly related liabilities; obtaining a
right-of-use asset for a lease liability (the old "capital lease"
wording, replaced); receiving a gift of an asset; exchanging noncash
assets or liabilities for others (also a beneficial interest obtained
in a securitization, not listed here). → rule 7's exchange inside one
section.
- **230-10-50-5** (EY p. 47): "Some transactions are part cash and part
noncash; only the cash portion shall be reported in the statement of
cash flows." → rule 3.
- **230-10-50-6** (EY p. 47): with only a few noncash transactions, they
may be on the same page as the statement; otherwise elsewhere, clearly
referenced to it. → the printed statement's noncash schedule.
- **830-230-45-1** (EY p. 81; DART 7.1): the effect of exchange-rate
changes on cash held in foreign currencies is reported as a separate
part of the reconciliation of the change in cash. → B-14's scope note
(single-currency books, R-5).
- **105-10-05-1, 05-2, 05-3** (read only in their 2009 text, ASU 2009-01
Appendix B, pp. 17-18, https://storage.fasb.org/ASU2009-01.pdf; the
current wording is not confirmed): the Codification is "the source of
authoritative generally accepted accounting principles"; where it does
not specify, an entity first considers principles for similar
transactions "and then consider[s] nonauthoritative guidance from other
sources"; practices not in the Codification are nonauthoritative
(sources include accounting textbooks, handbooks and articles). → rule
11: the Codification does not address payments made on the entity's
behalf (below), so this is where firm guidance comes in; rule 11
follows it (D-42), a choice the standard leaves open, not a requirement
of any paragraph.
Also read there, for the design (not authoritative, 105-10-05-3):
- DART 6.1.3 and EY 5.3.1 and 5.3.3 (equipment on account: payments soon
after purchase are investing, "soon" read by the SEC staff as three
months or less; the change in payables in the reconciliation leaves
out payables for investing; the noncash disclosure is the liability
that remains unpaid at the period's end). → rule 12.
- Payments a third party makes, or cash it receives, on the entity's
behalf (rule 11, D-42). No ASC paragraph addresses them: PwC Viewpoint,
Financial statement presentation 6.9.3 ("ASC 230 does not address these
situations"); KPMG Handbook, Statement of cash flows (March 2026)
Q8.3.10 ("Topic 230 does not directly address"); BDO Blueprint,
Statement of cash flows under ASC 230 (December 2025) 3.4 ("While ASC 230
is silent"); EY 4.6.2 ("we believe judgment will be needed"). Read
2026-10-20 for D-42, in each firm's public text (PwC
https://viewpoint.pwc.com/dt/us/en/pwc/accounting_guides/financial_statement_/financial_statement___18_US/chapter_6_statement__US/69_supplementary_cash.html;
DART https://dart.deloitte.com/USDART/home/codification/presentation/asc230-10/roadmap-statement-cash-flow/chapter-7-common-issues-related-cash/7-2-constructive-receipt-disbursement;
BDO https://arch.bdo.com/Statement-of-Cash-Flows-Under-ASC-230; EY as
above):
- **PwC 6.9.3.1** (Constructive receipts and disbursements): "a reporting
entity should include cash flows received or paid by a third party on
behalf of the reporting entity", as though through its own accounts.
Its examples: a transfer agent moving a new lender's proceeds to pay
off the old lender (gross up both), and a bank paying a vendor at the
entity's instruction ("a financing inflow for the receipt of the debt
proceeds", and an operating outflow for the vendor). "Judgment is
required."
- **DART Roadmap 7.2** (Constructive receipt and disbursement): when a
third party handles cash on the entity's behalf, the entity may have
constructive receipt or disbursement, because "the same economic
result would be achieved if the cash had been received by or disbursed
to" it directly. Inventory financed by an unrelated lender that pays
the supplier: a financing inflow and an operating outflow, repayments
financing; a mortgage lender wiring the seller: a financing inflow and
an investing outflow; Example 7-2, a lender paying an insurance
premium: an operating outflow for the premium and a financing inflow.
The contrast is a supplier's own finance subsidiary (AICPA Technical
Q&A 1300.16, and the SEC staff at the 2005 AICPA conference): a trade
loan, noncash.
- **BDO 3.4** (Constructive disbursements and receipts): among its cases,
"A parent might pay on behalf of a subsidiary expenses that are
recognized in the subsidiary's separate financial statements"; an
entity "generally should report constructive cash flows when it
contracts with a third party to act on its behalf (for example, a
transfer agent, investment bank, or lender) or when cash does not flow
through the entity's cash accounts for administrative convenience".
Example 3-5: a bank remitting the price of equipment to the supplier,
an investing outflow and a financing inflow, later principal payments
financing (citing TQA 1300.19); Example 3-6: a refinancing through an
agent, a financing inflow and outflow; Example 3-4: the supplier's own
finance subsidiary, noncash (TQA 1300.16).
- **EY 5.2.4 and 5.3.1**: inventory or equipment financed by a third
party (not the seller) is an operating or investing outflow and a
financing inflow; seller-financed purchases are noncash "to the extent
of the initial seller financing", disclosed under 50-3 to 50-6, and
later principal payments are financing whichever financed them.
- **KPMG Q8.3.10** accepts a noncash presentation (citing 50-3) for
property and equipment a lender pays for.
→ rule 11 (D-42): constructive receipt and disbursement for what a
member (through the members' financing account, or capital for an
expense) or a lender pays or receives for the company; noncash for
property a member already owned (50-4) and for the seller's own credit
(EY 5.3.1). The expense-to-capital case follows BDO 3.4's parent paying
a subsidiary's expenses, and the substance test of DART 7.2 and PwC
6.9.3.1, which turn on who paid whom, not on how the entity records
what it owes back.
## 606-10-55-36 through 55-38 (Revenue: principal or agent)
An entity controlling the specified good or service before transfer is
+159 -3
View File
@@ -23,7 +23,7 @@ promise.
| Model-based stateful | the Lean state machine, transcribed (3) | `tests/model.rs` | `just check` | ~3s | every change |
| Differential: Decimal vs i64 | the kernel at two types (3) | `kernel_bridge.rs` | `just check` | <1s | every change |
| Differential: GnuCash | another implementation, adjudicated (3) | `tests/oracle_gnucash.rs`, `oracle/gnucash/` | `just oracle` | ~2 min | weekly |
| Formal proofs | Kani (bounded) and Lean (unbounded) | `src/proofs.rs`, `verify/lean/` | `just prove` | ~3 min | weekly |
| Formal proofs | Kani (bounded) and Lean (unbounded) | `src/proofs.rs`, `verify/lean/` | `just prove` | ~15-20 min (bounded by `entry_flows_of_a_reversal_mirror`, ~14 min; all 29 harnesses ~43 min of CPU, run in parallel) | weekly |
| Fuzzing | crash, hang, broken books (4); for `fuzz_store_replay` (validly chained journals with fuzz-chosen events): books that open must verify, and the viewer must accept exactly what the writer does | `fuzz/fuzz_targets/`, corpora in `fuzz/corpus/` | `just fuzz <target> <secs>` | 10 min each | weekly |
| Miri | undefined behavior in our use of dependencies (4) | the core's unit, bridge, invariant tests | `just miri` | ~2 min | on demand |
| Golden | `tests/golden/fixture_company.json` (5) | `invariants.rs` | `just check` | <1s | every change |
@@ -606,7 +606,9 @@ worked by hand in the test's comment.
anonymized, with a close to retained earnings between two members closes.
The run rule left A −399.24 / B −399.22; the rule since P3 gives −399.23
each (March: Dr 3000 199.61, Dr 3001 199.62). Its bookspec example is
`bookspec/examples/members-close.odd-cent-across-closes.toml`.
`bookspec/examples/members-close.odd-cent-across-closes.toml`; it and the
other `members-close.*` examples are checked with every example by
`ledger-core` `tests/bookspec.rs` (`every_bookspec_example_holds`).
**Core** (`ledger-core` `tests/odd_cent.rs`): a true-up from inception
(`members_closes_true_up_from_inception`); a close that posts nothing
@@ -763,7 +765,17 @@ fixtures:
ones (`bookspec/examples/as-of-package-stops-at-as-of.toml`,
`1099-worksheet-through-as-of.toml`) and the IIF's
(`iif-quickbooks-journal-file.toml`, formats appendix), each expected
value derived by hand; `the_bookspec_iif_example_matches_the_engine`
value derived by hand. `ledger-core` `tests/bookspec.rs` loads every
example, the formats appendix's too, and checks the as-of ones' trial
balances, profits and losses and 1099 payments against the engine
(`every_bookspec_example_holds`, the one loader of every example; the
tests beside it refuse a query no crate answers, a format query outside
the formats appendix, an unknown appendix, a payee not in the setup, a
figure query leaving out an account, payee or entry line it covers, an
as-of query given a period, `after` past the last event, members'
shares not summing to 1 and a members close declared with another
rounding, and show `after` asks the books after that event);
`the_bookspec_iif_example_matches_the_engine`
reads the IIF example and checks the engine gives exactly its file and
changes.
- Review R18 and the README: `one_list_of_cash_accounts_per_package`,
@@ -895,6 +907,149 @@ condition and `receivable_payable`; `fonts.rs` and `theme.rs`
`parties.rs` `tin_separator`'s arms and `tin_invisible`, and the gap that
doesn't count them.
## P3: cash flow (defect 1, 2026-10-20)
The statement of cash flows was rebuilt by the direct method (rules.md
B-14, D-35), and what a member or a lender pays for the company shown as
cash borrowed and spent (D-42, rule 11). Built, reviewed twice, `just
check` and `just prove`; no mutation run (D-33): what P12 must cover is at
the end.
- **Named regressions** (`crates/ledger-core/tests/spec_cash_flow.rs`;
also bookspec examples, `bookspec/examples/cash-flow.*.toml`, checked by
`tests/bookspec.rs` on every run):
`defect1_reversed_contributions_foot_regression` (the minimal
reproduction: a property contribution reversed, which broke footing by
the contribution's amount), `defect1_two_member_llc_first_year_regression`
and `defect1_two_member_llc_as_of_march_18_regression` (a replica of
the 23 entries defect 1 was found in: the same shape, order, accounts
and roles, Member A and B and generic vendors, every amount and date
made up, so none is the real books'; to 2026-03-31, operating -596.24,
investing 0.00, financing +2,216.40, the change in cash +1,620.16, and
to 2026-03-18, operating -549.86, financing +2,549.86, worked by hand
in the test's doc comment).
- **The rule, case by case** (same file; each oracle worked by hand from
its paragraph in the test's doc comment): disposals at a gain, a loss
and before any depreciation (`disposal_proceeds_all_investing`); a sale
on an IOU (disclosed, flagged, with the fix); property contributed;
what a member or lender pays or receives for the company (D-42, rule
11): an expense through Due to Members, equipment a bank paid for, an
expense paid into capital, a financing card, part cash and part a
member's, a refund to a member, a customer paying a member, a payment
made for the company and its reversal (in the period and alone, a
prepaid and equipment too), the reimbursement, the uses' order (rule
11's convention); and what stays noncash: property a member owned (with
members configured and without), the seller's credit (flagged), interest
and guaranteed payments charged to a creditor, a fee withheld on a
contra-liability. From the second review: odd shapes (two cash accounts
in one entry, one account on both sides, a reversal chain across the
period start, a close: `odd_shapes_foot_and_net`) and taxes and
government fees as other payments, (g); reversals in the
period, alone, taking their root's sections and class, and reversals of
reversals (review item 1); part cash (50-5); a fee withheld from a loan;
interest with principal, paid and received; one entry per operating
class (a)-(g); depreciation; cash spent on a depreciation expense account
(D1-e); the reconciliation tying to operating; closes; the start date;
transfers between cash accounts; debt converted to capital, a note
received for equipment, a trade-in (review item 2); the bill split
(D-35, through a bill restored as a later version would journal it),
and a bill payment reversed in the period; a card purchase of
equipment, on an operating and a financing card; each member's kinds;
the five role refusals and `foot` directly. From the P3 review: interest
classed apart from the rest of an entry's operating cash
(`operating_cash_is_classed_kind_by_kind`) and kept operating in a
disposal; a loss on disposal on a revenue-typed or an expense-typed
account; an investment sold at a gain; a reversal three levels down;
and both of rule 3's conventions pinned (the sections' order, the kinds'
order).
- **Properties, 5,000 cases each** (`CF_CASES`, default 5,000, about 16 s):
`prop_cash_flow_laws` over random books of 33 templates (every shape
the rule names, rule 11's included) and reversals of any earlier entry,
reversals included: the sections are the change in cash and the
model's; each section is its lines and kinds; the reconciliation is
operating; an entry's lines are its cash, what was handled for it
netting to zero, each line's cash part with the entry's sign; every
disclosure is its parts' positive sum or its exchange; an entry and its
reversal in the period change nothing; periods split and add; closing
every month changes nothing; scaling scales every figure.
`prop_pure_entries_sections_are_movements`: for pure entries, each
section is minus its accounts' movement over the entries that touch
cash or that a member or lender settled whole for the company (the
plan's wording, with rule 11 modelled apart from the engine; review
item 7's definition of pure). The older properties in `spec_reports.rs`
are kept with new oracles (financing is the cash part of equity and
designated debt plus what the loan or capital paid or received for the
company, by an independent model of rules 3 and 11).
- **Bridge:** `entry_flows_agree`, `apply_cash_and_exchanged_agree`,
`constructive_agrees`.
- **Proofs:** Kani `entry_flows_sum_to_cash`,
`entry_flows_pure_are_movements`, `entry_flows_are_bounded`,
`entry_flows_of_a_reversal_mirror`, `no_cash_no_flow` (entries of up to
three lines), `take_is_odd_and_bounded`, `apply_cash_mirrors`,
`apply_cash_spends_exactly`, `exchanged_is_bounded`,
`constructive_nets_to_zero`, `constructive_mirrors`; Lean
`cashflow_sections_sum_to_cash_change`, `entry_flows_sum`,
`flows_reversal`, `constructive_nets`, `constructive_neg`,
`constructive_sections_net`, `stmt_flows_sum`, `stmt_flows_reversal`,
`operating_reconciliation_ties(_all)`, `cashflow_reversal_nets`,
`Reachable.cashflow_foots`, `Reachable.cashflow_is_change_in_cash`
(docs/verification.md, law 10).
- **Sensitivity (P3 review, by hand, no mutation run):** 18 deliberate
breaks to `cashflow.rs` and `kernel.rs` (a dropped reversal
flip, no netting, financing read as operating, no rule 4, no exchange
disclosure, no interest class, no warnings, the bill's payments
ignored, the label's depth parity, repeated codes allowed, depreciation
disclosed, the sections' or kinds' order reversed, the customer party
ignored, accumulated depreciation in the exchange, the interest
exception dropped, rule 4 for investing accounts): 17 fail a test (4
of them only since the review's tests); one is equivalent today
(`mirrors` ignoring amounts: every reversal mirrors its original until
P4's drafts).
- **Sensitivity, second round (after D-42, by hand, no mutation run):**
17 breaks to rule 11 and the kernel's `constructive` (no lender pass, no
member pass, no receipts for the company, a reversal not mirrored, a
lender paying for no investing, capital paying for property, receipts
for property, receivables not received, guaranteed payments or
interest paid for, `on_behalf` not reported, the exchange on the net
flow, owners' equity read as a lender, pairing that ignores
`on_behalf`, the kernel's received sign, `max` for `min`, the uses'
order reversed): 16 fail a test; one is equivalent today (pairing that
ignores `on_behalf`: a mirrored reversal's real and constructive parts
are each proved to mirror, Kani `entry_flows_of_a_reversal_mirror` and
`constructive_mirrors`, so the check is defensive, for P4's drafts).
The first round's 18 breaks, re-run on the reworked code (four
adapted where the code moved), and one more for the taxes class: 18
fail a test, `mirrors` ignoring amounts still the one equivalent.
- **End to end:** the printed statement's footing, schedules and rows as
the engine's (`cash_flow_foots_and_reconciles`,
`cash_flow_adjustments_appear_only_when_there_are_some`, ledger-import);
the CPA package's statement with both schedules
(`the_cash_flow_carries_both_schedules`); the MCP tool and its exports
field for field against the core (`cash_flow_exports_equal_the_core_statement`),
the CSV's warnings, the settings' roles and a member-paid expense over stdio
(`cash_flow_reads_its_account_roles_from_the_books_settings`), refusals
naming the setting (`cash_flow_refuses_contradictory_roles`), the
settings' problems from the same check; the viewer's statement as the
server's, a loan the setting leaves out operating in both, a refusal
shown as a reason and no number, and the page painted
(`the_cash_flow_page_is_the_servers_statement`,
`a_refused_cash_flow_shows_why_and_no_number`,
`the_cash_flow_page_paints_its_schedules`; with `SHOT_DIR`, a PNG); the
statement's warnings as Needs attention items
(`cash_flow_warnings_are_items`);
every old-books fixture's statement computed or refused, never an
engine error (`every_figure_over_old_books_is_computed_or_refused`).
**For P12** (D-33): `cargo mutants` on `ledger-core`'s `cashflow.rs`
(`cash_flow`, `analyse`, `pairs`, `label`, `class_of`, `reconcile`,
`warnings`, `bill_splits`, `role_problems`, `foot`, `on_behalf`) and
`kernel.rs`'s `take`, `apply_cash`, `entry_flows`, `constructive`,
`exchanged`; `ledger-import`'s
`report::cash_flow`; `ledger-mcp`'s `cash_flow_out`, `cash_flow_csv`,
`export_cash_flow` and `settings_problems`; zero unexplained survivors
(plan P3 accept). Likely equivalent, to adjudicate: `min` against `max`
in `take` where both bounds coincide, and the kind order's tie-breaks.
## Benchmarks (baseline 2026-10-13)
No budget, by decision (the owner, 2026-10-13: the books do little work
@@ -940,6 +1095,7 @@ accounting question), CHANGE (a source says otherwise; work pending).
| 6 | Reconciliation balances | CONFIRMED | Signed by the account's normal side (a card reads as owed), as statements show it; `reconciling_a_card_reads_its_normal_side_...` |
| 7 | A member's ending on one equity statement may differ by a cent from the next statement's beginning | CHANGED 2026-10-13; CHANGED P3 | A capital account is one running balance (Treas. Reg. §1.704-1(b)(2)(iv)(b); the Item L quote this row once gave was misread, P3 review R-4). Undistributed earnings now split cumulatively as of each date, so each member's capital chains exactly (`each_members_capital_chains_across_statements`; it fails on the old code); since P3 the split is what the count's next close would give, so a date's capital never moves when its month is closed (D-38; `each_members_capital_chains_and_holds_through_closes`); rules.md B-13 |
| 8 | Cash flow nets one line per account; investing comes only from registered assets | CHANGED 2026-10-13 | ASC 230-10-45-7: gross receipts and payments "more relevant" than net; 45-8 limits netting to quick-turnover items. Financing and investing are now gross; loans made and investments bought are investing (230-10-20, 45-13) via `[books] investing_accounts`. Owner-advanced expenses: PwC 6.9.3.1 constructive treatment via `[books] financing_accounts` (rules.md B-14) |
| 8a | Cash flow by the indirect method; member-paid expenses as constructive receipts | CHANGED 2026-10-20 | The direct method with the reconciliation as a separate schedule (ASC 230-10-45-25, 45-30); noncash investing and financing activities disclosed, only the cash portion reported (50-3, 50-5). Member-paid expenses stay constructive receipts and disbursements, now gross and on each payment's date, and the same for a lender's payments and an expense paid into capital: a choice (D-42, after a day as noncash under D-35), since ASC 230 doesn't address payments made on the entity's behalf and the firm guides present them so (PwC 6.9.3.1, DART 7.2, BDO 3.4, EY 4.6.2; KPMG Q8.3.10 also accepts noncash for property a lender pays for). rules.md B-14 rule 11, P3 defect 1 |
| 9 | An asset's life ends at purchase + life months, that day not held; day-count proration | CONVENTION | Exactly N months of service; day proration and the mid-month convention are both accepted book policies (ASC 360-10-35-4, read 2026-10-14: any systematic and rational allocation) |
| 10 | A payroll entry has one line per account total | CONFIRMED | The per-employee detail the IRS requires ("Amounts and dates of all wage ... payments", Employment Tax Recordkeeping) is kept in the run; a summary entry is standard |
| 11 | A period with exactly the dates of an existing one is allowed | DESIGN | Nothing governs duplicate periods; harmless (the second close locks only). Refusing exact duplicates is an option |
+95 -14
View File
@@ -83,6 +83,58 @@ Each law, and what proves it. Kani harnesses are in
`Reachable.accounting_equation_through` (any number of accounts)
9. **Period statements add up**: a year's P&L is the sum of its months'.
- Lean `statements_add_up`
10. **The statement of cash flows foots** (rules.md B-14, plan P3 defect
1): each entry's cash is applied to the sections moving against it,
operating, investing, financing, each up to its own movement; what a
member or a lender paid or received for the entry, with no cash
account moving (rule 11, D-42), is added as a constructive receipt
and disbursement that nets to zero within the entry; so each entry's
flows sum to its cash and what neither settled sums to zero, and
operating + investing + financing is exactly the change in the cash
accounts, over any entries, for any tagging whose cash tag follows
the account. A reversal's flows, constructive ones included, are its
original's negated (so an entry and its reversal in one period drop
out together), and net income plus the reconciling items (gains and
losses on investing assets, the noncash operating parts, the changes
in operating balances) is the operating section, whenever revenue and
expense lines are only operating or investing. The engine checks the
same identities at runtime and refuses (`CashFlowDoesNotFoot`) rather
than show a statement that doesn't foot.
- Kani `entry_flows_sum_to_cash`, `entry_flows_pure_are_movements`,
`entry_flows_are_bounded`, `entry_flows_of_a_reversal_mirror`,
`no_cash_no_flow` (end to end on entries of up to three lines, each
in any of the four places: four lines ran past half an hour per
harness; at three, the reversal's mirror is the slowest harness in
the suite, about 14 minutes on the development laptop, the others
seconds to 6 minutes), `take_is_odd_and_bounded`, `apply_cash_mirrors` (the
parts, for any amounts), `apply_cash_spends_exactly` (how a
section's cash splits among its kinds, operating's classes
included), `exchanged_is_bounded` (the
exchange inside investing and financing that is disclosed, given
the cash in and out of the two sections),
`constructive_nets_to_zero` and `constructive_mirrors` (what a
member or lender paid or received for the company, either way, for
any amounts: the parts net to zero, settle their own movements
toward zero and no further, leave no source beside a use it could
settle, and mirror under a reversal)
- Lean `net_splits_by_flow`, `applyCash_conserves`,
`applyCash_exhausts`, `applyCash_neg`, `entry_flows_sum`,
`flows_reversal`, `constructive_nets`, `constructive_neg`,
`constructive_sections_net` (the kernel's `constructive` modelled as
it is written: two passes of `applyCash`; its parts by section net
to zero), `stmt_flows_sum`, `stmt_flows_reversal` (an entry's
statement flows, its cash flows plus any constructive triple that
nets to zero, and mirrors for a reversal), and over them
`cashflow_sections_sum_to_cash_change`,
`secNet_cash_is_movement`, `operating_reconciliation_ties`,
`operating_reconciliation_ties_all`, `cashflow_reversal_nets`;
`Reachable.cashflow_foots` and `Reachable.cashflow_is_change_in_cash`
(in every reachable state: the sections over the entries between two
days are the cash accounts' ending balance less their beginning)
- bridge `entry_flows_agree`, `apply_cash_and_exchanged_agree`,
`constructive_agrees`;
properties `prop_cash_flow_laws`,
`prop_pure_entries_sections_are_movements` (5,000 cases each)
### The books over time
@@ -94,21 +146,21 @@ Each step carries the checks the engine makes before it mutates. These
theorems hold in **every state reachable from empty books, by any
sequence of commands, of any length**:
10. **The invariant holds**: chart codes are unique, every posted entry is
11. **The invariant holds**: chart codes are unique, every posted entry is
acceptable and on known accounts, and no draft is dated in a closed
period. (That last one is why the store can journal a post before
applying it: a post can never then fail on a closed period.)
- Lean `Step.inv`, `Reachable.inv`
11. **The books always net to zero.** · Lean `Reachable.books_net_zero`
12. **Posted is forever**: posting only appends. After any sequence of
12. **The books always net to zero.** · Lean `Reachable.books_net_zero`
13. **Posted is forever**: posting only appends. After any sequence of
commands the old log is a prefix of the new one. Nothing is edited,
reordered, or removed.
- Lean `Step.extends`, `Steps.extends`
13. **Closed periods are frozen**: once a period is closed, no sequence of
14. **Closed periods are frozen**: once a period is closed, no sequence of
commands adds, removes, or changes an entry dated in it, and it stays
closed.
- Lean `Step.frozen`, `Steps.frozen`
13a. **How the books are kept changes no entry**: in the model, a record
14a. **How the books are kept changes no entry**: in the model, a record
(a setting, convention, decision, open item or approval) leaves the
chart, every posted entry, every draft and every period exactly as they
were, and any number of them keeps a reachable state reachable. The
@@ -123,7 +175,7 @@ sequence of commands, of any length**:
### Closing
14. **A closing line zeroes its account**, and **a closing entry balances
15. **A closing line zeroes its account**, and **a closing entry balances
and zeroes every revenue and expense account** through the period's
last day, whether the net goes to one account or is split among
members.
@@ -131,14 +183,14 @@ sequence of commands, of any length**:
`closing_entry_balances`
- Lean `closingEntry_net`, `closingEntry_zeroes`,
`closingEntry_accepted`, `close_zeroes`
15. **A close credits equity with exactly the net income**: revenue minus
16. **A close credits equity with exactly the net income**: revenue minus
expenses through the period's last day.
- Lean `net_closings_is_net_income`, `close_credits_net_income`
16. **An allocation's parts sum to the whole, to the unit**, however the
17. **An allocation's parts sum to the whole, to the unit**, however the
other shares were rounded, and only the last share changes.
- Kani `plug_last_sums_exactly` · Lean `plugLast_total`,
`plugLast_keeps`
17. **A run of member closes telescopes**: each member's total from a run
18. **A run of member closes telescopes**: each member's total from a run
of cumulative closes is their allocation of everything the run closed
(so its rounding is one allocation's, never a sum of them), and each
close hands out exactly its net, for any allocation whose parts sum to
@@ -249,7 +301,10 @@ can also prove false claims. So:
- **The proofs are not vacuous.** `kani::cover!` statements make Kani
show that the interesting cases are reachable: an accepted four-line
entry, a reversal on one account with several lines, three distinct
accounts, a balanced three-account chart, a close to two members. `just prove` fails if any cover is unsatisfiable.
accounts, a balanced three-account chart, a close to two members, a
part-cash part-noncash investing entry, cash settling two sections at
once, a mixed entry reversed, property contributed for capital. `just
prove` fails if any cover is unsatisfiable.
## What is and isn't proved
@@ -257,7 +312,8 @@ Be precise about the claims:
- **Kani is bounded.** It proves the kernel for every input up to 4 lines
over 3 accounts and amounts to 2^40 units (the accounting equation end
to end: up to 3 accounts). Lean proves the laws for any
to end: up to 3 accounts; the cash flow entry harnesses: up to 3 lines,
each tagged any of 4 ways). Lean proves the laws for any
size, but of a *model*. The model is a direct restatement of the kernel,
and the bridge property test ties the `Decimal` instantiation to the
`i64` one Kani checked.
@@ -276,6 +332,24 @@ Be precise about the claims:
structurally), A/R and A/P documents, payroll, depreciation schedules
(those have their own property tests), and persistence (the journal
store's hash chain is tested in `ledger-store`).
- **The cash flow model tags lines per entry with any function** meeting
the engine's guarantees (the cash tag follows the account; revenue and
expense lines are operating or investing; a reversal takes its
original's tags); which tag the engine picks for a line (rule 4's
disposals, the bill split, the chain root) is checked by the property
and example tests, not proved. A line the engine splits between two
sections is two lines in the model, the entry's net unchanged.
- **Closing entries and the cash balance.** The engine leaves closing
entries out of the sections but not out of the cash accounts'
balances; the two agree because a close moves only revenue, expense
and equity (`Ledger::validate_close_to`) and cash accounts must be
assets (rules.md B-14 rule 2). The Lean model's close step lets a
target be any balance-sheet account, so `Reachable.cashflow_foots`
takes any selection of entries with the cash over the same selection,
and `Reachable.cashflow_is_change_in_cash` counts every entry, closes
included. That a close never moves cash is checked by tests
(`closing_entries_never_appear`, `prop_cash_flow_laws` law 7), not
proved.
### P0 guard rails (2026-10-16)
@@ -324,8 +398,15 @@ mise install # once: Kani, Lean, and the rest, pinned in mise.toml
just prove
```
`just prove` runs every Kani harness, builds the Lean proofs (seconds),
`just prove` runs every Kani harness, in parallel (`-j $(nproc)`, under
a 30-minute timeout), builds the Lean proofs (seconds),
and fails if any headline theorem depends on anything beyond Lean's
standard axioms (`propext`, `Quot.sound`, `Classical.choice`). In
particular, `sorryAx` fails it. Kani downloads its pinned nightly and
CBMC into `~/.kani` on first use.
particular, `sorryAx` fails it. Its time is the slowest harness's:
`entry_flows_of_a_reversal_mirror`, about 14 minutes on the development
laptop (8 cores); the 20 harnesses before P3 take about 17 minutes of
CPU in all (`accounting_equation` the longest, about 4), the cash flow's
other ten about 17 (`constructive_mirrors` about 2.5 minutes,
`constructive_nets_to_zero` about 1.5), so the whole run is about 15 to
20 minutes. Kani
downloads its pinned nightly and CBMC into `~/.kani` on first use.