Files
wanderbooks/plan/STATUS.md
T

8.8 KiB
Raw Blame History

STATUS — 2026-10-10 (evening: asset slice + testing initiative)

Where we are

Phase 1 (semantics core) is done and green. The first storage + MCP slice is built, tested, and green. The fixed-asset slice is built, tested, and green. A testing initiative (property + mutation + fuzz) is underway on ledger-core.

Done:

  • Repo swaits/wanderbooks created on git.swaits.com (private).
  • ledger-core 0.1.0: Money (exact Decimal + ISO currency), five account types with normal sides, chart of accounts (codes, hierarchy, placeholders), journal entries with full validation, Ledger command surface (create/add-line/post/reverse), append-only posting log.
  • Reports: trial balance, P&L, balance sheet (accounting equation holds; current earnings folded into equity pre-close), canonical JSON snapshot() for oracle diffing.
  • 14 tests green: validation rejections, posted-entry immutability, reversal semantics, the accounting laws on a fixture company, a 300-entry randomized invariant test, and the first golden file.
  • ledger-store 0.1.0: the source of truth is an append-only, hash-chained JSONL journal (fsync per append; tamper-evident); content-addressed SHA-256 blob store (immutable, deduplicated, hash-verified on read); SQLite as a disposable projection (TEXT amounts, WAL, synchronous=FULL, integrity_check on open). Single write path: validate → journal → mutate → apply. verify replays the journal and diffs reports three ways; rebuild drops SQLite and replays; a missing database heals on open. 7 tests green: round-trip, tamper detection, torn-tail truncation, rebuild, blob dedup/corruption detection, unbalanced-post rejection.
  • ledger-mcp 0.1.0: stdio server on official rmcp 3.5 (23 narrow typed tools, amounts as decimal strings, initialize.instructions carrying the agent operating contract). Draft → add lines → preview → confirmed post; server-side receipt policy (strictly greater than $25, per-account overrides, typed receipt_required rejection); digest; search; CSV/JSON export; period P&L and as-of balance sheet; fixed-asset tools (register, schedule, list, run-depreciation, dispose with preview). End-to-end stdio protocol tests green (initialize → tools → draft → preview → receipt_required → attach → post → reports → digest → reverse; and a full asset flow: register → schedule → idempotent runs → disposal preview → receipt_required → bill-of-sale → confirmed disposal → gain posted).
  • Fixed assets (ledger-core + ledger-store + ledger-mcp): fixed-asset register (description, purchase date, cost, salvage, useful life, linked cost/accumulated-depreciation/expense accounts), straight-line book depreciation with day-prorated partial months and a final-month true-up so the lifetime total is exactly (cost − salvage), idempotent monthly runs, disposal with auto-posted final depreciation and gain/loss. Tax depreciation stays with the CPA. Tests: 10 asset unit tests (ledger-core), 6 store tests, 7 property tests, MCP e2e.
  • Testing initiative (in progress): proptest property suite on ledger-core (trial balance always balances, A = L + E, reversals restore zero, posted-entry immutability, JSON round-trip, depreciation exactness — the last caught a real month-length-drift bug, fixed with the final-month true-up); cargo-mutants run on ledger-core (228 mutants); cargo-fuzz targets (journal-line parsing, entry validation, op sequences) scaffolded.
  • 40+ tests green workspace-wide; cargo fmt clean; clippy clean except one pre-existing phase-1 style lint on a public engine signature.
  • Docs: AGENTS.md (operating manual), requirements, architecture, oracle design, parity catalog (floor: 10 done), glossary, mcp-interface (incl. the 5 asset tools), receipt-store (journal design), capability-parity (10 of 12 rows covered). Plan: this file + roadmap.

In progress: nothing — the next arcs are queued below, unstarted.

Next arcs (in order)

