docs: reset plan around sqlite workflow

This commit is contained in:
Ashley Venn 2026-06-26 19:38:39 -07:00
parent 8b2ab6b64e
commit ea45d635e4
35 changed files with 1145 additions and 854 deletions

206
AGENTS.md
View file

@ -1,164 +1,114 @@
# AGENTS.md — Codex Project Rules # AGENTS.md — Codex Project Rules (SQLiteFirst, July 2026)
This file is persistent project guidance. Codex must treat it as standing instructions for this repository. This document supersedes all previous agent rule files. Treat it as the single source of truth.
## User and product context ---
The product owner is a software engineer building a personal scheduling app for difficult ADHD/executive-dysfunction scheduling problems. The app must reduce planning friction, preserve task order, prevent forgotten tasks, and recover gracefully when the user misses work, burns out, or cannot manually reorganize a plan. ## 0. Quickstart for Codex
Design priorities: * Blocks live in `Codex Documentation/Current Software Plan/`.
* Work strictly in numerical order (Block19  20 … 29).
* Each block contains numbered `XHIGH` / `HIGH` chunks.
* Stop at every `BREAKPOINT` in a chunk; wait for confirmation before continuing.
* Before coding, run `scripts/bootstrap_dev.sh` to set up the local dev DB.
1. Low-friction interactions. ---
2. Reliable scheduling behavior.
3. No shame, guilt, punishment, or productivity-slogan framing.
4. Preserve flexible task order unless the user explicitly chooses otherwise.
5. Never move locked or inflexible time during automatic rescheduling.
6. Keep hidden locked time hidden by default.
7. Make every scheduling rule testable.
8. Prefer explicit state transitions over vague magic behavior.
9. Do not add non-MVP features unless the active plan asks for them.
10. Update documentation when behavior changes.
The user prefers practical, concrete implementation work. Avoid broad redesigns unless the active plan calls for them. ## 1. Persistence
## Documentation structure rules | Element | Rule |
|---------|------|
| Local storage | **SQLite via Drift**, schemaVersion 1 |
| Abstraction | Domainonly repository interfaces (`scheduler_persistence`) |
| Swappable | New adapters must pass repository conformance tests |
| Backup | AES256GCM encrypted SQLite file (`Backup library`, Block24) |
| Migrations | Drift migrations with tests (Block20, Block26) |
Human-facing design/product documentation belongs in: No MongoDB runtime in V1.
```text ---
Human Documentation/
```
Codex execution planning belongs in: ## 2. Repository & Adapter Rules
```text 1. Interfaces expose domain objects only.
Codex Documentation/ 2. Optimistic `revision` on every mutable save.
``` 3. Owner scope parameter now for future multiuser.
4. Adapters implement compareandset; core never overwrites stale revision.
Current, active implementation plans belong in: ---
```text ## 3. Notification Rules
Codex Documentation/Current Software Plan/
```
Completed plans must be moved to: * Use `NotificationAdapter` (Block21).
* Desktop implementation (Block22), fake adapter for tests.
* Core never imports platform APIs directly.
```text ---
Codex Documentation/Archived plans/
```
This is firm. New plans may be uploaded, generated, or pointed at from elsewhere, but once Codex completes a plan, it must move the completed plan document into `Codex Documentation/Archived plans/`. Do not leave completed plans in `Current Software Plan/`. ## 4. Backup / Export Rules
* Backup: encrypted SQLite (`.sqlite.aes`) via Backup library.
* Readable exports: JSON + CSV via `ExportController` (Block23).
## Persistence target rules ---
MongoDB is the committed persistence target for this project. Treat MongoDB document storage as the future database direction when designing repository interfaces, serialization helpers, and persistence boundaries. ## 5. Testing Hierarchy
Rules: | Layer | Folder | Purpose |
|-------|--------|---------|
| Unit | `test/unit` | pure domain logic |
| Contract | `test/contract` | repository conformance |
| Migration | `test/migration` | Drift schema upgrades |
| Integration | `test/integration` | full stack InMemory + SQLite + fake notifications |
- Do not introduce alternative database assumptions unless the user explicitly reverses this decision. CI fails below **80% line coverage**.
- V1 planning may prepare MongoDB-friendly repository interfaces and document-shaped model mappings without adding a MongoDB driver yet.
- Do not add MongoDB connection strings, Atlas/cloud setup, local server requirements, sync behavior, accounts, or network/background behavior unless an active plan explicitly calls for that implementation work.
- Keep the scheduling core independent from MongoDB APIs; persistence adapters should sit behind repository interfaces.
## Planning document execution rules ---
Planning documents are organized into blocks, chunks, and optional stages. ## 6. Dev Scripts (Block27)
- Blocks are groups of related work. | Script | Description |
- Chunks are actionable pieces of work inside a block. |--------|-------------|
- Stages may be used inside larger chunks when helpful. | `bootstrap_dev.sh` | install deps, create dev DB |
- Blocks do **not** receive a Codex thinking-level classification. | `dev.sh` | hotreload desktop run |
- Chunks and stages must include one of these classifications: | `test.sh` | all tests + coverage |
- `low` | `package_release.sh` | build OS binaries |
- `medium`
- `high`
- `extra high`
Codex should rely on the planning documents as much as possible to avoid excess token use. Before doing exploratory work, check whether the current plan already answers the question. Flutter UI work starts in Block 29 under `apps/focus_flow_flutter/`. Keep it
out of the root Dart workspace until the Flutter toolchain gate is fully
integrated.
## Break point rules ---
Planning documents may contain `BREAKPOINT` markers. ## 7. Branch, Commit & CI
When the user says to do the next chunk: * Start each new block from `main` on a block branch named
`block-XX-simple-name` (for example, `block-20-sqlite-adapter`).
* Keep all chunk work for that block on the block branch.
* Commit every completed chunk before moving to the next chunk or breakpoint.
* Use conventional commits (`feat`, `fix`, `docs`, `test`, `refactor`,
`chore`, `ci`).
* Do not leave completed chunk work only in the working tree.
* When the block is complete and verified, merge the block branch back into
`main`.
* CI matrix: ubuntulatest, windowslatest, macoslatest.
* `dart analyze` and `dart test` must pass.
1. Execute only the next permitted chunk or stage. ---
2. Do not proceed past a `BREAKPOINT`.
3. If the next chunk or stage has a different recommended thinking level, stop and tell the user the next required level.
4. Wait for user confirmation that the mode has been switched before continuing.
A breakpoint is a hard stop. Do not skip it because the next task seems small. ## 8. MVP Boundaries
## Commit rules * Today + Backlog only.
* Task types: flexible, inflexible, critical, locked, surprise, free slot.
* No week/month views, sync, or shield in V1.
When finishing a work block or a clearly bounded chunk that leaves the project in a working state: ---
1. Run relevant formatting/analyze/tests when possible. ## 9. UX Language
2. Commit the work.
3. Use a descriptive conventional commit message.
Examples: * Use calm terms: missed, pushed, backlog, archived.
* Avoid blame language.
```text ---
feat(scheduling): add flexible task push behavior
fix(backlog): preserve stale age marker after task update
test(engine): cover locked block overlap rules
docs(plan): archive completed foundation block
```
Do not make vague commits such as `update files`, `changes`, or `work`. _Last updated: 2026-06-27_
## Engineering rules
- Keep scheduling/domain logic separate from UI.
- Start with pure Dart domain logic and tests.
- Add Flutter UI only when the plan calls for it.
- Avoid network/sync/background behavior unless explicitly planned.
- Use MongoDB as the committed future persistence target; do not add alternative database assumptions.
- Prefer immutable models or copy/update patterns.
- Avoid hidden side effects in scheduling functions.
- Every rule that changes task placement should have tests.
- Use clear names over clever abstractions.
- If a rule is ambiguous, add a TODO comment and a small safe default rather than inventing broad behavior.
## MVP boundaries
MVP includes:
- Today view data model.
- Backlog/wishlist model.
- Quick capture to backlog.
- Optional quick-capture scheduling into next available flexible slot.
- Flexible/inflexible/critical/locked/surprise task types.
- Recurring locked blocks, hidden by default.
- One-day overrides for locked blocks.
- Flexible task push behavior.
- Push options: next available slot, tomorrow/top of queue, backlog.
- End-of-day rollover notice.
- Manual compact mode state.
- Task actions: done, push, backlog, break up.
- Child task ownership and parent auto-completion logic.
- Internal statistics needed for future reporting.
MVP excludes unless explicitly added:
- Week view.
- Month view.
- Weekly reports.
- Overwhelm shield.
- Drag-and-drop reordering.
- Per-task history panel.
- Task dependencies.
- Context tags.
- Full sync.
- Long-running task auto-extension behavior.
## UX language rules
Use calm, non-punitive terminology:
- Prefer: `missed`, `pushed`, `moved to backlog`, `no longer relevant`, `cancelled`.
- Avoid: `failed`, `late again`, `bad`, `unproductive`, `overdue pile`, `punishment`.
The app should treat disruption as expected, not exceptional.

View file

@ -1,10 +1,66 @@
# Archived plans # Current Software Plan
Completed Codex implementation plans go here. Blocks 0112 are complete and remain historical records in
`Codex Documentation/Archived plans/`. The active path resumes at Block 13.
Rules: The backend sequence is Blocks 1117. Block 18 is a deliberately limited UI
foundation block and is blocked until the backend completion gate in Chunk 17.4
passes.
- Move completed plans here from `Codex Documentation/Current Software Plan/`. ## Execution rules
- Do not delete completed plans.
- Commit the archive move with a conventional commit message. 1. Read `AGENTS.md` first.
- If a completed plan later needs revision, create a new current plan rather than editing archived history unless the user explicitly asks. 2. Read `V1_BACKEND_COMPLETION_GAP_MATRIX.md` before starting Block 11.
3. Execute active block documents in numeric order.
4. Execute only the next chunk or stage requested by the user.
5. Respect every `BREAKPOINT` as a hard stop.
6. When the next chunk changes recommended Codex level, stop and ask the user to
confirm the mode switch before continuing.
7. Run the relevant formatter, analyzer, unit tests, contract tests, and
integration tests before claiming a chunk is complete.
8. Commit completed bounded work with a descriptive conventional commit.
9. Mark a completed plan `Complete`, move it to
`Codex Documentation/Archived plans/`, and commit the archive move.
10. Do not rewrite archived Blocks 0110 to make new work appear previously
complete. Add errata or new active work instead.
## Scope guardrails
Backend V1 includes the application-facing use cases, persistence schema,
MongoDB adapter boundary, deterministic scheduling behavior, internal statistics,
and UI-independent read models required by Today, Backlog, quick capture, locked
time, rollover, surprise logging, child tasks, free slots, project defaults, and
reminder policy decisions.
Backend V1 does not include week/month views, reports, overwhelm shield,
burnout catch-up, drag-and-drop, a visible task-history panel, task dependencies,
context tags, advanced sync, user accounts, production authentication, or
flexible-task overrun behavior.
The UI must never receive a MongoDB connection string or database credentials.
Block 16 must choose and document a trusted runtime boundary before adding a
runtime database dependency.
## Active plan index
| Order | Plan | Status | Backend/UI |
|---|---|---|---|
| 11 | `../Archived plans/V1_BLOCK_11_Backend_Baseline_Domain_Contracts.md` | Complete, archived | Backend |
| 12 | `../Archived plans/V1_BLOCK_12_Occupancy_Scheduling_Correctness.md` | Complete, archived | Backend |
| 13 | `V1_BLOCK_13_Lifecycle_Statistics_Project_Reminders.md` | Planned | Backend |
| 14 | `V1_BLOCK_14_Application_Use_Cases_Read_Models.md` | Planned | Backend |
| 15 | `../Archived plans/V1_BLOCK_15_Persistence_Schema_Codecs_Repositories.md` | Complete, archived | Backend |
| 16 | `V1_BLOCK_16_MongoDB_Runtime_Adapter.md` | In progress | Backend |
| 17 | `V1_BLOCK_17_Backend_Acceptance_Handoff.md` | Planned | Backend gate |
| 18 | `V1_BLOCK_18_UI_Foundation_Design_Spike.md` | Planned, blocked | UI foundation |
## Recommended mode labels
Chunks and stages use only:
- `low`
- `medium`
- `high`
- `extra high`
Blocks do not receive a Codex thinking-level classification.

View file

@ -1,66 +0,0 @@
# Current Software Plan
Blocks 0112 are complete and remain historical records in
`Codex Documentation/Archived plans/`. The active path resumes at Block 13.
The backend sequence is Blocks 1117. Block 18 is a deliberately limited UI
foundation block and is blocked until the backend completion gate in Chunk 17.4
passes.
## Execution rules
1. Read `AGENTS.md` first.
2. Read `V1_BACKEND_COMPLETION_GAP_MATRIX.md` before starting Block 11.
3. Execute active block documents in numeric order.
4. Execute only the next chunk or stage requested by the user.
5. Respect every `BREAKPOINT` as a hard stop.
6. When the next chunk changes recommended Codex level, stop and ask the user to
confirm the mode switch before continuing.
7. Run the relevant formatter, analyzer, unit tests, contract tests, and
integration tests before claiming a chunk is complete.
8. Commit completed bounded work with a descriptive conventional commit.
9. Mark a completed plan `Complete`, move it to
`Codex Documentation/Archived plans/`, and commit the archive move.
10. Do not rewrite archived Blocks 0110 to make new work appear previously
complete. Add errata or new active work instead.
## Scope guardrails
Backend V1 includes the application-facing use cases, persistence schema,
MongoDB adapter boundary, deterministic scheduling behavior, internal statistics,
and UI-independent read models required by Today, Backlog, quick capture, locked
time, rollover, surprise logging, child tasks, free slots, project defaults, and
reminder policy decisions.
Backend V1 does not include week/month views, reports, overwhelm shield,
burnout catch-up, drag-and-drop, a visible task-history panel, task dependencies,
context tags, advanced sync, user accounts, production authentication, or
flexible-task overrun behavior.
The UI must never receive a MongoDB connection string or database credentials.
Block 16 must choose and document a trusted runtime boundary before adding a
runtime database dependency.
## Active plan index
| Order | Plan | Status | Backend/UI |
|---|---|---|---|
| 11 | `../Archived plans/V1_BLOCK_11_Backend_Baseline_Domain_Contracts.md` | Complete, archived | Backend |
| 12 | `../Archived plans/V1_BLOCK_12_Occupancy_Scheduling_Correctness.md` | Complete, archived | Backend |
| 13 | `V1_BLOCK_13_Lifecycle_Statistics_Project_Reminders.md` | Planned | Backend |
| 14 | `V1_BLOCK_14_Application_Use_Cases_Read_Models.md` | Planned | Backend |
| 15 | `../Archived plans/V1_BLOCK_15_Persistence_Schema_Codecs_Repositories.md` | Complete, archived | Backend |
| 16 | `V1_BLOCK_16_MongoDB_Runtime_Adapter.md` | In progress | Backend |
| 17 | `V1_BLOCK_17_Backend_Acceptance_Handoff.md` | Planned | Backend gate |
| 18 | `V1_BLOCK_18_UI_Foundation_Design_Spike.md` | Planned, blocked | UI foundation |
## Recommended mode labels
Chunks and stages use only:
- `low`
- `medium`
- `high`
- `extra high`
Blocks do not receive a Codex thinking-level classification.

