110 lines
6.5 KiB
Markdown
110 lines
6.5 KiB
Markdown
# 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`): 10 of 12 rows
|
||
covered; cash flow (engine R-FUTURE-3) and full CPA export (xlsx/iif)
|
||
remain. 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.
|