be580598306eb675d16877c06f4cd490f6b7b064
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
be58059830 |
merge: P4b S6, paying on terms (branch S6, 6c4480cd)
The third of the paused branches: Ledger::settle with discounts and the processor's fee (kernel::settle, Kani settle_is_exact, Lean settle_posts_a_document_step), books.receive_payment and books.pay_bill with applications, books.bills_due, the agings' detail and tie-out, the aging exports and the CPA package's aging CSVs, the handlers in tools/settlements.rs. Twelve files conflicted with the S4.4 and S5 merges, resolved as plan 8.0.2 says: both routers; both test appends (the shared match arm in arap_standing.rs spliced into both tests; the shared `.unwrap()` in store.rs); the scope table at 124; one invoices-and-bills handbook (S5's send step 1 with S6's steps 2, 3, 5 and procedures) registered once; docs/mcp-interface.md with S4.4's create docs and S6's payment docs; S5's law renumbered 35 and S6's 36 (S1's is 34); the parity rows and sections of both. S6's wire tests create their bills as S4.4's contract now requires (confirmed, the vendor's number, a line account, the vendor's invoice uploaded) and live in their own module beside S4.4's tests. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HS8WZziDnyxunC23MUxrLp |
||
|
|
47c0e4396e |
verify(lean): Step.markSent, a send moves no figure (P4b S5)
AGENTS.md's formal-methods bar makes every new Ledger command a Lean Step with a preservation proof, so `Ledger::mark_sent` gets one even though the unit expected no Lean change (the As-built block records that). `Documents.lean`'s `Books` gains the sends recorded, and `Step.markSent` adds one on a document the lines carry. A send touches no line, so every control balance, every document's sum and what is unattached are unchanged through any day (`Step.markSent_changes_no_figure`, no axioms), and `Reachable.tagged` covers the new step. `Audit.lean` lists the theorem; rules.md B-38's model now covers the record side of a document's life as well as its figures. |
||
|
|
10ee0681c1 |
feat(arap): settle documents with discounts and a fee (P4b S6)
One payment had to name one document and could take no discount or processor fee, so paying several invoices from one deposit meant several entries and the fee had nowhere to go. This adds the kernel's exact settlement arithmetic (applications total, net deposit), a Ledger::settle that posts one entry for a customer's or vendor's documents, and the gross method and gross fee A-8/A-4 chose. - kernel::settle: sum(cash)+sum(discounts)=applications, sum(cash)-fee= deposit, None on overflow or a negative deposit. Kani settle_is_exact plus the Decimal bridge. - Ledger::settle / settlement_lines: one party and one kind per settlement, one application per document, each cash+discount within payment_room; a discount within the terms (discount_max and discount_by) needs no reason, a larger or later one does; a bill with an asset line is refused with D-49's remedy; a fee is a customer payment's only and posts gross. - Rows are payment lines in application order, then discount lines, the fee line and the cash line, so a journaled event's line indices are stable; replay tags exactly the line an event names and leaves an unmatched line unattached (never refuses). - receive_payment_with and pay_bill_with become one-application calls. - Roles: sales_allowances (4100), purchase_discounts (6995) and payment_processing_fees (6060), constants used on demand but not added to control_accounts() (existing charts may use those codes for other things). - Lean: settle posts through Step.document, so settle_posts_a_document_step and settle_unattached, no new constructor; both in Audit.lean. - Core tests: bill_on_terms_with_discount, late_discount_needs_a_reason, discount_on_an_asset_bill_is_refused_with_the_remedy, a_fee_posts_gross_to_receivables_and_net_to_the_bank, a_settlement_names_its_lines_and_refuses_a_document_twice, and equipment_bill_payment_is_investing_cash in the cash-flow suite. - Bookspec B-42 is stated, with its id BS-arap-6; the catalogue and index now record it as CONVENTION. just check and just prove green. |
||
|
|
d7fa16e974
|
feat(arap)!: documents read their figures from standing lines; control accounts
check / check (push) Canceled after 0s
refuse hand entries (P4b S1, part A) Plan P4b (D-45), slice S1, the engine half: rules.md B-38. - ledger-core: every receivables or payables line carries its document (Ledger.line_docs: DocRef, Movement, DocTag), written by the document commands in the step that posts it, derived on replay from the existing document events (the role's account as it stood then; payments by the ordinal rule), copied onto a reversal's mirror. Ledger::stands_on; doc_state / invoice_state / bill_state (total, paid, outstanding, status Open/Partial/Paid/WrittenOff/Void, overdue days) as of any day; ar_aging / ap_aging read them, so reversed payments and voids are right. The control guard (add_line, add_line_fx, post_entry, register_recurring) refuses untagged lines on receivables/payables, exempting a reversal's mirror of a legacy line; replay never refuses. Bounds (kernel::running_bounds, bounds_kept) on payments and reversals; a document reversal never dated before its entry; deposit/payer accounts must be cash-like and hold no role. New API: receive_payment_with / pay_bill_with (PaymentDetails: instrument, reference), void_document / check_void_document, control_check, payments_recorded, standing_payments, replay_reverse_entry. Invoice.amount_paid/status remain only as derived caches for the MCP layer until part B. cashflow bill_splits reads payments from the tags. - ledger-store: journal feature document_standing (D-39 gated) for a payment accepted only because an earlier one was reversed; receive_payment_with / pay_bill_with (instrument journaled as entry.instrument_set, reference in the description), void_document; replay uses replay_reverse_entry; schema 15 drops the projection's amount_paid/status. Fixture p4-arap-before + golden figures written by the version before S1, adjudicated in arap_standing.rs. - ledger-gui: party card, cash "coming up" and company owed totals read doc_state as of today (late from the derived state). - Lean Documents.lean (control_agrees and friends); Kani bounds_check_matches_definition, bounds_kept_is_the_definition_on_books_in_bounds; rules B-38, B-18/B-23 amended; bookspec `older = true` for legacy hand lines; tests that hand-post to 1200/2000 post as replay or renumbered. Review fixes (both reviews of part A): - control_role_of guards only an account the role is assigned to or one holding its documents' lines (a chart's own 1200 Equipment or card at 2000 is free until a document posts there); payment accounts check other roles by holds_role (type-checked). The MCP tests that failed on the guard (oracle_mcp, spec_projects) pass unchanged. - standing_payments leaves out reversals (sorted, deduped); replayed tags match the movement's side; payments_recorded counts every payment event (tagged or not, Ledger.payment_events) and refuses overflow. - The record caches settled (paid + discounted + written off) and owed (Invoice/Bill.owed, never serialized): a void never reads as paid. - assign_role: receivables/payables refuse moving onto an account with untagged lines (RoleAccountHasHandLines) and, on their control account holding a balance, say DocumentRoleHoldsBalance (no hand entry named); B-23 reworded. The reversal-mirror exemption only takes a hand line off (even chain depth); putting it back is refused. - DocStatus Overpaid and Unattached; aging leaves out credit balances; ControlCheck.attention lists out-of-bounds and unattached documents. - stands_on counts a chain in order; indexes (doc_index, doc_accounts, order_pos, reversed_by) keep the derived figures linear. - Viewer reads a post-dated document as of its own date; one state per row. bounds_kept's side-crossing documented as intended. - Tests: ten new spec_documents scenarios, stronger proptests, store proptest arap_props (live = replay = snapshot at every date, closed months), fuzz ops void/payments with details, a GUI post-dated test; Lean Step.assign / Step.release with unattached_zero kept; model limits stated in docs/testing.md and B-38. Review fixes (CPA and engineering lenses): only an assigned role's account or one holding document lines is a control account (a chart's own 1200 asset stays free); a role can't move onto untagged lines or off document lines (Lean Step.assign); a void's cache never reads as paid; no Decimal sum panics; per-document indexes keep figures linear; a replayed tag matches its side; the feature gate counts payment events; a payment's reversal is never listed as standing; an overpaid document has its own status; the viewer keeps post-dated documents. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T3gXMVt7XJPi6ens1or9Dj |