View file

@ -1,366 +0,0 @@
# V1 ADR 002: MongoDB Document Schema V1
Status: Accepted during Block 15.1
Date: 2026-06-25
## Context
MongoDB is the committed persistence target for this project. Blocks 11-14 added
the pure Dart domain model, repository boundaries, application unit of work,
Today/Backlog read models, management commands, notice acknowledgement, and
app-open rollover recovery.
Block 15 needs one versioned document contract before codecs, migrations, or a
runtime MongoDB adapter are implemented. This ADR defines that contract without
adding a database client, connection string, sync behavior, accounts, or
background services.
## Decision
V1 stores application data in MongoDB-friendly documents behind repository
interfaces. The core scheduling logic remains independent from MongoDB APIs.
Every top-level document uses:
- `schemaVersion`: integer, `1` for this contract.
- `_id`: stable document id, unique within its collection.
- `ownerId`: authorization-neutral owner scope. This is a data boundary, not an
account/auth implementation.
- `revision`: positive integer for mutable authoritative documents. Starts at
`1` and increments on compare-and-set saves. Append-only documents use
`revision: 1`.
- `createdAt`: UTC instant string.
- `updatedAt`: UTC instant string. Append-only documents set this equal to
`createdAt`.
The adapter may use BSON dates internally later, but the core V1 codec contract
uses the existing string conventions:
- Instant: UTC ISO-8601 string from `DateTime.toUtc().toIso8601String()`.
- Civil date: `YYYY-MM-DD` string with no timezone conversion.
- Wall time: `HH:MM` string with no date or timezone conversion.
- Time zone: IANA-style string chosen by the application boundary.
- Interval: embedded object `{start, end, label?}` where `start` and `end` are
UTC instant strings.
- Optional fields: V1 writers include known optional fields with `null` when
cleared. Decoders tolerate unknown extra fields and ignore them.
## Collections
### `tasks`
Authoritative task documents.
Required fields:
- common fields
- `title`
- `projectId`
- `type`
- `status`
- `priority`
- `reward`
- `difficulty`
- `durationMinutes`
- `scheduledStart`
- `scheduledEnd`
- `actualStart`
- `actualEnd`
- `completedAt`
- `parentTaskId`
- `backlogTags`
- `reminderOverride`
- `stats`
- `backlogEnteredAt`
- `backlogEnteredAtProvenance`
`backlogEnteredAt` is nullable in V1. V0 migration may set it from `createdAt`
with provenance `approximated_from_created_at`; new V1 backlog transitions should
set provenance `recorded`.
Task documents do not embed history, children, scheduling changes, or notice
lists. Child ownership is represented by `parentTaskId`.
### `projects`
Authoritative project configuration documents.
Required fields:
- common fields
- `name`
- `colorKey`
- `defaultPriority`
- `defaultReward`
- `defaultDifficulty`
- `defaultReminderProfile`
- `defaultDurationMinutes`
- `archivedAt`
Archiving a project sets `archivedAt` and increments `revision`. It never deletes
or rewrites task history.
### `project_statistics`
Project-level aggregate documents derived from internal activities.
Required fields:
- common fields
- `projectId`
- `completedTaskCount`
- `durationMinuteCounts`
- `completionTimeBucketCounts`
- `totalPushesBeforeCompletion`
- `completedAfterPushCount`
- `rewardCounts`
- `difficultyCounts`
- `reminderProfileCounts`
- `appliedActivityIds`
`appliedActivityIds` is bounded by compaction policy in future adapter work. It
prevents double-application of completion activities.
### `locked_blocks`
Authoritative recurring or one-off locked-time definitions.
Required fields:
- common fields
- `name`
- `startTime`
- `endTime`
- `date`
- `recurrence`
- `hiddenByDefault`
- `projectId`
- `archivedAt`
Archiving a locked block sets `archivedAt`, increments `revision`, and stops base
occurrence expansion. It does not delete one-day overrides.
### `locked_overrides`
Date-scoped locked-time override documents.
Required fields:
- common fields
- `lockedBlockId`
- `date`
- `type`
- `name`
- `startTime`
- `endTime`
- `hiddenByDefault`
- `projectId`
Override `type` is one of `remove`, `replace`, or `add`. Overrides are
append/update records, not edits to the recurring block.
### `task_activities`
Append-only internal activity facts.
Required fields:
- common fields with `revision: 1`
- `operationId`
- `code`
- `taskId`
- `projectId`
- `occurredAt`
- `metadata`
Activities are internal application data. They are not a visible per-task history
panel in V1.
### `owner_settings`
One owner settings document per owner.
Required fields:
- common fields
- `timeZoneId`
- `dayStart`
- `dayEnd`
- `compactModeEnabled`
- `backlogStaleness`
Changing `timeZoneId`, `dayStart`, or `dayEnd` can reinterpret local dates. The
application layer must return typed warnings or run an explicit migration path;
codecs must not silently shift existing instants.
### `notice_acknowledgements`
Owner-scoped consumed-notice records.
Required fields:
- common fields with `revision: 1`
- `noticeId`
- `acknowledgedAt`
The unique key is `(ownerId, noticeId)`. Acknowledgement hides a notice from
Today state without mutating the original operation/snapshot record.
### `operation_records`
Exactly-once operation records.
Required fields:
- common fields with `revision: 1`
- `operationId`
- `operationName`
- `committedAt`
The unique key is `(ownerId, operationId)`. These records support application
idempotency and are not a replacement for task/activity facts.
### `scheduling_snapshots`
Bounded diagnostics and pending-notice carrier documents.
Required fields:
- common fields with `revision: 1`
- `operationName`
- `sourceDate`
- `targetDate`
- `window`
- `tasks`
- `lockedIntervals`
- `requiredVisibleIntervals`
- `notices`
- `changes`
- `overlaps`
- `retentionExpiresAt`
Full scheduling snapshots remain in V1 as bounded diagnostics and as the carrier
for pending rollover notices. They are not the authoritative source of task
state, project state, locked-time definitions, or activity/statistics facts.
Production adapters should keep snapshots compact:
- retain no more than 100 embedded tasks per snapshot;
- retain no more than 100 changes or overlaps per snapshot;
- retain no more than 20 notices per snapshot;
- omit or redact hidden locked names from `lockedIntervals`;
- set `retentionExpiresAt` after all notices are acknowledged or after the
configured diagnostic retention window.
If an operation needs more diagnostic data than these bounds allow, it should
store the authoritative entity changes and a truncated snapshot with a typed
`truncated: true` marker.
## Stable Codes
V1 documents must not depend on Dart enum source `.name` values. Codecs will use
explicit encode/decode tables. Unknown codes fail closed with typed mapping
errors.
Initial code values:
| Domain enum | Codes |
|---|---|
| `TaskType` | `flexible`, `inflexible`, `critical`, `locked`, `surprise`, `free_slot` |
| `TaskStatus` | `planned`, `active`, `completed`, `missed`, `cancelled`, `no_longer_relevant`, `backlog` |
| `PriorityLevel` | `very_low`, `low`, `medium`, `high`, `very_high` |
| `RewardLevel` | `not_set`, `very_low`, `low`, `medium`, `high`, `very_high` |
| `DifficultyLevel` | `not_set`, `very_easy`, `easy`, `medium`, `hard`, `very_hard` |
| `ReminderProfile` | `silent`, `gentle`, `persistent`, `strict` |
| `BacklogTag` | `wishlist` |
| `LockedWeekday` | `monday`, `tuesday`, `wednesday`, `thursday`, `friday`, `saturday`, `sunday` |
| `LockedBlockOverrideType` | `remove`, `replace`, `add` |
| `TaskActivityCode` | `completed`, `missed`, `cancelled`, `no_longer_relevant`, `manually_pushed`, `automatically_pushed`, `moved_to_backlog`, `restored_from_backlog`, `activated` |
| `SchedulingNoticeType` | `info`, `moved`, `overlap`, `no_fit`, `overflow` |
| `SchedulingIssueCode` | `task_not_found`, `invalid_task_state`, `missing_duration`, `missing_scheduled_slot`, `non_positive_duration`, `no_available_slot`, `unfinished_tasks_could_not_fit`, `no_unfinished_flexible_tasks`, `duplicate_surprise_log` |
| `SchedulingMovementCode` | `backlog_task_inserted`, `flexible_task_moved_to_make_room`, `flexible_task_pushed_to_next_available_slot`, `flexible_task_moved_to_tomorrow`, `unfinished_flexible_tasks_rolled_over`, `flexible_task_moved_to_backlog`, `required_commitment_scheduled` |
| `SchedulingConflictCode` | `flexible_task_overlaps_blocked_time`, `surprise_task_overlaps_required_visible_time`, `required_commitment_overlaps_protected_free_slot` |
| `ProjectCompletionTimeBucket` | `overnight`, `morning`, `afternoon`, `evening`, `night` |
Codec tables may add newer codes in later schema versions. They must not remap
an existing code to a different semantic meaning.
## Indexes And Uniqueness
Required index specifications are adapter-neutral in V1 and are created in
Block 16.
| Collection | Index | Purpose |
|---|---|---|
| all collections | unique `(_id)` | Stable document identity |
| all owner-scoped collections | `(ownerId, _id)` | Owner boundary lookup |
| `tasks` | `(ownerId, status, scheduledStart, scheduledEnd)` | Today/window and lifecycle queries |
| `tasks` | `(ownerId, status, projectId)` | backlog/project filters |
| `tasks` | `(ownerId, parentTaskId)` | child task lookup |
| `tasks` | `(ownerId, status, backlogEnteredAt, createdAt)` | backlog candidate ordering |
| `projects` | `(ownerId, archivedAt, name)` | active project pickers |
| `project_statistics` | unique `(ownerId, projectId)` | aggregate lookup |
| `locked_blocks` | `(ownerId, archivedAt, date)` | one-off locked expansion |
| `locked_blocks` | `(ownerId, archivedAt, recurrence.weekdays)` | recurring locked expansion |
| `locked_overrides` | `(ownerId, date, lockedBlockId, type)` | date-scoped override expansion |
| `task_activities` | unique `(ownerId, _id)` | append-only activity identity |
| `task_activities` | `(ownerId, operationId)` | command idempotency/debug lookup |
| `task_activities` | `(ownerId, taskId, occurredAt)` | task activity loading |
| `task_activities` | `(ownerId, projectId, code, occurredAt)` | project-stat aggregation |
| `owner_settings` | unique `(ownerId)` | one settings document per owner |
| `notice_acknowledgements` | unique `(ownerId, noticeId)` | notice consume idempotency |
| `operation_records` | unique `(ownerId, operationId)` | exactly-once command boundary |
| `scheduling_snapshots` | unique `(ownerId, sourceDate, operationName)` for rollover-style operations | source-day idempotency |
| `scheduling_snapshots` | `(ownerId, window.start, window.end)` | Today pending notice lookup |
| `scheduling_snapshots` | `(retentionExpiresAt)` | bounded diagnostic cleanup |
Partial indexes should prefer active records where applicable, such as
`archivedAt: null` for project and locked-block picker/expansion queries.
## Archive, Delete, And Retention
Normal user-facing removal uses lifecycle state or archive fields:
- Tasks are not hard-deleted by automatic scheduling. `cancelled`,
`no_longer_relevant`, and `backlog` preserve history.
- Projects use `archivedAt`; task `projectId` values remain unchanged.
- Locked blocks use `archivedAt`; overrides remain independent.
- Scheduling snapshots are bounded diagnostics and may expire after retention
rules once they are no longer carrying pending notices.
Hard delete is reserved for explicit adapter/admin operations outside the normal
V1 app flow.
Operation records and task activities are internal operation data. V1 retains
them long enough to preserve idempotency, statistics, and migration safety.
Adapter-level pruning must not remove authoritative task/project/locked state or
break exactly-once guarantees for active retry windows.
## Privacy Boundaries
Documents must not contain credentials, database connection strings, OAuth
tokens, sync tokens, or platform-notification secrets.
Hidden locked-time details are sensitive. They may live in the owner-scoped
`locked_blocks` and `locked_overrides` documents, but they should not be copied
into denormalized notices, public summaries, or unnecessary snapshot labels.
When snapshots need locked intervals for diagnostics, hidden labels should be
redacted or replaced with source IDs and `hiddenByDefault: true`.
Internal statistics and activity records are implementation data for future
reports and scheduling correctness. They should remain behind repository/use-case
boundaries and should not become a visible task-history UI in V1.
## Consequences
- Chunk 15.2 must replace the current enum `.name` mapping helpers with explicit
stable code tables.
- Chunk 15.2 must add codecs for every collection listed above, including
owner-scoped notices and bounded scheduling snapshots.
- Chunk 15.3 must migrate V0 task documents to V1 with explicit provenance for
approximated backlog entry time.
- Chunk 15.4 must expand repository contracts so Block 14 use cases can use
owner-scoped, indexed query methods instead of broad `findAll()` loading.
- Chunk 15.5 must turn the index table in this ADR into tested adapter-neutral
index specifications.

