Split administrative-correction into typed development/remission corrections

Resolves the WP-0003-T06 review flag: the single administrative-correction
ledger entry type had an unstated fold-side effect (concept §17 names the
type but never says which side of the target it corrects). Maintainer chose
option (a) — split into administrative-correction-development and
administrative-correction-remission so the corrected side is explicit in
the type name rather than an implicit library default.

- schemas/ledger_entry.schema.json: enum split, no other behavior change.
- src/target_revenue/fold.py: each new type maps to its named side only.
- specs/TargetLedgerSpecification.md, TechnicalSpecificationDocument.md
  §3.2, ProductRequirementsDocument.md FR-5: updated to the split types.
- tests/test_ledger_fold.py: dedicated coverage for both new types plus a
  regression test that the old unsplit type name is now rejected.

spec/TargetRevenueLicenseConcept.md §17 is left unedited — its entry-type
list is explicitly non-exhaustive ("may include"), so this specializes
rather than contradicts it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-07-29 09:16:22 +02:00
parent 754d104b7a
commit 2b675c11ad
7 changed files with 129 additions and 29 deletions

View file

@ -24,7 +24,8 @@ _KNOWN_TYPES = frozenset(
"remission-credit",
"credit-reversal",
"remission-correction",
"administrative-correction",
"administrative-correction-development",
"administrative-correction-remission",
"conversion-checkpoint",
}
)
@ -50,17 +51,22 @@ def fold_outstanding_target(
"""Fold an ordered list of ledger entries into cumulative totals.
Entry-type effects (Stage 0):
development-credit += amount to Development Credit
remission-credit += amount to Remission Credit
credit-reversal -= amount from Development Credit (Rule 8:
compensating entry, never edits the
original)
remission-correction += amount to Remission Credit (amount may be
negative to correct an over-remission)
administrative-correction += amount to Development Credit (Stage 0
simplification: a generic correction
bucket; not yet specialized by target side)
conversion-checkpoint no numeric effect (marker only)
development-credit += amount to Development Credit
remission-credit += amount to Remission Credit
credit-reversal -= amount from Development Credit
(Rule 8: compensating entry,
never edits the original)
remission-correction += amount to Remission Credit
(amount may be negative to
correct an over-remission)
administrative-correction-development += amount to Development Credit
administrative-correction-remission += amount to Remission Credit
(split 2026-07-29 so the
corrected target side is
explicit in the type name,
replacing the single ambiguous
administrative-correction type)
conversion-checkpoint no numeric effect (marker only)
"""
development_credit = 0.0
remission_credit = 0.0
@ -81,8 +87,10 @@ def fold_outstanding_target(
development_credit -= amount
elif entry_type == "remission-correction":
remission_credit += amount
elif entry_type == "administrative-correction":
elif entry_type == "administrative-correction-development":
development_credit += amount
elif entry_type == "administrative-correction-remission":
remission_credit += amount
outstanding_target = max(
0.0, initial_target_amount - development_credit - remission_credit