Tests and docs: no figures from the first company's books
check / check (push) Canceled after 0s

The odd-cent regression's net loss and its splits, the website's example
Apple charge and the GUI plan's example receipt now use made-up amounts.

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:38:17 -06:00
1 parent eb4329bb2a
commit 8255ac2103
6 files changed
+51 -51

No files matched your search

@@ -6,18 +6,18 @@ sources = ["26 U.S.C. §704(a)", "Treas. Reg. §1.704-1(b)(2)(iv)(b)"]
tags = ["partnership", "close", "rounding", "book", "us"]
# The regression this example comes from (wanderbooks P3 defect 17, audit
# F52, anonymized): a net loss of 399.23 at 50/50, closed in January and
# F52, anonymized): a net loss of 287.53 at 50/50, closed in January and
# again in March, with February closed to retained earnings. Restarting the
# count at March gave A the tied cent twice (A −399.24, B −399.22).
# count at March gave A the tied cent twice (A −287.54, B −287.52).
#
# By hand, from the rule:
# January: −399.23 × 0.5 = −199.615 each; rounded toward zero, −199.61
# January: −287.53 × 0.5 = −143.765 each; rounded toward zero, −143.76
# each, one cent short; the remainders tie (0.005), so the cent goes to
# the member listed first: A −199.62, B −199.61.
# the member listed first: A −143.77, B −143.76.
# February: 10.00 to retained earnings; the members' count skips it.
# March: the count's running total is −798.46, −399.23 each exactly;
# less January's −199.62 / −199.61, March gives A −199.61, B −199.62.
# Each member ends at −399.23, their exact share.
# March: the count's running total is −575.06, −287.53 each exactly;
# less January's −143.77 / −143.76, March gives A −143.76, B −143.77.
# Each member ends at −287.53, their exact share.
[setup]
currency = "USD"
@@ -65,8 +65,8 @@ share = "0.5"
date = "2026-01-15"
description = "January's fees"
lines = [
{ account = "6000", side = "debit", amount = "399.23" },
{ account = "1000", side = "credit", amount = "399.23" },
{ account = "6000", side = "debit", amount = "287.53" },
{ account = "1000", side = "credit", amount = "287.53" },
]
[[events]] # event 2: the closing entry
@@ -91,8 +91,8 @@ close = { start = "2026-02-01", to = "retained_earnings" }
date = "2026-03-15"
description = "March's fees"
lines = [
{ account = "6000", side = "debit", amount = "399.23" },
{ account = "1000", side = "credit", amount = "399.23" },
{ account = "6000", side = "debit", amount = "287.53" },
{ account = "1000", side = "credit", amount = "287.53" },
]
[[events]] # event 6
@@ -105,25 +105,25 @@ query = "entry"
entry = 2
[expect.values]
"6000.credit" = "399.23"
"3000.debit" = "199.62"
"3001.debit" = "199.61"
"6000.credit" = "287.53"
"3000.debit" = "143.77"
"3001.debit" = "143.76"
[[expect]]
query = "entry"
entry = 6
[expect.values]
"6000.credit" = "399.23"
"3000.debit" = "199.61"
"3001.debit" = "199.62"
"6000.credit" = "287.53"
"3000.debit" = "143.76"
"3001.debit" = "143.77"
[[expect]]
query = "balances"
as_of = "2026-03-31"
[expect.values]
"3000" = "-399.23"
"3001" = "-399.23"
"3000" = "-287.53"
"3001" = "-287.53"
"3999" = "-10.00"
"1000" = "-808.46"
"1000" = "-585.06"
+4 -4
View File
@@ -2225,10 +2225,10 @@ impl Ledger {
/// 6. IF a journaled MembersCumulative names a start other than the
/// one the books derive: SHOULD refuse (InvalidMembers)
/// BECAUSE replay would split differently from the journal.
/// 7. IF 50/50 members closed −399.23 in January (A −199.62, B
/// −199.61), February closed to retained earnings, and March closes
/// −399.23 to the members: SHOULD give A −199.61, B −199.62, so
/// each has −399.23 (the count skips February's close).
/// 7. IF 50/50 members closed −287.53 in January (A −143.77, B
/// −143.76), February closed to retained earnings, and March closes
/// −287.53 to the members: SHOULD give A −143.76, B −143.77, so
/// each has −287.53 (the count skips February's close).
/// ```
pub fn close_period_to(
&mut self,
+22 -22
View File
@@ -205,50 +205,50 @@ const THIRDS: [&str; 3] = ["0.3333", "0.3333", "0.3334"];
// The regression (audit F52, 2026-10-16, anonymized)
// ---------------------------------------------------------------------------
/// Regression (P3 defect 17; audit F52's −399.23, anonymized): members A
/// and B at half each. January's net loss of 399.23 closes to them: exact
/// −199.615 each, so A −199.62, B −199.61 (the tie to the member listed
/// Regression (P3 defect 17; audit F52's −287.53, anonymized): members A
/// and B at half each. January's net loss of 287.53 closes to them: exact
/// −143.765 each, so A −143.77, B −143.76 (the tie to the member listed
/// first). February's 10.00 loss closes to retained earnings. March's
/// 399.23 loss closes to them again. The run rule (2026-10-13 to P3)
/// 287.53 loss closes to them again. The run rule (2026-10-13 to P3)
/// started over at March, handing A the tied cent a second time: A
/// −399.24, B −399.22 for an exact −399.23 each. Now February's close is
/// skipped and March continues January's count: the running −798.46 splits
/// −399.23 each, less January's −199.62 / −199.61, so March gives A
/// −199.61 and B −199.62. The March entry: Cr 6000 399.23, Dr 3000 199.61,
/// Dr 3001 199.62.
/// −287.54, B −287.52 for an exact −287.53 each. Now February's close is
/// skipped and March continues January's count: the running −575.06 splits
/// −287.53 each, less January's −143.77 / −143.76, so March gives A
/// −143.76 and B −143.77. The March entry: Cr 6000 287.53, Dr 3000 143.76,
/// Dr 3001 143.77.
#[test]
fn the_audit_odd_cent_never_piles_up_across_closes() {
type Rule = fn(Vec<MemberClose>) -> CloseTo;
let (run, cumulative): (Rule, Rule) = (CloseTo::MembersRun, CloseTo::Members);
for (rule, a, b) in [
(run, "-399.24", "-399.22"),
(cumulative, "-399.23", "-399.23"),
(run, "-287.54", "-287.52"),
(cumulative, "-287.53", "-287.53"),
] {
let mut co = company(Currency::USD, 2);
let to = rule(co.members(&[0, 1], &HALF));
let jan = co.month(1, "-399.23", &to);
let jan = co.month(1, "-287.53", &to);
let jan_entry = co.l.get_period(jan).unwrap().closing_entry.unwrap();
assert_eq!(
co.lines(jan_entry),
[
line("6000", Side::Credit, "399.23"),
line("3000", Side::Debit, "199.62"),
line("3001", Side::Debit, "199.61"),
line("6000", Side::Credit, "287.53"),
line("3000", Side::Debit, "143.77"),
line("3001", Side::Debit, "143.76"),
]
);
co.month(2, "-10.00", &CloseTo::RetainedEarnings { sweep: vec![] });
let mar = co.month(3, "-399.23", &to);
let mar = co.month(3, "-287.53", &to);
assert_eq!(co.capitals(), decs(&[a, b]));
let retained = co.l.chart().find_by_code("3999").unwrap().id;
assert_eq!(co.l.account_balance(retained).unwrap(), dec("-10.00"));
if a == "-399.23" {
if a == "-287.53" {
let mar_entry = co.l.get_period(mar).unwrap().closing_entry.unwrap();
assert_eq!(
co.lines(mar_entry),
[
line("6000", Side::Credit, "399.23"),
line("3000", Side::Debit, "199.61"),
line("3001", Side::Debit, "199.62"),
line("6000", Side::Credit, "287.53"),
line("3000", Side::Debit, "143.76"),
line("3001", Side::Debit, "143.77"),
]
);
let (since, split) = co.l.member_close_split(mar).unwrap();
@@ -257,8 +257,8 @@ fn the_audit_odd_cent_never_piles_up_across_closes() {
assert_eq!(
rows,
[
(dec("-199.61"), dec("-399.23"), dec("-399.23")),
(dec("-199.62"), dec("-399.23"), dec("-399.23")),
(dec("-143.76"), dec("-287.53"), dec("-287.53")),
(dec("-143.77"), dec("-287.53"), dec("-287.53")),
]
);
}
+3 -3
View File
@@ -602,10 +602,10 @@ Defect 17 (rules.md B-13; D-10, D-38), built without its mutation run
worked by hand in the test's comment.
**The named regression.** `the_audit_odd_cent_never_piles_up_across_closes`
(`ledger-core` `tests/odd_cent.rs`): audit F52's −399.23 at 50/50,
(`ledger-core` `tests/odd_cent.rs`): an audit finding's −287.53 at 50/50,
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
The run rule left A −287.54 / B −287.52; the rule since P3 gives −287.53
each (March: Dr 3000 143.76, Dr 3001 143.77). Its bookspec example is
`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`).
+1 -1
View File
@@ -37,7 +37,7 @@ journal with its verification status.
hash-chained journal and the blob store and builds its own in-memory
view (`ledger_store::Snapshot`). Changes happen through the agent (MCP).
Where the GUI finds something to fix, it offers a ready-to-paste prompt
for the agent ("Attach the receipt for entry 12 — Anthropic, $5.82").
for the agent ("Attach the receipt for entry 12 — Anthropic, $7.40").
5. **Live.** It follows the journal: a change made by the agent appears
within a second, highlighted as new.
6. **Numbers are typography.** Tabular figures everywhere (Inter with
+1 -1
View File
@@ -193,7 +193,7 @@ footer { padding: 72px 0 48px; color: var(--faint); font-size: 14px; display: fl
<h2>Just ask.</h2>
<p class="sub">Your bookkeeper is the AI you already use, working through an accounting engine that won't let it be wrong. Talk to it the way you'd talk to a good bookkeeper. It does the work, shows you the result, and waits for your OK before anything is posted.</p>
<div class="grid">
<div class="card ask"><div class="say">Find the receipt for the $106.38 Apple charge in my email and record it.</div><p>Searches your inbox, files the receipt as a PDF, drafts the entry with the right accounts, and shows you the preview.</p></div>
<div class="card ask"><div class="say">Find the receipt for the $84.17 Apple charge in my email and record it.</div><p>Searches your inbox, files the receipt as a PDF, drafts the entry with the right accounts, and shows you the preview.</p></div>
<div class="card ask"><div class="say">Here's last month's bank export. Categorize everything.</div><p>Imports the transactions as drafts, proposes an account for each from how you've booked them before, and asks about the ones it isn't sure of.</p></div>
<div class="card ask"><div class="say">The domain renewal went to the wrong account. Fix it.</div><p>Reverses the entry and records it correctly. Nothing is ever erased; the history shows exactly what changed and why.</p></div>
<div class="card ask"><div class="say">Show me every Adobe charge this year.</div><p>Opens the search in the viewer beside you, every charge listed, each one a click from its receipt.</p></div>