View file

@ -0,0 +1,35 @@
# V1 ADR 002: SQLite Document Schema V1
Status: **Accepted**
Date: 2026-06-26
## Context
The project pivoted from MongoDB to **SQLitefirst** persistence.
We need a stable, versioned relational schema that maps cleanly to the domain
objects while staying behind the repository abstraction. Drift will manage
migrations.
## Decision
* **Database file**: `adhd_scheduler.sqlite` in the user data directory.
* **Schema version**: `1` (managed by Drift).
* **Tables**
| Table | Purpose | Key fields |
|-------|---------|------------|
| `tasks` | Authoritative task rows | `id TEXT PRIMARY KEY`, `owner_id TEXT`, `project_id`, `parent_id`, `type`, `status`, `priority`, `reward`, `difficulty`, `scheduled_start_utc`, `scheduled_end_utc`, `actual_start_utc`, `actual_end_utc`, `completed_at_utc`, `revision INT`, `created_at_utc`, `updated_at_utc`, `backlog_entered_at_utc`, `backlog_entered_provenance TEXT` |
| `projects` | Project configuration | `id TEXT PRIMARY KEY`, `owner_id`, `name`, `color_key`, config defaults …, `archived_at_utc`, `revision` |
| `locked_blocks` | Recurring / oneoff locked time | `id TEXT PRIMARY KEY`, `owner_id`, `name`, `date TEXT`, `start_time TEXT`, `end_time TEXT`, `recurrence_json`, `hidden_by_default INT`, `archived_at_utc`, `revision` |
| `locked_overrides` | Datescoped overrides | `id TEXT PRIMARY KEY`, `owner_id`, `locked_block_id`, `date TEXT`, `type`, JSON fields |
| `settings` | One row per owner | `owner_id TEXT PRIMARY KEY`, `timezone_id`, `day_start_minutes`, `day_end_minutes`, `compact_mode INT`, `revision` |
| `activities` | Appendonly internal events | `id TEXT PRIMARY KEY`, `owner_id`, `task_id`, `code`, `occurred_at_utc`, `metadata_json` |
| `snapshots` | Bounded diagnostic schedule snapshots | `id TEXT PRIMARY KEY`, `owner_id`, `operation_name`, `source_date TEXT`, `window_json`, `notice_json`, `changes_json`, `retention_expires_utc` |
* All timestamps are stored as **UTC**.
* Optimistic concurrency: every mutable row carries `revision`. Updates must
include `WHERE revision = :expected` and increment on success.
* Drift migrations are generated and tested; downgrades are not supported.
## Consequences
* Domain objects remain unchanged; adapters translate.
* Backup library (Block 24) can copy and encrypt this single file.
* Repository contract tests assert schema integrity via Drift introspection.

View file

@ -1,177 +0,0 @@
# V1 ADR 003: MongoDB Runtime Topology
Status: Accepted during Block 16.1
Date: 2026-06-25
## Context
MongoDB is the committed persistence target for V1, but the Flutter UI and pure
Dart scheduling core must not own production database credentials. Block 15
completed the adapter-neutral document schema, codecs, repository contracts,
index catalog, payload limits, and migration contracts.
Before adding a MongoDB dependency, Block 16 needs a runtime decision that keeps
credentials inside a trusted boundary, supports transactions, and avoids
deprecated MongoDB client-access products.
Sources checked on 2026-06-25:
- MongoDB official client libraries list:
`https://www.mongodb.com/docs/drivers/`
- MongoDB Node.js driver docs:
`https://www.mongodb.com/docs/drivers/node/current/`
- MongoDB Node.js transaction docs:
`https://www.mongodb.com/docs/drivers/node/current/crud/transactions/`
- MongoDB transaction manual:
`https://www.mongodb.com/docs/manual/core/transactions/`
- MongoDB Atlas App Services EOL notice:
`https://www.mongodb.com/docs/api/doc/atlas-app-services-admin-api-v3/`
- Deprecated Atlas Data API docs:
`https://www.mongodb.com/docs/api/doc/atlas-data-api-v1/`
- Dart package checks:
`https://pub.dev/packages/mongo_dart` and
`https://pub.dev/packages/mongo_db_driver`
## Decision
V1 selects a trusted service boundary for MongoDB persistence.
The MongoDB-owning runtime is a separate Node.js/TypeScript service using the
official MongoDB Node.js driver. This service owns:
- MongoDB connection strings and credentials;
- TLS/SRV driver configuration;
- client lifecycle and health checks;
- index bootstrap from the Block 15 index catalog;
- document reads/writes against the V1 collection contract;
- sessions and transactions for multi-record scheduling writes;
- redacted diagnostics and failure mapping.
The Flutter UI never connects directly to MongoDB and never receives connection
strings, database credentials, raw MongoDB documents, driver clients,
collections, sessions, or cursors.
The pure Dart package remains dependency-free with respect to MongoDB. Dart
domain and application code continue to use repository interfaces and typed use
case results. The trusted service exposes a narrow versioned application API
that maps to the Block 14 use cases and Block 15 document contract.
During the UI foundation/design spike, the first Flutter UI should use the
existing in-memory application composition by default. Persisted development
flows may use a local trusted service process, but that process remains outside
the Flutter binary and reads secrets only from runtime configuration.
## Rejected Options
### Direct MongoDB from Flutter or mobile Dart
Rejected. It would place database credentials in an untrusted binary and force
the UI to own network/database failure modes. It also couples the UI to driver
types and makes owner-scope/security mistakes harder to contain.
### Pure Dart MongoDB adapter as the production V1 foundation
Rejected for now. MongoDB's official client library list does not include Dart.
`mongo_dart` is active and useful for experiments, but it is community-supported
rather than an official MongoDB driver. `mongo_db_driver` advertises sessions and
transactions, but its package page explicitly identifies it as pre-alpha and not
suitable for production. Neither should become the V1 persistence foundation
without a later ADR reversing this decision.
### Atlas Data API, Atlas Device SDKs, App Services, GraphQL, Functions, or
Custom HTTPS Endpoints
Rejected. MongoDB's App Services notice says these paths reached end-of-life on
September 30, 2025, with database triggers remaining available. They are not a
stable V1 foundation.
### SQLite or another local fallback
Rejected. MongoDB remains the committed persistence target. A disconnected
fallback would add an unplanned sync/reconciliation problem and violate the
current persistence target rules.
## Driver and Deployment Requirements
The selected service must use the official MongoDB Node.js driver current major
line at implementation time.
Mandatory capabilities:
- `mongodb+srv://` and TLS-capable connections for Atlas;
- BSON fidelity at the adapter edge;
- sessions and multi-document transactions;
- explicit transaction retry handling for documented retryable categories;
- bounded connection and operation timeouts;
- graceful startup/shutdown and health checks;
- idempotent index creation;
- redacted logging;
- no raw driver values in public service DTOs.
MongoDB deployment requirements:
- Multi-document scheduling writes require MongoDB Server 4.0 or later.
- Transaction acceptance requires a transaction-capable deployment. V1 local and
CI testing must use a replica set or supported sharded deployment, not a
standalone server.
- If the service cannot verify transaction capability at startup for a
production Mongo-backed configuration, it must fail closed instead of falling
back to untracked in-memory writes.
## Configuration Boundary
Development configuration:
- Uses environment variables or a local secret file excluded from git.
- May point to a disposable local replica set or scoped Atlas development
database.
- Must use a database name or prefix that is safe for destructive test cleanup.
Test configuration:
- Uses uniquely named disposable databases/collections.
- Fails if the configured target does not match the expected test scope.
- Redacts connection strings and credentials from test output.
Production configuration:
- Secrets come from deployment secret storage.
- The Flutter/mobile app receives only service endpoint configuration and
application-layer auth/session material once that future work is explicitly
planned.
- Production authentication, account management, cross-device sync, Atlas
provisioning, network allowlists, and cluster creation remain out of scope for
this block.
## Threat and Safety Checklist
- No MongoDB connection string is committed to source control.
- No MongoDB credential is embedded in Flutter, mobile, desktop, or web UI
assets.
- Normal logs do not include task titles, hidden locked-block names, full
documents, connection strings, or credential fragments.
- Every repository query and write includes owner scope.
- Hidden locked-time details remain hidden by default in service responses.
- Duplicate operation IDs are enforced by a unique owner-operation index.
- Revision predicates are required for authoritative updates.
- Transaction retries are bounded and observable.
- A production Mongo connection failure fails closed.
- In-memory composition remains available only as explicit local/design-spike
wiring, not as a silent production persistence fallback.
## Consequences
Block 16.2 must add any MongoDB dependency only in the trusted service/runtime
module, not in the pure Dart core package.
The implementation path should provide two composition roots:
- in-memory Dart application wiring for tests and UI design work;
- trusted service-backed persistence for MongoDB-backed development and future
deployment.
If a later chunk cannot implement the selected service boundary without
duplicating scheduling rules unsafely, it must stop and record the blocker
rather than embedding credentials in Flutter or adopting an unmaintained driver
as a shortcut.

View file

@ -0,0 +1,26 @@
# V1 ADR 003: Embedded Local Runtime Topology
Status: **Accepted**
Date: 2026-06-26
## Context
With SQLite as the local persistence engine, V1 no longer requires a separate
service process. The entire stack can run inside a single Flutter/Dart desktop
binary.
## Decision
* **Embedded DB** The application opens an ondisk SQLite file via Drift.
* **No background daemon** starting the desktop app is enough; automated tests
use an inmemory or temporaryfile database.
* **Dev hotreload** `scripts/dev.sh` launches Flutter desktop and watches
Drift files.
* **Pluggable adapters** A future remote/sync adapter will satisfy the same
repository interfaces; switching happens at composition root.
## Rejected
* Running a local Node.js or Go service to host SQLite unnecessary complexity.
* Direct file writes bypassing Drift loses migration guarantees.
## Consequences
* Deployment simplifies to one executable per platform.
* CI can run integration tests without Docker or external DB.

View file

@ -0,0 +1,9 @@
# V1 ADR 004: Repository & Domain Boundary
Status: **Accepted**
Date: 2026-06-26
Repository interfaces (`packages/scheduler_persistence`) expose **domain objects only**.
Adapters must implement optimistic revision, immutable returns, and pass the Repository Conformance Suite (Block 26).
No open questions remain.

View file

@ -0,0 +1,9 @@
# V1 ADR 005: Export & Backup Boundary
Status: **Accepted**
Date: 2026-06-26
* **Backup** passphraseencrypted SQLite copy (`.sqlite.aes` via AES256GCM, PBKDF2 200k rounds).
* **Readable export** JSON and CSV via `ExportController`.
No open questions remain.

View file

@ -0,0 +1,8 @@
# V1 ADR 006: Schedule Snapshot Policy
Status: **Accepted**
Date: 2026-06-26
Persist committed diagnostic snapshots only; bounded retention 30 days or until notices acknowledged.
No open questions remain.

View file

@ -0,0 +1,8 @@
# V1 ADR 007: Test Strategy
Status: **Accepted**
Date: 2026-06-26
Four layers: Unit, Contract, Migration, Integration. CI fails below 80% line coverage.
No open questions remain.

View file

@ -0,0 +1,8 @@
# V1 ADR 008: Notification Abstraction
Status: **Accepted**
Date: 2026-06-26
`NotificationAdapter` interface abstracts scheduling/cancellation and feedback stream. Desktop implementation in `scheduler_notifications_desktop`; Fake adapter for tests.
No open questions remain.

View file

@ -0,0 +1,74 @@
# V1 Block 19 — Repository & Persistence Abstraction
**Purpose**: Define repository interfaces and memory adapter.
> **Note for Codex**: Follow tasks exactly; avoid exploratory calls when tasks specify names/files/tests.
## Chunk 19.1 — Define repository interfaces
Recommended level: **XHIGH**
Status: Complete on 2026-06-26.
### Tasks
1. Create Dart library **`packages/scheduler_persistence/lib/persistence.dart`** and declare abstract classes `TaskRepository`, `ProjectRepository`, `LockedBlockRepository`, `SettingsRepository`, `ScheduleSnapshotRepository`.
2. Each repository must expose **only** domain objects from `packages/scheduler_core` (import that package).
3. Add shared value objects in `scheduler_core` if missing (e.g., `Revision`, `OwnerId`, `PageRequest`, `Page<T>`).
4. Document every method with tripleslash Dart doc.
5. Publish typedef `RepoResult<T>` = `Either<RepositoryFailure,T>` (use sealed class).
### Acceptance criteria
1. `dart analyze` shows 0 hints in `scheduler_persistence`.
2. Running `dart test` passes new autogenerated stub tests in `packages/scheduler_persistence/test/repo_contract_smoke_test.dart`.
### Completed implementation
1. Rehomed the core package to `packages/scheduler_core` with package name `scheduler_core`.
2. Added shared repository value objects in `scheduler_core`: `OwnerId`, `Revision`, `PageRequest`, and `Page<T>`.
3. Added package `packages/scheduler_persistence` with domain-only repository contracts for tasks, projects, locked blocks, settings, and schedule snapshots.
4. Added sealed repository failure types, sealed `Either<L,R>`, and `RepoResult<T>`.
5. Added `packages/scheduler_persistence/test/repo_contract_smoke_test.dart`.
### Verification
1. `dart format test/scheduler_core_test.dart packages/scheduler_core packages/scheduler_persistence`: passed.
2. `dart analyze`: passed, no issues found.
3. `cd packages/scheduler_persistence && dart analyze`: passed, no issues found.
4. `cd packages/scheduler_persistence && dart test`: passed, 3 tests.
5. `cd packages/scheduler_core && dart test`: passed, 298 tests.
6. `dart test`: passed, 301 tests.
---
## Chunk 19.2 — Memory adapter & conformance tests
Recommended level: **HIGH**
Status: Complete on 2026-06-26.
### Tasks
1. Implement **`packages/scheduler_persistence_memory`** with class `InMemoryTaskRepository` etc. They must implement optimistic revision (increment int).
2. Add conformance test suite in `scheduler_persistence/test/repo_conformance.dart` with shared `runRepositoryComplianceTests()`.
3. Ensure cloning (deep copy) on return values using `jsonEncode/jsonDecode` for simplicity.
### Acceptance criteria
1. Inmemory adapter passes conformance suite covering CRUD, paging, optimistic revision conflict.
2. 100% statement coverage > 80% lines in this package.
### Completed implementation
1. Added package `packages/scheduler_persistence_memory` and workspace wiring.
2. Added in-memory implementations for task, project, locked block, settings, and schedule snapshot repository contracts.
3. Implemented owner scoping, duplicate-id checks, compare-and-set saves/deletes/archives, stale-revision failures, and deterministic offset paging.
4. Added JSON round-trip defensive cloning through the existing core document mappers.
5. Added shared conformance suite `packages/scheduler_persistence/test/repo_conformance.dart`.
6. Added `packages/scheduler_persistence_memory/test/memory_repository_conformance_test.dart` and root test wrapper wiring.
### Verification
1. `dart pub get`: passed.
2. `dart format test/scheduler_core_test.dart packages/scheduler_persistence/test/repo_conformance.dart packages/scheduler_persistence_memory`: passed.
3. `dart analyze`: passed, no issues found.
4. `cd packages/scheduler_persistence && dart analyze`: passed, no issues found.
5. `cd packages/scheduler_persistence_memory && dart analyze`: passed, no issues found.
6. `cd packages/scheduler_persistence && dart test`: passed, 3 tests.
7. `cd packages/scheduler_persistence_memory && dart test`: passed, 7 tests.
8. `cd packages/scheduler_core && dart test`: passed, 298 tests.
9. `dart test`: passed, 308 tests.
10. `cd packages/scheduler_persistence_memory && dart test --coverage=coverage`: passed; generated LCOV line coverage is 93.79% (302/322).
---

