Skip to Content
Fund AccountingAcceptance Lab (How-To)

Acceptance Lab: Run a Fund End-to-End

The Acceptance Lab (apps/acceptance-lab) turns a declarative FundScenario — a fund described as data: calendar, terms, investors — into a deterministic multi-period close on an in-memory Postgres (pglite), and emits Carta-shaped statements (P&L, balance sheet, per-LP PCAP) that tie out against an independent set of §1a reconciliation identities.

It exists to be a data-model forcing function — because the cheapest place to discover that the schema cannot express a real LPA is a synthetic run, not a live customer close. You author a real fund’s terms, run it, and either it ties out or it surfaces a gap. Where an option isn’t built yet, the Lab fails closed (errors) rather than guessing.

Running a scenario

Author the scenario

A FundScenario is JSON validated by @opsdna/fund-scenario: fiscal calendar, terms (fee schedule, waterfall, expenses), investors and their commitments, and optional side letters/investments. The full option reference is apps/acceptance-lab/README.md.

Validate

bun apps/acceptance-lab/src/cli.ts validate path/to/scenario.json

Exits 1 on a decode failure or any error-severity issue. Fast, no DB.

Explain (optional, no DB)

bun apps/acceptance-lab/src/cli.ts explain path/to/scenario.json --quarters 2

Emits JSON: the normalized scenario, the event timeline + hash, per-period fee summaries, the per-LP allocation split, and coverage gaps. Deterministic — useful for eyeballing computed numbers before a full run.

Run the close

bun apps/acceptance-lab/src/cli.ts run path/to/scenario.json --out ./out --quarters 2

Stands up pglite, runs the multi-period close, and writes a RunManifest directory. Exits 1 if a period fails to freeze or any §1a reconciliation identity fails. Add --no-artifacts to skip PDF/xlsx rendering, --explain to also print the explain JSON. Under accrual_cadence: "annual", --quarters counts fiscal years.

Review and diff

bun apps/acceptance-lab/src/cli.ts review ./out bun apps/acceptance-lab/src/cli.ts diff a.json b.json --timeline bun apps/acceptance-lab/src/cli.ts diff-ir old-ir.json new-ir.json --format text

review prints the one-page review packet (scenario summary, period-by-period activity, the §1a checklist, top deltas vs a prior run with --prior-ir). diff is a semantic scenario diff — two scenarios that serialize differently but decode to the same value produce an empty diff (fundScenarioContentHash is the oracle). diff-ir compares statements IR at per-period → statement → LP → line-code grain in integer minor units. Both diffs exit 1 when a difference exists, so CI can gate on them.

The package script form is bun run --cwd apps/acceptance-lab cli <mode> …, and the test suite runs with bun run --cwd apps/acceptance-lab test.

What a run exercises

The Lab drives the whole stack documented in this section: it lowers the scenario’s terms through the policy IR layer, runs the runtime evaluators that emit canonical application records, posts through the ledger kernel, projects PCAP, and builds statements. The per-domain close modules live in apps/acceptance-lab/src/ — e.g. european-carry-persisted-quarter-close.ts, distribution-persisted-quarter-close.ts, fair-value-adjustment-persisted-quarter-close.ts, fund-statements-builder.ts, and live-pcap-bridge.ts. The Lab’s gates also reconcile the persisted *_application_details rows row-for-row against the runtime records — which is how they earned their keep in the ADR-0019 §5 drop-wave proof.

Pitfalls.

  • The Lab runs on pglite, which silently accepts things real Postgres rejects (EXECUTE grants, RLS FORCE, catalog invariants). A green Lab run is not a green postgres integration lane — schema changes need the real-Postgres tests too (see Persistence).
  • Fields a milestone hasn’t built yet (waterfall, expense, investments, side_letters at AL0) are accepted by the schema but not exercised; the Lab fails closed rather than guessing. Don’t interpret an error as a bug before checking the current scope note in apps/acceptance-lab/README.md.
  • The IR diff (diff-ir) is the “safer golden review” artifact — prefer it over byte-diffing rendered PDFs/xlsx when reviewing golden changes.

The Lab’s composed-close identity model is recorded in docs/adrs/0008-acceptance-lab-partner-capital-gl-and-composed-close-identity.md.

Last updated on