- Anchor the timeline and elapsed window on min(created_at, earliest tagged
transaction) so tagging pre-existing savings no longer inflates the rate/ETA
or disconnects the chart's solid line from the projection.
- Only surface 'estimated completion' when a target date is set (matches the
minimal no-date spec).
- Defer the create-chooser dialog open past the Radix dropdown close to avoid
the pointer-events/focus race.
- Clamp displayed progress percentage to >= 0.
- Centralize the feature-flag guard in a HasMiddleware closure (matches
McpTokenController) instead of repeating abort_unless in every action.
- Move the index aggregation into SavingsGoal::withStatsForUser so budgets
stay decoupled from goals.
- Route single-goal reads through savedAmountInCents() so the sign convention
lives in one place.
- Extract useControllableOpen hook shared by both create dialogs.
Savings goals track net inflow toward a target using a per-goal label
(source=saving_goal, hidden from the labels settings screen). Saved is the
negated net flow of tagged transactions, with a linear on-track/estimated-date
projection. Lives on the budgets page behind a Pennant flag, gated identically
to budgets.