This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady
What I Built
I have been a procrastinator for as long as I can remember. It's a habit that feels baked into me from the start.
I've tried the standard fixes. The 15-minute rule: just start, and you can stop after fifteen minutes. Timers. Announcing my plans out loud so someone would hold me to them. Honestly, they work. I get started, I stay on task, and I finish things I would once have avoided for weeks.
I still procrastinate, though. What changed is the amount, not the habit. And the habit has cost me real things: missed deadlines, and some opportunities that never came back.
At some point I noticed something strange. Every productivity tool I used tracked what I finished. None of them told me what I was about to postpone. All the effort went into the plan, and none went into asking whether the plan would survive a bad day.
That's how Slothcast 🦥 started. It's a deadline-risk forecast for your own planned work. Each night you log what you plan to do tomorrow, with the duration, how close the deadline is, and how much energy you expect to have. The next day you record whether it happened. Slothcast learns from that history and tells you the chance that tomorrow's plan slips. Then it shrinks the plan, so a bad day still counts for something.
Weather forecasts don't stop the rain, but they tell you to carry an umbrella. A procrastination forecast should do the same for your calendar.
Demo
Live app: https://slothcast.onrender.com
The app opens on synthetic demo data until you have a real log, and it flags that data clearly so a demo number is never mistaken for your real behavior. (It's on a free Render instance, so the first load may take a few seconds to wake up.)
You can also run it locally:
python -m venv .venv && source .venv/bin/activate
make install
make test
make sample # synthetic demo log, clearly tagged as synthetic
make eval-sample # chronological evaluation, written to results/
make demo # opens the dashboard
To use it for real:
slothcast log --task "DSA block" --minutes 120 --deadline-days 3 --energy 3
slothcast done --date 2026-10-22 --done 1
slothcast eval
slothcast forecast --task "DSA block" --minutes 120 --deadline-days 3 --energy 3
Code
GitHub: https://github.com/KomalDeep355/Slothcast
Live app: https://slothcast.onrender.com
MIT licensed, with about 40 tests and a Makefile.
How I Built It
Forecasting, not coaching
Most "AI productivity" apps hand your to-do list to a chatbot and ask it for advice. I wanted the opposite. Slothcast puts a real, testable prediction at the center, and the language model only helps explain it. That one decision shaped everything else, and it's why I wrote the rules below into the code instead of only promising them in a README.
Data, labeled by how much I trust it
The log is a simple CSV: date, planned task, planned minutes, days to deadline, energy (1-5), and whether it was completed. The labels come from three places:
-
A nightly check-in. I plan tomorrow in the evening and record the outcome the next day. These labels are marked
verified. -
GitHub commits. An optional ingester counts my commits. If I left a day blank, commits can infer an outcome, but that label is tagged
inferredand never mixed up with a verified one. -
Backfilled history. I can import old milestones from a CSV. These default to
inferred.
Demo data is tagged synthetic. Every label keeps its provenance, and the evaluation also reports results on verified labels alone whenever there are enough of them. I didn't want my model quietly learning from guesses I couldn't trust.
No leakage from the future
For a forecasting project, the easiest way to cheat is to let the future leak into the past. In Slothcast, the features for day i only see outcomes from before day i. Evaluation is rolling-origin: train on the past, test on what comes next, and move forward. Nothing is shuffled. Both rules are unit-tested, because a shuffled split on time-ordered habit data gives you beautiful, meaningless numbers.
The data-sufficiency gate
This is the part I'm proudest of. A model trained on five days of your life isn't a forecaster, it's a coin flip with a confident voice. So Slothcast has a gate:
- Under 15 labelled days (or fewer than 4 of either outcome), it shows "Not enough history yet" instead of a probability.
- 15 to 29 days is labelled preliminary.
Showing nothing is a feature here. A tool that always has an answer isn't being honest.
TabPFN versus honest baselines
The model at the center of the project is TabPFN, a pretrained model built for small tabular datasets, which is exactly what a personal habit log is. A few weeks of check-ins is tiny data. Classic models struggle with that, and a pretrained model might help.
But I didn't want to assume it. Slothcast compares TabPFN against five baselines: the base rate, "same as yesterday", the weekday rate, logistic regression, and a random forest. TabPFN has to beat them. The evaluation reports the Brier score, calibration, a learning curve by history length (how much data does the fancy model need before it's worth it?), and a bootstrap interval for the gain over the base rate. If TabPFN doesn't win, the report says so.
TabPFN runs locally. The first fit downloads the open weights, and after that it works offline.
A local Gemma planner
Once the forecast gives a risk label, a local Gemma model (gemma3:4b through Ollama) turns it into a plan. A risky task becomes a smaller, concrete first step. If Ollama isn't running, Slothcast falls back to a deterministic template plan and tells you it did.
The LLM is never allowed to write a number
This is my favorite guardrail. agent/guardrails.py rejects any percentage, decimal probability, or odds that the model didn't get from the forecasting model. If Gemma invents a "73% chance", the output is thrown away and the template plan is used instead.
A language model that confidently makes up statistics about your behavior is worse than useless, because you'd believe it. The forecast comes from a model that was tested. The words come from a model that was fenced in.
Optional pieces
- A hosted habit coach for any OpenAI-compatible provider. It only sends aggregate completion counts, rates, and pattern groups, never task names, and only when you ask for coaching. Without it, the numerical habit forecasts still work.
- Temporal to run the nightly job as a durable workflow.
- Sentry tracing, where spans carry timings and token counts but never task text.
Stack
Python, Pandas, NumPy, scikit-learn, TabPFN, Gemma via Ollama, Streamlit, Pytest, GitHub Actions, and an MIT license. Temporal and Sentry are optional.
What I Learned
The hard part of a forecasting project isn't the model. It was keeping the future out of the past, keeping guessed labels apart from real ones, and deciding when to say "I don't know". The model was a small part of the work.
Small data needs honesty more than cleverness. With a few dozen data points, a sophisticated model can look great by accident. The learning curve and the bootstrap interval are there to stop me from fooling myself.
Constraining the LLM made the product better. Letting Gemma speak freely was easy. Fencing it in, so it explains evidence but never produces it, is what made the app trustworthy.
It's a mirror, not a judge. I started this to fix my own procrastination. What I ended up with is a way to see my patterns without the shame that usually comes with them.
One thing Slothcast doesn't claim is that its nudges change behavior. Showing that would need an A/B period of nudged versus not-nudged weeks, which only makes sense once the forecast itself works. That's the next step.
Why Does Open Innovation Matter?
A procrastination log is some of the most personal data a person can produce. It records when you avoid things, how tired you were, and what you keep putting off. I wasn't willing to send that to a closed API.
Open models made a local-first design possible:
- Gemma runs on my machine through Ollama, so my task history stays there.
- TabPFN runs offline after the first download of the open weights, so the forecasting is private too.
- It costs nothing to run. No API bill, no usage limit, no account.
- I could test it fairly. Because the models are open and local, I could benchmark them against simple baselines and report whatever came out.
One honest note: TabPFN's weights are under Prior Labs' non-commercial license, while the code in my repo is MIT. That's fine for research, evaluation, and a portfolio, but not for a commercial product. I'd rather say that plainly than hide it.
Open innovation also means anyone can fork Slothcast and swap in their own model, their own labels, or their own habits. A procrastination forecaster should be something you can inspect, not something you have to trust.
Prize Categories
Gemma, TabPFN
If you've ever missed something important because you waited "just a little longer", you're not lazy. You're predictable, and predictable can be forecast.
What's the one task you keep postponing? Tell me in the comments. I'm curious whether the forecast would have caught it.
Top comments (0)