# Roadmap

> Build order is deliberate. Each milestone proves something the next depends on.

Source: https://lopifi.com/docs/roadmap
Part of: Lopifi — US GAAP books on autopilot, reviewed by a CPA (https://lopifi.com)

---

# Roadmap

Build order is deliberate. Each milestone proves something the next depends on.

---

## M0 — Foundations (docs complete, tokens shipped)

**Deliverable:** `@lopifi/theme` installable, and every claim in the design docs demonstrable.

- [ ] `tokens.css` — the complete set from `foundations/`, both themes, plus the signal palette
- [ ] Tailwind v4 `@theme` + v3 preset
- [ ] `scripts/check-tokens.ts` — contrast ratios computed from tokens, grid conformance on every spacing value, **failing the build** on violation
- [ ] Font subsetting + `size-adjust` fallback metrics, CLS measured at zero
- [ ] Docs site skeleton with theme / density / signal / reduced-motion toggles

**Exit gate:** a contrast-failing token change fails CI.

---

## M1 — The money proof

**Deliverable:** correctness, provable. The thing that makes this a finance library.

- [ ] `lib/money.types.ts`, `format-money.ts`, `allocate.ts`, `fiscal-period.ts`
- [ ] `Money` · `Delta` · `Figure` · `Percent` · `Rule`
- [ ] **Property-based tests** (`fast-check`): `format(parse(x)) === x` over all valid inputs; `allocate(total, w).sum() === total` over all inputs
- [ ] Every currency edge case: JPY 0dp, KWD 3dp, `bigint`, negative zero
- [ ] `tnum` + `case` verified visually — a rendered column of mixed-sign values with proven decimal alignment
- [ ] The greyscale test automated as a visual-regression assertion

**Exit gate:** a public "Why most money components are wrong" doc page, with live side-by-side comparisons. This is the marketing artifact and it writes itself if M1 is done properly.

**Why first:** every component above this inherits its correctness. And the `case`/paren-alignment craft is the hardest thing to retrofit.

---

## M2 — Surfaces

- [ ] `Card` base · `BalanceCard` · `KpiCard` · `StatCard` · `KpiRow`
- [ ] `Sparkline` · `Trend` · `StatusPill` · `AsOf` · `Redacted` · `Reference` · `EntityMark`
- [ ] `EmptyState` (3 variants) · `ErrorState` · `Skeleton` · `StaleIndicator`
- [ ] The isometric object library + the first five scenario illustrations
- [ ] Elevation, borders, and dark-mode top-highlight validated across every surface

**Exit gate:** a dashboard built entirely from these that looks finished, at 390px and 1280px.

---

## M3 — The table

**Deliverable:** the workhorse, at every width.

- [ ] `TransactionTable` · `TransactionRow` · `TransactionCard` · `TransactionDetail`
- [ ] Virtualization with correct `aria-rowcount`/`aria-rowindex`
- [ ] Full grid keyboard model — arrows navigate, one tab stop
- [ ] All four responsive presentations, **including the 768–1024 sticky-both-edges pattern**
- [ ] `FilterBar` (URL-backed) · `BulkActionBar` · `ColumnManager` · `ExportMenu`
- [ ] `use-density` + `DensityToggle`

**Exit gate:** 10,000 rows at 60fps **and INP under 200ms** on a mid-range Android at 4× CPU throttle; full keyboard-only operation; the 390px card list is genuinely usable, not a compromise.

---

## M3.5 — The ledger core

**Deliverable:** the general ledger the statements are a view over. Built before the statements, because a statement that can't drill down to journal entries is a picture of a statement.

- [ ] `JournalEntry` · `JournalEntryForm` · `JournalEntryTable` — **two columns, always**
- [ ] `AccountPicker` · `ChartOfAccounts` · `AccountRegister` · `DimensionPicker`
- [ ] `AdjustingEntryForm` with auto-reverse defaulting on for accruals
- [ ] `EntryReversalDialog` — and **no delete path anywhere on a posted entry**
- [ ] `PeriodStatus` · `CutoffWarning` — the period state machine
- [ ] `RollForward` · `ScheduleTable` · `AccountTieOut` · `SchedulePreview`
- [ ] `AuditTrail` · `EvidencePanel`
- [ ] `IntegrityCheckPanel` with all eleven assertions wired

**Exit gate:** post an entry, reverse it, and prove from the UI alone that history was never rewritten. Every balance sheet account has a tie-out, and a failing tie-out owns the screen.

---

## M4 — Statements

**The differentiator.** Nothing else in the ecosystem has this.

- [ ] `StatementTable` · `StatementRow` · `Rule` in anger
- [ ] `ProfitAndLoss` · `BalanceSheet` · `CashFlowStatement`
- [ ] `StatementToolbar` · `PeriodPicker` (fiscal-aware) · `VarianceCell`
- [ ] `DrilldownSheet` · `FluxAnalysis`
- [ ] Full statement semantics for screen readers
- [ ] **Print stylesheet** — multi-page, repeating headers, no orphaned totals
- [ ] Phone presentation: one period at a time, swipeable, fixed label column

**Exit gate:** an accountant who closes books reviews a rendered P&L and balance sheet and finds nothing wrong. That's the real test, and it should happen before the code is called stable.

**Why here:** it's the hardest thing to retrofit, the biggest differentiator, and it stress-tests the primitives harder than anything else.

---

## M4.5 — The close

**Deliverable:** the workflow the statements exist for. This is the Numeric/FloQast lane, operating on the same components that render the statements rather than beside them.

- [ ] `CloseStatus` — the seven-section gated pipeline
- [ ] `CloseChecklist` with owners, blockers, weighted progress, and audited sign-off
- [ ] `ReconciliationView` with basis-stated match suggestions + `CategoryPicker` with inline rule creation
- [ ] `FluxAnalysis` — required explanations on material variances, with drivers
- [ ] `MaterialityPolicy` · `RestatementBanner` · `SubsequentEventLog`
- [ ] `ApprovalChain` · `ApprovalInbox` (mobile-first) · `RoleMatrix`

**Exit gate:** a full month-end close run end to end in the product, by someone who closes books for a living, with no spreadsheet.

---

## M5 — Receivables (AR)

- [ ] `InvoiceForm` with the per-line revenue-recognition preview · `InvoiceDetail` · `InvoiceRegister`
- [ ] `AgingTable` tied to the AR control account
- [ ] `CashApplication` + `PaymentSuggestion` — **every case**, not the happy path
- [ ] `UnappliedCashPanel` · `CreditNoteForm` · `CustomerStatement`
- [ ] `CollectionsWorklist` with promise-to-pay · `DunningTimeline`
- [ ] `RevenueWaterfall` from performance obligations

**Exit gate:** a lump-sum payment covering seven invoices with a short pay and a bank fee applies correctly, with every difference given an explicit disposition.

---

## M6 — Payables (AP)

- [ ] `BillForm` + `DuplicateBillAlert` (blocking) · `BillDetail` · `BillRegister`
- [ ] `ThreeWayMatch` with line-level variance · `MatchExceptionQueue`
- [ ] `ApprovalChain` version-binding — editing a bill voids its approvals
- [ ] `PaymentRunBuilder` · `PaymentRunPreview` with hold-to-confirm and resulting cash
- [ ] `VendorMaster` with versioned bank details · `BankDetailChangeAlert`
- [ ] `ExpenseCapture` (camera-first) · `CardTransactionMatch`
- [ ] `UninvoicedReceiptsReport` driving the GR/IR accrual

**Exit gate:** segregation of duties cannot be bypassed by any path in the UI, and a vendor bank-detail change before a payment run is impossible to miss.

---

## M7 — Payments

- [ ] `AmountInput` — with the full parse/format/caret test suite
- [ ] `PaymentForm` · `CurrencySelect` · `PayeeSelect` · `PaymentMethodList`
- [ ] `ConfirmPaymentDialog` · `HoldToConfirm` **with all accessible fallbacks**
- [ ] `PaymentStatusTimeline` · `PaymentSuccess` · `CheckoutSummary`
- [ ] `Sheet` (Vaul) · `Toast` (Sonner) configured
- [ ] Full gesture layer: velocity dismissal, boundary damping, pointer capture, multi-touch protection

**Exit gate:** the whole payment flow completed one-handed on a real iPhone SE, over a throttled network, with VoiceOver on.

---

## M8 — Swaps & FX

- [ ] `SwapWidget` + the flip · `RateLine` · `RateLock` · `ConversionBreakdown`
- [ ] `CurrencyPairChart` · `RateTicker` · `SlippageControl` · `FxExposure`
- [ ] Live-value infrastructure: `use-live-value`, the value flash, throttled `aria-live`

**Exit gate:** a rate expiring mid-transaction is handled correctly — the action blocks until the user acknowledges the new rate. Never executes at an unseen rate.

---

## M9 — Charts, dashboard & metrics

- [ ] `MoneyChart` · `MoneyBarChart` · `WaterfallChart` · `CategoryBreakdown`
- [ ] `ChartLegend` · `ChartTooltip` · `DataTableToggle`
- [ ] `DashboardShell` · `AnomalyCard` · `RunwayCard` · `CashCalendar`
- [ ] Money Law 2 enforced in tests: assert **no animation on data change**
- [ ] `MetricDefinition` — and **no metric card ships without one**
- [ ] `NonGaapReconciliation` · `MrrBridge` · `BudgetVsActual` · `CovenantMonitor`

**Exit gate:** every chart has a working table equivalent; every metric shows its formula with values substituted; the greyscale test passes on all of them.

---

## M10 — Multi-entity & consolidation

- [ ] `EntitySelector` — standalone vs. consolidated visually distinct
- [ ] `ConsolidationView` · `NciPanel` · `EliminationEntry`
- [ ] `IntercompanyMatrix` — must net to zero, break types named
- [ ] `TranslationSummary` · `CtaRollForward` · `FxRevaluation` · `FxGainLossPanel` · `RateTable`

**Exit gate:** a three-entity group with two functional currencies consolidates, eliminates, translates, and ties — with the CTA visible as its own equity line.

---

## M11 — Completeness & polish

- [ ] Remaining specified components
- [ ] `CommandPalette` (motionless), the reconciliation match animation
- [ ] `LedgerTable` · `TrialBalance` · `AuditorMode` · `SamplingTool` · `EvidenceBundle`
- [ ] `LeaseSchedule` · `AllowanceRollForward` · `ForecastTable`
- [ ] Full visual regression matrix: every component × {light, dark, forced-colors, signal} × {compact, default, comfortable} × {320, 768, 1280}
- [ ] Motion review pass — every animation at 4× slowdown, frame-stepped
- [ ] An [audit pass](craft/03-quality-bar.md#the-audit-pass) per shipped surface — three findings maximum, plans written to `design-plans/`
- [ ] The next-day review on every component

---

## Deferred

| Item | Gate |
|---|---|
| `corner-shape: squircle` | Baseline Widely Available. Progressive enhancement, no layout change. |
| View Transitions | Not for in-app finance navigation. Revisit only if interruption handling improves. |
| Figma library | After M4, so it's generated from settled components rather than guiding them. |
| Additional themes | Never as a marketplace. A consumer overrides `--accent` and `--font-display`; anything more is a fork. |
| Vue / Svelte ports | After the React system is stable. The tokens and the docs port; the components don't. |

---

## Definition of done

A component is `stable` only when **all** of these are true:

1. The four-layer spec exists, was reviewed **before** the code, and ships in its sibling `README.md`
2. The full [quality bar](craft/03-quality-bar.md) passes — every section, 4b included
3. Every edge case in the checklist has a test or a story
4. `axe` clean; keyboard-only pass; VoiceOver **and** NVDA pass
5. Visual regression across the full matrix
6. Motion reviewed at 4× slowdown on a throttled real device
7. Financial review by someone who has actually closed a month — and for anything in families 9–13, a review against the [domain docs](domain/) clause by clause
8. **The next-day review is done**

Merged is not stable. Step 8 is not optional — it catches more real problems than every automated check combined.
