104 lines
4.2 KiB
Markdown
104 lines
4.2 KiB
Markdown
<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
|
|
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
|
|
|
|
# Persistence Plan 1 Summary — SQLite Runtime Persistence
|
|
|
|
**Status:** Complete on 2026-07-02.
|
|
**Scope level:** XHIGH implementation plan.
|
|
**Primary outcome:** The Flutter desktop app persists real task state to an
|
|
on-disk SQLite database instead of recreating arbitrary demo seed data at launch.
|
|
|
|
---
|
|
|
|
## Current repo facts this plan is based on
|
|
|
|
1. The project is SQLite-first and V1 has no MongoDB runtime.
|
|
2. `packages/scheduler_persistence_sqlite` already contains a Drift database and
|
|
repository implementations for task/project/locked-time/settings/snapshot
|
|
persistence.
|
|
3. The Flutter app still starts through `DemoSchedulerComposition.seeded()` and
|
|
an `InMemoryApplicationUnitOfWork`.
|
|
4. The dev runner already passes `SCHEDULER_SQLITE_PATH` into Flutter as a Dart
|
|
define, but the Flutter app does not yet consume that path.
|
|
5. `V1ApplicationCommandUseCases` and `GetTodayStateQuery` already operate
|
|
against the public `ApplicationUnitOfWork` boundary.
|
|
6. Existing command flows write more than tasks: completion can also write task
|
|
activities, project statistics, and operation records.
|
|
7. Current SQLite schema files do not yet expose all app-layer repository data
|
|
needed for durable application semantics across restarts.
|
|
|
|
---
|
|
|
|
## Definition of done
|
|
|
|
Persistence Plan 1 is complete when all of the following are true:
|
|
|
|
1. `main.dart` no longer boots the normal app through static seeded demo data.
|
|
2. App startup opens an on-disk SQLite database at the configured path.
|
|
3. The composition root builds scheduler queries/use cases with a SQLite-backed
|
|
`ApplicationUnitOfWork`.
|
|
4. The app creates or loads required owner bootstrap data, including owner
|
|
settings and a default Inbox/Home project, without inserting arbitrary demo
|
|
timeline tasks.
|
|
5. Quick capture persists a task to SQLite.
|
|
6. Scheduling a backlog task persists `status`, `durationMinutes`,
|
|
`scheduledStart`, and `scheduledEnd`.
|
|
7. Completing and uncompleting a task persist `status`, actual/completion
|
|
timestamps, and updated metadata.
|
|
8. Closing and reopening the app against the same database reloads the task,
|
|
schedule placement, and done/not-done state.
|
|
9. Widgets/controllers still consume read models/controllers and do not contain
|
|
scheduling, Drift, SQL, or OS path logic.
|
|
10. Temp-file lifecycle tests prove close/reopen persistence.
|
|
11. Existing backend gates and Flutter gates pass, or every unavailable command
|
|
is documented with the reason.
|
|
|
|
---
|
|
|
|
## Non-goals
|
|
|
|
1. No UI redesign beyond empty/loading/error text needed for real persisted data.
|
|
2. No new scheduling algorithm behavior.
|
|
3. No manual SQL in Flutter widgets.
|
|
4. No backup/restore UI.
|
|
5. No JSON/CSV export UI.
|
|
6. No calendar sync.
|
|
7. No notifications wiring.
|
|
8. No week/month views.
|
|
9. No Shield/Recovery UX beyond preserving existing backend recovery contracts.
|
|
|
|
---
|
|
|
|
## Architecture rule
|
|
|
|
The SQLite runtime must sit behind the existing application boundaries:
|
|
|
|
```text
|
|
Flutter widgets/controllers
|
|
-> app composition/root runtime object
|
|
-> V1ApplicationCommandUseCases / GetTodayStateQuery
|
|
-> ApplicationUnitOfWork
|
|
-> SQLite application repositories / Drift database
|
|
```
|
|
|
|
The UI may request capture/schedule/done actions. The scheduler core remains the
|
|
source of truth for schedule state and task transitions.
|
|
|
|
---
|
|
|
|
## Important implementation decision
|
|
|
|
The current `scheduler_persistence_sqlite` adapter package implements
|
|
repository-conformance contracts, but the app command layer needs the richer
|
|
`scheduler_core` application repository surface. This plan therefore adds a
|
|
SQLite-backed `ApplicationUnitOfWork` adapter and the missing app-layer rows it
|
|
requires instead of wiring Flutter directly to low-level persistence
|
|
repositories.
|
|
|
|
Recommended default: implement the application unit of work in
|
|
`packages/scheduler_persistence_sqlite` and expose it from `sqlite.dart`.
|
|
|
|
Optional stricter boundary: create a small pure-Dart runtime package that owns
|
|
SQLite file opening and depends on `scheduler_persistence_sqlite`; Flutter then
|
|
imports only that runtime package. Use this option only if keeping all SQLite
|
|
package imports out of `apps/focus_flow_flutter/lib/` remains a hard boundary.
|