# Trial-Balance Validation — frozen definition and exact wire

25 October 2026. D30-F04-A02. Root ratified zero-genesis/full history, cumulative booking-period basis, all chosen USD accounts including zero, independent reported vector, exact normal-side presentation, historical p-versus-h coverage and source trust boundaries before code. This owner-selected exact schema completes those choices. All examples are synthetic.

## Financial variant and learning contract

Recompute a cumulative booked functional-USD trial balance from the declared ledger's zero genesis and complete accepted journal history, then compare every account and aggregate debit/credit columns with an independently identified reported balance vector. A financial pass establishes arithmetic and projection agreement under supplied trusted evidence, not economic classification, recognition completeness, source authentication or complete financial statements.

Never filter by economic effective_at. Include a journal only when its complete group receipt is at or before K and command.booking_period is at or before the requested period. This is a cumulative ledger balance, not the requested month's movement-only profit. Authorized late prior-effective/current-booking adjustments remain in their actual booking period. Ordinary closing journals, if accepted, remain normal journal history; the implementation does not close income accounts by itself.

Opening is explicitly zero for every chart account at stream sequence 0 under trusted genesis evidence. Nonzero opening balances must be accepted balanced opening journals. No checkpoint or caller-supplied opening vector bypass is supported. The separate CB-CLOSE-2026 close branch is valid without changing CB-GENERAL's earlier locked-month policies.

USD is the only reporting currency in this functional-USD profile, exponent 2. Complete EUR journal/account evidence is validated but its amounts are excluded and counted, never translated or added. FX quantity and USD carrying are separate views. Every chosen USD chart account is retained, including zero and now-closed accounts. Historical accepted journals are not rechecked against today's posting eligibility or open periods.

Raw balance is debit-positive. Normal display equals raw for debit-normal asset/expense and minus raw for credit-normal liability/equity/income. Debit balance column is max(raw,0), credit column max(-raw,0), regardless of normal type. An abnormal negative normal balance is a diagnostic, not automatically invalid.

Primary evidence accessed 2026-10-25:
- OpenStax, Principles of Accounting Vol.1, `3.6: https://openstax.org/books/principles-financial-accounting/pages/3-6-prepare-a-trial-balance — debit/credit ending-balance columns and equal columns not guaranteeing correctness. We retain zero accounts explicitly, unlike its illustrative nonzero-account presentation.
- GnuCash v5, `10.3.5.11: https://www.gnucash.org/docs/v5/C/gnucash-guide/rpt_standardrpts.html — ending balances and debit/credit arithmetic purpose.
- GnuCash v5 accounting concepts: https://code.gnucash.org/website/docs/v5/C/gnucash-guide/basics-accounting1.html — account-type normal sign context.

No published transaction table is copied. Historical-case decision: not useful without complete reusable ledger/chart/genesis and independently retained report chronology.

## API and scalars

Python `validate_trial_balance(query,groups,accounts,context)` / TypeScript `validateTrialBalance`.

All objects reject unknown/missing fields. Reuse frozen Stage 1/2 IDs, journal/leg/export/group/correction/head schemas and ordered committed-history semantics. Group/journal order is semantic and cannot be sorted to rescue missing/reordered evidence. The local self-contained module pins the Stage 2 historical validator unchanged and tests its shared cases; other topic sources are untouched.

Query exact keys:

`schema_version,ledger_id,entity_id,period,currency,basis,knowledge_cutoff`.

- schema_version d30-trial-balance-v1.
- scope strict ASCII IDs.
- period genuine YYYY-MM, year 0001..9999.
- currency USD; basis functional-usd.
- Derived measurement_at is requested month's final UTC millisecond. K genuine strict UTC milliseconds and K >= measurement_at.
- balance_basis is the fixed output/profile value cumulative-booking-period-v1.

All input money remains canonical decimal strings. Journal legs positive <=30 digits. Reported signed raw balances permit zero and optional minus before a positive magnitude, <=120 magnitude digits. No -0, plus, leading zeros, decimal, exponent, Number, bool or coercion. All outputs are exact canonical integer strings; derived sums are not clamped to input limits.

## Accounts, independent chart and genesis

accounts is a list of <=256 exact Stage 1 seven-field records: `account_id,ledger_id,entity_id,currency,account_type,normal_side,status`. IDs unique; every record belongs to query ledger/entity; USD/EUR only; asset/expense debit-normal and liability/equity/income credit-normal; active/closed status. Contra account classification is excluded from this initial profile. A closed account's historical balance remains included.

Context exact keys `head,genesis,chart_evidence,reported_trial_balance`. Head is unchanged Stage 2 `stream_id,ledger_id,entity_id,observed_at,head_sequence,receipt_ref`, an independent consistent committed-source snapshot. Full group history 1..head is validated before receipt/booking filters; at most 4096 groups. Missing sequence/tail or K beyond head observation is indeterminate, while structural/identity/clock/account/correction defects reject.

