Files
wanderbooks/docs/capability-parity.md
swaitsandClaude Opus 5.5 e59e8001c6 feat: receipt unlink and attachment withdrawal
Posted entries stay immutable (R-3), but their evidence can now change the
same way the ledger does: by appending events, never by editing or
deleting. New R-13a.

- books.unlink_receipt {attachment_id, reason} journals receipt.unlinked
  and leaves the receipt filed, unlinked. The receipt policy holds: an
  entry that requires a receipt can't lose its last one (structured
  receipt_required error), so a replacement is attach-new, then
  unlink-old. Drafts and reversals are exempt, as at posting.
- books.withdraw_attachment {attachment_id, reason} journals
  attachment.withdrawn for an unlinked receipt or a filed document: hidden
  from list_receipts (unless include_withdrawn), never linkable again. The
  blob stays in the store, hash-verified and readable.
- link_receipt now refuses an already-linked or withdrawn attachment.
  Before, re-linking silently moved a receipt off a posted entry,
  bypassing the policy; evidence now leaves an entry only through a
  recorded unlink. dispose_asset checks its receipt ids before posting
  instead of after.
- Schema v5 adds attachments.withdrawn_at/withdrawn_reason; existing
  stores migrate on open and replay rebuilds the projection.

Tests: store test (errors, reopen, rebuild, verify, journal history) and
an MCP stdio test (policy refusal, replace flow, withdraw, listings,
under-threshold unlink). Dry-run and live use on the Wanderland Labs books:
8 migrated .eml attachments swapped for their PDF renders, trial balance
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtYEaR6M6Ybdhm6X98BWNu
2026-10-11 18:40:51 -07:00

53 lines
3.0 KiB
Markdown

# Capability parity — GSheet+GDrive → wanderbooks
The parity target for the AI-first phase is **not QuickBooks**. It is the
system actually in use today: the "Wanderland Labs LLC — Books" Google Sheet
(double-entry accounts with live P&L, Balance Sheet, and Cash Flow tabs, plus
the Transaction Journal) together with the Drive folder, operated through an
AI assistant. Every capability below must be reachable through MCP tools
before the sheet retires.
Statuses: `covered` (built and tested), `partial` (built, known gaps listed),
`specced` (designed, not yet built), `future` (on the roadmap).
| # | Today's capability | wanderbooks equivalent | Status |
|---|---|---|---|
| 1 | Record a double-entry transaction (Transaction Journal row) | `books.draft_entry` / `add_line` / `post_entry` (engine: `Ledger`) | covered |
| 2 | Chart of accounts | engine + `books.chart` (with live balances) | covered |
| 3 | Live P&L tab | engine + `books.profit_and_loss` | covered |
| 4 | Live Balance Sheet tab | engine + `books.balance_sheet` | covered |
| 5 | Live Cash Flow tab | engine `cash_flow` (indirect) + `books.cash_flow` | covered |
| 6 | Transaction Journal as append-only log | engine posting log + `books.search_entries` | covered |
| 7 | Receipt storage in Drive | blob store + `books.attach_receipt` / `link_receipt` / `unlink_receipt` / `withdraw_attachment` | covered |
| 8 | Document filing by category (01 Formation / 02 Legal / 03 Tax / 04 Accounting) | `books.file_document` | covered |
| 9 | Ad-hoc questions ("what did we spend on X?") | `search_entries` + reports; the AI itself is the query layer | covered |
| 10 | Human review of what the assistant recorded | `books.digest` | covered |
| 11 | CPA-ready export of the books | `books.export` (csv/json/xlsx/iif; xlsx is base64) | covered |
| 12 | Company email filing (every company email → Drive folder) | out of books scope; the existing mail-filing automation keeps running unchanged | — |
## Notes
- Row 9 is the quiet superpower of the AI-first design. The sheet answers
questions with formulas the human must write; the MCP design answers them
with an agent that already knows how to read a trial balance. The
capability is "ask anything about the books," and the tool surface above
is what makes it true.
- Row 10 (`books.digest`) has no sheet equivalent — the sheet can't tell you
what changed. This is parity *plus*: the new system is more reviewable
than the old one, which is the point of the exercise.
- Row 12 is deliberately excluded. Email filing is a mail problem, not a
books problem; it stays where it is.
## Cutover rule
The sheet does not retire on a date. It retires when **all three** hold:
1. Every `specced` row above is `covered` (built, tested, golden-covered
where reports are involved).
2. A full month of parallel run — every real company transaction recorded in
both systems — diffs clean.
3. Stephen says so.
The parallel run is the acceptance test. Until then the sheet is the system
of record and wanderbooks is the shadow ledger; after, it inverts.