fix(core,store): child accounts share their parent's type; periods nest; lines checked when added
Three spec decisions from Stephen (2026-10-13), each test-first:
- A child account has its parent's type (ParentTypeMismatch): a child
subdivides its parent. Test: a_child_account_has_its_parents_type.
- Periods nest (a month in a quarter in a year) but never partially
overlap (PeriodsOverlap; a refusal uses no id). Test:
periods_nest_but_never_partially_overlap.
- A line's account must exist and take postings when the line is added,
not only at post (UnknownAccount / PlaceholderAccount from add_line
and add_line_fx); posting still re-checks. Two older tests that pinned
the post-time refusal now check both (the post-time check is reached
through the unchecked replay path, as old journals can).
Compatibility: replay reads history through new Ledger::replay_*
commands (add_account, add_line, add_line_fx, create_period) that skip
checks added later, so books written before these rules still open.
The contract test books_written_under_older_rules_still_open writes such
a journal directly and found, on its first run, that the SQLite
cross-check rebuild used the checked commands and would have failed
verification ("sqlite projection can't be read back"); it now replays
too. Documented in docs/spec/README.md; decisions recorded in rules.md
(B-1, B-4, B-12).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GWVo7x3UHw5kwCUaWxiejX
This commit is contained in:
1 parent
df38dcccf9
commit
925c3ba523
7 files changed
+362
-12
No files matched your search
@@ -31,6 +31,14 @@ SOURCE: CONVENTION (QuickBooks aging); nearest authority ASC 326-20-55-38 (illus
|
||||
A rule whose only source is CONVENTION or DECISION is a candidate for a
|
||||
human to confirm or overturn; nothing else is.
|
||||
|
||||
## Rules added later never lock out older books
|
||||
|
||||
When a rule is tightened (a check added to a command), books written
|
||||
before it must still open. Journal replay and the SQLite cross-check read
|
||||
history through the engine's `replay_*` commands, which skip checks added
|
||||
later; new commands go through the checked ones. Pinned by
|
||||
`books_written_under_older_rules_still_open` (ledger-store).
|
||||
|
||||
## Vendoring rules
|
||||
|
||||
- Public-domain texts are copied **verbatim** (whitespace normalized), each
|
||||
|
||||
+11
-3
@@ -27,7 +27,10 @@ Spec blocks in the code cite these as `SOURCE: rules.md B-n`.
|
||||
total credits after you post the journal entries to the ledger accounts."
|
||||
|
||||
**Enforced:** `kernel::check_lines` via `JournalEntry::validate` (two or
|
||||
more lines, debits = credits exactly). **Checked:** Kani
|
||||
more lines, debits = credits exactly). A line's account must exist and
|
||||
take postings when the line is added, not only at post: DECISION
|
||||
(Stephen, 2026-10-13), `Ledger::add_line`
|
||||
(`a_line_on_an_unknown_or_placeholder_account_is_refused_when_added`). **Checked:** Kani
|
||||
`check_lines_is_exact`, `accepted_entry_nets_to_zero`; Lean
|
||||
`Accepted.net_zero`; property `prop_posted_entries_balance`.
|
||||
|
||||
@@ -74,7 +77,9 @@ its liabilities … from delivering or producing goods, rendering services,
|
||||
or carrying out other activities." E81 expenses "are outflows or other
|
||||
using up of assets … or incurrences of its liabilities …".
|
||||
|
||||
**Enforced:** `AccountType` (five variants). **Checked:** by type.
|
||||
**Enforced:** `AccountType` (five variants). A child account has its
|
||||
parent's type: DECISION (Stephen, 2026-10-13), `Ledger::add_account`
|
||||
(`ParentTypeMismatch`). **Checked:** `a_child_account_has_its_parents_type`.
|
||||
|
||||
## B-5 Normal balances
|
||||
|
||||
@@ -178,7 +183,10 @@ the entity
|
||||
Periods themselves: IRS Pub. 538 (`sources/irs-periods-and-methods.md`)
|
||||
defines the tax year, calendar and fiscal. Locking a closed period and
|
||||
closing in order are practice (and follow from B-8: a closed period's
|
||||
book is not rewritten). **Enforced:** `closed_period_containing`,
|
||||
book is not rewritten). Periods nest (a month in a quarter in a year)
|
||||
and never partially overlap: DECISION (Stephen, 2026-10-13),
|
||||
`Ledger::create_period` (`PeriodsOverlap`;
|
||||
`periods_nest_but_never_partially_overlap`). **Enforced:** `closed_period_containing`,
|
||||
`CloseOutOfOrder`, `Store::rehearse`. **Checked:** Lean `Steps.frozen`;
|
||||
store property `refused_commands_never_reach_the_journal` (no draft in a
|
||||
closed period).
|
||||
|
||||
Reference in new issue
Block a user