View file

@ -0,0 +1,77 @@
# V1 Block 20 — SQLite Persistence Adapter Package
**Purpose**: Implement Drift-based SQLite storage backend.
> **Note for Codex**: Follow tasks exactly; avoid exploratory calls when tasks specify names/files/tests.
## Chunk 20.1 — SQLite schema & Drift setup
Recommended level: **XHIGH**
Status: Complete on 2026-06-26.
### Tasks
1. Create new Dart package **`packages/scheduler_persistence_sqlite`** with Drift as dependency.
2. Define Drift database `SchedulerDb` with tables: `tasks`, `projects`, `locked_blocks`, `settings`, `snapshots`.
3. Fields: follow domain model; include `revision INT`, `owner_id TEXT`.
4. Add drift migrations using drift_dev build runner; start at schemaVersion=1.
5. Generate DAO classes via build_runner.
### Acceptance criteria
1. `dart run build_runner build --delete-conflicting-outputs` completes with zero errors.
2. Generated drift files checked in.
### Completed implementation
1. Added package `packages/scheduler_persistence_sqlite` with Drift, `drift_dev`, and `build_runner` wiring.
2. Added `SchedulerDb` in `lib/src/scheduler_db.dart` with `schemaVersion = 1` and `MigrationStrategy(onCreate: createAll)`.
3. Added tables for `tasks`, `projects`, `locked_blocks`, `locked_overrides`, `settings`, and `snapshots`.
4. Included owner scope and optimistic revision columns on mutable rows.
5. Added generated Drift data classes/accessor mixins in `lib/src/scheduler_db.g.dart`.
6. Added a schema smoke test that opens an in-memory Drift database and checks the expected table names.
### Verification
1. `dart pub get`: passed.
2. `cd packages/scheduler_persistence_sqlite && dart run build_runner build --delete-conflicting-outputs`: passed, exit 0; current build_runner warned that the option is ignored.
3. `dart format packages/scheduler_persistence_sqlite`: passed.
4. `cd packages/scheduler_persistence_sqlite && dart analyze`: passed, no issues found.
5. `dart analyze`: passed, no issues found.
6. `cd packages/scheduler_persistence_sqlite && dart test`: passed, 1 test.
7. `dart test`: passed, 308 tests.
---
## Chunk 20.2 — SQLite adapter implementation & tests
Recommended level: **HIGH**
Status: Complete on 2026-06-26.
### Tasks
1. Implement `SqliteTaskRepository` etc mapping domain objects to Drift rows with explicit converters.
2. Use transaction for multirecord save; ensure optimistic revision by `WHERE revision = ?` clause.
3. Add repository conformance tests reused from block19 suite pointed at SQLite adapter (use `sqflite_ffi` in tests).
### Acceptance criteria
1. SQLite adapter passes full conformance suite with `sqflite_ffi` on Linux/Windows/mac.
2. Average write latency in test ≤50ms.
### Completed implementation
1. Added `SqliteTaskRepository`, `SqliteProjectRepository`, `SqliteLockedBlockRepository`, `SqliteSettingsRepository`, and `SqliteScheduleSnapshotRepository`.
2. Mapped Drift rows to domain objects through the existing core document mappers and explicit row/JSON converters.
3. Implemented duplicate-id checks, owner isolation, deterministic paging, archive behavior, snapshot retention deletion, and typed repository failures.
4. Implemented optimistic compare-and-set writes/deletes/archives with `WHERE revision = expected` clauses.
5. Added SQLite conformance tests using the Block 19 shared suite and an in-memory Drift SQLite executor.
6. Added a write-latency test for task inserts and wired SQLite tests into the root test wrapper.
### Notes
1. Tests use Drift `NativeDatabase.memory()` instead of `sqflite_ffi`. A sqflite-backed Drift executor would require `drift_sqflite`, which pulls Flutter SDK dependencies into this pure Dart adapter package.
2. The current repository contracts expose single-record writes. No multi-record repository save method exists yet; future multi-record SQLite writes should use `SchedulerDb.transaction`.
### Verification
1. `dart pub get`: passed.
2. `dart format test/scheduler_core_test.dart packages/scheduler_persistence_sqlite`: passed.
3. `cd packages/scheduler_persistence_sqlite && dart analyze`: passed, no issues found.
4. `cd packages/scheduler_persistence_sqlite && dart test`: passed, 9 tests.
5. `dart analyze`: passed, no issues found.
6. `dart test`: passed, 316 tests.
7. `scripts/test.sh`: not present or not executable.
---

View file

@ -0,0 +1,40 @@
# V1 Block 21 — Notification Abstraction Layer
**Purpose**: Define NotificationAdapter contract.
> **Note for Codex**: Follow tasks exactly; avoid exploratory calls when tasks specify names/files/tests.
## Chunk 21.1 — NotificationAdapter contract
Recommended level: **XHIGH**
Status: Complete on 2026-06-26.
### Tasks
1. Add package **`packages/scheduler_notifications`**.
2. Declare sealed class `NotificationRequest` with fields: `id`, `title`, `body`, `scheduledDateTimeUtc`, `payloadJson`.
3. Declare enum `NotificationFeedbackType` (clicked,dismissed,action).
4. Define abstract `NotificationAdapter` with methods `Future<void> schedule(NotificationRequest)`, `Future<void> cancel(String id)`, `Stream<NotificationFeedback>`.
5. Add stub `FakeNotificationAdapter` for tests emitting events via StreamController.
### Acceptance criteria
1. Package compiles and `dart test` passes stub test `fake_adapter_test.dart`.
### Completed implementation
1. Added package `packages/scheduler_notifications` with public entry points `notifications.dart` and `scheduler_notifications.dart`.
2. Added sealed `NotificationRequest` with factory construction and fields `id`, `title`, `body`, `scheduledDateTimeUtc`, and `payloadJson`.
3. Added `NotificationFeedbackType` with `clicked`, `dismissed`, and `action`.
4. Added `NotificationFeedback` event model.
5. Added abstract `NotificationAdapter` with `schedule`, `cancel`, and `feedback`.
6. Added `FakeNotificationAdapter` backed by a broadcast `StreamController`.
7. Wired fake adapter tests into the root test wrapper.
### Verification
1. `dart pub get`: passed.
2. `dart format test/scheduler_core_test.dart packages/scheduler_notifications`: passed.
3. `cd packages/scheduler_notifications && dart analyze`: passed, no issues found.
4. `cd packages/scheduler_notifications && dart test`: passed, 2 tests.
5. `dart analyze`: passed, no issues found.
6. `dart test`: passed, 318 tests.
7. `scripts/test.sh`: not present or not executable.
---

View file

@ -0,0 +1,46 @@
# V1 Block 22 — OS-Notification Package
**Purpose**: Desktop notification implementation.
> **Note for Codex**: Follow tasks exactly; avoid exploratory calls when tasks specify names/files/tests.
## Chunk 22.1 — Desktop notification adapter
Recommended level: **HIGH**
Status: Complete on 2026-06-26.
### Tasks
1. Create package **`packages/scheduler_notifications_desktop`**.
2. Implement adapters per platform with conditional import using `dart:io` Platform.
3. For Linux use `notify-send` via `Process.run`; for macOS use `osascript`; for Windows use `win32` Toast via `windows_notification` package.
4. Implement fallback to write to stdout if unsupported.
5. Add adapter factory `DesktopNotificationAdapter.defaultInstance()`.
6. Write integration test using `FakeNotificationAdapter` mocks to assert scheduling logic; skip on CI if platform not supported.
### Acceptance criteria
1. Desktop adapter compiles on all OS; tests skip rather than fail on unsupported.
2. Adapter passes NotificationAdapter contract tests.
### Completed implementation
1. Added package `packages/scheduler_notifications_desktop` with public entry points `desktop_notifications.dart` and `scheduler_notifications_desktop.dart`.
2. Added `DesktopNotificationAdapter.defaultInstance()` and injectable backend support.
3. Added conditional export for IO vs non-IO environments.
4. Added Linux `notify-send` backend via `Process.run`.
5. Added macOS `osascript` backend via `Process.run`.
6. Added stdout/log fallback backend for unsupported platforms and Windows.
7. Added desktop adapter tests covering delegation, Linux/macOS command selection, fallback behavior, fake-adapter scheduling workflow, and default adapter construction.
8. Wired desktop adapter tests into the root test wrapper.
### Notes
1. Windows currently uses the stdout fallback. Adding `windows_notification` would pull Flutter SDK dependencies into this pure Dart package; a true Windows toast adapter should be revisited if the desktop packaging layer already depends on Flutter.
### Verification
1. `dart pub get`: passed.
2. `dart format test/scheduler_core_test.dart packages/scheduler_notifications_desktop`: passed.
3. `cd packages/scheduler_notifications_desktop && dart analyze`: passed, no issues found.
4. `cd packages/scheduler_notifications_desktop && dart test`: passed, 6 tests.
5. `dart analyze`: passed, no issues found.
6. `dart test`: passed, 324 tests.
7. `scripts/test.sh`: not present or not executable.
---

View file

@ -0,0 +1,40 @@
# V1 Block 23 — Export Abstraction Layer
**Purpose**: Define Export controller and writer interface.
> **Note for Codex**: Follow tasks exactly; avoid exploratory calls when tasks specify names/files/tests.
## Chunk 23.1 — Export controller contract
Recommended level: **XHIGH**
Status: Complete on 2026-06-26.
### Tasks
1. Add package **`packages/scheduler_export`**.
2. Define abstract class `ExportWriter` with `Future<void> begin(ExportContext)`, `Future<void> writeTask(Task)`, `Future<void> end()`, plus factory registry.
3. Define `ExportController` orchestrating repository queries and writer.
4. Provide context object with `ownerId`, `timezone`, `version`.
### Acceptance criteria
1. JSONWriter and CSVWriter stubs compile and implement interface.
2. Unit test writes small set and verifies output.
### Completed implementation
1. Added package `packages/scheduler_export` with public entry points `export.dart` and `scheduler_export.dart`.
2. Added `ExportContext` carrying `ownerId`, `timezone`, and `version`.
3. Added `ExportWriter`, `ExportWriterFactory`, and `ExportWriterRegistry` with default `json` and `csv` mappings.
4. Added `ExportController` that reads owner-scoped paged tasks through `TaskRepository` and streams them to a writer.
5. Added compiling `JsonExportWriter` and `CsvExportWriter` implementations backed by `StringSink`.
6. Added unit tests for owner-scoped JSON export, CSV output, and custom writer factory registration.
7. Wired export tests into the root test wrapper.
### Verification
1. `dart pub get`: passed.
2. `dart format test/scheduler_core_test.dart packages/scheduler_export`: passed.
3. `cd packages/scheduler_export && dart analyze`: passed, no issues found.
4. `cd packages/scheduler_export && dart test`: passed, 3 tests.
5. `dart analyze`: passed, no issues found.
6. `dart test`: passed, 327 tests.
7. `scripts/test.sh`: not present or not executable.
---

View file

