from pathlib import Path ROOT = Path(__file__).parents[1] def _text(relative_path: str) -> str: return (ROOT / relative_path).read_text(encoding="utf-8") def test_data_model_documents_cache_authority_and_legacy_basis_migration() -> None: data_model = _text("docs/data-model.md") required_contract = ( "`last_balance` is the current cache value", "`last_balance_basis_date`", "`last_synced_at` is the execution/sync timestamp", "imports and account writes advance the account cache", "`account_valuations` is the historical authority", "older evidence never rolls back the current cache", "additive migration", "legacy rows with unknown basis remain unknown; no inference", ) for marker in required_contract: assert marker in data_model, marker def test_interface_contract_documents_public_valuation_enums_validation_and_mapping() -> None: interface = _text("docs/interface-contract.md") assert "actual enums in source" not in interface required_contract = ( "source_type: `manual`, `import`, `account_write`, `reconciliation`, `snapshot`", "verification_status: `verified`, `unverified`, `rejected`", "valuation_kind: `balance`, `cash_balance`, `total_value`, `loan`, `loan_balance`", "representative_liability_definition: `principal_only`, `principal_interest_fees`", "loan accounts require representative_liability_definition for `loan`, `loan_balance`, and `balance` aliases", "legacy valuation-kind aliases remain accepted and map to the canonical purpose", "validation failure returns `validation_error` and performs no write", "loan valuations map to liabilities and non-loan valuations map to assets", ) for marker in required_contract: assert marker in interface, marker def test_data_model_documents_valuation_selection_contract_and_index_mapping() -> None: data_model = _text("docs/data-model.md") required_contract = ( "select_account_valuation", "account_id is mandatory", "currency and valuation_kind/purpose are optional filters", "basis_date exact match or <= upper bound", "verified leaf valuations only", "future-dated and unverified valuations are excluded", "idx_account_valuations_account_date supports account/date selection", "idx_account_valuations_status_date supports status/date selection", "neither index covers account + currency + purpose", "idempotency and single_correction indexes enforce write integrity, not selection", ) for marker in required_contract: assert marker in data_model, marker def test_loan_cache_writers_document_no_inferred_valuation_history() -> None: data_model = _text("docs/data-model.md") interface = _text("docs/interface-contract.md") requirement = _text("docs/requirements/req-003_account-valuation-history.md") assert "loan cache writes without an explicit liability definition do not append" in data_model assert "loan cache writes without an explicit liability definition do not append" in interface assert "대출 cache write는 대표 부채 정의가 없으면 이력 후보를 추가하지 않는다" in requirement