docs: sent tracking in the rules, parity and test records (P4b S5)

rules.md B-27 lists `documents_v2`, the one feature S4 to S7 share
(D-52), including `invoice.sent`; receipt-store.md lists the event;
parity.md gains the sent-tracking row (done: implemented, tested, and
golden-covered by the trial balance of the fixture book around a send);
testing.md records the tests and what P12 must mutate, and names the
two attention predicates as deferred with step 4 until U0b lands.
This commit is contained in:
swaits committed 2026-10-27 13:24:10 -06:00
1 parent 47c0e4396e
commit 7c5a2fe3ce
4 files changed
+72 -4

No files matched your search

+51
View File
@@ -3050,3 +3050,54 @@ and `BooksServer::new`'s copy (a dropped field must fail
`isolation_label_is_enforced_under_the_unit`); the host's `server_flags`
extension and `parse_args`' passthrough of `--isolation` and its optional
`--http` value.
## P4b S5: sent tracking (2026-10-27)
The books record that an invoice went out; they never send it (A-4). A
send is `invoice.sent`, under `documents_v2` (D-52), and moves no figure:
`Ledger::mark_sent` pushes a `Sent` onto the invoice, the store journals
one line and no entry, replay restores it and the projection keeps it in
`schema` v17's `invoice_sends` (S4.3 took 16).
- **`ledger-store` `tests/arap_standing.rs`:** `mark_sent_waits_for_documents_v2`
(books with no features: refused, nothing journaled; after `upgrade`,
taken, and the reopen equals what was live), `sends_replay_and_project`
(two sends: the journal's `invoice.sent` carries the whole record in
order, `verify` passes, the reopened invoice holds both),
`a_send_changes_no_figure` (on the `p4-arap-before` fixture: the report
snapshot, the invoice's `DocState` and every derived cache are equal
before and after), `mark_sent_on_void_refused` (`DocumentVoid`,
nothing journaled; a send dated before the void is taken).
- **`ledger-store` `tests/arap_props.rs`:** `status_is_a_function_of_journal_and_date`
gains `Op::Sent` (random sends on invoices, skipped on bills): every
figure, the control check and both agings still agree across live,
replay and snapshot.
- **`ledger-store` `tests/format.rs`:** `an_older_version_stops_at_invoice_sent`
(`invoice.sent` is this version's, a reader without `documents_v2` waits,
and the books declare the feature before the first send line).
- **8.0.6:** `books_written_under_older_rules_still_open` hand-writes an
`invoice.sent` and still opens; the fixture `old-books/p4_s5_before`
was written by eeee9658 (the revision before this unit) and opens to
the same figures; `books_p2_served_cut_over_whole` refuses a send before
consent and takes it after.
- **`ledger-cli` `tests/documents.rs`:** `mark_sent_records_who_and_how`
(two sends over the wire: the token's name, email and original by
default, then a reminder with a message id; `books.documents` shows
`last_sent`, `books.document` both sends, and the invoice still owes its
total).
- **`ledger-mcp/src/handbook.rs`:** the new `invoices-and-bills` section
renders, and its id is unique (the existing handbook tests).
**For P12 (mutation targets):** `Ledger::mark_sent`'s refusals (unknown
invoice, a send dated before it, `DocumentVoid`, empty `to`, and each of
the three `check_text` calls; the note's check is stricter than the plan's
list, to keep a full TIN out of the journal); `SentVia::parse`'s arms and
its `other:` prefix; `SendKind::parse`'s two arms; `sent_via`'s arms and
its empty fallback; `send_kind`'s error arm; the handler's `kind` default
(`original` when `sends` is empty, `reminder` after), its `to` fallback
(bill-to, then party, then refused) and its `by` fallback; `invoice_id`'s
`invoice:` strip; `last_sent`'s `max`; and the replay reader's
`newer_content` arms for an unknown channel or kind. The two attention
predicates ("invoice never sent", "overdue invoice not reminded") and
their day comparisons are deferred with the unit's step 4 until U0b
lands, and are named here when they do.