target-revenue/tests/test_ledger_fold.py
tegwick 55a1756f7c Merge spec/ into specs/: one specs directory for the whole repo
Moves TargetRevenueLicenseConcept.md from the separate singular spec/
directory into specs/ (git mv, preserving history) and updates every live
cross-reference (README, CONTRIBUTING, all specs/*.md, workplans, schema
comments, source docstrings, test file) to the new path.

This resolves the spec/ vs specs/ split that history/260728-SWOT-Assessment.md
flagged as a "perpetual footgun" and recommended deciding on. The historical
record of that split and the recommendation itself are left unedited in
history/ (a dated assessment, not a living document) — only README and TSD
now document the merge as resolved, with a pointer back to that history file
for context.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-29 10:22:14 +02:00

211 lines
7.2 KiB
Python

import copy
import pytest
from conftest import golden_entries, golden_manifest
from target_revenue import fold, hashing, validation
def test_golden_entries_are_individually_conformant():
for entry in golden_entries():
validation.validate_ledger_entry(entry)
def test_golden_entries_currency_matches_phase():
errors = validation.check_currency_consistency(golden_manifest(), golden_entries())
assert errors == []
def test_currency_mismatch_is_detected():
manifest = golden_manifest()
entries = copy.deepcopy(golden_entries())
entries[0]["currency"] = "EUR"
errors = validation.check_currency_consistency(manifest, entries)
assert len(errors) == 1
assert "EUR" in errors[0]
def test_golden_hash_chain_is_valid():
hashing.verify_chain(golden_entries())
def test_tampered_entry_breaks_hash_chain():
entries = copy.deepcopy(golden_entries())
entries[2]["amount"] = 999999 # tamper after the chain was computed
with pytest.raises(ValueError, match="hash chain broken"):
hashing.verify_chain(entries)
def test_reordered_entries_break_hash_chain():
entries = copy.deepcopy(golden_entries())
entries[1], entries[2] = entries[2], entries[1]
with pytest.raises(ValueError, match="hash chain broken"):
hashing.verify_chain(entries)
def test_fold_matches_concept_section_23_first_checkpoint():
"""specs/TargetRevenueLicenseConcept.md §23: after the first four entries,
Development Credit $37,000, Remission Credit $18,000, Outstanding $45,000."""
manifest = golden_manifest()
first_four = golden_entries()[:4]
result = fold.fold_outstanding_target(
manifest["phase"]["initial_target"]["amount"], first_four
)
assert result.development_credit == 37000
assert result.remission_credit == 18000
assert result.outstanding_target == 45000
assert not result.is_converted
def test_fold_reaches_zero_and_converts():
"""specs/TargetRevenueLicenseConcept.md §23: full six-entry sequence
reaches Outstanding Target = 0 (Development Credit $67,000 + Remission
Credit $33,000 = Initial Target $100,000)."""
manifest = golden_manifest()
result = fold.fold_phase(manifest, golden_entries())
assert result.development_credit == 67000
assert result.remission_credit == 33000
assert result.outstanding_target == 0
assert result.is_converted
def test_credit_reversal_reduces_development_credit():
entries = [
{
"id": "trsl:entry:t0001",
"phase": "trsl:phase:t",
"type": "development-credit",
"amount": 5000,
"currency": "USD",
"recognized_at": "2026-01-01T00:00:00Z",
"extension": {"id": "trsl:extension:development-license", "version": "1.0"},
"evidence_reference": "confidential:evidence:t0001",
"previous_entry_hash": "GENESIS",
},
]
entries.append(
{
"id": "trsl:entry:t0002",
"phase": "trsl:phase:t",
"type": "credit-reversal",
"amount": 5000,
"currency": "USD",
"recognized_at": "2026-01-02T00:00:00Z",
"evidence_reference": "confidential:evidence:t0002-refund",
"previous_entry_hash": hashing.entry_hash(entries[0]),
"reverses": "trsl:entry:t0001",
}
)
result = fold.fold_outstanding_target(100000, entries)
assert result.development_credit == 0
assert result.outstanding_target == 100000
def test_remission_correction_can_reduce_over_remission():
entries = [
{
"id": "trsl:entry:t0001",
"phase": "trsl:phase:t",
"type": "remission-credit",
"amount": 20000,
"currency": "USD",
"recognized_at": "2026-01-01T00:00:00Z",
"extension": {"id": "trsl:policy:linear-longstop-v0", "version": "1.0"},
"evidence_reference": "confidential:evidence:t0001",
"previous_entry_hash": "GENESIS",
},
]
entries.append(
{
"id": "trsl:entry:t0002",
"phase": "trsl:phase:t",
"type": "remission-correction",
"amount": -5000,
"currency": "USD",
"recognized_at": "2026-01-02T00:00:00Z",
"evidence_reference": "confidential:evidence:t0002-correction",
"previous_entry_hash": hashing.entry_hash(entries[0]),
"reverses": "trsl:entry:t0001",
}
)
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)