mirror of
https://github.com/we-promise/sure.git
synced 2026-09-03 05:41:18 +00:00
40fd4aa6eeefe7ed838bb25192cb6b0c536682d2
6
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7f6346ecbd |
Merge remote-tracking branch 'origin/main' into feat/goals-v2-architecture
# Conflicts: # .github/workflows/preview-deploy.yml # app/models/account/provider_import_adapter.rb |
||
|
|
7685650e63 |
feat(assistant): add get_budget function for budget tracking (#1966)
* feat(assistant): add get_budget function for budget tracking Exposes the existing Budget / BudgetCategory pacing data to the AI assistant as a `get_budget` function. Supports a target month and an optional `prior_months` window for trend comparison, with the response shape matching the budget UI (totals, income, per-category status, suggested daily spend on the current month). Honors custom month_start_day by matching `Budget.param_to_date` semantics for explicit slug input, so `month` round-trips with the response's `month` field. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(assistant): use fixture reference for Food & Drink lookup Replace fragile string match on `bc.category.name == "Food & Drink"` with the `categories(:food_and_drink)` fixture so the test setup isn't sensitive to category-name translations. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(assistant): enforce strict month format in get_budget `Date.strptime` is lenient about trailing characters, so inputs like `"2026-05-01"` or `"may-2026foo"` were parsing successfully and being silently truncated to May 2026. Pre-validate the raw string with anchored regex patterns for the documented YYYY-MM and MMM-YYYY shapes so malformed tool arguments raise Assistant::Error instead. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(budgets): suggested_daily_spending handles custom-month periods The helper compared `budget.start_date.month/year` against `Date.current.month/year` and returned nil whenever the current period straddled two calendar months — common for families with `month_start_day != 1` (e.g., May 15–Jun 14 viewed on Jun 1). Replace the calendar-month check with `budget.current?` and compute remaining days from `budget.end_date` so the helper works for both standard and custom periods. This also restores the daily pacing row in the budget UI for custom-month families. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(assistant): make get_budget read-only for prior months `prior_months: N` was calling `Budget.find_or_bootstrap` for every month, which created empty `Budget` rows (and synced `BudgetCategory` children) as a side effect of an AI query. Only the explicit target month now bootstraps; prior months use `Budget.find_by` and are dropped from the response if they don't exist. The response now includes `months_unavailable: N` so the LLM can phrase a sensible answer when fewer months come back than requested. Extract `Budget.period_for(date, family:)` to share the date-bracket math between `find_or_bootstrap`, `budget_date_valid?`, and the new read-only path in `get_budget`. Adds two tests covering the no-bootstrap behavior for prior months and the `prior_months` clamp at `MAX_PRIOR_MONTHS`. Updates the existing N+1 sorted-months test to seed prior budgets explicitly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: wolstad <wesleyolstad@protonmail.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
88032ce020 |
feat(goals): v2 architecture — drop ledger, derive balance, add pledge
Reshape the goals feature to live on top of linked-account balances. A goal's balance is now the live balance of every depository account linked to it — no parallel ledger, no "log a contribution" step. The "Add contribution" affordance is replaced by a 7-day GoalPledge (kind: transfer | manual_save). GoalPledge::Reconciler matches incoming Transactions (via Account::ProviderImportAdapter) and Valuations (via Account::ReconciliationManager) against open pledges within ±5 days, ±$0.50, or ±1% — single hook covers every provider (Plaid, SimpleFIN, Lunchflow, Enable Banking, Brex, IBKR, Kraken, SnapTrade) plus manual balance edits. A 15-minute Sidekiq cron sweeps expired pledges. Goal model: balance derived from linked_accounts.sum(&:balance), new pace (90-day net non-transfer inflow), months_of_runway, last_matched_pledge_*, pledge_action_label_key (the "I just transferred…" vs "I just saved…" verb switch). UI: - Index gets a 3-card KPI strip (Contributed last 30d / Needs this month / On track) plus a pending-pledges callout. - Show page swaps the "Add contribution" CTA for the pledge modal, replaces the contribution list with a pending-pledge banner, and rebuilds the funding widget into per-account rows with a 12-bucket weekly sparkline and last-30 inflow. - Projection chart adds a required-line (dashed light from today → target) and a translucent pending-pledge bump at today's X. Schema (3 migrations): 1. goal_pledges table with PG enums (goal_pledge_kind, goal_pledge_status), open-by-expiry index, and unique-when-not-null matched_transaction_id. 2. Drop goal_contributions. 3. Partial unique index on transactions ((extra -> 'goal' ->> 'pledge_id')) built CONCURRENTLY so it doesn't block prod. After pulling: run bin/rails db:migrate, then commit the schema.rb sync separately (or let CI regenerate). Deferred to v1.1: allocation columns, contention/archived banners, "why is this behind?" diagnostic, reallocate flow, refresh-sync + Plaid throttle, unallocated-cash chip, joint-account approval, goal_activities log, polymorphic matched_entry_id/type for manual pledge audit. |
||
|
|
9b61e4a41b |
refactor: rename Savings Goals feature to Goals
User-facing rename + structural rename. Feature is now called just "Goals" everywhere — page title, sidebar nav, modal headings, flash messages, AI assistant tool. Code identifiers follow: - Models: SavingsGoal → Goal, SavingsContribution → GoalContribution, SavingsGoalAccount → GoalAccount. - Tables: savings_goals → goals, savings_contributions → goal_contributions, savings_goal_accounts → goal_accounts. FK columns savings_goal_id → goal_id. New migration db/migrate/20260511100003_rename_savings_to_goals.rb uses rename_table + rename_column; PG handles index renaming and FK redirection automatically. - Controllers: SavingsGoalsController → GoalsController, SavingsContributionsController → GoalContributionsController. - Routes: /savings_goals → /goals, nested /goals/:id/contributions (resource name shifts; old route name aliases dropped). - ViewComponent namespace: Savings::* → Goals::*. Component class names drop their redundant "Goal" prefix where the namespace already carries it: Savings::GoalCardComponent → Goals::CardComponent, Savings::GoalAvatarComponent → Goals::AvatarComponent. Others keep their names (Goals::ProgressRingComponent, Goals::StatusPillComponent, Goals::AccountStackComponent, Goals::FundingAccountsBreakdownComponent). - Stimulus controllers: savings_goal_* → goal_*, savings_goals_filter → goals_filter. Stimulus identifiers in data-controller / data-* attributes follow. - Locale keys: savings_goals: → goals: (top level), savings_contributions: → goal_contributions: (top level). All t() callers updated. - AI assistant tool: Assistant::Function::CreateSavingsGoal → Assistant::Function::CreateGoal, tool name "create_savings_goal" → "create_goal", description / response text updated. - Sidebar nav label "Savings" → "Goals". Goals/show + index page title "Savings" → "Goals". Empty goals_section heading/subtitle dropped (duplicated the page title post-rename). Original migrations create_savings_goals / create_savings_goal_accounts / create_savings_contributions remain untouched so historical replay still works; the rename migration runs on top. |
||
|
|
77660d2ee4 |
feat(savings): add savings goals
Adds a standalone Savings goals feature: a piggy-bank style tracker that lets a family set a target, link one or more Depository accounts as funding sources, and log manual contributions over time. Supersedes #1569 (closed) — same intent, redesigned per reviewer + Discord feedback. What this adds: - New `/savings_goals` sidebar entry (piggy-bank icon) with index, show, state-filtered tabs (all/active/paused/completed/archived), and a 2-step modal stepper for creation (Identity → Review). - Multi-account funding via a `SavingsGoalAccount` join: a goal requires ≥1 linked Depository account (checking/savings/HSA/CD/money-market), and all linked accounts must share the goal's currency. - Tracker balance model: goal balance = SUM(contributions.amount). No auto-flow from account balances. Contributions are pure logical records and don't move money between accounts. - Manual contributions modal scoped to the goal's linked accounts. Initial contributions seeded at creation can't be deleted; manual ones can. - AASM lifecycle: active / paused / completed / archived. Hard-delete only after archive. - Status pills (On track / Behind / Reached / No date) derived from pace vs target_date. - AI Assistant tool `create_savings_goal` lets the sidebar chat create a goal end-to-end from a natural-language prompt; soft errors carry the available-accounts list back to the LLM (mirrors the existing `import_bank_statement` pattern). - Family-scoped throughout (`Current.family`-only access, account family-scoping enforced both in controllers and the AI tool). - Demo data seed wires up 4 sample goals across the Depository accounts. Intentionally out of scope (separate PRs / v1.1): - Auto-fund from budget surplus + Sidekiq cron + budget-show card. - Dashboard "Savings goals" widget. - "Behind pace" projection chart on the detail page. - `evaluate_savings_goal_feasibility` LLM tool (level-setting before create_savings_goal). - Spend-less goals inside Budgets. - Family-member-private goals (deferred investigation). |
||
|
|
9e57954a99 |
Add Family vector search function call / support for document vault (#961)
* Add SearchFamilyImportedFiles assistant function with vector store support Implement per-Family document search using OpenAI vector stores, allowing the AI assistant to search through uploaded financial documents (tax returns, statements, contracts, etc.). The architecture is modular with a provider- agnostic VectorStoreConcept interface so other RAG backends can be added. Key components: - Assistant::Function::SearchFamilyImportedFiles - tool callable from any LLM - Provider::VectorStoreConcept - abstract vector store interface - Provider::Openai vector store methods (create, upload, search, delete) - Family::VectorSearchable concern with document management - FamilyDocument model for tracking uploaded files - Migration adding vector_store_id to families and family_documents table https://claude.ai/code/session_01TSkKc7a9Yu2ugm1RvSf4dh * Extract VectorStore adapter layer for swappable backends Replace the Provider::VectorStoreConcept mixin with a standalone adapter architecture under VectorStore::. This cleanly separates vector store concerns from the LLM provider and makes it trivial to swap backends. Components: - VectorStore::Base — abstract interface (create/delete/upload/remove/search) - VectorStore::Openai — uses ruby-openai gem's native vector_stores.search - VectorStore::Pgvector — skeleton for local pgvector + embedding model - VectorStore::Qdrant — skeleton for Qdrant vector DB - VectorStore::Registry — resolves adapter from VECTOR_STORE_PROVIDER env - VectorStore::Response — success/failure wrapper (like Provider::Response) Consumers updated to go through VectorStore.adapter: - Family::VectorSearchable - Assistant::Function::SearchFamilyImportedFiles - FamilyDocument Removed: Provider::VectorStoreConcept, vector store methods from Provider::Openai https://claude.ai/code/session_01TSkKc7a9Yu2ugm1RvSf4dh * Add Vector Store configuration docs to ai.md Documents how to configure the document search feature, covering all three supported backends (OpenAI, pgvector, Qdrant), environment variables, Docker Compose examples, supported file types, and privacy considerations. https://claude.ai/code/session_01TSkKc7a9Yu2ugm1RvSf4dh * No need to specify `imported` in code * Missed a couple more places * Tiny reordering for the human OCD * Update app/models/assistant/function/search_family_files.rb Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Signed-off-by: Juan José Mata <jjmata@jjmata.com> * PR comments * More PR comments --------- Signed-off-by: Juan José Mata <jjmata@jjmata.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> |