---
name: budget-track
title: "Budget Tracking"
description: "Track spend against budgets per (period, scope, category). Surface variance, threshold alerts (80% / 100% / 120%), and burn-rate. Owned by the accountant."
category: finance
status: active
model_tier: fast
priority: 5
triggers:
  - "how much have I spent"
  - "budget remaining"
  - "show budgets"
  - "track budget"
  - "budget variance"
  - "am I over budget"
tools_granted:
  - set_budget
  - query_budget
  - delete_budget
  - query_finance
language:
  output_policy: source
---

## What this skill is

Phase 2 budget surface for the accountant. Reads from `finance_budgets` + `finance_budget_consumed` to answer the user's questions about spending caps. Distinct from `period-report` (slow LLM-narrated rollups) — this skill is fast and structured.

## When to use

- User asks about a specific budget: "How much groceries budget left for May?"
- User asks for a budgets overview: "Show me all my active budgets."
- User wants to set or remove a budget: "Cap my AI infra spend at $200/month."
- Threshold alerts surface during heartbeat / daily cycle (separate trigger; not via direct user query).

## Flow

1. Identify the budget(s) in scope. If user names a category/project/period, scope the `query_budget` call accordingly. Otherwise, list all active budgets matching the current period.
2. Pull each budget's consumption via `query_budget(budget_id)` — returns `{spent, txn_count, txn_ids}`.
3. Compute `percent_consumed = spent / amount` (handle zero-amount budgets gracefully — they're tracking-only, not capping).
4. Classify each budget by threshold:
   - `< 80%` → on track
   - `80% – 100%` → near cap
   - `100% – 120%` → at/over cap
   - `> 120%` → significantly over
5. Report in plain prose with a structured trailing block. Cite specific txn_ids when discussing top contributors.

## Hard rules

- NEVER fabricate a budget that doesn't exist. If the user names "groceries May" and no matching budget exists, say so — don't quote a phantom cap.
- NEVER auto-create a budget when reporting. `set_budget` is reserved for explicit user requests like "cap my X budget at Y".
- NEVER convert currencies. If the user asks about a budget in EUR and only USD budgets exist, list the USD budgets with their currency labels and explain the mismatch.
- NEVER quote a percent over 100% as "fine" — surface it as variance + name the contributing transactions.

## Output format

```
## Budgets — {period}

- {scope_label}: ${spent} / ${cap} ({pct}%) — {classification}
  Top contributors: {txn_id} ({merchant}, ${amount}), ...

(repeat per budget)

{summary line: "All on track" | "N near cap, M over cap"}
```

Mention only material details. A brand-new budget with $0 spend gets one line, not a paragraph.

## Examples

**User**: "How am I doing on the AI infra budget this month?"

**Output**:

> ## Budgets — 2026-04
>
> - AI infra (project: phoenix, category: ai-infra): $172.30 / $200.00 (86%) — near cap
>   Top contributors: t_abc123 (anthropic, $80.00), t_xyz789 (openai, $52.00)
>
> Near cap with 4 days remaining in the period. At current burn rate ($172.30 / 26 days × 30 days = $199 projected), expect to land within $1 of the cap.

**User**: "Set a $300 fuel budget for May."

**Output** (after calling `set_budget(period="2026-05", scope_type="category", category_slug="fuel", amount="300.00", currency="USD")`):

> Budget created: fuel category, May 2026, $300.00 USD cap.
