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

@ -131,3 +131,81 @@ def test_remission_correction_can_reduce_over_remission():
result = fold.fold_outstanding_target(100000, entries)
assert result.remission_credit == 15000
assert result.outstanding_target == 85000
def test_administrative_correction_development_adjusts_development_side():
entries = [
{
"id": "trsl:entry:t0001",
"phase": "trsl:phase:t",
"type": "administrative-correction-development",
"amount": 3000,
"currency": "USD",
"recognized_at": "2026-01-01T00:00:00Z",
"evidence_reference": "confidential:evidence:t0001-admin",
"previous_entry_hash": "GENESIS",
},
]
result = fold.fold_outstanding_target(100000, entries)
assert result.development_credit == 3000
assert result.remission_credit == 0
assert result.outstanding_target == 97000
def test_administrative_correction_remission_adjusts_remission_side():
entries = [
{
"id": "trsl:entry:t0001",
"phase": "trsl:phase:t",
"type": "administrative-correction-remission",
"amount": 3000,
"currency": "USD",
"recognized_at": "2026-01-01T00:00:00Z",
"evidence_reference": "confidential:evidence:t0001-admin",
"previous_entry_hash": "GENESIS",
},
]
result = fold.fold_outstanding_target(100000, entries)
assert result.development_credit == 0
assert result.remission_credit == 3000
assert result.outstanding_target == 97000
def test_administrative_correction_types_are_schema_valid():
from target_revenue import validation
for entry_type in (
"administrative-correction-development",
"administrative-correction-remission",
):
entry = {
"id": "trsl:entry:t0001",
"phase": "trsl:phase:t",
"type": entry_type,
"amount": 100,
"currency": "USD",
"recognized_at": "2026-01-01T00:00:00Z",
"evidence_reference": "confidential:evidence:t0001",
"previous_entry_hash": "GENESIS",
}
validation.validate_ledger_entry(entry)
def test_old_unsplit_administrative_correction_type_is_no_longer_valid():
"""The single ambiguous administrative-correction type was split
2026-07-29 (specs/TargetLedgerSpecification.md §2); it must no longer
validate as a known type."""
from target_revenue import validation
entry = {
"id": "trsl:entry:t0001",
"phase": "trsl:phase:t",
"type": "administrative-correction",
"amount": 100,
"currency": "USD",
"recognized_at": "2026-01-01T00:00:00Z",
"evidence_reference": "confidential:evidence:t0001",
"previous_entry_hash": "GENESIS",
}
with pytest.raises(validation.ConformanceError):
validation.validate_ledger_entry(entry)