<!-- 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.
