* feat(mcp): Add MCP budget update tool
Adds an update_budget assistant/MCP function so AI assistants can write
monthly budgets: total budgeted spending, expected income, and
per-category allocations in one transactional call.
- Month resolution and slug format mirror get_budget (YYYY-MM or
MMM-YYYY, custom month start respected); targeting a valid month with
no budget row bootstraps it via Budget.find_or_bootstrap, same as the
budgets UI.
- Category allocations accept an exact (case-insensitive) name or id and
go through BudgetCategory#update_budgeted_spending!, so subcategory
writes keep the parent total in sync.
- All writes in one call share a transaction: an invalid category rolls
back a totals change from the same call.
- Family-scoped like the budgets UI; amounts validated non-negative.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor(mcp): harden update_budget per review feedback
- Extract shared month resolution into Assistant::Function::MonthResolvable
so get_budget and update_budget can't drift on custom month starts
- Run budget bootstrap inside the update transaction so a failed entry
no longer leaves a newly created budget behind
- Apply explicit parent amounts after subcategory syncs so results don't
depend on the caller's array order
- Reject non-finite amounts (NaN/Infinity)
- Explain the synthetic Uncategorized bucket instead of a generic
category-not-found error
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>