feat: opening-balance pad automation (#7) #14

Open
agent-int wants to merge 1 commit from feat/issue-7-opening-balance-pad into main
Collaborator

Opening-balance pad automation

First item of the P1 double-entry tier (#7): Beancount pad / Ledger balance-assignment.

Pad an account to a target balance as-of a date by posting the computed difference
(delta = target - currentBalance(asOf date)) as a .system two-leg transaction, balanced
against a pad/equity account (default "Opening Balance Equity"). A zero delta is a no-op.
Idempotent per (account, date) via a pad: content hash, mirroring setOpeningBalance.

Unlike setOpeningBalance, a caller-supplied pad account is guarded like txnAdd's offset: it
must differ from the account (else the two legs self-cancel and never reach the target) and
share its currency (else the offset balance is silently corrupted). No schema migration —
reuses transactions/splits.

Surfaces (server-depth, mirroring the P0 features)

  • Store: Commands.padBalance + Commands.PadOutcome
  • gRPC: PadBalance RPC (+ proto messages), WriterExecutor + service impl
  • Client: LedgerClient.padBalance + PadOutcomeInfo
  • MCP: propose_pad_balance / commit_pad_balance (money-moving → propose/commit split)

Tests

Store (OpeningBalancePadTests), gRPC (PadBalanceRPCTests), and MCP (LedgerToolRegistryTests)
layers — including pad-from-zero, non-zero adjust + passing assertion, no-op, idempotent re-pad,
explicit offset, negative delta, self-offset rejection, currency-mismatch rejection,
and re-pad-collision. Full suite green (make test, 0 failures).

Review

Independent architect review: APPROVE. Independent critic review raised two MAJOR findings on
the custom-offset surface (self-offset silent-wrong-result; currency-mismatch silent-corruption) —
both fixed here with the guards txnAdd already uses, plus tests.

Scope

Delivers exactly one item of #7. The remaining P1 items (budgets/envelopes, pending/cleared,
attachments, bitemporal dates, and the rest) stay open — this does not close #7.

## Opening-balance pad automation First item of the **P1 double-entry tier** (#7): Beancount `pad` / Ledger balance-assignment. Pad an account to a target balance as-of a date by posting the **computed difference** (`delta = target - currentBalance(asOf date)`) as a `.system` two-leg transaction, balanced against a pad/equity account (default **"Opening Balance Equity"**). A zero delta is a no-op. Idempotent per `(account, date)` via a `pad:` content hash, mirroring `setOpeningBalance`. Unlike `setOpeningBalance`, a caller-supplied pad account is guarded like `txnAdd`'s offset: it must **differ** from the account (else the two legs self-cancel and never reach the target) and **share its currency** (else the offset balance is silently corrupted). No schema migration — reuses `transactions`/`splits`. ### Surfaces (server-depth, mirroring the P0 features) - **Store**: `Commands.padBalance` + `Commands.PadOutcome` - **gRPC**: `PadBalance` RPC (+ proto messages), `WriterExecutor` + service impl - **Client**: `LedgerClient.padBalance` + `PadOutcomeInfo` - **MCP**: `propose_pad_balance` / `commit_pad_balance` (money-moving → propose/commit split) ### Tests Store (`OpeningBalancePadTests`), gRPC (`PadBalanceRPCTests`), and MCP (`LedgerToolRegistryTests`) layers — including pad-from-zero, non-zero adjust + passing assertion, no-op, idempotent re-pad, explicit offset, **negative delta**, **self-offset rejection**, **currency-mismatch rejection**, and **re-pad-collision**. Full suite green (`make test`, 0 failures). ### Review Independent architect review: **APPROVE**. Independent critic review raised two MAJOR findings on the custom-offset surface (self-offset silent-wrong-result; currency-mismatch silent-corruption) — both fixed here with the guards `txnAdd` already uses, plus tests. ### Scope Delivers exactly one item of #7. The remaining P1 items (budgets/envelopes, pending/cleared, attachments, bitemporal dates, and the rest) stay open — this does **not** close #7.
feat: opening-balance pad automation (#7)
Some checks failed
ci / macos (pull_request) Successful in 4m0s
ci / linux (pull_request) Has been cancelled
ci / proto (pull_request) Has been cancelled
ci / purity (pull_request) Has been cancelled
743ffa3e8c
Add Beancount `pad` / Ledger balance-assignment: pad an account to a target
balance as-of a date by posting the computed difference (target - current
balance) as a system two-leg transaction, offset to a pad/equity account
(default "Opening Balance Equity"). A zero delta is a no-op; idempotent per
(account, date) via a `pad:` content hash, mirroring setOpeningBalance.

The caller-supplied pad account is guarded like txnAdd's offset: it must
differ from the account (else the two legs self-cancel and never reach the
target) and share its currency (else the offset balance is silently corrupted).

Server-depth surfaces, mirroring the P0 double-entry features:
- Store: Commands.padBalance + PadOutcome
- gRPC: PadBalance RPC (+ proto messages), WriterExecutor + service impl
- Client: LedgerClient.padBalance + PadOutcomeInfo
- MCP: propose_pad_balance / commit_pad_balance (money-moving -> propose/commit)
- Tests at the store, gRPC, and MCP layers (incl. negative delta, self-offset,
  currency-mismatch, and re-pad-collision cases)

First item of the P1 double-entry tier (#7); the remaining items (budgets,
pending/cleared, attachments, bitemporal dates) stay open.
Some checks failed
ci / macos (pull_request) Successful in 4m0s
ci / linux (pull_request) Has been cancelled
ci / proto (pull_request) Has been cancelled
ci / purity (pull_request) Has been cancelled
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin "feat/issue-7-opening-balance-pad:feat/issue-7-opening-balance-pad"
git switch "feat/issue-7-opening-balance-pad"

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch "main"
git merge --no-ff "feat/issue-7-opening-balance-pad"
git switch "feat/issue-7-opening-balance-pad"
git rebase "main"
git switch "main"
git merge --ff-only "feat/issue-7-opening-balance-pad"
git switch "feat/issue-7-opening-balance-pad"
git rebase "main"
git switch "main"
git merge --no-ff "feat/issue-7-opening-balance-pad"
git switch "main"
git merge --squash "feat/issue-7-opening-balance-pad"
git switch "main"
git merge --ff-only "feat/issue-7-opening-balance-pad"
git switch "main"
git merge "feat/issue-7-opening-balance-pad"
git push origin "main"
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
nic/commons!14
No description provided.