The left column is the conversation exactly as it happened, in Claude with a Saybooks connector open on one client's books. The right column is what the books recorded while it went on: every command, who ran it, why, and the two that were refused. Nothing has been edited for either.
I checked the file before importing — the arithmetic doesn't close, so I'd rather not push it through with a guess.
Every one of the 18 rows ties exactly to its own printed running balance, and the chain from the opening balance is clean all the way down. But the chain lands at $20,628.57, while the statement's printed closing balance is $20,592.57 — short by exactly $36.00.
Since all 18 rows are internally consistent, the discrepancy is at one of the two ends: either a row is missing from the list, or the closing balance itself is off. The file is a retype, which makes a transcription slip plausible either way. Saybooks refuses a batch where opening + rows ≠ closing (that guard is the whole point), and I won't fudge a row to make it fit.
Caught it — nothing was written to the book, so Harborline Studio LLC is still clean (no sources on record). Send the good file and I'll import it.
Reconciles cleanly now — the retype had the hotel at 848.25 instead of 884.25. Opening 24,845.03 − 4,252.46 = 20,592.57, 18 rows, every running balance ties.
Imported into the Harborline Studio LLC book as SRC-0001 — accepted whole, reconciled, 18 of 18 rows in, none skipped.
Money in: $11,409.60 (three ACH client receipts plus the Stripe transfer) Spend: $15,662.06 Opening $24,845.03 → closing $20,592.57
All 18 rows are sitting unreviewed — nothing has been categorized, since that needs your words rather than my guesses. A few will want a decision rather than a label: the Gusto run and the savings transfer aren't purchases, the wire fee and foreign-transaction fee are bank fees, and Adobe/GitHub/Notion/Hetzner look like recurring subscriptions worth declaring as such so future months match automatically.
Want me to walk you through the review and propose a status and category for each row?
Row 14 is T-0014 — the Delta ticket, −$612.40 on 2026-08-21.
It came straight out of the second CSV you sent, line 20:
2026-08-21,DELTA AIR 0062318844901 PDX-JFK,-612.40,"18,513.82"
That exact line is stored on the row as raw, with source_id: SRC-0001 and row_index: 14, so it traces back to the file position it was read from. Date, description and amount are verbatim — the ticket number 0062318844901 and the PDX-JFK routing were printed in the statement's description, not added by me.
One field on that row is mine, not the statement's: counterparty: "Delta Air". I derived it by taking the leading merchant text off the description. I kept it to what was printed rather than expanding it to "Delta Air Lines," but it's still a read of the line rather than a copy of it — same for the other rows where I filled that field. If you'd rather counterparty stay strictly verbatim or empty until review, say so and I'll correct them.
Refused, as designed:
This statement is already imported as SRC-0001 (Harborline Studio LLC Business Checking August 2026.csv, 2026-09-10). The same file never goes in twice (P-4).
The guard fired on the content hash, before any row was touched — so it's a hard refusal at the source level rather than an import that lands and skips 18 duplicate rows. Nothing was written; the book still has one source and 18 transactions.
Worth noting what this test did not exercise: the per-row skip path. That one only shows up when the hash differs but rows overlap — e.g. a re-export of the same account covering Aug 16–Sep 15. That import would be accepted as a new source, with the overlapping August rows skipped and listed back. If you want to test that branch, I can build a September statement that overlaps the back half of August.
The refusal itself is in the audit trail as a blocked agent command, if you want to see how it reads there.
No payroll report and no receipts of any kind in the book — so item 2 lands on “leave it whole.”
purch_split_transaction is in the registry — but it isn't in my callable tool list. That's the cache staleness the connector warns about: the schema is the truth, the tool list is a snapshot taken when the connector was added.
Let me get the definitive account list before I ask you for the chart.
Items 1 and 2 are done or answered; 3 and 4 need you.
1. T-0012 re-reviewed — still a transfer, but the category moved from the generic "own accounts" to savings, naming the destination. Amount and date untouched.
That incidentally explains the $2,000 gap I flagged. Watch the account count: it was 10 in use before, it's 11 now. Under "own accounts" the category was never registered as in-use at all — so the QBO shape had no counter-account for that entry and silently dropped it (17 entries / $25,071.66), while the plain CSV kept it (18 / $27,071.66). The row was reviewed and correct the whole time; it just fell out of one format. Clean repro if you want it: review a transfer row via purch_review_batch, then check whether its category shows up in bridge_accounts. The eight non-transfer categories from that same batch all registered fine.
2. Gusto split — not done, left whole. Two reasons:
No payroll report. purch_receipts is empty, so there's no document giving the wages / employer taxes / processor fee breakdown, and the doctrine is explicit that the legs come from a person or a document, never from me. I'm not inventing a split of $7,420.16.
purch_split_transaction exists in core_schema but is not in my callable tool list — the connector's cached tool list predates it. Per your own instructions, that needs a remove-and-re-add of the connector plus a new chat before I can call it.
So T-0010 stands as one recurring row, $7,420.16, monthly, Gusto.
3. The chart. Eleven accounts, all unmapped. QuickBooks matches on account name, exactly as spelled in their chart — the code is optional for QBO but worth capturing if you want Xero later.
| Saybooks account | August | Their QBO account name |
|---|---|---|
| Business Checking ending 8827 | the bank account itself | ? |
| client payments | $9,225.00 in | ? |
| card sales | $2,184.60 in | ? |
| hosting | $536.82 | ? |
| software | $839.88 | ? |
| contractors | $3,200.00 | ? |
| payroll | $7,420.16 | ? |
| travel | $1,496.65 | ? |
| legal & compliance | $119.00 | ? |
| Bank Fees | $49.55 | ? |
| savings | $2,000.00 | ? |
Paste their names against that list in any format — hosting = Computer and Internet Expenses, one per line, is fine — and add codes if you have them. Two worth a specific thought: client payments and card sales may both belong to one income account in their chart, and savings should point at the actual savings bank account rather than an expense account.
Once those land I'll map all eleven, re-preview, and export — and item 4's "what's left out" will be the left_out block, which I'll show you in full whether it's empty or not.
| Saybooks account | August | Their QBO account name |
|---|---|---|
| Business Checking ending 8827 | the bank account itself | Checking |
| client payments | $9,225.00 in | Client payments |
| card sales | $2,184.60 in | Card sales |
| hosting | $536.82 | Hosting |
| software | $839.88 | Software |
| contractors | $3,200.00 | Contractors |
| payroll | $7,420.16 | Payroll |
| travel | $1,496.65 | Travel |
| legal & compliance | $119.00 | Legal |
| Bank Fees | $49.55 | Bank Fees |
| savings | $2,000.00 | Savings |
Mapping all eleven now.
EXP-0002 handed over. 18 entries, 36 lines, $27,071.66 debits and $27,071.66 credits, balanced, qbo shape, all eleven accounts carrying the client's own names.
What's left out: nothing. left_out came back count: 0, empty rows, empty by-currency, no note — same on the preview and on the export. Every reviewed row in the period made it into the journal. That's what I wanted to see after the $2,000 business, and the QBO shape now agrees with the plain CSV entry-for-entry.
Two things still open, neither blocking the hand-over:
The Gusto split. Needs the payroll report and a connector re-add before purch_split_transaction is callable. If you re-add and start a fresh chat with the report, splitting T-0010 into wages / employer taxes / processor fee is a re-export of August afterward — the record will show both hand-overs and what changed.
legal & compliance needed a retry. My first bridge_map_account call sent the ampersand HTML-escaped and the server correctly refused it, listing the real category names back. Worth knowing that a category with punctuation in it is a place client-side escaping can bite; the refusal message was exactly right and made the fix obvious.
One cosmetic note on the file: the Name column is empty throughout. The format note says it carries the customer on receivable lines, and these are all direct bank entries rather than AR, so empty looks correct — but you'd know better whether their QBO import wants a payee there.
Reads are never logged; every write is, refusals included. This is the same audit trail a person sees in their browser.