@ -0,0 +1,73 @@
# V1 Block 24 — Backup & Export Library Package
**Purpose**: Encrypted backup and readable exports.
> **Note for Codex**: Follow tasks exactly; avoid exploratory calls when tasks specify names/files/tests.
## Chunk 24.1 — Encrypted backup implementation
Recommended level: **HIGH**
Status: Complete on 2026-06-26.
### Tasks
1. Within `packages/scheduler_backup`, implement function `Future<File> createEncryptedBackup({required String passphrase})` which copies SQLite file then AES-256 encrypts with `encrypt` package.
2. Implement `Future<void> restoreEncryptedBackup(File backup, String passphrase)`.
3. Store backup in `~/ADHD_Scheduler/backups/yyyymmdd_hhmm.db.enc`.
4. Add CLI script `bin/backup.dart` for manual backups.
### Acceptance criteria
1. Roundtrip backup/restore integration test passes using temp directory.
2. Wrong passphrase throws `BackupDecryptionException`.
### Completed implementation
1. Added package `packages/scheduler_backup` with public entry points `backup.dart` and `scheduler_backup.dart`.
2. Added `createEncryptedBackup({required String passphrase})` with optional test-path overrides.
3. Added `restoreEncryptedBackup(File backup, String passphrase)` with optional target-file override.
4. Added default source path `~/ADHD_Scheduler/scheduler.sqlite` and default backup directory `~/ADHD_Scheduler/backups/`.
5. Added backup naming as `yyyymmdd_hhmm.db.enc`, with collision suffixes when needed.
6. Added authenticated encrypted backup envelope using PBKDF2-HMAC-SHA256 with 200,000 iterations and AES-256-GCM.
7. Added `BackupDecryptionException` and `BackupException`.
8. Added CLI script `bin/backup.dart` for manual encrypted backups.
9. Added temp-directory round-trip and wrong-passphrase tests.
### Verification
1. `dart pub get`: passed.
2. `dart format .` in `packages/scheduler_backup`: passed.
3. `cd packages/scheduler_backup && dart analyze`: passed, no issues found.
4. `cd packages/scheduler_backup && dart test`: passed, 2 tests.
5. `dart analyze`: passed, no issues found.
6. `dart test`: passed after Chunk 24.2, 332 tests.
7. `scripts/test.sh`: not present or not executable.
---
## Chunk 24.2 — Readable export writers
Recommended level: **HIGH**
Status: Complete on 2026-06-26.
### Tasks
1. Implement `JsonExportWriter` and `CsvExportWriter` in `scheduler_export_json` package.
2. Hook into `ExportController` factory mapping.
### Acceptance criteria
1. Export command `bin/export.dart --json` outputs valid JSON verified by jsonDecode.
### Completed implementation
1. Added package `packages/scheduler_export_json` with public entry points `export_json.dart` and `scheduler_export_json.dart`.
2. Added concrete `JsonExportWriter` and `CsvExportWriter` implementations.
3. Added `readableExportWriterRegistry()` that maps `json` and `csv` writer factories for `ExportController`.
4. Added CLI script `bin/export.dart` supporting `--json`, `--csv`, `--owner`, and `--timezone`.
5. Added tests for JSON export, CSV quoting, and `bin/export.dart --json` output validated with `jsonDecode`.
6. Wired export-json tests into the root test wrapper.
### Verification
1. `dart pub get`: passed.
2. `dart format test/scheduler_core_test.dart packages/scheduler_export_json`: passed.
3. `cd packages/scheduler_export_json && dart analyze`: passed, no issues found.
4. `cd packages/scheduler_export_json && dart test`: passed, 3 tests.
5. `dart analyze`: passed, no issues found.
6. `dart test`: passed, 332 tests.
7. `scripts/test.sh`: not present or not executable.
---

View file

@ -0,0 +1,37 @@
# V1 Block 25 — Scheduler Integration Tests
**Purpose**: Endtoend tests.
> **Note for Codex**: Follow tasks exactly; avoid exploratory calls when tasks specify names/files/tests.
## Chunk 25.1 — Integration test harness
Recommended level: **HIGH**
Status: Complete on 2026-06-26.
### Tasks
1. Add test file `integration/scheduler_flow_test.dart` in `packages/scheduler_integration_tests`.
2. Spin up InMemory repos, schedule engine, fake notification adapter.
3. Create tasks, invoke scheduler, assert placements, save via SQLite adapter, reload and assert persistence.
### Acceptance criteria
1. Test passes on CI in < 2s runtime.
### Completed implementation
1. Added package `packages/scheduler_integration_tests`.
2. Added required integration test file `integration/scheduler_flow_test.dart`.
3. Added test wrapper `test/scheduler_flow_test.dart` so package-level `dart test` runs the integration flow.
4. Integration flow seeds `InMemoryTaskRepository`, invokes `SchedulingEngine.insertBacklogTaskIntoNextAvailableSlot`, asserts task placement, schedules through `FakeNotificationAdapter`, saves through `SqliteTaskRepository`, reloads, and asserts persisted schedule/status.
5. Added an in-test runtime guard asserting the flow completes in under 2 seconds.
6. Wired integration test into the root test wrapper.
### Verification
1. `dart pub get`: passed.
2. `dart format test/scheduler_core_test.dart packages/scheduler_integration_tests`: passed.
3. `cd packages/scheduler_integration_tests && dart analyze`: passed, no issues found.
4. `cd packages/scheduler_integration_tests && dart test`: passed, 1 test.
5. `dart analyze`: passed, no issues found.
6. `dart test`: passed, 333 tests.
7. `scripts/test.sh`: not present or not executable.
---

View file

@ -0,0 +1,37 @@
# V1 Block 26 — Verification & Contract Test Suite
**Purpose**: Repository contract tests.
> **Note for Codex**: Follow tasks exactly; avoid exploratory calls when tasks specify names/files/tests.
## Chunk 26.1 — Coverage & adapter verification
Recommended level: **HIGH**
Status: Complete on 2026-06-26.
### Tasks
1. Extend repo conformance tests to compute coverage report using `dart run coverage`.
2. Fail CI if coverage < 80%.
3. Ensure desktop notification adapter passes mock contract tests.
### Acceptance criteria
1. Coverage report generated in CI artifacts; threshold met.
### Completed implementation
1. Added root dev dependency `coverage`.
2. Added executable `scripts/test.sh` running `dart analyze`, `dart test`, `dart run coverage:test_with_coverage`, and an 80% coverage threshold check.
3. Added `tool/check_coverage.dart` to parse `coverage/lcov.info`, scope coverage to package `lib/` code, exclude generated `.g.dart`, and fail below threshold.
4. Added shared notification adapter contract test helper `packages/scheduler_notifications/test/notification_adapter_contract.dart`.
5. Ran the contract against `FakeNotificationAdapter`.
6. Ran the same contract against `DesktopNotificationAdapter` using a recording backend.
7. Normalized desktop adapter cancellation ids before passing them to the backend.
### Verification
1. `dart pub get`: passed.
2. `dart format ...`: passed for touched Dart files.
3. `cd packages/scheduler_notifications && dart analyze && dart test`: passed, 4 tests.
4. `cd packages/scheduler_notifications_desktop && dart analyze && dart test`: passed, 8 tests.
5. `scripts/test.sh`: passed.
6. Coverage result: 83.31% package `lib/` line coverage, above the 80% threshold.
---

View file

@ -0,0 +1,69 @@
# V1 Block 27 — Deployment & Dev Experience
**Purpose**: Dev scripts and packaging.
> **Note for Codex**: Follow tasks exactly; avoid exploratory calls when tasks specify names/files/tests.
## Chunk 27.1 — Dev/test scripts & CI
Recommended level: **HIGH**
Status: Complete on 2026-06-26.
### Tasks
1. Create `scripts/dev.dart` which executes `dart run build_runner watch` and launches Flutter desktop with hot reload pointing to local SQLite file.
2. Create `scripts/test.dart` running `dart pub global activate coverage`, `dart test --coverage=coverage`, then combine reports.
3. GitHub Actions YAML to run tests matrix {ubuntu-latest, windows-latest, macos-latest}.
### Acceptance criteria
1. Running `dart run scripts/dev.dart` starts app and prints sqlite path.
2. CI green on all platforms.
### Completed implementation
1. Added `scripts/dev.dart` that prints the SQLite path, starts `dart run build_runner watch --delete-conflicting-outputs`, and launches `flutter run` for the current/selected desktop device with `SCHEDULER_SQLITE_PATH`.
2. Added `scripts/test.dart` that runs `dart pub global activate coverage`, `dart test --coverage=coverage`, combines LCOV with `coverage:format_coverage`, and enforces the 80% threshold.
3. Updated `scripts/test.sh` to run analyzer plus `scripts/test.dart`.
4. Added GitHub Actions workflow `.github/workflows/ci.yml` with test matrix `ubuntu-latest`, `windows-latest`, and `macos-latest`.
5. Added `scripts/bootstrap_dev.sh` and `scripts/dev.sh` wrappers so the
agent rule file has concrete shell entry points for setup and development.
### Verification
1. `dart pub get`: passed.
2. `dart format scripts/dev.dart scripts/test.dart`: passed.
3. `dart analyze`: passed, no issues found.
4. `dart run scripts/test.dart`: passed, coverage 83.27%.
5. `bash -n scripts/bootstrap_dev.sh scripts/dev.sh`: passed.
6. `scripts/test.sh`: passed.
7. `dart run scripts/dev.dart` and `scripts/dev.sh`: not executed locally because they launch a long-running Flutter desktop session and require the Flutter app/toolchain.
---
## Chunk 27.2 — Packaging scripts
Recommended level: **HIGH**
Status: Complete on 2026-06-26.
### Tasks
1. Add `scripts/build.dart` building Flutter macOS .app, Windows .exe + msix, Linux AppImage.
2. Document prerequisites in README.
### Acceptance criteria
1. Artifacts upload step in CI produces release binaries.
### Completed implementation
1. Added `scripts/build.dart` with platform targets `current`, `macos`, `windows`, and `linux`.
2. macOS target runs `flutter build macos --release` and copies `.app` artifacts.
3. Windows target runs `flutter build windows --release`, copies the release bundle, and runs `dart run msix:create`.
4. Linux target runs `flutter build linux --release` and `appimage-builder --recipe AppImageBuilder.yml --skip-test`.
5. Added tagged CI packaging job with matrix `linux`, `windows`, and `macos`, plus artifact upload from `build/releases/`.
6. Replaced README with workspace test, development, packaging, and prerequisite instructions.
7. Added `scripts/package_release.sh` wrapper for the release packaging runner
named in the agent rule file.
### Verification
1. `dart format scripts/build.dart`: passed.
2. `dart analyze`: passed, no issues found.
3. `bash -n scripts/package_release.sh`: passed.
4. `scripts/test.sh`: passed.
5. Packaging commands were not executed locally because they require Flutter desktop toolchains, platform-specific packaging tools, and app packaging config.
---

View file

@ -0,0 +1,36 @@
# V1 Block 28 — Projectwide Documentation Sweep
**Purpose**: JavaDoc-style commenting.
> **Note for Codex**: Follow tasks exactly; avoid exploratory calls when tasks specify names/files/tests.
## Chunk 28.1 — Documentation sweep
Recommended level: **HIGH**
Status: Complete on 2026-06-26.
### Tasks
1. Enable `dart doc` in CI; fail build if undocumented public members.
2. Add docs to all public symbols across packages using tripleslash style.
3. Document build scripts and CI YAML with comments at top describing purpose.
### Acceptance criteria
1. `dart doc` generates site without warnings.
2. CI passes doc coverage gate.
### Completed implementation
1. Added `tool/check_docs.dart` to generate docs for every package with a `lib/` directory under `doc/api/packages/`.
2. The doc gate fails on any `dart doc` warning or nonzero doc generation exit.
3. Added doc generation to `scripts/test.dart`, so `scripts/test.sh` and CI run the docs gate.
4. Updated CI artifact upload to include generated docs under `doc/api/`.
5. Added `.gitignore` entry for generated `doc/api/` output.
6. Fixed unresolved documentation references in `scheduler_core`, `scheduler_export`, and `scheduler_export_json`.
7. Added top-of-file purpose comments to `scripts/dev.dart`, `scripts/test.dart`, `scripts/build.dart`, `tool/check_coverage.dart`, `tool/check_docs.dart`, and `.github/workflows/ci.yml`.
### Verification
1. `dart run tool/check_docs.dart`: passed; docs generated for all public-library packages with 0 warnings and 0 errors.
2. `dart analyze`: passed, no issues found.
3. `scripts/test.sh`: passed.
4. Coverage result in final gate: 83.27% package `lib/` line coverage, above the 80% threshold.
---

View file

@ -0,0 +1,131 @@
# V1 Block 29 — Flutter UI Foundation
**Purpose**: Restart the V1 Flutter UI foundation after the SQLite-first backend
refresh, without moving scheduling or persistence rules into widgets.
> **Note for Codex**: Keep the scheduler core Flutter-free. UI code may depend
> on public package APIs and read models only.
## Chunk 29.1 — Flutter app shell and in-memory composition
Recommended level: **HIGH**
Status: Complete on 2026-06-26.
### Tasks
1. Add `apps/focus_flow_flutter` as a Flutter application outside the root Dart
workspace for now.
2. Wire a minimal in-memory composition root using public scheduler packages.
3. Render provisional Today and Backlog shells from application/read-model data.
4. Add app startup, theme/token placeholders, and a widget test harness.
5. Document UI-specific analyze/test commands without changing `scripts/test.sh`
until Flutter CI gating is intentionally added.
### Acceptance criteria
1. `cd apps/focus_flow_flutter && flutter analyze` passes.
2. `cd apps/focus_flow_flutter && flutter test` passes.
3. Core packages remain Flutter-free and `scripts/test.sh` still passes.
4. UI code does not import Drift, SQLite, platform notification APIs, or core
`lib/src/` paths directly.
5. Today and Backlog screens render from read-model objects, not duplicated
scheduling rules.
BREAKPOINT: Stop here. Confirm `high` before adding navigation/controllers and
component contracts.
### Completed implementation
1. Added `apps/focus_flow_flutter` as a Flutter desktop app outside the root
Dart workspace.
2. Added a local path dependency on `packages/scheduler_core`.
3. Replaced the starter counter template with `FocusFlowApp`, a seeded
`DemoSchedulerComposition`, and Today/Backlog tabs rendered from
`TodayState` and `BacklogQueryResult`.
4. Added a widget test that verifies Today and Backlog read-model data renders
through the Flutter shell.
5. Documented app-local Flutter analyze/test commands in the README.
### Verification
1. `flutter pub get` in `apps/focus_flow_flutter`: passed.
2. `dart format apps/focus_flow_flutter/lib/main.dart apps/focus_flow_flutter/test/widget_test.dart`: passed.
3. `cd apps/focus_flow_flutter && flutter analyze`: passed, no issues found.
4. `cd apps/focus_flow_flutter && flutter test`: passed, 1 widget test.
---
## Chunk 29.2 — UI controllers and component contracts
Recommended level: **HIGH**
Status: Complete on 2026-06-26.
### Tasks
1. Split seeded composition, read controllers, and widgets into focused files
under `apps/focus_flow_flutter/lib/`.
2. Add controller states for loading, empty, typed failure, and retry paths for
Today and Backlog.
3. Add provisional component contracts for timeline rows, compact panels,
backlog rows, notice banners, and staleness markers.
4. Centralize token-to-visual mapping for project color, task type background,
reward icon, and difficulty icon.
5. Add widget tests for compact rendering, backlog empty state, and typed failure
state.
### Acceptance criteria
1. `cd apps/focus_flow_flutter && flutter analyze` passes.
2. `cd apps/focus_flow_flutter && flutter test` passes.
3. `scripts/test.sh` still passes.
4. Widgets import app controllers/read models, not persistence adapters or
scheduler internals.
5. Component contracts satisfy the remaining MVP-AC-05 token-mapping gap without
locking final visual design.
BREAKPOINT: Stop here. Confirm `high` before adding command flows and a vertical
quick-capture smoke slice.
### Completed implementation
1. Split `lib/main.dart` into app shell, seeded composition, read controllers,
visual-token mapping, and focused widgets under `apps/focus_flow_flutter/lib/`.
2. Added `UiReadController<T>` and `ApplicationReadController<T>` with loading,
data, empty, typed-failure, and retry states.
3. Added provisional component contracts for compact panels, timeline rows,
backlog rows, notice banners, staleness markers, empty state, and failure
state.
4. Centralized project color, task-type background, reward icon, difficulty
icon, and staleness-marker visual mapping in `SchedulerVisualTokens`.
5. Added widget tests for seeded Today/Backlog rendering, compact rendering,
Backlog empty state, and typed failure retry.
### Verification
1. `dart format lib test` in `apps/focus_flow_flutter`: passed.
2. `cd apps/focus_flow_flutter && flutter analyze`: passed, no issues found.
3. `cd apps/focus_flow_flutter && flutter test`: passed, 4 widget tests.
4. Forbidden-import scan for app `lib/` and `test/`: no persistence adapters,
scheduler `src/` imports, Drift, or SQLite imports found.
---
## Chunk 29.3 — Command flows and vertical quick-capture slice
Recommended level: **HIGH**
Status: Open.
### Tasks
1. Add UI controllers for quick capture, schedule-from-backlog, and mark-done
commands using public application command use cases.
2. Add forms/actions for title-only quick capture, duration entry, and done.
3. Refresh Today and Backlog controllers after successful commands.
4. Add typed conflict/failure states for command attempts.
5. Add a widget/integration smoke test for quick capture → Backlog → schedule →
Today → done using in-memory composition.
### Acceptance criteria
1. `cd apps/focus_flow_flutter && flutter analyze` passes.
2. `cd apps/focus_flow_flutter && flutter test` passes.
3. `scripts/test.sh` still passes.
4. Widgets continue to call public app controllers/use cases only.
5. No scheduling rules are implemented in Flutter widgets.
BREAKPOINT: Stop here. Confirm `high` before adding persistent SQLite-backed UI
composition or broader screen expansion.
---
---

