P3: depreciation straight-line by days through the final month, schedules by day (defects 22, 9, D-37)

The final month takes what the months before leave, spread over its days;
a disposed asset stops on its disposal day. A skipped month is caught up
in the month the run is made; a reversed run un-posts its month. New
schedules spread by day; equal-months schedules must start on the 1st.
Amounts round to the currency's own minor unit. Kani and Lean proofs; an
exhaustive search over runs, reversals and disposals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T3gXMVt7XJPi6ens1or9Dj
This commit is contained in:
swaitsandClaude Opus 5.5 committed 2026-10-21 14:04:11 -06:00
1 parent 1304b9c0ad
commit b0a9fd8ad4
69 files changed
+10529 -841

No files matched your search

+16
View File
@@ -153,6 +153,7 @@ const PARTY_POLICY: &[(&str, &[&str])] =
const APPROVAL_MODE: &[(&str, &[&str])] = &[("off", &[]), ("enforce", &[])];
const TAX_CATEGORY_POLICY: &[(&str, &[&str])] =
&[("warn", &[]), ("refuse", &["required", "require"])];
const SCHEDULE_CONVENTION: &[(&str, &[&str])] = &[("daily", &[]), ("monthly_even", &[])];
/// A return's key as a setting keeps it.
pub fn tax_form_key(f: TaxForm) -> &'static str {
@@ -334,6 +335,13 @@ pub static KEYS: &[Key] = &[
sensitivity: Sensitivity::Public,
doc: "Prefix of generated asset tags (\"AC\" for AC-0001): one to eight letters or digits. Unset: the company name's initials.",
},
Key {
name: "books.schedule_convention",
toml: ("books", "schedule_convention"),
kind: Kind::Choice(SCHEDULE_CONVENTION),
sensitivity: Sensitivity::Public,
doc: "How a new prepaid-expense or deferred-revenue schedule spreads its total: daily (from its start date: full months equal, the first and last partial months by their days, like depreciation) or monthly_even (equal months; the schedule starts on the 1st of a month). Unset: daily (D-11). Existing schedules keep theirs.",
},
Key {
name: "policy.evidence.threshold",
toml: ("books", "receipt_threshold"),
@@ -1296,6 +1304,14 @@ impl Settings {
self.str("books.asset_tag_prefix")
}
/// `books.schedule_convention`: how a new schedule spreads its total.
/// Unset: daily (plan/served.md D-11, confirmed in D-37).
pub fn schedule_convention(&self) -> crate::ScheduleConvention {
self.str("books.schedule_convention")
.and_then(crate::ScheduleConvention::parse)
.unwrap_or(crate::ScheduleConvention::Daily)
}
/// `policy.parties`.
pub fn parties(&self) -> PartyPolicy {
self.str("policy.parties")