Inspiration

Every personal finance app we tried had the same failure mode: a dashboard nobody opens twice, and a monthly report that arrives after the money is already gone. Discipline doesn't happen in a spreadsheet review — it happens in the 10 seconds before you click "buy." We wanted to build for that exact moment, not for the retrospective.

The second problem was trust. Every "AI budget coach" we looked at hands the actual math to the LLM — and LLMs are unreliable at arithmetic and threshold logic. If an app is going to tell you "no," that "no" has to come from code you can read, not from a model's best guess.

What It Does

You type one purchase — item, amount, category, planned or impulsive — and get one sentence back: keep it, cut it, or swap it. No dashboard. No monthly review. Just a rule check, right at the moment of temptation.

Output Description
Decision GARDE (keep) / REMPLACE (swap) / COUPE (cut)
Basis Category threshold + total monthly budget, both self-declared
Instant path ALLOW cases return in milliseconds — zero LLM call
Guided path WARNING/BLOCK cases get an LLM-formulated sentence, built from a strict JSON payload the model cannot deviate from

This isn't financial advice — it's a personal discipline rule, and the app never uses regulated language to describe it.

How We Built It

A two-layer pipeline, deterministic-first, LLM-second — deliberately, so the decision never depends on a model.

Layer 1 — Decision Gate (deterministic, Python) Computes the percentage of the declared category threshold the purchase would push the user to, and checks it against the total monthly budget. Three outcomes only: ALLOW, WARNING_IMPULSIVE, BLOCK_CRITICAL. No LLM involved at this stage — this is the part a judge can read in two minutes and verify by hand.

Layer 2 — Sentence Formulator (Claude, conditional) Only called when the gate returns anything other than ALLOW. Receives a strict JSON payload (status, pct_categorie, reste_dispo) and is explicitly instructed to never invent numbers or override the decision — it writes the sentence, the gate already made the call.

Frontend: a single Flask-served page, one input form, one output. No accounts, no persistence beyond the session — by design, this is the smallest possible surface that proves the mechanic works.

Challenges We Ran Into

1. The threshold math looked wrong before it was wrong. Our first live test case (a $150 impulsive purchase) landed at 60% of its category threshold — comfortably ALLOW — when we expected a warning. The gate was correct; our test scenario wasn't primed with enough prior spend in that category. It forced us to script exact, reproducible test sequences instead of trusting one-off numbers.

2. Template path mismatch broke the first local run. Flask's render_template silently assumes a templates/ folder — our HTML file sat at the project root and threw jinja2.exceptions.TemplateNotFound. A five-minute fix, but a reminder that "it runs on my machine" needs to mean the exact folder structure, not just the code.

3. Keeping the repo judge-ready. A stray duplicate file (0_app.py) from an earlier local iteration made it into the first commit. We caught it before submission and stripped the repo down to exactly three files — app.py, requirements.txt, templates/index.html — because a public repo a judge opens in two minutes should show nothing that isn't load-bearing.

Accomplishments That We're Proud Of

  • A gate a judge can verify by hand — three rules, plain Python, no black box
  • Zero-latency path for the common caseALLOW never touches the API
  • The LLM cannot invent a number — it only ever formulates from a payload it didn't compute
  • Reproducible test sequence confirmed across all three decision states (GARDE / REMPLACE / COUPE)
  • A repo with nothing extra in it — three files, no dead weight
  • Built end-to-end in a single evening under hackathon deadline pressure

What We Learned

The instinct to make the AI "smarter" is often the wrong instinct. The strongest thing we shipped wasn't a clever prompt — it was the discipline to keep the LLM out of the one place it doesn't belong: deciding a number. Once the gate owned the math, the LLM's job got smaller and more reliable, not less useful.

We also learned that a good demo script is itself a spec. Writing out the exact three test cases we'd show on camera surfaced a threshold bug before a judge ever could.

What's Next for Fit Money Rule Check

  • Receipt/photo capture (OCR) so the input takes five seconds, not thirty
  • Persistent per-user state beyond a single session
  • A public API (B2A-ready): expose the gate as a callable endpoint other apps or agents can query directly
  • Multi-category budgeting presets tuned to real spending profiles, not one flat default

Built With

Share this project:

Updates

Submission history