A to-do app that doesn't believe you — an enforcement layer rather than a
neutral ledger.
Architecture ported from Autoreceptives/Frontend/Receptive: stacked MVVM with
the mandatory 4-file screen pattern, one ParentViewModel owning the loading /
network / error overlays and the handleError decision tree, one AppDataManager
gateway, dio comms carrying the three identity headers, secure storage with
random-suffixed keys, and a single-chokepoint Navigator. Package root and Dart
package name are both Grounded; org is nya.
The enforcement engine, one unit per formula in utils/:
- DebtEngine w(class) x severity(d) x decay(t), sublinear severity so old
misses cannot swamp the score; abandonment 2x with 30-day
decay immunity; late complete retains 30%
- StandingEngine Good -> Warned -> Grounded -> Lockdown, derived not set;
Grounded replaces home with the overdue queue
- CapacityEngine blocks over-scheduling against p50 of historically completed
minutes, with a learned per-category estimation multiplier
- IntegrityEngine session integrity, weekly volume, plyometric contact ceiling
and enforced recovery gaps
- ExcuseAnalyser on-device excuse clustering plus the confrontation copy
- GuardrailEngine distress detection and rationed amnesty
- ToneEngine all enforcement copy, so the tone cap lives in one place
CommitmentEvent is append-only and is the source of truth rather than the
status field, which is what makes honest history and excuse analysis possible.
Goals contain commitments via parentId, and a task can be run from a
full-screen runner that derives elapsed time from wall-clock so screen-off
cannot lose time. Backgrounding pauses the clock and is counted. The runner is
mirrored into an ongoing notification, with alarm-class full-screen intents
reserved for non-negotiables.
Design language, fonts, icon and native splash are in place; Mason bricks are
retargeted to this project and verified end-to-end.
flutter analyze lib/ reports no errors.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mfu2gQLSFN21YRBcU2NrTt
95 lines
3.4 KiB
Markdown
95 lines
3.4 KiB
Markdown
# Grounded
|
||
|
||
*A to-do app that doesn't believe you.*
|
||
|
||
Most to-do apps are neutral ledgers — they record intent and never object when
|
||
you ignore it. Grounded is an **enforcement layer**: it holds a model of what
|
||
you committed to, notices when reality diverges, and imposes escalating
|
||
consequences you agreed to in advance.
|
||
|
||
Design axiom: **the checkbox is the enemy.** Every feature exists because
|
||
self-reported completion is worthless to someone trying to stop lying to
|
||
themselves.
|
||
|
||
---
|
||
|
||
## Repository
|
||
|
||
```
|
||
frontend/ Flutter app (Android · iOS · Web · Windows)
|
||
```
|
||
|
||
See [`frontend/CLAUDE.md`](frontend/CLAUDE.md) for the architecture and
|
||
conventions, and [`frontend/design.md`](frontend/design.md) for the design
|
||
language.
|
||
|
||
---
|
||
|
||
## The model
|
||
|
||
Three primitives; everything else is derived.
|
||
|
||
| Primitive | Meaning |
|
||
|---|---|
|
||
| **Commitment** | Something you said you'd do. Has a due *window*, a class, and a proof requirement. |
|
||
| **Debt** | The weight of what you've missed — a decaying, weighted score rather than a count. |
|
||
| **Standing** | `Good → Warned → Grounded → Lockdown`. Derived from debt; decides what the app lets you do. |
|
||
|
||
Streaks reward perfection and collapse permanently on one miss. Debt is
|
||
continuous, forgiving in shape, hard to ignore, and gives you a way back.
|
||
|
||
**Goals** contain commitments — "Workout" holds "Monday shoulders". A goal
|
||
never carries debt; the tasks inside it do.
|
||
|
||
---
|
||
|
||
## What makes it different
|
||
|
||
- **Due windows, not due dates.** `Mon 06:00–08:00` can actually close. A miss
|
||
is a permanent event, never a silent rollover to today.
|
||
- **Capacity blocking.** Chronic overdue is usually overcommitment misdiagnosed
|
||
as laziness. The app plans against what you *historically complete*, learns
|
||
your per-category estimation multiplier, and refuses plans that don't fit.
|
||
- **Excuses get clustered.** *"'Too tired' has appeared 14 times this month, 11
|
||
of them on gym days, 9 of them after 7pm. Consider moving gym to morning."*
|
||
- **Proof of completion.** Honour · Photo · Timer · Location · Health · Witness.
|
||
Completing outside the window records as *late complete* — distinct in
|
||
history, and it never reduces debt to zero.
|
||
- **A live runner.** Starting a task takes over the screen, keeps time from
|
||
wall-clock so screen-off can't cheat it, and pauses when you leave the app.
|
||
- **Plyometrics is where it stops you.** Weekly ground-contact ceilings and
|
||
enforced recovery gaps — connective tissue doesn't recover on a motivation
|
||
schedule.
|
||
|
||
## And what keeps it usable
|
||
|
||
An app built on guilt has an obvious failure mode: the people who need it most
|
||
delete it during their worst week. So — rationed **amnesty tokens**, **sick and
|
||
travel mode** that pauses debt entirely, a **tone slider** hard-capped so no
|
||
copy ever attacks the person rather than the behaviour, and **distress
|
||
detection** that drops the strict persona completely when debt spikes while
|
||
engagement and readiness fall. Strictness is never the response to someone who
|
||
is actually struggling.
|
||
|
||
---
|
||
|
||
## Running it
|
||
|
||
```bash
|
||
cd frontend
|
||
cp .env.example .env # then point it at your backend
|
||
flutter pub get
|
||
flutter run
|
||
```
|
||
|
||
Requires Flutter with Dart `^3.6.2`.
|
||
|
||
---
|
||
|
||
## Status
|
||
|
||
Frontend scaffold complete: the full architecture, the debt/standing/capacity/
|
||
integrity engines, and every screen in the MVP cut. The backend is not in this
|
||
repository yet — `CommsDirections.dart` defines the contract it needs to
|
||
satisfy.
|