# Flexible household year forecast release pattern

Use when evolving a private household budget into an understandable annual orientation and forecast without introducing accounting-style period closure.

## Product semantics

- Treat the annual budget as a changeable orientation. Persist confirmed edits as immutable versions for auditability, but never present the current version as a hard spending limit.
- Do not add month-end approval, period locks, closing workflows, or mandatory contract/subscription maintenance.
- Keep the normal path automatic: import → canonical categorization → actuals → monthly/year forecast → understandable household overview. User intervention is for genuine exceptions only.
- Keep `Plan`, `Ist`, and `Prognose` visibly distinct. Never relabel actual cashflow as a normalized monthly reserve.
- A normalized monthly amount is the correctly annualized value divided by 12. A quarterly payment is payment × 4 annually, then annual ÷ 12 monthly. One-time purchases must not become recurring monthly costs.

## Forecast hierarchy

For each expense category:

1. Use actuals before the current month.
2. For the current month, use the greater of current actual and the expected current-month amount so already-booked costs are not duplicated and unbooked planned remainder is not lost.
3. Prefer a complete 12-month prior-year seasonal profile for future months.
4. Otherwise use remaining annual-orientation positions.
5. Otherwise annualize actuals only after a sufficient observed period; label sparse data as not reliably forecastable.

At household level, include uncategorized actual effects and unassigned plan positions exactly once. Compute forecast income and expense independently, then forecast remainder = forecast income − forecast expense. A special-expense what-if subtracts each planned one-time amount once from that remainder and must not mutate the persisted plan until explicit Preview → Confirm.

## Missing-comparator semantics

A category without an annual orientation cannot be described as “within the expected range” and cannot support an over-budget optimization hint.

- Keep such categories visible in the category table.
- Label their evaluation explicitly, e.g. `Jahresorientierung fehlt`.
- Route them to the budget-adjustment workflow or Today clarification list.
- Exclude them from optimization/overspend hints that claim a comparison against annual orientation.
- Generate optimization hints only when the comparator exists, the forecast is reliable enough, and the deviation is material.

When repairing this class of issue, trace the semantic property through every presentation surface in one pass: KPI, hint card, category table, Today card, API field, and empty/partial states. Do not fix only the first visible surface and discover the same contradiction in a follow-up deployment.

## Data-quality behavior

- Missing CHF conversion, unresolved refund linkage, duplicates, or partial settlement coverage must produce a visible uncertainty state.
- A partial-data response may still expose an estimate or orientation, but it must not advertise a precise free/investable amount as reliable.
- Keep recurring/fixed-cost values as optional informational metadata when compatibility requires them; do not let them drive the household forecast or create routine Today chores.
- Group actionable review candidates by user-visible decision and show count plus aggregate financial effect without exposing raw records.

## UI contract

- Extend the existing budget page; do not add a competing primary navigation or parallel forecast page.
- Keep at most five prominent annual KPIs and at most three optimization hints.
- The page should answer: where money goes, largest categories, budget/prior-year deviations, expected annual income/expense/remainder, and where optimization is justified.
- Keep actual monthly cashflow separate from normalized monthly orientation.
- On mobile, verify no horizontal page overflow and ≥44 px touch targets; internal table scrolling is acceptable when explicit and usable.

## Spreadsheet reference discipline

- Read XLS/XLSX directly and read-only. Confirm the named sheet, title, control totals, cadence examples, and known bad source formulas.
- Recompute controls independently; never inherit legacy numeric category codes as a second product taxonomy.
- Map spreadsheet labels to canonical product categories, but do not import into production or commit the workbook unless explicitly authorized.

## Release and UAT discipline

- Stabilize changed modules with focused tests first; reserve the full CI for the final candidate.
- “One full CI run” means one expected successful run, not permission to merge a failed run. If that run finds a real regression, the candidate was not final: fix narrowly, rerun invalidated local gates, allow the unavoidable corrective CI, and report the exception truthfully.
- Before merge, test both positive and inverse cases: planned overspend creates a hint; unplanned high spend does not claim an annual-orientation comparison.
- Use synthetic responsive UAT at desktop/tablet/mobile widths. A harness assertion failure is not automatically a product failure: inspect the DOM/screenshot and distinguish case-sensitive/test-harness defects from product defects without silently downgrading acceptance.
- For production read-only smoke, bracket the browser/API loads with an all-table digest or equally strict no-write sentinel. Verify exact deployed SHA, schema, FK/integrity state, services, console errors, uncertainty labels, and comparator truth.
- A production UAT finding after merge requires a follow-up PR, green CI, exact-SHA redeploy, and repeated no-write smoke. Before publishing that follow-up, perform the semantic closure scan across all related surfaces to avoid serial hotfixes.