The project went AI-first on 2026-10-10 (Stephen's call): the primary interface is MCP, not a cloned GUI. The first storage + MCP slice is done (arcs 1–3 below). What remains:

  1. ledger-store done — journal + blob store + SQLite projection.
  2. Blob store done — folded into ledger-store.
  3. ledger-mcp done — 18 tools, receipt policy, digest, export. Remaining from the spec: MCP resources (rmcp 3.x has no resource macros; hand-roll list_resources/read_resource next), Streamable HTTP transport, XLSX/IIF export formats.
  4. Capability parity (docs/capability-parity.md): 11 of 12 rows covered; full CPA export (xlsx/iif) remains. Then the month-long parallel run against the GSheet; cutover per the cutover rule.
  5. Then: oracle harness (GnuCash diff), read-only GUI on the event log, workflow parity.

Decisions log

  • 2026-10-10: Single currency per ledger for day one (R-5). Multi-currency is designed-for, not built.
  • 2026-10-10: Money arithmetic is checked and returns Result; no panicking ops, no float paths anywhere.
  • 2026-10-10: Negative zero is normalized away at account_balance — money never prints "-0". (Caught by the golden test on day one; the oracle works.)
  • 2026-10-10: License MIT OR Apache-2.0, matching the storytold projects. GnuCash clean-room boundary documented in docs/oracle.md.
  • 2026-10-10: AI-first pivot (Stephen). Primary interface is MCP (docs/mcp-interface.md), not a cloned GUI. Receipts/documents become a content-addressed blob store (docs/receipt-store.md). Parity target for the phase is the GSheet+GDrive system (docs/capability-parity.md), with a parallel-run cutover rule. GUI drops to read-only, event-log-driven, phase 4.
  • 2026-10-10: Import/export targets QuickBooks formats (CSV, IIF, XLSX) — "could not give a single shit about GnuCash XML." GnuCash stays the behavioral oracle only. Receipt enforcement is server-side policy in the MCP layer (threshold + per-account overrides, typed receipt_required error, checklist in every preview); the engine stays policy-free.
  • 2026-10-10: Storage durability (Stephen). SQLite is the query engine, not the source of truth: the source of truth is an append-only, hash-chained JSONL journal (fsync per append; tamper-evident; git-backup-friendly), SQLite is a disposable projection rebuilt from it, blobs stay content-addressed. Single write path: journal → fsync → apply to SQLite.
  • 2026-10-10: Draft durability (house decision). Drafts are durable, not ephemeral: entry.created + entry.line_added journal lines record the draft as the agent builds it, so drafts and their attached receipts survive restarts. Drafts never touch the SQLite projection until posted. Rationale: the journal is the source of truth (phantom entry.created lines without draft lines were the worst of both worlds), and the draft → attach receipts → post workflow spans multiple MCP calls.
  • 2026-10-10: Corrupt SQLite heals itself. If the projection fails integrity_check (or isn't a database at all), Store::open quarantines it to wanderbooks.corrupt.<timestamp> and rebuilds from the journal, instead of failing open. WAL/SHM are dropped as derived state.
  • 2026-10-10: Cash flow statement (R-FUTURE-3) done. Engine reports::cash_flow (indirect method) + books.cash_flow MCP tool (24 tools total). Disposals identified structurally; gains/losses move from operating to investing; the three sections always reconcile to the net change in the designated cash accounts. Two invariant tests, including a full purchase → depreciate → dispose cycle.
  • 2026-10-10: MCP resources done (hand-rolled list_resources / read_resource: chart, trial-balance, balance-sheet, profit-and-loss, digest, receipts). #[tool_handler] must sit on the impl ServerHandler block, not the inherent impl — misplacing it silently drops all tools.
  • 2026-10-10: QuickBooks interop (R-FUTURE-4) done. New ledger-import crate: QBO bank CSV parse (3-col and 4-col layouts), chart CSV parse, IIF journal generation, XLSX report generation (rust_xlsxwriter, MIT). MCP: books.import_bank_csv (drafts + categorization rules), books.import_chart_csv (all-or-nothing), books.export gains xlsx (base64) and iif formats plus cash_flow report. 26 tools total. Capability parity 12 of 12 rows covered.
  • 2026-10-10: Streamable HTTP transport done. ledger-mcp --http ADDR serves MCP at /mcp via rmcp's tower StreamableHttpService (axum). 27 tools total. Verified with curl: initialize returns SSE stream.
  • 2026-10-10: Drive backfill path done. books.import_local_file reads a file from the server's filesystem into the blob store (receipt/document). The agent downloads from Drive via the CLI, then calls this — Drive credentials never enter the server.