docs(spec): every rule traced to an authority; public-domain sources vendored

Stephen asked that specs come from recognized documents, not from
anyone's memory. There is no single US bookkeeping bible; authority is
layered, and this records it:

- docs/spec/sources/: verbatim excerpts (whitespace normalized), each
  with URL, retrieval date, and the SHA-256 of the fetched file, of
  public-domain texts: Pacioli's 1494 treatise in Geijsbeek's 1914
  translation (double entry, the trial balance, one money, write only
  forward, correct by opposite entry, close into capital); IRS Pub. 583,
  538, 946, 15; the 1099-MISC/NEC instructions (2025 and 2026); 26 U.S.C.
  §6041, §6041A, §704; Treas. Reg. §1.263(a)-1(f) and -4(f); Notice
  2015-82; Rev. Proc. 98-25; Form 1065 instructions; 17 U.S.C. §105. The
  excerpts were extracted by matching each passage against the fetched
  file, so none can contain text the source doesn't.
- docs/spec/rules.md: the rule catalog, B-1 to B-22. Each rule says
  AUTHORITY, CONVENTION, or DECISION; cites its sources (FASB's
  Codification and Concepts Statement 8 and OpenStax quoted briefly,
  never copied: copyright and CC BY-NC-SA); and names the code that
  enforces it and the tests and proofs that check it.
- Spec blocks in the code now carry SOURCE: lines into the catalog;
  AGENTS.md makes sourcing rule 0 of the formal-methods bar.

Corrections the sources turned up: the de minimis limit is $500 in the
regulation and $2,500 by Notice 2015-82 (both now cited); 1099
thresholds after 2026 are inflation-indexed, so the engine's flat
$2,000 for 2027+ is an open question (B-19). Unverified ASC paragraphs
(360-10-35-4, 340-10, 230-10-45-10, 606-10-55-37B, 210) are listed in
docs/spec/README.md until someone with a FASB basic-view login reads
them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GWVo7x3UHw5kwCUaWxiejX
This commit is contained in:
swaitsandClaude Opus 5.5 committed 2026-10-13 12:18:57 -06:00
1 parent 0340f316ee
commit ad572ae89d
15 files changed
+849 -9

No files matched your search