View file

@ -7,7 +7,7 @@ Starting commit: `775c2ed406f03a73a9b0ca621dea5b4482468616`
Public import: Public import:
```dart ```dart
import 'package:adhd_scheduler_core/scheduler_core.dart'; import 'package:scheduler_core/scheduler_core.dart';
``` ```
The public library entry point is `lib/scheduler_core.dart`. It exports the The public library entry point is `lib/scheduler_core.dart`. It exports the
@ -398,23 +398,185 @@ Chunk 15.5 intentionally changed the public API:
`PersistencePayloadGuard`. `PersistencePayloadGuard`.
- Added repository integrity failure codes for invalid revisions and owner - Added repository integrity failure codes for invalid revisions and owner
mismatches. mismatches.
- Added `V1_BLOCK_16_REPOSITORY_ADAPTER_CHECKLIST.md` for MongoDB adapter - Added `V1_BLOCK_16_REPOSITORY_ADAPTER_CHECKLIST.md` for the former document
implementation prerequisites. adapter implementation prerequisites, archived after the SQLite-first pivot.
Chunk 19.1 intentionally changed the public/package API:
- Rehomed the core library under `packages/scheduler_core` with public import
`package:scheduler_core/scheduler_core.dart`.
- Added shared repository value objects exported from `scheduler_core`:
`OwnerId`, `Revision`, `PageRequest`, and `Page<T>`.
- Added `packages/scheduler_persistence` with domain-only repository
interfaces for tasks, projects, locked blocks, settings, and schedule
snapshots.
- Added `RepositoryFailure` variants, sealed `Either<L, R>`, and
`RepoResult<T>` for expected repository success/failure paths.
Chunk 19.2 intentionally changed the public/package API:
- Added `packages/scheduler_persistence_memory` with
`InMemoryTaskRepository`, `InMemoryProjectRepository`,
`InMemoryLockedBlockRepository`, `InMemorySettingsRepository`, and
`InMemoryScheduleSnapshotRepository`.
- Added package entry points
`package:scheduler_persistence_memory/persistence_memory.dart` and
`package:scheduler_persistence_memory/memory.dart`.
- Added shared adapter conformance test surface
`runRepositoryComplianceTests()` and `RepositoryComplianceFactories` under
`packages/scheduler_persistence/test/repo_conformance.dart`.
Chunk 20.1 intentionally changed the public/package API:
- Added `packages/scheduler_persistence_sqlite` with Drift-backed schema
package entry point `package:scheduler_persistence_sqlite/sqlite.dart`.
- Added `SchedulerDb` with schema version 1 and generated Drift table/data
classes for `tasks`, `projects`, `locked_blocks`, `locked_overrides`,
`settings`, and `snapshots`.
- Added generated accessor classes: `TaskDao`, `ProjectDao`, `LockedBlockDao`,
`SettingsDao`, and `SnapshotDao`.
Chunk 20.2 intentionally changed the public/package API:
- Added SQLite repository implementations exported from
`package:scheduler_persistence_sqlite/sqlite.dart`:
`SqliteTaskRepository`, `SqliteProjectRepository`,
`SqliteLockedBlockRepository`, `SqliteSettingsRepository`, and
`SqliteScheduleSnapshotRepository`.
- Added SQLite adapter conformance and write-latency tests under
`packages/scheduler_persistence_sqlite/test/`.
Chunk 21.1 intentionally changed the public/package API:
- Added `packages/scheduler_notifications` with package entry points
`package:scheduler_notifications/notifications.dart` and
`package:scheduler_notifications/scheduler_notifications.dart`.
- Added notification abstraction types: `NotificationRequest`,
`NotificationFeedbackType`, `NotificationFeedback`, `NotificationAdapter`,
and `FakeNotificationAdapter`.
Chunk 22.1 intentionally changed the public/package API:
- Added `packages/scheduler_notifications_desktop` with package entry points
`package:scheduler_notifications_desktop/desktop_notifications.dart` and
`package:scheduler_notifications_desktop/scheduler_notifications_desktop.dart`.
- Added desktop notification types: `DesktopNotificationPlatform`,
`DesktopNotificationBackend`, `DesktopNotificationAdapter`,
`StdoutNotificationBackend`, and the IO backends for Linux/macOS.
Chunk 23.1 intentionally changed the public/package API:
- Added `packages/scheduler_export` with package entry points
`package:scheduler_export/export.dart` and
`package:scheduler_export/scheduler_export.dart`.
- Added readable export contracts and orchestration types: `ExportContext`,
`ExportWriter`, `ExportWriterFactory`, `ExportWriterRegistry`,
`ExportController`, `ExportException`, and `ExportRepositoryException`.
- Added sink-backed writer implementations `JsonExportWriter` and
`CsvExportWriter`.
Chunk 24.1 intentionally changed the public/package API:
- Added `packages/scheduler_backup` with package entry points
`package:scheduler_backup/backup.dart` and
`package:scheduler_backup/scheduler_backup.dart`.
- Added encrypted backup functions `createEncryptedBackup`,
`restoreEncryptedBackup`, `defaultSchedulerSqliteFile`, and
`defaultSchedulerBackupDirectory`.
- Added backup constants `defaultSchedulerDirectoryName`,
`defaultSchedulerDatabaseFileName`, and
`defaultSchedulerBackupDirectoryName`.
- Added backup exceptions `BackupException` and
`BackupDecryptionException`.
Chunk 24.2 intentionally changed the public/package API:
- Added `packages/scheduler_export_json` with package entry points
`package:scheduler_export_json/export_json.dart` and
`package:scheduler_export_json/scheduler_export_json.dart`.
- Added readable writer factory `readableExportWriterRegistry`.
- Added concrete readable export writers `JsonExportWriter` and
`CsvExportWriter`.
- Added CLI export command `bin/export.dart`.
Chunk 25.1 intentionally changed the workspace test surface:
- Added test-only package `packages/scheduler_integration_tests`.
- Added integration harness `integration/scheduler_flow_test.dart` covering
scheduler placement, fake notification scheduling, SQLite save, and reload.
Chunk 26.1 intentionally changed the verification surface:
- Added executable `scripts/test.sh` as the required analyze/test/coverage gate.
- Added `tool/check_coverage.dart` for LCOV threshold enforcement.
- Added shared notification adapter contract test helper
`packages/scheduler_notifications/test/notification_adapter_contract.dart`.
- Desktop notification adapter cancellation now normalizes ids before backend
cancellation.
Chunk 27.1 intentionally changed the dev/CI surface:
- Added `scripts/dev.dart` for local build-runner watch plus Flutter desktop
launch with a SQLite path define.
- Added `scripts/test.dart` for cross-platform coverage collection and LCOV
combination.
- Added `scripts/bootstrap_dev.sh` and `scripts/dev.sh` shell entry points for
agent-compatible setup and desktop development.
- Added GitHub Actions test matrix in `.github/workflows/ci.yml`.
Chunk 27.2 intentionally changed the packaging surface:
- Added `scripts/build.dart` for platform-specific Flutter desktop packaging.
- Added `scripts/package_release.sh` shell entry point for release packaging.
- Added tagged CI release artifact upload steps.
- Replaced README content with workspace test, dev, packaging, and prerequisite
instructions.
Chunk 28.1 intentionally changed the documentation verification surface:
- Added `tool/check_docs.dart` to generate package docs and fail on warnings.
- Added generated docs upload under the CI artifact step.
- Added generated `doc/api/` output to `.gitignore`.
- Fixed unresolved public API documentation references in core and export
packages.
Chunk 29.1 intentionally changed the UI surface:
- Added provisional Flutter app `apps/focus_flow_flutter` outside the root Dart
workspace.
- Added app-local path dependency on `packages/scheduler_core`.
- Added `FocusFlowApp`, `DemoSchedulerComposition`, `SchedulerHome`,
`TodayPane`, and `BacklogPane` in the Flutter app.
- Added widget test coverage for rendering Today and Backlog read-model data.
Chunk 29.2 intentionally changed the UI surface:
- Split the Flutter shell into `app.dart`, `composition/`, `controllers/`,
`theme/`, and `widgets/`.
- Added `UiReadController<T>`, `ApplicationReadController<T>`, and
`SchedulerReadState<T>` variants for loading, data, empty, and typed failure
states.
- Added `SchedulerVisualTokens` for centralized project/task/reward/difficulty
and staleness visual mappings.
- Added component widgets for Today, Backlog, compact panels, timeline rows,
backlog rows, notice banners, empty states, and failure retry states.
- Expanded Flutter widget coverage to 4 tests.
## Repository contracts ## Repository contracts
The current repository surface is pure Dart and in-memory only: The current repository surface is pure Dart and adapter-backed:
- Task repository behavior is represented by `InMemoryTaskRepository`. - Core legacy repository fakes remain in `scheduler_core` for existing domain
- Project repository behavior is represented by `InMemoryProjectRepository`. services and tests.
- Locked block repository behavior is represented by - The Block 19 repository abstraction lives in `scheduler_persistence`.
`InMemoryLockedBlockRepository`. - The Block 19 conformance-tested memory adapter lives in
- Snapshot repository behavior is represented by `scheduler_persistence_memory`.
`InMemorySchedulingSnapshotRepository`. - The Block 20 conformance-tested SQLite adapter lives in
`scheduler_persistence_sqlite`.
- Application transaction behavior is represented by - Application transaction behavior is represented by
`InMemoryApplicationUnitOfWork`. `InMemoryApplicationUnitOfWork`.
- Application read-query behavior uses `ApplicationUnitOfWork.read`, which - Application read-query behavior uses `ApplicationUnitOfWork.read`, which
stages repository access without committing operation records. stages repository access without committing operation records.
Future MongoDB adapter work must remain behind repository interfaces and must Future SQLite adapter work must remain behind repository interfaces and must not
not import MongoDB APIs into the scheduling core. import storage APIs into the scheduling core.

View file

