Rules Manifest
copy yaml code of a rule to clipboard
This directory uses a manifest to load rules and merchant mappings.
todo: Reiseversicherung, travel, work: AWS.EMEA, GOOGLE.CLOUD, ANTHROPIC Gemischtwaren, S.Bahn Ratskeller < Restaurant NANU.NANA CIAO.BELLA
Landeshochschulkasse < edu daniela FIELMANN C.A.Haus.0564/Berlin ?? Reformhaus
museum HUMANA
Register other accounts: trade republic DE23100123450351479101
Structure
manifest.yaml: entry point for loading filesmerchants/*.yaml: merchant normalization + defaultsrules/system/*.yaml: built-in system rulesrules/user/*.yaml: not used here; user rules live indata/users/...ml_taxonomy.yaml: optional validation metadata
Manifest Example
version: 1
profile: default
load:
taxonomy: ml_taxonomy.yaml
merchants:
- merchants/base.yaml
rules:
system:
- rules/system/10_transfers.yaml
- rules/system/99_fallback.yaml
Precedence
- User rules from
data/users/... - Merchant defaults (manifest mode only)
- System rules (priority desc, then manifest order)
- Fallback (uncategorized)
V2 rules system overview (from code)
- Rule files are YAML under data/rules and loaded via manifest.yaml when present (app/ingest/importer/pipeline/ruleset_loader.py).
- Each file has slug, version, and a rules: list. Each rule has id, match (or if), and set (or then). Optional: enabled, scope, explain, stop (app/ingest/importer/pipeline/ rules_loader.py).
- Rule evaluation order: user rules first, then merchant defaults (if manifest mode), then system rules in order; first matching system rule wins and stops (app/ingest/ importer/pipeline/rules.py).
How match.all works
- match: { all: [ ... ] } requires every child match to succeed (app/ingest/importer/pipeline/rules_loader.py and _match_node in app/ingest/importer/pipeline/rules.py).
- Each child can itself be another match block (with any/all/not) or a clause (text, amount, merchant, merchant_in).
- If you donβt specify any/all/not and just list multiple fields inside match, they are implicitly combined as all (AND).
Match options (current) From _compile_clauses in app/ingest/importer/pipeline/rules_loader.py:
- merchant: string or list
- string β equality
- list β membership
- merchant_in: same behavior as merchant (just different field name)
- text:
- string β contains (casefold)
- { contains: "..." }
- { matches: "regex" } (regex compiled with IGNORECASE; invalid regex errors on load)
- amount:
- number β eq
- { lt|lte|gt|gte|eq: number }
Logical wrappers:
- any: list of match blocks, OR semantics
- all: list of match blocks, AND semantics
- not: list of match blocks; if multiple entries, theyβre grouped as all and then negated
Set options (current) From _apply_rule in app/ingest/importer/pipeline/rules.py:
- direction (money flow direction, see taxonomy below)
- group
- category
- subcategory
- tags (list or string)
- type (stored as txn_type / cl_type, deprecated: use direction)
- confidence
- flags (dict; merged into cls.flags)
Also supported in user rules (_apply_user_rule):
- recurring, recurring_period, visible, rule_active (mapped to flags)
Notes:
- stop and explain are parsed into CompiledRule but not used in evaluation yet (app/ingest/importer/pipeline/rules_loader.py vs app/ingest/importer/pipeline/rules.py).
- Text matching uses res.cls.full_text which is built during pipeline normalization; amount uses res.txn.amount.
Complete Taxonomy
Direction (Money Flow)
| Direction | Amount | Meaning | Example |
|---|---|---|---|
income |
+ | External money in | Salary, child benefit, dividends |
expense |
β | External money out | Groceries, rent, subscriptions |
transfer_out |
β | To own account | Savings deposit, investment |
transfer_in |
+ | From own account | Withdraw from savings |
refund |
+ | Return from prior expense | Amazon refund, insurance payout |
Groups
| Group | Direction | Purpose |
|---|---|---|
fixed_costs |
expense | Housing, insurance, tax, telecom |
daily_life |
expense | Groceries, transport, clothing, food |
family |
expense | Kids, education |
fun_lifestyle |
expense | Leisure, sports, gifts, vacation |
finance_misc |
mixed | Income, transfers, savings, refunds |
Hierarchy
direction (flow)
βββ group (budget category)
βββ category (specific area)
βββ subcategory (detail)
Example rule:
- id: groceries.supermarket.rewe
match:
merchant: REWE
set:
direction: expense
group: daily_life
category: groceries
subcategory: supermarket
confidence: 0.85
tags:
- food
Refunds
Refunds keep their original expense category:
- id: refund.amazon
match:
all:
- text: { matches: amazon|amzn }
- amount: { gt: 0 }
set:
direction: refund # direction is refund
group: daily_life # same group as original
category: shopping # same category as original
subcategory: refunds