Add independent pill segments and biweekly/semi-monthly goal types
Details
Replace the overlay-divider approach for weekly goal progress bars with
truly independent pill segments. Each segment now has its own track and
fill bar, eliminating visual artifacts where fill would bleed through
divider gaps. The new GoalSegmentViewModel drives per-pill rendering
with independent fill widths, corner radii, and funding state colors.
Add two new GoalTargetType enum values: BiweeklySpending (anchored to a
user-selected date, repeating every 14 days, producing 2-3 segments per
month) and SemiMonthlySpending (two user-picked days of month, always 2
segments). GoalService gains CountBiweeklyOccurrences and a generalized
CalculateSegmentProgress method that handles rollover for all segmented
goal types.
Category management now shows an anchor date picker for biweekly goals
and two day-of-month ComboBoxes (1-30 + Last of Month) for semi-monthly
goals. The Category record gains GoalAnchorDate, GoalSemiMonthlyDay1,
and GoalSemiMonthlyDay2 fields. Seed data includes demo biweekly and
semi-monthly categories. Indexable content labels updated for new types.
Version bump 3.13.0 -> 3.14.0 (csproj + PluginMetadata).
Add YNAB-style weekly targets with dynamic day-of-week segments
Details
Weekly spending goals now let users pick which day of the week their
recurring expense falls on (e.g., Saturday for groceries). The monthly
budget is calculated as weeklyTarget × actual occurrences of that day
in the month (4 or 5), replacing the approximate weeks-remaining math.
The progress bar dynamically renders 3 or 4 dividers via an
ItemsRepeater bound to computed divider positions, instead of
hardcoding 3 dividers for a fixed 4-segment layout.
Changes:
- Category model: added GoalWeekday (DayOfWeek?) field
- GoalService: added CountWeekdayOccurrences() and
CalculateWeeklySegmentProgress(); rewrote CalculateWeeklyForMonth()
to use exact weekday counting; updated CalculateGoalProgress() to
compare allocated against the true monthly total for weekly goals
- CategoryViewModel: added WeeklySegmentCount, WeeklyDividers
(ObservableCollection<WeeklyDividerViewModel>) with computed
Canvas.Left positions; updated GoalProgressDisplay to show monthly
total for weekly goals
- BudgetDashboardView: replaced 3 hardcoded Border dividers with
dynamic ItemsControl bound to WeeklyDividers
- CategoryManagementViewModel: added WeekdayOption record,
WeekdayOptions array, SelectedWeekdayOption property, HasWeekday
computed property; persist GoalWeekday in SaveCategoryAsync
- CategoryManagementView: added day-of-week ComboBox visible only
when goal type is Weekly Spending
- FinanceSeedService: Groceries defaults to Saturday; allocation
uses CountWeekdayOccurrences for accurate monthly totals
- Version bump: 3.12.4 → 3.13.0
Add SPENT column and help tooltips to budget dashboard
Details
Added a SPENT column between BUDGETED and AVAILABLE to make the data
flow clear: BUDGETED -> SPENT -> AVAILABLE. Activity (spending) data
is fetched via new BudgetService.GetCategoryActivityAsync and displayed
as an absolute dollar amount per category.
All column headers now include a (?) indicator with tooltip explanations:
- CATEGORY: grouped spending categories
- BUDGETED: allocated amount, click to edit
- SPENT: total spent this month
- AVAILABLE: remaining after spending, color-coded
- GOAL: funding target progress
Goal bar width reduced from 300px to 260px to accommodate the new
column. Version bumped to 3.12.0.
Add conversation history support to local LLM provider
Details
Local models were running every message as a standalone prompt with zero
conversational context — follow-up questions like "but my income is 4700"
had no reference to the prior exchange. This made multi-turn chat useless.
FormatPrompt now accepts ConversationHistory and builds proper multi-turn
chat templates for all three model families (Llama 3.x, Mistral, Phi-3),
including correct turn delimiters and system prompt positioning. History
is capped at 6 turns to fit within local context windows.
The chat view model now passes BuildConversationHistory() to local model
requests, giving Duncan the same conversational continuity as cloud models.
Bump version to 1.60.0.
Improve Duncan AI response quality and add model recommendation
Details
Three fixes for Duncan giving hallucinated, context-unaware responses:
1. System prompt now instructs Duncan to use provided data context and
never fabricate numbers — applies to both local and cloud prompts.
2. Local RAG context budget increased from 200 to 400 chars per chunk
(6 chunks max, up from 5) so budget data isn't truncated to nothing.
Mistral 7B context window increased from 4096 to 8192 tokens to
accommodate the richer context.
3. System RAM detection via GC.GetGCMemoryInfo().TotalAvailableMemoryBytes
drives a model recommendation in AI settings: 16+ GB gets Mistral 7B,
8+ GB gets Phi-3 Mini, smaller systems get Llama 3.2 1B. The recommended
model is labeled in the dropdown and an explanation shown below it.
Bump version to 1.59.0.
Get notified about new releases