genesis is null (missing evidence) or exact:

`schema_version,stream_id,ledger_id,entity_id,opening_sequence,opening_basis,available_at,receipt_ref`.

Version d30-ledger-genesis-v1; stream/scope equal head/query; opening_sequence exactly "0"; opening_basis exactly all-chart-balances-zero; IDs strict; available_at genuine UTC milliseconds and <=K. A nonzero/imported vector or different origin basis is unsupported, not a zero default. Missing genesis => MISSING_GENESIS; valid but not available => GENESIS_NOT_AVAILABLE. Trusted genesis is a host claim, not cryptographic proof.

chart_evidence is null or exact:

`schema_version,chart_id,chart_version_ref,ledger_id,entity_id,available_at,observed_at,account_count,account_ids,receipt_ref`.

Version d30-chart-evidence-v1; strict IDs and matching scope. account_count canonical nonnegative string <=256; account_ids a unique strict-ID list of exactly that size, representing the trusted complete entity chart, not inferred from supplied accounts. Its set must equal the supplied account-ID set. A missing declared account is INCOMPLETE_CHART; undeclared/extra or contradictory identities reject CHART_ACCOUNT_SET_MISMATCH. Array delivery is nonsemantic. Chart receipts must be available_at<=K<=observed_at; malformed clocks reject; missing/unavailable/observation gaps are indeterminate. Account metadata/type/source completeness remains an authenticated host obligation outside JSON.

## Independently reported vector receipt

reported_trial_balance is null or the generic trusted close-source envelope extended exactly as follows.

Base exact keys:
`schema_version,evidence_id,ledger_id,entity_id,period,currency,basis,knowledge_cutoff,observed_at,head_sequence,receipt_ref`.

Additional exact keys:
`stream_id,balance_basis,chart_id,chart_version_ref,available_at,balances`.

Base version d30-close-source-v1. Scope/currency/basis bind query; period and knowledge_cutoff bind the queried view; stream binds the complete source head. balance_basis exactly cumulative-booking-period-v1; chart identity/version bind chart_evidence. Genuine UTC clocks: measurement_at <= available_at <= K <= observed_at. A genuinely later/unavailable report is indeterminate, never relabeled known earlier. Contradictory pre-boundary or reversed intrinsic clocks reject INVALID_REPORTED_CLOCK.

head_sequence binds p, the complete whole-group visible observer position at K, **not** the later full validation head h. The output records both p and h. Require report.available_at >= the last selected whole-group receipt, so a report cannot claim a source revision not yet available at its own publication. Wrong current position or stale publication yields REPORTED_HEAD_MISMATCH / STALE_REPORTED_RECEIPT, indeterminate. A final current-close adapter additionally requires p == the actual captured frozen h; historical queries remain supported.

balances is a list of <=256 exact `account_id,raw_balance_minor` objects. It contains every chosen USD chart account exactly once, including explicit zero. No other currency/account is silently dropped. Missing required account => INCOMPLETE_REPORTED_BALANCES; unknown/foreign/extra account => REPORTED_ACCOUNT_SET_MISMATCH. Strict signed money as above. Same-ID changed payload => REPORTED_ACCOUNT_CONFLICT, exact duplicate => DUPLICATE_REPORTED_ACCOUNT, conflict wins before duplicate copies independently of delivery order.

A missing report => MISSING_REPORTED_TRIAL_BALANCE. Valid old period/K/chart identity => REPORTED_QUERY_MISMATCH / REPORTED_CHART_MISMATCH, indeterminate. Wrong ledger/entity/stream/currency/basis is a rejected scope/basis mismatch. No arithmetic is emitted until required source, genesis, chart and report evidence are complete and causally available.

## Computation and complete output

For each USD account, begin raw0 and accumulate every selected journal leg: debit +amount, credit -amount. Preserve each complete correction group and all original/reversal/replacement legs. Derive expected normal and debit/credit presentation. Independently normalize reported signed values using the same immutable account normal side, then compare each account.

Always exact top-level:

`status,code,scope,source_evidence,chart_evidence,reported_receipt,lines,totals,trace`.

Rejected or indeterminate has its typed code and null scope/source_evidence/chart_evidence/reported_receipt/totals, lines[] and trace[]. No partial projection is presented.

scope exact `ledger_id,entity_id,period,currency,basis,balance_basis,measurement_at,knowledge_cutoff`.

source_evidence exact `stream_id,receipt_ref,observed_at,head_sequence,validated_through_sequence,visible_through_sequence,last_visible_group_id,last_visible_available_at,genesis_receipt_ref,excluded_currency_account_count,excluded_currency_journal_count,excluded_later_booking_journal_count,selected_journal_count`. Last fields are null at visible0 where appropriate; counts canonical strings. Visible position includes complete known groups even when their journals are outside the reporting period/currency. No future group/journal identities leak into trace.

