Product · In development
ROOT
A personal life operating system. Module one is a habit and identity tracker built on a pure-Dart domain core that carries the behaviour-change rules and has no Flutter dependency.
- verifiedROOT — pubspec version 0.1.0, publish_to: none
- Role
- Sole author — all 255 commits
- Period
- 2026-07-22 — ongoing
- Flutter
- Dart
The artifact
artifactROOT — PRODUCT HEROreserved · 16/10
Why it exists
ROOT began as something I built for myself. I wanted a deliberate system for building and maintaining a life across the things that actually matter — health, habits, home, relationships, learning, projects, reflection and long-term direction — rather than another place to keep tasks. The distinction it rests on is that a life is not a backlog: what you become is the accumulation of what you repeatedly do, so the system is organised around repeated action, reflection and direction rather than around completion. ROOT is deliberately not a productivity app, a habit tracker or an AI assistant. It is a personal Life Operating System — a system for cultivating identity over time.
- unverifiedROOT — the author's account of why it exists
Who built it
- Engineering role
- Sole author
- verifiedROOT — 255 commits, single author
- Measured contribution
- 255 of 255 commits (100%)the ROOT Flutter application, single repository
- verifiedROOT — 255 commits, single author
- Team
- Sole author. No other committers in the audited repository.
- verifiedROOT — 255 commits, single author
Constraints
- teamBuilt alone. 255 of 255 commits by one author, so nothing reached the tree through review — the first audit finding was a test-only id generator that had been running in production, quietly overwriting the first entity created in each session.
- verifiedROOT — 255 commits, single author
- verifiedROOT — technical debt audit, 26 findings across four severities
How it holds together
ROOT is built against a specific failure: a single containment tree that life does not fit. Habits under goals, runs under a marathon — every attempt to make one hierarchy hold everything ends up asserting a relationship that is not real. The resolution it settled on is structure only where it is real, and references everywhere else.That shows up in the storage layer rather than only in a diagram. Areas and goals are dimensions: deleting one leaves what referenced it intact, and the repositories that own them declare no cascade and say in their own comments that they never should. Task dependencies carry no foreign key at all, so removing one task can never silently remove another. Votes and reflections are append-only — the code offers a way to record one and no way to edit or delete it, because they describe something that happened.Underneath, the rules that decide what a habit or an identity means live in a pure-Dart domain core of thirty-seven files with no Flutter import anywhere in it, so the part of the system that reasons about behaviour cannot reach for a widget to do it. Storage is local-first SQLite through drift, with sync layered above rather than assumed beneath. That is what makes the local write the moment of truth — and why the write path is where the hardest engineering went.
- verifiedROOT — repositories enforce that references never cascade
- verifiedROOT — votes and reflections have no update or delete path
- verifiedROOT — domain core carries no Flutter dependency
- verifiedROOT — local-first SQLite through drift
Numbered architecture record, 01 through 48
Domain model, migration strategy, event vocabulary, phase acceptance.
- verifiedROOT — 48 architecture documents
146-file test suite
- verifiedROOT — 197 Dart files, 69,290 lines, 146 test files
What happens when a write fails
Make every write survive being interrupted
A Writer that opens a transaction around each action, and a WriteFailureSurface mounted in the app shell that receives failures with a retry closure attached. Controllers mix in WriterAccess and wrap their saves in runWrite('Create area', …) rather than calling the repository directly.How this was decided
- Context
- An audit of the write path found 33 fire-and-forget repository writes — every write of user data in the app — with zero transactions anywhere in the codebase and no error surface of any kind. A single user action could be four to eight unordered, untransacted writes, so a failure halfway through left a half-built entity and the interface never knew.
- verifiedROOT — write-path audit
- Options considered
- Leave it: SQLite writes rarely fail in practice
- Surface failures with a snackbar at each call site
- A provider-driven failure surface behind a transactional writer
- verifiedROOT — write-path audit
- Trade-off
- There were two ways to keep the invariant. A naming convention — public methods wrap, internal and cross-controller callers use unwrapped twins — works, and its cost is that every controller grows a parallel method surface while the rule lives in a contributor’s memory. Making the writer re-entrant instead was six lines, changed no signature, and left every controller reading identically. It won on one argument: a convention is correct only as long as everyone remembers, and ROOT already had one data-loss bug that came from exactly that. It needed a zone value rather than a flag, because two actions can be in flight at once and a plain boolean would let the second mistake itself for a child of the first.What it cost was a second rule that has to be held by hand — nothing enforces it, no lint and no test, so it survives on discipline alone: a transaction body contains repository calls and nothing else — no state assignment, no provider invalidation, no scheduling, no navigation — because a transaction holds the write lock and a platform call inside one is a stall waiting to happen. Actions crossing controllers had to be given explicit compound methods. And the inner action’s name is deliberately discarded, so a failure reads “Could not save: Complete issue” rather than naming whichever inner write happened to fail.What it did not cost was the database. The schema came through unchanged — the entire remediation was control flow.
- verifiedROOT — write-path audit
- verifiedROOT — the writer joins an in-flight action rather than nesting
- Outcome
- Verified in source on 2026-08-18: 34 of 34 repository write sites are awaited and routed through the writer, the transaction wrapper is real, and the failure surface is mounted. The generator behind the first P0 no longer appears anywhere in production code.
- verifiedROOT — write path verified in source: 34 of 34 writes awaited and transacted
- verifiedROOT — SequentialIdGenerator no longer used in production
- provisionalROOT — 492 tests recorded passing at a documented checkpoint
- verifiedROOT — write-path audit
- verifiedROOT — write path verified in source: 34 of 34 writes awaited and transacted
- verifiedROOT — technical debt audit, 26 findings across four severities
The system, drawn
- diagramROOT — SYSTEM ARCHITECTURE DIAGRAMreserved · 16/9
The product
Step through the sequence — every step is also readable in order without doing so.
- 01 — HOME / LIFE OVERVIEWproduct screenROOT — HOME / LIFE OVERVIEWreserved · 16/10
- 02 — HABITS / ROUTINESproduct screenROOT — HABITS / ROUTINESreserved · 16/10
- 03 — PLANS / PROJECTSproduct screenROOT — PLANS / PROJECTSreserved · 16/10
- 04 — REFLECTION / REVIEWproduct screenROOT — REFLECTION / REVIEWreserved · 16/10
- 05 — MOBILE EXPERIENCEproduct screenROOT — MOBILE EXPERIENCEreserved · 9/16
Where it stands
- Audit findings
- 26 logged
- verifiedROOT — technical debt audit, 26 findings across four severities
- Writes transacted
- 34 of 34
- verifiedROOT — write path verified in source: 34 of 34 writes awaited and transacted
- Dart source
- 69,290 lines
- verifiedROOT — 197 Dart files, 69,290 lines, 146 test files
- Test files
- 146 files
- verifiedROOT — 197 Dart files, 69,290 lines, 146 test files
- Architecture documents
- 48 documents
- verifiedROOT — 48 architecture documents
- Commits
- 255 commits
- verifiedROOT — 255 commits, single author
Evidence
17 sources · how each was obtained
- verifiedROOT — local Flutter repositoryrepository · attests existence · captured 2026-08-18directory listing and pubspec.yaml readLocal working copy. No public remote has been confirmed.
- verifiedROOT — 255 commits, single authorcommit-history · attests measurement · captured 2026-08-18git log --format=%an | sort | uniq -c255 of 255 commits authored by sgc93. First 2026-07-22, last 2026-08-17.
- verifiedROOT — 197 Dart files, 69,290 lines, 146 test filesgenerated-audit · attests measurement · captured 2026-08-18find <root> -name '<ext>' -not -path '*/node_modules/*' -not -path '*/build/*' -exec cat {} + | wc -lLine count includes comments and blank lines; it is a size signal, not a productivity measure.
- verifiedROOT — 48 architecture documentsdocument · attests existence · captured 2026-08-18directory listingNumbered 01–48, covering domain model, migration strategy, event vocabulary and phase acceptance.
- verifiedROOT — 103 evidence screenshots across 8 phase directoriesscreenshot-set · attests existence · captured 2026-08-18find <root> -type f -name '<pattern>' | wc -lA phase-evidence archive, not a curated set. Selection for the case study is still to be done.
- verifiedROOT — pubspec version 0.1.0, publish_to: nonedocument · attests structure · captured 2026-08-18file readEvidence that v1 has not been released. Nothing here supports a release claim.
- verifiedROOT — technical debt audit, 26 findings across four severitiesdocument · attests structure · captured 2026-08-18document read; dated 2026-08-05, method stated as a static read of all 102 lib/ files plus the test suite, schema and design specsFive findings are rated P0 data-loss. Each carries a confidence marker distinguishing findings the author re-traced personally from those found by sweep.
- verifiedROOT — write-path auditdocument · attests structure · captured 2026-08-18document read; counts stated as re-derived from the tree rather than copied from the earlier database auditRecords the pre-remediation state: 33 fire-and-forget writes, zero transactions, no error surface anywhere in the app. Its own status line is now stale — the source has moved past it.
- verifiedROOT — write path verified in source: 34 of 34 writes awaited and transactedgenerated-audit · attests structure · captured 2026-08-18grep over lib/ on 2026-08-18: 34 repository write sites, 34 awaited, 0 unawaited; controllers mix in WriterAccess and wrap writes in runWrite(); Writer.run wraps db.transaction; WriteFailureSurface mounted at app_shell.dart:106Structural verification by reading the source, not by running the application. Says nothing about the other 25 debt findings, which were not re-checked.
- verifiedROOT — SequentialIdGenerator no longer used in productiongenerated-audit · attests structure · captured 2026-08-18grep over lib/ excluding id_generator.dart: one match remaining, and it is a comment describing the former behaviourThe audit's first P0 — a test-only generator running in production, silently overwriting the first entity created each session.
- unverifiedROOT — the author's account of why it existsmanual-confirmation · attests existence · captured 2026-08-18stated directly, 2026-08-18Motivation and intent. No audience beyond the author is claimed, and none is evidenced.
- verifiedROOT — domain core carries no Flutter dependencygenerated-audit · attests structure · captured 2026-08-1837 Dart files; grep for package:flutter returns 0 matches
- verifiedROOT — votes and reflections have no update or delete pathgenerated-audit · attests structure · captured 2026-08-18saveVote and saveReflection are the only write methods; grep for updateVote/deleteVote/updateReflection/deleteReflection across lib/ returns nothingStructural: the code offers no way to edit one. Whether a correction path exists elsewhere in the product was not tested.
- verifiedROOT — repositories enforce that references never cascadegenerated-audit · attests structure · captured 2026-08-18area_repository.dart, goal_repository.dart and dependency_repository.dart each declare no cascade and say so in enforcement comments; tables.dart records that task dependencies are dropped explicitly rather than by foreign keyThe design vocabulary appears in the storage layer itself, not only in the ontology document.
- verifiedROOT — local-first SQLite through driftgenerated-audit · attests structure · captured 2026-08-18drift ^2.34.2, drift_flutter ^0.3.1, sqlite3 ^3.0.0 declared as dependencies
- verifiedROOT — the writer joins an in-flight action rather than nestinggenerated-audit · attests structure · captured 2026-08-18a zone value (#rootWriteInProgress) is read at entry; an inner call returns the body directly, an outer call opens db.transaction inside runZoned
- provisionalROOT — 492 tests recorded passing at a documented checkpointdocument · attests existence · captured 2026-08-18recorded in the document as 492 tests at commit 43558e4 — 186 modules, 287 foundation, 19 widgetsThe author's figure at that commit. Not re-run here; the suite was not executed as part of this audit.
Still open
What this case study does not yet cover, and what would close it.
Awaiting a written account
- No browser demonstration of this project was built.
- No repository or deployment link was recorded.
Never measured
- No outcome was measured while this project was active.
Awaiting first-person reflection
- What this project taught has not been written up yet.
- The alternatives that were considered were not recorded.
- A first-hand account of this work has not been written yet.