merge: P6, the evidence pipeline (branch P6, checkpoint ce366408)

The last of the paused branches, from its "not for merge" checkpoint:
extraction in ledger-import (text, pages, page images; capped, caught),
journaled as attachment.text_extracted; dedup by hash with
books.find_attachment and books.consolidate_duplicates; annotations and
books.set_entry_settles; the company record categories; the two fuzz
targets; feature attachment_text. Nineteen files conflicted with the
four P4b merges, resolved as plan 8.0.2 says: P6 retakes schema 18 (it
had taken 16, which S4.3 holds; S5 holds 17); the tool table is 129 and
the destructive count 31; both sides' appends kept with their seams
restored; one B-27 paragraph naming every feature; in the old-books
fixture P6's hand-written reimbursement is entry 7 (its ids collided
with S4.3's invoice); the replay fuzzer's list gains S7's
invoice.written_off; S4.3's issued-PDF test expects the extraction
record P6 journals right after a filing.

One integration defect between S7 and P6, found by the arap property
test and fixed here: under P6's dedup, a write-off whose evidence bytes
were filed already (the same collection letter for a second write-off of
the same invoice) was refused only after its entry had been journaled,
at the final link to the invoice ("already linked"). The write-off now
resolves the dedup before anything is journaled and keeps a link the
record already has to the invoice instead of refusing it; an explicit
existing_attachment_id already on an entry is still refused (S7's
one-receipt-once rule). P6's gate never ran before the pause; it runs on
main after this merge, and its ledger-store -> ledger-import dependency
is the open review point (plan 8.0.1).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HS8WZziDnyxunC23MUxrLp
This commit is contained in:
swaitsandClaude Fable 5.1 committed 2026-10-28 23:08:59 -06:00
commit 2ad192bbcd
70 files changed
+4618 -384

No files matched your search

@@ -5,3 +5,8 @@
- Not receipt-checked yet: books.create_invoice, books.create_bill, books.receive_payment, books.pay_bill, books.run_payroll and books.remit_payroll_taxes post at once, with no preview and no receipt check. Attach their evidence (the invoice, the bill, the payment confirmation, the payroll register) right after, linked to the entry they return.
- Receipt corrections: receipts can change, but nothing is erased. To replace one, attach the new receipt, then books.unlink_receipt the old (with a reason); retire unwanted receipts or documents with books.withdraw_attachment (with a reason). The journal keeps every step.
- File a receipt once and link it wherever it is evidence (the attachments section).
- **Reading a file.** Call books.get_receipt first: its default answer gives what the file is, the first 8 KiB of the text it was read as, and how many pages it has. Read the text (`view text` gives all of it). Open a page picture (`view page_image`, `page` 1 for the first) only when the text is empty or looks wrong on a page you must check, and never ask for `view bytes` into your context: a file goes to the human as a download, not through you (D-46). A picture-only receipt has no text by design (no OCR): read its pages.
- **When a file's text failed.** A PDF whose reading failed is listed in Needs attention; read its pages and, if you need the words, ask the human. Do not retype or re-save a file to get it past a check.
- **The same file twice.** Filing bytes the books already hold returns the existing attachment and links it to the new subject: one record, several subjects. Older books may hold two records of one file; `books.consolidate_duplicates` previews them (the oldest is kept, linked where the others were, and the rest withdrawn as duplicates, nothing deleted). It refuses whole rather than leave a posted entry the policy covers with no evidence. Annotations of a withdrawn duplicate are not moved: annotate the kept file.
- **Annotating a receipt.** Record what you read off it with books.annotate_attachment: the receipt number, payee, amount (a decimal string), date, instrument, category, source, who is to be reimbursed, and a note. It changes no amount and no file. Receipt numbers run from the highest one annotated: the answer's `next_receipt_number` is the one to give the next new receipt, so numbers are never reused.
- **Who paid, and who was paid back.** An expense a member paid personally is the company borrowing from them and spending it (the cash flow statement shows both). When a payment pays them back, record what it settles with books.set_entry_settles on the payment, naming the entries it pays back; Needs attention asks until you do, once per entry. Never guess which expense a payment covered (no oldest-first rule): ask the human.
@@ -7,3 +7,5 @@
- Before it upgrades, the server makes a backup of the books, their vault and keys included, and proves it whole; a backup that can't be made or proven upgrades nothing. Then the books move to the new format in one step, on the record.
- After the upgrade an older version of wanderbooks can't open these books; the backup made first keeps them as they were. Going back is the owner's choice, never yours.
- This upgrade is `documents_v2`: invoice numbers, terms and line accounts (S4), sent records (S5), payments that settle several documents with early-payment discounts and a processor's fee (S6), and write-offs (S7). Until it is given, those writes are refused and everything else works as before.
- The journal features an upgrade can add: `members_cumulative`, `account_renamed`, `require_tax_category`, `tax_categories_gain_exempt`, `disposal_before_service`, `depreciation_catch_up`, `party_creditors`, `payment_instruments`, `vendor_1099_decisions`, `schedule_convention`, `month_reposting`, `asset_basis`, `projects`, `document_line_projects`, `document_standing`, `documents_v2`, and `attachment_text` (P6: a filed file's extracted text, what a human annotated of it, and the entries a payment settles). All are declared at once; a version that doesn't know one stops at the declaration instead of misreading the books.