@ -99,19 +99,19 @@ Status values:
| ID | Acceptance criterion | Production API surface | Representative tests | Status | Active-plan reference or issue | | ID | Acceptance criterion | Production API surface | Representative tests | Status | Active-plan reference or issue |
|---|---|---|---|---|---| |---|---|---|---|---|---|
| MVP-AC-01 | Create a task through quick capture with only a title. | `V1ApplicationCommandUseCases.quickCaptureToBacklog`, `Task.quickCapture`, `QuickCaptureRequest`, `QuickCaptureService.capture` | `test/scheduling_engine_test.dart`, `test/edge_case_regression_test.dart`, `test/application_commands_test.dart` | complete | Chunk 14.3 adds the atomic application command boundary. | | MVP-AC-01 | Create a task through quick capture with only a title. | `V1ApplicationCommandUseCases.quickCaptureToBacklog`, `Task.quickCapture`, `QuickCaptureRequest`, `QuickCaptureService.capture` | `test/scheduling_engine_test.dart`, `test/edge_case_regression_test.dart`, `test/application_commands_test.dart` | complete | Chunk 14.3 adds the atomic application command boundary. |
| MVP-AC-02 | Store quick-capture tasks in Backlog with neutral defaults. | `Task.quickCapture`, `QuickCaptureService.capture`, `TaskStatus.backlog`, `PriorityLevel.medium`, `RewardLevel.notSet`, inbox project default | `test/scheduling_engine_test.dart`, `test/edge_case_regression_test.dart` | complete | Backlog-entered timestamp remains incomplete; see Blocks 11 and 15. | | MVP-AC-02 | Store quick-capture tasks in Backlog with neutral defaults. | `Task.quickCapture`, `QuickCaptureService.capture`, `TaskStatus.backlog`, `PriorityLevel.medium`, `RewardLevel.notSet`, inbox project default, `TaskDocumentFields.backlogEnteredAt` | `test/scheduling_engine_test.dart`, `test/edge_case_regression_test.dart`, `test/document_mapping_test.dart`, `packages/scheduler_persistence_sqlite/test/sqlite_repository_conformance_test.dart` | complete | Backlog-entered timestamp fields are covered by document mapping and SQLite persistence. |
| MVP-AC-03 | Optionally schedule a quick-capture task into the next available slot after entering duration. | `V1ApplicationCommandUseCases.quickCaptureToNextAvailableSlot`, `QuickCaptureRequest.scheduleImmediately`, `QuickCaptureService.capture`, `SchedulingEngine.insertBacklogTaskIntoNextAvailableSlot` | `test/scheduling_engine_test.dart`, `test/edge_case_regression_test.dart`, `test/scheduling_invariants_test.dart`, `test/application_commands_test.dart` | complete | Block 12 covers scheduling rules; Chunk 14.3 adds the atomic application command boundary. | | MVP-AC-03 | Optionally schedule a quick-capture task into the next available slot after entering duration. | `V1ApplicationCommandUseCases.quickCaptureToNextAvailableSlot`, `QuickCaptureRequest.scheduleImmediately`, `QuickCaptureService.capture`, `SchedulingEngine.insertBacklogTaskIntoNextAvailableSlot` | `test/scheduling_engine_test.dart`, `test/edge_case_regression_test.dart`, `test/scheduling_invariants_test.dart`, `test/application_commands_test.dart` | complete | Block 12 covers scheduling rules; Chunk 14.3 adds the atomic application command boundary. |
| MVP-AC-04 | Create recurring hidden locked blocks and one-day overrides. | `LockedBlock`, `LockedBlockRecurrence.weekly`, `LockedBlockOverride.remove`, `LockedBlockOverride.replace`, `LockedBlockOverride.add`, `expandLockedBlocksForDay` | `test/scheduling_engine_test.dart`, `test/timeline_state_test.dart`, `test/edge_case_regression_test.dart` | complete | Date-only/time-zone hardening remains in Chunk 11.4 and Block 15. | | MVP-AC-04 | Create recurring hidden locked blocks and one-day overrides. | `LockedBlock`, `LockedBlockRecurrence.weekly`, `LockedBlockOverride.remove`, `LockedBlockOverride.replace`, `LockedBlockOverride.add`, `expandLockedBlocksForDay` | `test/scheduling_engine_test.dart`, `test/timeline_state_test.dart`, `test/edge_case_regression_test.dart` | complete | Date-only/time-zone hardening remains in Chunk 11.4 and Block 15. |
| MVP-AC-05 | Render Today as a timeline with project border, task-type background, task name, reward icon, and difficulty icon. | `GetTodayStateQuery`, `TodayState`, `TodayTimelineItem`, `TimelineItemMapper`, `TimelineItem`, timeline token enums | `test/timeline_state_test.dart`, `test/today_state_test.dart` | incomplete | Backend Today read model and tokens are complete; actual Flutter rendering is Block 18. | | MVP-AC-05 | Render Today as a timeline with project border, task-type background, task name, reward icon, and difficulty icon. | `GetTodayStateQuery`, `TodayState`, `TodayTimelineItem`, `TimelineItemMapper`, `TimelineItem`, timeline token enums, `TodayPane`, `TimelineRow`, `SchedulerVisualTokens` | `test/timeline_state_test.dart`, `test/today_state_test.dart`, `apps/focus_flow_flutter/test/widget_test.dart` | complete | Backend Today read model and provisional Flutter token-driven rendering are complete through Block 29.2; final visual design remains intentionally open. |
| MVP-AC-06 | Use compact Today mode manually. | `GetTodayStateQuery`, `TodayCompactState`, `TimelineItemMapper.compactStateForTasks`, `CompactTimelineState` | `test/timeline_state_test.dart`, `test/today_state_test.dart` | complete | Complete at backend/read-model level, including current/next deduplication; Flutter UI remains Block 18. | | MVP-AC-06 | Use compact Today mode manually. | `GetTodayStateQuery`, `TodayCompactState`, `TimelineItemMapper.compactStateForTasks`, `CompactTimelineState`, `CompactPanel` | `test/timeline_state_test.dart`, `test/today_state_test.dart`, `test/application_management_test.dart`, `packages/scheduler_persistence_sqlite/test/sqlite_repository_conformance_test.dart`, `apps/focus_flow_flutter/test/widget_test.dart` | complete | Complete at backend/read-model and settings-persistence level, including current/next deduplication; Block 29.2 renders compact state through a component contract, while a user-facing toggle remains a later UI command/control task. |
| MVP-AC-07 | Push flexible tasks to next available slot, tomorrow, or backlog. | `V1ApplicationCommandUseCases.pushFlexibleToNextAvailableSlot`, `V1ApplicationCommandUseCases.pushFlexibleToTomorrowTopOfQueue`, `V1ApplicationCommandUseCases.moveFlexibleToBacklog`, `FlexibleTaskActionService.applyPushDestination`, `SchedulingEngine` push methods, `TaskActivityCode` | `test/scheduling_engine_test.dart`, `test/required_task_actions_test.dart`, `test/task_lifecycle_test.dart`, `test/application_commands_test.dart` | complete | Chunk 14.3 adds atomic application commands with persisted activities and operation records. | | MVP-AC-07 | Push flexible tasks to next available slot, tomorrow, or backlog. | `V1ApplicationCommandUseCases.pushFlexibleToNextAvailableSlot`, `V1ApplicationCommandUseCases.pushFlexibleToTomorrowTopOfQueue`, `V1ApplicationCommandUseCases.moveFlexibleToBacklog`, `FlexibleTaskActionService.applyPushDestination`, `SchedulingEngine` push methods, `TaskActivityCode` | `test/scheduling_engine_test.dart`, `test/required_task_actions_test.dart`, `test/task_lifecycle_test.dart`, `test/application_commands_test.dart` | complete | Chunk 14.3 adds atomic application commands with persisted activities and operation records. |
| MVP-AC-08 | Move backlog items into the soonest flexible slot where they fit and shift later flexible tasks. | `V1ApplicationCommandUseCases.scheduleBacklogItemToNextAvailableSlot`, `SchedulingEngine.insertBacklogTaskIntoNextAvailableSlot` | `test/scheduling_engine_test.dart`, `test/edge_case_regression_test.dart`, `test/occupancy_policy_test.dart`, `test/free_slots_test.dart`, `test/scheduling_invariants_test.dart`, `test/application_commands_test.dart` | complete | Block 12 covers scheduling rules; Chunk 14.3 adds the atomic application command boundary. | | MVP-AC-08 | Move backlog items into the soonest flexible slot where they fit and shift later flexible tasks. | `V1ApplicationCommandUseCases.scheduleBacklogItemToNextAvailableSlot`, `SchedulingEngine.insertBacklogTaskIntoNextAvailableSlot` | `test/scheduling_engine_test.dart`, `test/edge_case_regression_test.dart`, `test/occupancy_policy_test.dart`, `test/free_slots_test.dart`, `test/scheduling_invariants_test.dart`, `test/application_commands_test.dart` | complete | Block 12 covers scheduling rules; Chunk 14.3 adds the atomic application command boundary. |
| MVP-AC-09 | Automatically roll unfinished flexible tasks to tomorrow/top of queue with a small notice. | `SchedulingEngine.rolloverUnfinishedFlexibleTasks`, `SchedulingNotice`, `TodayPendingNotice`, `GetTodayStateQuery` | `test/scheduling_engine_test.dart`, `test/edge_case_regression_test.dart`, `test/scheduling_invariants_test.dart`, `test/today_state_test.dart` | incomplete | Domain movement, structured rollover notices, and Today pending-notice read model exist; explicit durable app-open rollover orchestration remains in Chunk 14.5. | | MVP-AC-09 | Automatically roll unfinished flexible tasks to tomorrow/top of queue with a small notice. | `SchedulingEngine.rolloverUnfinishedFlexibleTasks`, `SchedulingNotice`, `TodayPendingNotice`, `GetTodayStateQuery`, `V1AppOpenRecoveryUseCases` | `test/scheduling_engine_test.dart`, `test/edge_case_regression_test.dart`, `test/scheduling_invariants_test.dart`, `test/today_state_test.dart`, `test/application_recovery_test.dart` | complete | Domain movement, durable app-open recovery orchestration, scheduling snapshots, and Today pending-notice lifecycle are complete. |
| MVP-AC-10 | Log unplanned completed tasks and push overlapping flexible tasks normally. | `V1ApplicationCommandUseCases.logSurpriseTask`, `SurpriseTaskLogRequest`, `SurpriseTaskLogService.log`, `SurpriseTaskLogResult`, `Task.completedAt` | `test/surprise_task_logging_test.dart`, `test/scheduling_invariants_test.dart`, `test/task_lifecycle_test.dart`, `test/application_commands_test.dart` | complete | Chunk 14.3 adds atomic surprise logging use case with flexible repair, activity persistence, project stats, and operation records. | | MVP-AC-10 | Log unplanned completed tasks and push overlapping flexible tasks normally. | `V1ApplicationCommandUseCases.logSurpriseTask`, `SurpriseTaskLogRequest`, `SurpriseTaskLogService.log`, `SurpriseTaskLogResult`, `Task.completedAt` | `test/surprise_task_logging_test.dart`, `test/scheduling_invariants_test.dart`, `test/task_lifecycle_test.dart`, `test/application_commands_test.dart` | complete | Chunk 14.3 adds atomic surprise logging use case with flexible repair, activity persistence, project stats, and operation records. |
| MVP-AC-11 | Break a large task into child tasks with row-level priority, reward, and duration. | `V1ApplicationCommandUseCases.breakUpTask`, `ApplicationChildTaskDraft`, `ChildTaskEntry`, `ChildTaskBreakUpRequest`, `ChildTaskBreakUpResult`, `ChildTaskBreakUpService`, `ChildTaskView` | `test/child_tasks_test.dart`, `test/application_commands_test.dart` | complete | Chunk 14.3 adds atomic child break-up command wiring. | | MVP-AC-11 | Break a large task into child tasks with row-level priority, reward, and duration. | `V1ApplicationCommandUseCases.breakUpTask`, `ApplicationChildTaskDraft`, `ChildTaskEntry`, `ChildTaskBreakUpRequest`, `ChildTaskBreakUpResult`, `ChildTaskBreakUpService`, `ChildTaskView` | `test/child_tasks_test.dart`, `test/application_commands_test.dart` | complete | Chunk 14.3 adds atomic child break-up command wiring. |
| MVP-AC-12 | Auto-complete parent tasks when all children are done and allow force-completing all children from the parent or a child. | `V1ApplicationCommandUseCases.completeChildTask`, `V1ApplicationCommandUseCases.completeParentTask`, `V1ApplicationCommandUseCases.completeParentFromChild`, `ChildTaskCompletionService`, `ChildTaskCompletionResult`, parent-child helpers, `TaskActivity` | `test/child_tasks_test.dart`, `test/application_commands_test.dart` | complete | Chunk 14.3 adds atomic parent/child completion command wiring. | | MVP-AC-12 | Auto-complete parent tasks when all children are done and allow force-completing all children from the parent or a child. | `V1ApplicationCommandUseCases.completeChildTask`, `V1ApplicationCommandUseCases.completeParentTask`, `V1ApplicationCommandUseCases.completeParentFromChild`, `ChildTaskCompletionService`, `ChildTaskCompletionResult`, parent-child helpers, `TaskActivity` | `test/child_tasks_test.dart`, `test/application_commands_test.dart` | complete | Chunk 14.3 adds atomic parent/child completion command wiring. |
| MVP-AC-13 | Display backlog staleness icons without per-task stale prompts. | `BacklogStalenessMarker`, `BacklogStalenessSettings`, `BacklogView` | `test/scheduling_engine_test.dart`, `test/edge_case_regression_test.dart` | incomplete | Backend marker exists; settings persistence and UI display remain in Blocks 14, 15, and 18. | | MVP-AC-13 | Display backlog staleness icons without per-task stale prompts. | `BacklogStalenessMarker`, `BacklogStalenessSettings`, `BacklogView`, `OwnerSettings`, `BacklogPane` | `test/scheduling_engine_test.dart`, `test/edge_case_regression_test.dart`, `test/application_management_test.dart`, `packages/scheduler_persistence_sqlite/test/sqlite_repository_conformance_test.dart`, `apps/focus_flow_flutter/test/widget_test.dart` | complete | Backend marker, settings persistence, and provisional Flutter backlog icon rendering are complete without per-task stale prompts. |
| MVP-AC-14 | Track baseline internal statistics needed for later reports and filtering. | `TaskStatistics`, `ProjectStatistics`, `TaskActivity`, `TaskActivityApplicationResult`, `TaskActivityAccountingService`, `ProjectStatisticsAggregationService`, `ApplicationUnitOfWork`, `V1ApplicationCommandUseCases`, selected action services | `test/scheduling_engine_test.dart`, `test/required_task_actions_test.dart`, `test/document_mapping_test.dart`, `test/task_lifecycle_test.dart`, `test/child_tasks_test.dart`, `test/project_statistics_test.dart`, `test/application_layer_test.dart`, `test/application_commands_test.dart` | complete | Chunks 13.1-13.4 add canonical statistics/accounting; Chunk 14.3 persists command activities and project aggregate updates atomically in memory. MongoDB adapter persistence remains tracked separately under MVP-SUP-07. | | MVP-AC-14 | Track baseline internal statistics needed for later reports and filtering. | `TaskStatistics`, `ProjectStatistics`, `TaskActivity`, `TaskActivityApplicationResult`, `TaskActivityAccountingService`, `ProjectStatisticsAggregationService`, `ApplicationUnitOfWork`, `V1ApplicationCommandUseCases`, selected action services | `test/scheduling_engine_test.dart`, `test/required_task_actions_test.dart`, `test/document_mapping_test.dart`, `test/task_lifecycle_test.dart`, `test/child_tasks_test.dart`, `test/project_statistics_test.dart`, `test/application_layer_test.dart`, `test/application_commands_test.dart` | complete | Chunks 13.1-13.4 add canonical statistics/accounting; Chunk 14.3 persists command activities and project aggregate updates atomically in memory. Blocks 19-20 add repository contracts and SQLite adapter conformance. |
## Additional MVP backend requirements ## Additional MVP backend requirements
@ -123,7 +123,7 @@ Status values:
| MVP-SUP-04 | Cancelled and no-longer-relevant are separate calm lifecycle outcomes. | `TaskStatus.cancelled`, `TaskStatus.noLongerRelevant`, `RequiredTaskAction`, `TaskActivityCode` | `test/required_task_actions_test.dart`, `test/task_lifecycle_test.dart` | complete | Chunk 13.1 centralizes both transitions and emits distinct activity codes. | | MVP-SUP-04 | Cancelled and no-longer-relevant are separate calm lifecycle outcomes. | `TaskStatus.cancelled`, `TaskStatus.noLongerRelevant`, `RequiredTaskAction`, `TaskActivityCode` | `test/required_task_actions_test.dart`, `test/task_lifecycle_test.dart` | complete | Chunk 13.1 centralizes both transitions and emits distinct activity codes. |
| MVP-SUP-05 | Free Slot is intentional rest that blocks normal flexible placement and suppresses normal flexible reminders. | `V1ApplicationCommandUseCases.createProtectedFreeSlot`, `V1ApplicationCommandUseCases.updateProtectedFreeSlot`, `V1ApplicationCommandUseCases.removeProtectedFreeSlot`, `TaskType.freeSlot`, `OccupancyPolicy`, `FreeSlotService`, `ReminderPolicyService`, timeline tokens | `test/timeline_state_test.dart`, `test/occupancy_policy_test.dart`, `test/free_slots_test.dart`, `test/scheduling_invariants_test.dart`, `test/reminder_policy_test.dart`, `test/application_commands_test.dart` | complete | Blocks 12 and 13 cover scheduling/reminder policy; Chunk 14.3 adds atomic protected Free Slot commands. | | MVP-SUP-05 | Free Slot is intentional rest that blocks normal flexible placement and suppresses normal flexible reminders. | `V1ApplicationCommandUseCases.createProtectedFreeSlot`, `V1ApplicationCommandUseCases.updateProtectedFreeSlot`, `V1ApplicationCommandUseCases.removeProtectedFreeSlot`, `TaskType.freeSlot`, `OccupancyPolicy`, `FreeSlotService`, `ReminderPolicyService`, timeline tokens | `test/timeline_state_test.dart`, `test/occupancy_policy_test.dart`, `test/free_slots_test.dart`, `test/scheduling_invariants_test.dart`, `test/reminder_policy_test.dart`, `test/application_commands_test.dart` | complete | Blocks 12 and 13 cover scheduling/reminder policy; Chunk 14.3 adds atomic protected Free Slot commands. |
| MVP-SUP-06 | Project defaults apply, learned suggestions stay optional, and task reminder overrides are possible. | `ProjectProfile`, `ProjectStatistics`, `ProjectSuggestionService`, `ProjectDefaultResolution`, `ReminderPolicyService`, `Task.reminderOverride`, `ReminderProfile` | `test/scheduling_engine_test.dart`, `test/domain_invariants_test.dart`, `test/project_statistics_test.dart`, `test/reminder_policy_test.dart` | complete | Chunk 13.5 adds effective reminder resolution without using learned suggestions as silent configuration. | | MVP-SUP-06 | Project defaults apply, learned suggestions stay optional, and task reminder overrides are possible. | `ProjectProfile`, `ProjectStatistics`, `ProjectSuggestionService`, `ProjectDefaultResolution`, `ReminderPolicyService`, `Task.reminderOverride`, `ReminderProfile` | `test/scheduling_engine_test.dart`, `test/domain_invariants_test.dart`, `test/project_statistics_test.dart`, `test/reminder_policy_test.dart` | complete | Chunk 13.5 adds effective reminder resolution without using learned suggestions as silent configuration. |
| MVP-SUP-07 | Repository boundaries prepare for MongoDB without coupling the scheduler to MongoDB APIs. | Repository interfaces, in-memory repositories, `ApplicationUnitOfWork`, `V1ApplicationCommandUseCases`, document mapping helpers | `test/repositories_test.dart`, `test/document_mapping_test.dart`, `test/persistence_edge_cases_test.dart`, `test/application_layer_test.dart`, `test/application_commands_test.dart` | incomplete | Chunks 14.1-14.3 add pure Dart transaction/read/command contracts; complete codecs, durable revisions, and runtime adapter remain in Blocks 15 and 16. | | MVP-SUP-07 | Repository boundaries prepare for swappable persistence without coupling the scheduler to database APIs. | Repository interfaces, in-memory repositories, SQLite repositories, `ApplicationUnitOfWork`, `V1ApplicationCommandUseCases`, document mapping helpers | `test/repositories_test.dart`, `test/document_mapping_test.dart`, `test/persistence_edge_cases_test.dart`, `test/application_layer_test.dart`, `test/application_commands_test.dart`, `packages/scheduler_persistence_memory/test/memory_repository_conformance_test.dart`, `packages/scheduler_persistence_sqlite/test/sqlite_repository_conformance_test.dart` | complete | Blocks 19-20 add domain-only repository contracts, in-memory conformance, SQLite adapter conformance, durable revisions, and compare-and-set saves. |
| MVP-SUP-08 | Hidden locked time remains hidden by default, with explicit reveal as an overlay. | `LockedBlockOccurrence.hiddenByDefault`, `TimelineItemMapper.fromLockedOccurrence`, `GetTodayStateQuery`, `TodayTimelineItem` | `test/timeline_state_test.dart`, `test/edge_case_regression_test.dart`, `test/today_state_test.dart` | complete | Chunk 14.2 adds hidden-by-default Today omission, explicit reveal mode, and date-stable locked overlay IDs. | | MVP-SUP-08 | Hidden locked time remains hidden by default, with explicit reveal as an overlay. | `LockedBlockOccurrence.hiddenByDefault`, `TimelineItemMapper.fromLockedOccurrence`, `GetTodayStateQuery`, `TodayTimelineItem` | `test/timeline_state_test.dart`, `test/edge_case_regression_test.dart`, `test/today_state_test.dart` | complete | Chunk 14.2 adds hidden-by-default Today omission, explicit reveal mode, and date-stable locked overlay IDs. |
| MVP-SUP-09 | Push/backlog/restore movement should be activity/stat data, not shame language. | `TaskStatistics`, `ProjectStatistics`, `TaskActivity`, `TaskActivityCode`, `SchedulingChange`, `SchedulingMovementCode`, `ApplicationUnitOfWork`, `V1ApplicationCommandUseCases`, action result objects | `test/scheduling_engine_test.dart`, `test/required_task_actions_test.dart`, `test/scheduling_invariants_test.dart`, `test/task_lifecycle_test.dart`, `test/project_statistics_test.dart`, `test/application_layer_test.dart`, `test/application_commands_test.dart` | complete | Chunk 14.3 adds atomic command persistence for movement activities, task stats, project stats, and operation records. | | MVP-SUP-09 | Push/backlog/restore movement should be activity/stat data, not shame language. | `TaskStatistics`, `ProjectStatistics`, `TaskActivity`, `TaskActivityCode`, `SchedulingChange`, `SchedulingMovementCode`, `ApplicationUnitOfWork`, `V1ApplicationCommandUseCases`, action result objects | `test/scheduling_engine_test.dart`, `test/required_task_actions_test.dart`, `test/scheduling_invariants_test.dart`, `test/task_lifecycle_test.dart`, `test/project_statistics_test.dart`, `test/application_layer_test.dart`, `test/application_commands_test.dart` | complete | Chunk 14.3 adds atomic command persistence for movement activities, task stats, project stats, and operation records. |
| MVP-SUP-10 | The human spec lists `pushed` and `skipped` as statuses. | `TaskStatus` excludes both; movement and burnout compatibility are modeled as activity/stat metadata. | `test/domain_contracts_test.dart` | contradictory | Resolved by `V1_ADR_001_Lifecycle_Metadata_Reminder_Semantics.md`; the contradiction is kept visible so later chunks do not add movement labels as statuses. | | MVP-SUP-10 | The human spec lists `pushed` and `skipped` as statuses. | `TaskStatus` excludes both; movement and burnout compatibility are modeled as activity/stat metadata. | `test/domain_contracts_test.dart` | contradictory | Resolved by `V1_ADR_001_Lifecycle_Metadata_Reminder_Semantics.md`; the contradiction is kept visible so later chunks do not add movement labels as statuses. |