chart_evidence and reported_receipt are detached canonical copies of input evidence; their availability has passed current query checks. The nonsemantic chart account_ids and reported balances arrays are sorted by ASCII account_id after strict identity checks; every field value and provenance string is preserved. lines sorted ASCII account_id, with each exact:

`account_id,currency,account_type,normal_side,status,debit_movement_minor,credit_movement_minor,raw_balance_minor,normal_balance_minor,debit_balance_minor,credit_balance_minor,reported_raw_balance_minor,reported_normal_balance_minor,reported_debit_balance_minor,reported_credit_balance_minor,difference_minor,abnormal_balance,matches_reported`.

Here status is the chart active/closed enum. difference_minor = reported raw - expected raw. abnormal_balance is expected normal<0, exact bool; matches_reported exact bool. Every chosen account appears, including zero. Consumers use expected raw/normal/debit/credit fields from a **passed** actual validation; arbitrary extracted receipt claims do not become verified merely by their IDs.

totals exact:

`debit_movement_minor,credit_movement_minor,raw_movement_residual_minor,debit_balance_minor,credit_balance_minor,residual_minor,reported_debit_balance_minor,reported_credit_balance_minor,reported_residual_minor,mismatched_account_count,account_count,zero_account_count,abnormal_account_count`.

Movement totals are historical selected leg volumes, not closing balance columns. Expected balance residual = expected debit balances - expected credit balances. Reported residual uses reported balance columns. All signed amounts/counts strings; expected residual is an invariant zero under complete balanced journals/zero genesis. An independently wrong reported vector can have a nonzero residual or balanced but per-line wrong values.

trace preserves selected journal order and exact semantic leg order. Each entry exact `group_id,available_at,journal_id,business_operation_id,sequence,recorded_at,effective_at,booking_period,currency,debit_minor,credit_minor,legs`. Each leg exact `account_id,side,amount_minor,raw_delta_minor,raw_balance_after_minor`. This is committed observer-sequence audit order, not a claim about intraday availability or economic recognition. No automatic journal is generated.

## Status and error precedence

1. Strict query/context/account/journal/receipt schemas, scopes, identities, intrinsic clocks and full history defects are validated before financial output; malformed/conflicting inputs reject.
2. Missing/incomplete/unavailable source/genesis/chart/report evidence => indeterminate, no projection. Valid stale report position/period/K/chart/availability => indeterminate.
3. Complete evidence: nonzero reported debit-minus-credit residual => fail/TRIAL_BALANCE_UNBALANCED.
4. Otherwise any per-account reported-versus-recomputed difference => fail/TRIAL_BALANCE_PROJECTION_MISMATCH.
5. Otherwise pass/TRIAL_BALANCE_VALIDATED.

A structural unbalanced journal rejects UNBALANCED_JOURNAL rather than fabricating a complete projection. Both entire omitted balanced journals and wrong same-normal-side account assignment can remain arithmetically balanced. Independent source-head completeness and per-line report comparison address declared evidence/projection errors, not unposted obligations or incorrect economic coding.

Within fixed validation phases, independent malformed-field codes use lexical priority. Changed report identities precede exact copies. Ordered committed groups retain Stage 2 typed errors; no delivery sorting rescues them. Account/chart/report arrays are canonicalized only after strict identity checks.

## Canonical independent close-branch arithmetic

Use CB-CLOSE-2026/entity CB-A, distinct from the earlier CB-GENERAL/interest-product stories. A balanced opening journal Dr cash_usd100000 / Cr opening_equity_usd100000 establishes the nonzero ledger through accepted entries. September estimated operating accrual Dr operating_accrual_expense_usd25000 / Cr operating_accrual_payable_usd25000 is booked September, caught up in October; exact reversal is booked October. At a K after both acceptances, September cumulative report still contains the September expense/payable: debit/credit totals125000. October cumulative report includes both estimate and reversal and returns expense/payable0, totals100000. Every zero USD account remains visible.

Foreign EUR opening journals may share the same complete source stream; validate them but count/exclude their values. A late prior-effective expense booked October must remain excluded from September. A reported cash +1 produces reported residual+1 and fails arithmetic. Reported cash+100 and opening-equity−100 stays balanced but fails both per-account comparisons. A wrong expense account in both accepted journals and report may pass; its economic correctness is outside this algorithm.

The final close adapter must actually run this kernel, require pass, bind p to the frozen current h, retain the reported/chart/genesis/source receipts and verify any FX/intercompany extracted line amounts against returned exact raw balances. A trial pass does not substitute for scheduler acceptance, FX posting/current carrying or other period-close prerequisites.