+329
View File
@@ -0,0 +1,329 @@
# Rule catalog
Every rule the engine enforces, the authority for it, and what checks it.
Status is **AUTHORITY** (a source states the rule), **CONVENTION** (common
practice no authority states; the best reference is given), or
**DECISION** (a human chose, and when). Vendored sources are in
`sources/`; FASB and OpenStax are quoted briefly under their copyright and
license (see `README.md`). Quotes from FASB's Codification were read in
Deloitte's DART roadmaps, which reproduce it ("FASB Accounting Standards
Codification: Copyright © 2005 - 2026 by Financial Accounting
Foundation").
Spec blocks in the code cite these as `SOURCE: rules.md B-n`.
---
## B-1 Every entry is a double entry: debits equal credits
**Status:** AUTHORITY
- Pacioli ch. 36 (`sources/pacioli-1494.md`): "All entries made in the
ledger have to be double entries — that is, if you make one creditor,
you must make some one debtor."
- IRS Pub. 583 (`sources/irs-records.md`): "It is self-balancing because you
record every transaction as a debit entry in one account and as a credit
entry in another. Under this system, the total debits must equal the
total credits after you post the journal entries to the ledger accounts."
**Enforced:** `kernel::check_lines` via `JournalEntry::validate` (two or
more lines, debits = credits exactly). **Checked:** Kani
`check_lines_is_exact`, `accepted_entry_nets_to_zero`; Lean
`Accepted.net_zero`; property `prop_posted_entries_balance`.
## B-2 A line's amount is positive; its side gives the direction
**Status:** CONVENTION
Pacioli keeps amounts in a debit column and a credit column (ch. 36: "All
the creditors must appear in the Ledger at the right hand side, and all the
debtors at the left"); the side, not a sign, says which way money moves. No
authority forbids a negative amount outright; wanderbooks refuses them so
that every line reads one way (2026-10-13, found by the formal pass).
**Enforced:** `kernel::check_lines` (`NegativeAmountLine`, `ZeroAmountLine`).
**Checked:** Kani `check_lines_is_exact`; test
`negative_amount_line_is_rejected`.
## B-3 One money through the ledger; foreign amounts at the transaction-date rate
**Status:** AUTHORITY
- Pacioli ch. 36: "the money that you reckon by at the beginning should be
the same all through the Ledger."
- ASC 830-20-30-1 (cited): "each asset, liability, revenue, expense, gain,
or loss arising from the transaction shall be measured initially in the
functional currency of the recording entity by use of the exchange rate
in effect at that date."
**Enforced:** `Ledger::add_line` (base currency only),
`Ledger::add_line_fx` (base amount = foreign amount × rate, original kept).
**Checked:** `foreign_currency_line_is_rejected`, `fx_overflow_is_an_error`.
## B-4 Five elements, closed list
**Status:** AUTHORITY (definitions); the five-type chart is CONVENTION
FASB Concepts Statement No. 8, Ch. 4 (2021), which replaced Concepts
Statement 6 (cited): E16 "An asset is a present right of an entity to an
economic benefit." E37 "A liability is a present obligation of an entity to
transfer an economic benefit." E61 equity is "the residual interest in the
assets of an entity that remains after deducting its liabilities." E80
revenues "are inflows or other enhancements of assets … or settlements of
its liabilities … from delivering or producing goods, rendering services,
or carrying out other activities." E81 expenses "are outflows or other
using up of assets … or incurrences of its liabilities …".
**Enforced:** `AccountType` (five variants). **Checked:** by type.
## B-5 Normal balances
**Status:** CONVENTION
No standard defines normal balances. OpenStax, *Principles of Accounting,
Vol. 1* §3.1 (cited; "Access for free at openstax.org"): "As assets and
expenses increase on the debit side, their normal balance is a debit…
Since liabilities, equity (such as common stock), and revenues increase
with a credit, their 'normal' balance is a credit." Pacioli ch. 12: capital
"must always be placed as creditor … and the cash always debtor."
**Enforced:** `AccountType::normal_side`, `kernel::normal_balance`.
**Checked:** Kani `normal_balance_is_signed`, `normal_side_increases`; Lean
`balance_after_line`.
## B-6 The trial balance balances
**Status:** AUTHORITY
Pacioli ch. 36: "the total of the credits — I do not say creditors —
should be equal to the total of the debits — I do not say debtors. If they
were not equal there would be a mistake in the Ledger." IRS Pub. 583 (B-1).
**Enforced:** follows from B-1. **Checked:** Kani `trial_balance_columns`;
Lean `trial_balance_iff`, `Reachable.trial_balance`,
`Reachable.trial_balance_through`; properties.
## B-7 The accounting equation
**Status:** AUTHORITY
CON 8 Ch. 4 ¶E62 (cited): equity "is the difference between the entity's
assets and its liabilities." On a live book, income not yet closed is part
of equity (B-11).
**Checked:** Kani `accounting_equation`; Lean `accounting_equation`,
`Reachable.accounting_equation[_through]`; property
`prop_balance_sheet_balances`.
## B-8 Posted is forever: the book is written only forward
**Status:** AUTHORITY
- Pacioli ch. 36: "You should not write backward, but always forward —
that is, go forward as the days go, which never come back. If you do
otherwise, the book would be untrue."
- German Commercial Code (HGB) §239(3) (cited; official English
translation): "An entry or a documented record may not be modified such
that it is no longer possible to establish its original content."
- Rev. Proc. 98-25 (`sources/irs-records.md`): machine-sensible records
must keep the audit trail.
**Enforced:** posted entries immutable; the journal is append-only and
hash-chained. **Checked:** Lean `Step.extends`, `Steps.extends`; property
`prop_posted_entries_immutable`; store `journal_tamper_is_detected`.
## B-9 A mistake is corrected by an opposite entry, never erased
**Status:** AUTHORITY
Pacioli ch. 31 (the *storno*): "you shall make another entry opposite this
one in the credit for the same amount … After you have made this
correction it is just as if you had written nothing in the debit column."
Ch. 36: "Mark with a cross or with an "H" that special entry, and then make
an entry on the opposite side under the same account."
**Enforced:** `Ledger::reverse_entry` (same lines, sides flipped, linked by
`reversal_of`). **Checked:** Kani `reversal_mirrors`, `reversal_cancels`;
Lean `accepted_reversal_iff`, `movement_with_reversal`.
## B-10 An entry is reversed at most once; a closing entry never
**Status:** DECISION (Stephen, 2026-10-13)
Follows from B-9 (a correction corrects once) and B-11 (a closed period
stays closed). **Enforced:** `Ledger::check_reversal`. **Checked:**
`an_entry_is_reversed_at_most_once`, `a_closing_entry_is_never_reversed`.
## B-11 Revenue and expenses close into profit and loss, and that into capital
**Status:** AUTHORITY (mechanics); the account the net lands in depends on
the entity
- Pacioli ch. 34: "you shall close this account into the capital account";
ch. 27: profit and loss "must then be transferred for its closing (saldo)
into the capital account."
- OpenStax §5.1 (cited): "Temporary (nominal) accounts are accounts that
are closed at the end of each accounting period." Corporations close into
retained earnings; partnerships into each partner's capital (B-13).
**Enforced:** `Ledger::close_period_to`. **Checked:** Kani
`closing_line_zeroes`, `closing_entry_balances`; Lean
`closingEntry_zeroes`, `closingEntry_accepted`, `close_zeroes`,
`close_credits_net_income`; `a_close_sweeps_only_through_the_period_end`.
## B-12 A closed period takes no new postings; periods close in order
**Status:** CONVENTION
Periods themselves: IRS Pub. 538 (`sources/irs-periods-and-methods.md`)
defines the tax year, calendar and fiscal. Locking a closed period and
closing in order are practice (and follow from B-8: a closed period's
book is not rewritten). **Enforced:** `closed_period_containing`,
`CloseOutOfOrder`, `Store::rehearse`. **Checked:** Lean `Steps.frozen`;
store property `refused_commands_never_reach_the_journal` (no draft in a
closed period).
## B-13 Partners share income by the partnership agreement; capital accounts carry it
**Status:** AUTHORITY (shares); DECISION (cent rounding)
- 26 U.S.C. §704(a) (`sources/irs-partnerships.md`): "A partner's
distributive share of income, gain, loss, deduction, or credit shall,
except as otherwise provided in this chapter, be determined by the
partnership agreement."
- Form 1065 Schedule M-2: "Show what caused changes during the tax year in
the partners' tax-basis capital accounts."
- **No authority** says how to round a share to the cent. Largest
remainder, ties to the earlier member: DECISION (Stephen, 2026-10-13).
Closes made before then replay with the last member absorbing it.
**Enforced:** `CloseTo::Members`, `periods::allocate`,
`kernel::apportion`, `members_equity`. **Checked:** Kani
`apportion_is_exact`, `apportion_is_fair`; properties `prop_split_*`;
`closes_journaled_under_the_old_rule_replay_with_it`.
## B-14 Statements: P&L for a period; cash flow by the indirect method
**Status:** AUTHORITY
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.
**Enforced:** `profit_and_loss_for_period`, `cash_flow`. **Checked:** Lean
`statements_add_up`; `prop_period_pnl_partitions`;
`cash_flow_reconciles_to_change_in_cash`.
## B-15 Depreciation: straight line, salvage never depreciated, partial months by days
**Status:** CONVENTION (book method); AUTHORITY for tax conventions, which
wanderbooks does not apply
OpenStax §11.3 (cited): "Straight-line depreciation is a method of
depreciation that evenly splits the depreciable amount across the useful
life of the asset," with "(Cost – salvage value)/Useful life"; partial
periods: "A common method is to allocate depreciation expense based on the
number of months the asset is owned in a year." wanderbooks prorates
partial months by days. ASC 360-10-35-4 not yet verified (see README).
Tax conventions (half-year, mid-month, mid-quarter): IRS Pub. 946
(`sources/irs-depreciation.md`), for the CPA.
**Enforced:** `assets::depreciation_schedule`. **Checked:**
`schedule_sums_exactly_to_depreciable_amount`,
`salvage_value_is_never_depreciated`, `prop_depreciation_schedule_exact`.
## B-16 Prepaid expenses and deferred revenue are recognized over the period benefited or earned
**Status:** AUTHORITY (revenue); CONVENTION (prepaids)
ASC 606-10-45-2 (cited): payment before transfer → "the entity shall
present the contract as a contract liability"; 606-10-25-23: "An entity
shall recognize revenue when (or as) the entity satisfies a performance
obligation by transferring a promised good or service." Prepaids: OpenStax
§4.2 (cited). Tax: the 12-month rule, Treas. Reg. §1.263(a)-4(f)
(`sources/irs-capitalization.md`).
**Enforced:** `schedules`. **Checked:** `a_prepaid_expense_is_expensed_month_by_month`,
`deferred_revenue_is_earned_to_the_cent`.
## B-17 Platform payouts are recorded gross when the business is the principal
**Status:** AUTHORITY
ASC 606-10-55-37 (cited): "An entity is a principal if it controls the
specified good or service before that good or service is transferred to a
customer." 606-10-55-38: an agent "recognizes revenue in the amount of any
fee or commission to which it expects to be entitled." Whether an app
developer is principal for app-store sales is a judgment under 55-39; the
CPA confirms.
**Enforced:** `payouts::payout_plan`. **Checked:**
`a_payout_is_grossed_up_to_revenue_and_fees`.
## B-18 Aging buckets: Current, 1–30, 31–60, 61–90, 90+ days past due
**Status:** CONVENTION (bucket edges); DECISION (due today is Current)
ASC 326-20-55-37/38 (cited) illustrates "one way" to age trade
receivables with buckets "current … 1–30 days past due … 31–60 … 61–90 …
more than 90 days past due"; it is illustrative, not a rule. The FFIEC
Call Report instructions (bank regulators, not binding here): "The past
due status … should be determined in accordance with its contractual
repayment terms." A document due today is not yet past due: DECISION
(Stephen, 2026-10-13).
**Enforced:** `arap::aging_bucket`. **Checked:** `aging_boundaries`,
`aging_is_exclusive_and_only_ages`.
## B-19 1099 reporting thresholds
**Status:** AUTHORITY (`sources/irs-1099-thresholds.md`)
$600 through 2025; $2,000 for payments made after Dec. 31, 2025 (26 U.S.C.
§6041(a), §6041A(a)(2), as amended by Pub. L. 119-21 §70433); for calendar
years after 2026, indexed to inflation and rounded to the nearest $100
(§6041(h)). Card payments are reported on Form 1099-K, not 1099-NEC/MISC.
Attorneys' gross proceeds stay at $600 (not modeled).
**Enforced:** `form1099::default_threshold`. **Open:** for 2027 and later
the indexed amount is not yet published; the engine must not silently
assume $2,000 (see the open-questions list in the strategy note).
## B-20 Every transaction has supporting documents; records are kept
**Status:** AUTHORITY (`sources/irs-records.md`)
IRS Pub. 583: "In addition, you must keep supporting documents"; they
"support the entries in your books and on your tax return"; keep records
"until the period of limitations for that return runs out" (3 years
generally; 7 for bad debts).
**Enforced:** the MCP receipt policy (not the engine; R-13).
## B-21 Exact amounts in the books; rounding only on returns
**Status:** AUTHORITY (for where rounding happens)
Form 1065 instructions (`sources/irs-partnerships.md`): "If two or more
amounts are added to figure the amount to enter on a line, include cents
when adding the amounts and round off only the total." The books keep
cents (and FX precision) exactly (R-2).
**Enforced:** `Decimal` money, `Amount` checked arithmetic, line range.
**Checked:** Kani `sums_are_exact`; bridge tests.
## B-22 Expense or capitalize (book policy, mirrors tax)
**Status:** AUTHORITY (`sources/irs-capitalization.md`)
Treas. Reg. §1.263(a)-1(f)(1)(ii)(D) sets $500 per invoice or item for a
taxpayer without an applicable financial statement "or other amount as
identified in published guidance"; Notice 2015-82 raised it to $2,500 for
taxable years beginning on or after January 1, 2016. The 12-month rule:
§1.263(a)-4(f)(1). The election is made yearly on the return.
**Enforced:** bookkeeper policy (books' AGENTS.md), not the engine.