151
README.md
View file

@ -1,106 +1,75 @@
# ADHD Scheduling App Core # ADHD Scheduler Workspace
This is a pure Dart scheduling-core project for an ADHD-focused scheduling SQLite-first Dart workspace for the ADHD scheduler backend, persistence
application. adapters, notifications, exports, backups, integration tests, and CI scripts.
The repository intentionally keeps the scheduling core **pure Dart** before ## Test
adding a full Flutter UI. The hardest part of the product is the scheduling
behavior: flexible task shifting, locked time, backlog recovery, recurring
availability blocks, and task-state correctness. Keeping that logic independent
makes it easier to test and safer to hand off to Codex.
## Current V1 core status ```sh
scripts/test.sh
- Implemented V1 core: Today timeline view models, backlog/wishlist behavior,
quick capture, flexible task insertion/pushing, recurring hidden locked blocks,
one-day locked-block overrides, required task state transitions, surprise task
logging, child task ownership/completion, internal statistics, and
persistence-preparation helpers.
- V2.0: Week/month views, reports, overwhelm shield, drag-and-drop, task history panels.
- Persistence direction: MongoDB is the committed database target. Current V1
work prepares repository interfaces and document-shaped mappings only; it does
not add a MongoDB adapter, connection string, Atlas setup, local server
requirement, accounts, sync, or background service.
- Wishlist/future: Dependencies, context tags, advanced sync, actual MongoDB
adapter/runtime setup, long-running task behavior decisions.
## Repository layout
```text
.
├── AGENTS.md
├── README.md
├── pubspec.yaml
├── analysis_options.yaml
├── lib/
│ ├── scheduler_core.dart
│ └── src/
│ ├── backlog.dart
│ ├── child_tasks.dart
│ ├── document_mapping.dart
│ ├── locked_time.dart
│ ├── models.dart
│ ├── persistence_contract.dart
│ ├── quick_capture.dart
│ ├── repositories.dart
│ ├── scheduling_engine.dart
│ ├── task_actions.dart
│ ├── task_statistics.dart
│ └── timeline_state.dart
├── test/
│ ├── child_tasks_test.dart
│ ├── document_mapping_test.dart
│ ├── edge_case_regression_test.dart
│ ├── persistence_edge_cases_test.dart
│ ├── repositories_test.dart
│ ├── required_task_actions_test.dart
│ ├── scheduling_engine_test.dart
│ ├── surprise_task_logging_test.dart
│ └── timeline_state_test.dart
├── Human Documentation/
│ ├── Original Chat-Compiled Design Spec.md
│ ├── Overall App Design Spec.docx
│ ├── Starter Architecture Notes.md
│ └── Unified Product Design Summary.md
└── Codex Documentation/
├── README.md
├── Current Software Plan/
└── Archived plans/
``` ```
## Basic commands The test gate runs analyzer, tests with coverage, combines LCOV output, and
fails below 80% package `lib/` coverage.
Install a Dart SDK that satisfies `pubspec.yaml` first. This is a pure Dart ## Development
package, so Flutter is not required for the current core/test loop. MongoDB is
the planned persistence target, but no MongoDB service, Atlas account,
connection string, network access, or sync/background process is required for the
current in-memory domain/test loop.
```bash ```sh
dart pub get scripts/bootstrap_dev.sh
dart format lib test scripts/dev.sh
dart analyze
dart test
git diff --check
``` ```
Run these before committing changes whenever the local environment has Dart The shell scripts prepare the default SQLite path and delegate to the Dart
available. development runner.
## Documentation ```sh
dart run scripts/dev.dart
```
Product and design context belongs in `Human Documentation/`. Codex execution The dev script prints the SQLite path, starts `dart run build_runner watch`, and
plans belong in `Codex Documentation/`, with active work under launches Flutter desktop with `SCHEDULER_SQLITE_PATH` passed as a dart define.
`Codex Documentation/Current Software Plan/` and finished plans moved to
`Codex Documentation/Archived plans/`.
## Codex handoff Prerequisites:
Codex should begin by reading: - Dart stable SDK
- Flutter stable SDK with desktop support enabled
- platform desktop toolchain: Xcode for macOS, Visual Studio Build Tools for
Windows, and Linux desktop build dependencies for Linux
1. `AGENTS.md` Optional flags:
2. `Human Documentation/Overall App Design Spec.docx` or the Markdown companion
3. `Codex Documentation/Current Software Plan/README.md`
4. The next numbered block document in `Codex Documentation/Current Software Plan/`
Each completed work block should be committed with a conventional commit message. ```sh
dart run scripts/dev.dart --device linux --sqlite /tmp/scheduler.sqlite
```
## Flutter UI
The provisional UI app lives outside the root Dart workspace at
`apps/focus_flow_flutter` so backend package gates can stay Dart-only while the
Flutter foundation settles.
```sh
cd apps/focus_flow_flutter
flutter analyze
flutter test
```
## Packaging
```sh
scripts/package_release.sh --platform current --output build/releases
```
```sh
dart run scripts/build.dart --platform current --output build/releases
```
Packaging prerequisites:
- macOS: Flutter desktop support and Xcode; produces a `.app`
- Windows: Flutter desktop support, Visual Studio Build Tools, and `msix`
package configuration available to `dart run msix:create`
- Linux: Flutter desktop support plus `appimage-builder` and
`AppImageBuilder.yml`; produces an AppImage
Tagged CI runs upload release artifacts from `build/releases/`.

Binary file not shown.

Binary file not shown.

Binary file not shown.