fix: preserve schema 15 compatibility for v0.1.8

This commit is contained in:
2026-10-17 18:27:53 +09:00
parent a97548c36b
commit 1134f058cc
61 changed files with 2650 additions and 644 deletions
+32 -3
View File
@@ -341,7 +341,7 @@ loan accounts require representative_liability_definition for `loan`, `loan_bala
loan valuations map to liabilities and non-loan valuations map to assets. The output mapping preserves the existing envelopes and signatures: `success` remains the outcome field, failures include `error_code` and `error`, and validation or conflict failures do not partially write.
Account current-cache writes keep `last_balance_basis_date` (optional `YYYY-MM-DD`) separate from `last_synced_at` (execution/sync timestamp). Account types include `bank`, `card`, `cash`, `investment`, `loan`, `other`, and `real_estate`; a new `real_estate` account defaults its liquidity bucket to `real_estate` when no bucket is supplied. `create_ledger_account` keeps the established positional `db_path` argument and adds `last_balance_basis_date` after it as an optional keyword. `update_ledger_account` accepts the same field through its existing keyword-field boundary. A balance with no explicit basis advances only the current display cache, leaves the basis unknown, and creates no historical candidate. A dated older non-loan balance appends historical evidence but cannot roll back a newer current cache. loan cache writes without an explicit liability definition do not append a historical candidate; they preserve current-cache and import behavior without inferring a definition. Import and account writers use deterministic candidate keys.
Account current-cache writes keep `last_balance_basis_date` (optional `YYYY-MM-DD`) separate from `last_synced_at` (execution/sync timestamp). `create_ledger_account` keeps the established positional `db_path` argument and adds `last_balance_basis_date` after it as an optional keyword. `update_ledger_account` accepts the same field through its existing keyword-field boundary. A balance with no explicit basis advances only the current display cache, leaves the basis unknown, and creates no historical candidate. A dated older non-loan balance appends historical evidence but cannot roll back a newer current cache. loan cache writes without an explicit liability definition do not append a historical candidate; they preserve current-cache and import behavior without inferring a definition. Import and account writers use deterministic candidate keys.
### shared contract and adapter limits
@@ -392,7 +392,7 @@ preview_asset_snapshot_close(basis_date="2026-06-30", selection_policy="exact")
## 검증 추가
- 정상 계약: `tests/test_account_valuation_service_actual.py`, `tests/test_account_snapshot_linking.py`, `tests/test_comprehensive_settlement_adapters.py`
- 정상 계약: `tests/test_account_valuations.py`, `tests/test_asset_snapshots.py`, `tests/test_contract_regression.py`
- 실패 계약: idempotency/correction/conditional approval tests and source validation
- 경계 계약: exact/as_of, NULL/0, future/unverified candidate, correction/re-close
- 구현·스키마·예시 정합성: `tests/test_requirement_docs.py`, actual service/MCP/gateway symbols
@@ -403,7 +403,7 @@ preview_asset_snapshot_close(basis_date="2026-06-30", selection_policy="exact")
The application contracts are these actual signatures (defaults included):
```python
register_account_valuation(account_id: str, basis_date: str, amount: int, currency: str = "KRW", valuation_kind: str = "balance", source_type: str = "manual", source_ref: str = "", verification_status: str = "unverified", memo: str = "", idempotency_key: str = "", as_of_at: str | None = None, timezone: str | None = None, cost_basis: int | None = None, net_contributed: int | None = None, reported_principal_kind: str | None = None, reported_principal_label: str | None = None, profit: int | None = None, return_rate: float | None = None, return_basis: str | None = None, principal: int | None = None, interest: int | None = None, fee: int | None = None, representative_liability_definition: str | None = None, db_path: str | None = None, supersedes_id: str | None = None, correction_reason: str = "") -> dict[str, Any]
register_account_valuation(account_id: str, basis_date: str, amount: int, currency: str = "KRW", valuation_kind: str = "balance", source_type: str = "manual", source_ref: str = "", verification_status: str = "unverified", memo: str = "", idempotency_key: str = "", as_of_at: str | None = None, timezone: str | None = None, cost_basis: int | None = None, net_contributed: int | None = None, reported_principal_kind: str | None = None, reported_principal_label: str | None = None, profit: int | None = None, return_rate: float | None = None, return_basis: str | None = None, principal: int | None = None, interest: int | None = None, fee: int | None = None, representative_liability_definition: str | None = None, db_path: str | None = None, supersedes_id: str | None = None, correction_reason: str = "", *, monthly_settlement_id: str | None = None, liquidity_bucket: str | None = None, selection_policy: str = "manual", valuation_source: str = "manual", source_note: str = "") -> dict[str, Any]
list_account_valuations(account_id: str, include_rejected: bool = True, db_path: str | None = None) -> dict[str, Any]
select_account_valuation(account_id: str, basis_date: str, as_of: bool = False, currency: str | None = None, valuation_kind: str | None = None, db_path: str | None = None) -> dict[str, Any]
correct_account_valuation(valuation_id: str, amount: int, correction_reason: str, idempotency_key: str = "", db_path: str | None = None, **fields: Any) -> dict[str, Any]
@@ -527,3 +527,32 @@ Saved reader root example:
```
A `validation_error` results when cashflow review blockers must be resolved before approval/finalize. Remediate policy or transaction classification, then re-review and re-approve. Examples use synthetic identifiers, not raw secrets.
Schema 15 preserves the positional v0.1.7 valuation API and manual asset and
snapshot run APIs. `register_account_valuation(..., monthly_settlement_id=...)`
explicitly selects canonical unverified account snapshot registration; omitted
monthly identity uses legacy valuation evidence and correction semantics.
Canonical monthly review/approval/close APIs remain separate from legacy draft
finalization. Neither finalizer rewrites the other's frozen records.
## Public immutable monthly settlement history
The read-only application contracts are:
```python
list_monthly_settlement_history(month: str = "", db_path: str | None = None) -> dict[str, Any]
get_monthly_settlement_history_record(run_id: str, db_path: str | None = None) -> dict[str, Any]
```
Both operations are public MCP tools. MCP signatures omit internal `db_path`:
the list schema exposes optional `month`, while the exact-record schema requires
`run_id`. Successful list responses contain `history`, normalized `month`, and
`read_only=true`; successful exact reads contain one `history` record and
`read_only=true`. The list is newest-first and exposes run/version, close time,
close status, and correction linkage without consulting or rewriting live data.
The authenticated Dashboard wrapper is unchanged. In the completed/cancelled
draft panel, `마감내역보기` opens read-only history state, lists immutable runs
for the draft month, lets the operator select a run, and fetches that exact
record. Opening or changing this selection performs no lifecycle mutation.