Wire Backlog nav, Break up, Settings dialog + merge Backlog Board feature #20
23 changed files with 2532 additions and 54 deletions
82
AGENTS.md
82
AGENTS.md
|
|
@ -1,7 +1,7 @@
|
||||||
<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
|
<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
|
||||||
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
|
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
|
||||||
|
|
||||||
# AGENTS.md — Codex Project Rules (SQLite‑First, July 2026)
|
# AGENTS.md — Codex Project Rules (SQLite‑First, July 2026)
|
||||||
|
|
||||||
This document supersedes all previous agent rule files. Treat it as the single source of truth.
|
This document supersedes all previous agent rule files. Treat it as the single source of truth.
|
||||||
|
|
||||||
|
|
@ -10,9 +10,10 @@ This document supersedes all previous agent rule files. Treat it as the single s
|
||||||
## 0. Quick‑start for Codex
|
## 0. Quick‑start for Codex
|
||||||
|
|
||||||
* Blocks live in `Codex Documentation/Current Software Plan/`.
|
* Blocks live in `Codex Documentation/Current Software Plan/`.
|
||||||
* Work strictly in numerical order (Block 19 → 20 … 29).
|
* Work strictly in numerical order unless the active plan explicitly says otherwise.
|
||||||
* Each block contains numbered `XHIGH` / `HIGH` chunks.
|
* Treat each block or named plan as the primary work unit.
|
||||||
* Stop at every `BREAKPOINT` in a chunk; wait for confirmation before continuing.
|
* New or updated plan documents must use blocks of work, implementation steps, tasks, or acceptance checks.
|
||||||
|
* Stop at any explicit `BREAKPOINT` in the active block or plan; wait for confirmation before continuing.
|
||||||
* Before coding, run `scripts/bootstrap_dev.sh` to set up the local dev DB.
|
* Before coding, run `scripts/bootstrap_dev.sh` to set up the local dev DB.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -21,13 +22,13 @@ This document supersedes all previous agent rule files. Treat it as the single s
|
||||||
|
|
||||||
| Element | Rule |
|
| Element | Rule |
|
||||||
|---------|------|
|
|---------|------|
|
||||||
| Local storage | **SQLite via Drift**, schemaVersion 1 |
|
| Local storage | **SQLite via Drift**, schemaVersion 1 |
|
||||||
| Abstraction | Domain‑only repository interfaces (`scheduler_persistence`) |
|
| Abstraction | Domain-only repository interfaces (`scheduler_persistence`) |
|
||||||
| Swappable | New adapters must pass repository conformance tests |
|
| Swappable | New adapters must pass repository conformance tests |
|
||||||
| Backup | AES‑256‑GCM encrypted SQLite file (`Backup library`, Block 24) |
|
| Backup | AES-256-GCM encrypted SQLite file (`Backup library`, Block 24) |
|
||||||
| Migrations | Drift migrations with tests (Block 20, Block 26) |
|
| Migrations | Drift migrations with tests (Block 20, Block 26) |
|
||||||
|
|
||||||
No MongoDB runtime in V1.
|
SQLite is the selected V1 implementation database. Keep Drift and database details inside the SQLite persistence adapter; core/domain code must not import database libraries or depend on row shapes.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -35,15 +36,15 @@ No MongoDB runtime in V1.
|
||||||
|
|
||||||
1. Interfaces expose domain objects only.
|
1. Interfaces expose domain objects only.
|
||||||
2. Optimistic `revision` on every mutable save.
|
2. Optimistic `revision` on every mutable save.
|
||||||
3. Owner scope parameter now for future multi‑user.
|
3. Owner scope parameter now for future multi-user.
|
||||||
4. Adapters implement compare‑and‑set; core never overwrites stale revision.
|
4. Adapters implement compare-and-set; core never overwrites stale revision.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Notification Rules
|
## 3. Notification Rules
|
||||||
|
|
||||||
* Use `NotificationAdapter` (Block 21).
|
* Use `NotificationAdapter` (Block 21).
|
||||||
* Desktop implementation (Block 22), fake adapter for tests.
|
* Desktop implementation (Block 22), fake adapter for tests.
|
||||||
* Core never imports platform APIs directly.
|
* Core never imports platform APIs directly.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -51,7 +52,7 @@ No MongoDB runtime in V1.
|
||||||
## 4. Backup / Export Rules
|
## 4. Backup / Export Rules
|
||||||
|
|
||||||
* Backup: encrypted SQLite (`.sqlite.aes`) via Backup library.
|
* Backup: encrypted SQLite (`.sqlite.aes`) via Backup library.
|
||||||
* Readable exports: JSON + CSV via `ExportController` (Block 23).
|
* Readable exports: JSON + CSV via `ExportController` (Block 23).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -64,16 +65,16 @@ No MongoDB runtime in V1.
|
||||||
| Migration | `test/migration` | Drift schema upgrades |
|
| Migration | `test/migration` | Drift schema upgrades |
|
||||||
| Integration | `test/integration` | full stack InMemory + SQLite + fake notifications |
|
| Integration | `test/integration` | full stack InMemory + SQLite + fake notifications |
|
||||||
|
|
||||||
CI fails below **80 % line coverage**.
|
CI fails below **80% line coverage**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Dev Scripts (Block 27)
|
## 6. Dev Scripts (Block 27)
|
||||||
|
|
||||||
| Script | Description |
|
| Script | Description |
|
||||||
|--------|-------------|
|
|--------|-------------|
|
||||||
| `bootstrap_dev.sh` | install deps, create dev DB |
|
| `bootstrap_dev.sh` | install deps, create dev DB |
|
||||||
| `dev.sh` | hot‑reload desktop run |
|
| `dev.sh` | hot-reload desktop run |
|
||||||
| `test.sh` | all tests + coverage |
|
| `test.sh` | all tests + coverage |
|
||||||
| `package_release.sh` | build OS binaries |
|
| `package_release.sh` | build OS binaries |
|
||||||
|
|
||||||
|
|
@ -83,29 +84,48 @@ integrated.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6.1 File Hygiene
|
## 6.1 Code Documentation & File Hygiene
|
||||||
|
|
||||||
All future project files must include the relevant SPDX metadata for their file
|
All future project files must include the relevant SPDX metadata for their file
|
||||||
format. New Dart files must include file-level Dartdoc library docs and Dartdoc
|
format.
|
||||||
comments for every class, enum, enum value, constructor, method, field, and
|
|
||||||
top-level declaration. When adding code, keep large feature surfaces organized
|
All new and modified code must be commented or documented in detail while the
|
||||||
under descriptive subfolders instead of expanding flat top-level `src` or app
|
work is being done. Update existing comments and docs whenever functionality,
|
||||||
directories.
|
contracts, invariants, side effects, persistence mappings, scheduling rules, or
|
||||||
|
error behavior change. Stale comments are treated as incorrect code.
|
||||||
|
|
||||||
|
New Dart files must include file-level Dartdoc library docs and Dartdoc comments
|
||||||
|
for every class, enum, enum value, constructor, method, field, and top-level
|
||||||
|
declaration. Existing Dart declarations touched by a change must have their
|
||||||
|
Dartdoc added or updated as part of that same change.
|
||||||
|
|
||||||
|
Keep files small and focused. If a file grows to cover multiple responsibilities,
|
||||||
|
split it into smaller files with clear names rather than expanding a broad
|
||||||
|
catch-all file. Use increasingly specific folder scopes, ordered from broad
|
||||||
|
package/feature ownership down to concrete responsibility. Prefer descriptive
|
||||||
|
folder names that explain the domain area or adapter boundary.
|
||||||
|
|
||||||
|
Aim for fewer than 10 files per folder. This is a guideline, not a hard rule:
|
||||||
|
do not create artificial one-file folders merely to satisfy the count, and do
|
||||||
|
split crowded folders when the files naturally form smaller responsibility
|
||||||
|
groups.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Branch, Commit & CI
|
## 7. Branch, Commit & CI
|
||||||
|
|
||||||
* Start each new block from `main` on a block branch named
|
* Start each new block or plan from `main` on a dedicated branch named for the
|
||||||
`block-XX-simple-name` (for example, `block-20-sqlite-adapter`).
|
work, such as `block-20-sqlite-adapter` or `plan-backlog-tab`.
|
||||||
* Keep all chunk work for that block on the block branch.
|
* Keep all work for the active block or plan on its dedicated branch.
|
||||||
* Commit every completed chunk before moving to the next chunk or breakpoint.
|
* Commit completed work after it is implemented, documented, and locally
|
||||||
|
validated.
|
||||||
|
* Do not leave completed work only in the working tree.
|
||||||
* Use conventional commits (`feat`, `fix`, `docs`, `test`, `refactor`,
|
* Use conventional commits (`feat`, `fix`, `docs`, `test`, `refactor`,
|
||||||
`chore`, `ci`).
|
`chore`, `ci`).
|
||||||
* Do not leave completed chunk work only in the working tree.
|
* When a full plan is complete and no work remains for that plan, rerun the
|
||||||
* When the block is complete and verified, merge the block branch back into
|
required validation. If tests still pass, merge the plan branch back into
|
||||||
`main`.
|
`main`.
|
||||||
* CI matrix: ubuntu‑latest, windows‑latest, macos‑latest.
|
* CI matrix: ubuntu-latest, windows-latest, macos-latest.
|
||||||
* `dart analyze` and `dart test` must pass.
|
* `dart analyze` and `dart test` must pass.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -125,4 +145,4 @@ directories.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
_Last updated: 2026-06-27_
|
_Last updated: 2026-07-07_
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,120 @@
|
||||||
|
<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
|
||||||
|
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
|
||||||
|
|
||||||
|
# UI Plan 2 Block 01 — Repo Scope, Guardrails, and Mockup Assets
|
||||||
|
|
||||||
|
**Goal:** Prepare the repo for Backlog board implementation without changing product behavior yet.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Block outcome
|
||||||
|
|
||||||
|
After this block, Codex has verified repo conventions, copied/registered the mockups for local reference, captured baseline validation, and identified the smallest safe implementation path.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 1.1 — Read repo instructions and baseline state
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
1. Read `AGENTS.md` first.
|
||||||
|
2. Read root `README.md`.
|
||||||
|
3. Read `apps/focus_flow_flutter/README.md`.
|
||||||
|
4. Read UI Plan 1 summary and block files under:
|
||||||
|
- `Codex Documentation/Completed Plans/UI Plan 1 - Compact Today Timeline Mockup/`
|
||||||
|
5. Inspect current Backlog-related files:
|
||||||
|
- `apps/focus_flow_flutter/lib/widgets/backlog_pane.dart`
|
||||||
|
- `apps/focus_flow_flutter/lib/widgets/schedule_components.dart`
|
||||||
|
- `apps/focus_flow_flutter/lib/controllers/scheduler_read_controller.dart`
|
||||||
|
- `apps/focus_flow_flutter/lib/controllers/command/scheduler_command_controller_impl.dart`
|
||||||
|
- `packages/scheduler_core/lib/src/application/application_management/**`
|
||||||
|
- `packages/scheduler_core/lib/src/scheduling/backlog/**`
|
||||||
|
6. Confirm that Flutter app code imports only public scheduler APIs.
|
||||||
|
7. Confirm current tests and expected command names.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Codex understands that V1 is SQLite-first and Flutter must not import persistence adapters directly.
|
||||||
|
- Codex has identified whether domain/persistence changes are needed for notes/tags/remove/someday.
|
||||||
|
- No code behavior changed in this chunk.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 1.2 — Place mockup references in the plan folder
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
1. Ensure the plan folder contains:
|
||||||
|
- `mockups/backlog_board_default.png`
|
||||||
|
- `mockups/backlog_task_drawer.png`
|
||||||
|
2. Add or preserve `mockups/README.md` explaining which image represents which state.
|
||||||
|
3. Do not store generated image prompt text in code comments.
|
||||||
|
4. Do not overwrite existing UI Plan 1 mockups.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Mockup files are available from the plan folder.
|
||||||
|
- The default and drawer states are unambiguous.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 1.3 — Run baseline validation
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
From repo root:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
dart analyze
|
||||||
|
dart test
|
||||||
|
```
|
||||||
|
|
||||||
|
From Flutter app:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd apps/focus_flow_flutter
|
||||||
|
flutter analyze
|
||||||
|
flutter test
|
||||||
|
```
|
||||||
|
|
||||||
|
If environment setup is missing, run the highest-confidence subset and record exact failures.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Baseline validation result is known before coding.
|
||||||
|
- Existing failures are documented separately from new work.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 1.4 — Create implementation notes for scope boundaries
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Create a short working note, either in the block commit message or a temporary implementation checklist, identifying:
|
||||||
|
|
||||||
|
1. Which files currently render the sidebar and app shell.
|
||||||
|
2. Which controller/composition object will own navigation state.
|
||||||
|
3. Which read-model expansion is required for the board.
|
||||||
|
4. Which commands already exist and which must be added.
|
||||||
|
5. Which UI widgets can be reused from UI Plan 1:
|
||||||
|
- dark theme tokens,
|
||||||
|
- reward icon,
|
||||||
|
- difficulty bars,
|
||||||
|
- selected overlay patterns,
|
||||||
|
- top-bar button style patterns.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Codex has a narrow implementation map before writing new code.
|
||||||
|
- No speculative large refactors are planned.
|
||||||
|
|
||||||
|
BREAKPOINT: Stop here if baseline tests fail in a way that could hide regressions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Block acceptance criteria
|
||||||
|
|
||||||
|
- Repo instructions read.
|
||||||
|
- Mockup assets placed and documented.
|
||||||
|
- Baseline validation attempted and recorded.
|
||||||
|
- No unrelated code changed.
|
||||||
|
|
@ -0,0 +1,328 @@
|
||||||
|
<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
|
||||||
|
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
|
||||||
|
|
||||||
|
# UI Plan 2 Block 02 — Backlog Read Models, Metadata, and Demo Data
|
||||||
|
|
||||||
|
**Goal:** Add the application/read-model support needed to render the Backlog board, summary, and drawer from backend-owned data.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Block outcome
|
||||||
|
|
||||||
|
After this block, the scheduler/application layer can provide a Backlog board projection with columns, summary statistics, detail metadata, and suggested slot previews. Flutter should not need to invent board grouping or summary counts.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 2.1 — Audit current backlog API and identify exact extension points
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
1. Inspect the public export path in `packages/scheduler_core/lib/scheduler_core.dart`.
|
||||||
|
2. Inspect existing:
|
||||||
|
- `GetBacklogRequest`
|
||||||
|
- `BacklogQueryResult`
|
||||||
|
- `BacklogItemReadModel`
|
||||||
|
- `BacklogView`
|
||||||
|
- `BacklogFilter`
|
||||||
|
- `BacklogSortKey`
|
||||||
|
- `V1ApplicationManagementUseCases.getBacklog`
|
||||||
|
3. Decide whether to extend existing types or add board-specific types.
|
||||||
|
4. Prefer adding board-specific read models if extending existing types would break existing tests or consumers.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Existing simple backlog query remains compatible.
|
||||||
|
- New board query is public through `scheduler_core.dart` if Flutter needs it.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 2.2 — Add board bucket policy in pure Dart
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Add a deterministic policy type in scheduler core, such as:
|
||||||
|
|
||||||
|
- `BacklogBoardBucket`
|
||||||
|
- `BacklogBoardBucketPolicy`
|
||||||
|
- `BacklogBoardBucketResolution`
|
||||||
|
|
||||||
|
Default V1 policy, unless repo docs already define a better one:
|
||||||
|
|
||||||
|
1. `notNow`
|
||||||
|
- task has `BacklogTag.wishlist`, or
|
||||||
|
- priority is `veryLow`/`low` and not otherwise urgent, or
|
||||||
|
- duration is missing and task is not ready to schedule.
|
||||||
|
2. `breakUpFirst`
|
||||||
|
- duration is `>= 90`, or
|
||||||
|
- difficulty is `hard`/`veryHard`, or
|
||||||
|
- task has child previews / parent-child metadata indicating it is already broken down.
|
||||||
|
3. `needTimeBlock`
|
||||||
|
- duration is `>= 45`, or
|
||||||
|
- priority is `high`/`veryHigh`, or
|
||||||
|
- task is estimated to require focused work.
|
||||||
|
4. `doNext`
|
||||||
|
- default for schedule-ready flexible backlog items.
|
||||||
|
|
||||||
|
Each resolution must include a short user-facing reason string.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Policy is pure Dart.
|
||||||
|
- Policy is deterministic.
|
||||||
|
- Unit tests cover all four buckets and tie-breaking precedence.
|
||||||
|
- No Flutter code duplicates this policy.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 2.3 — Add board and summary read models
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Add read models following repo style. Exact file paths may vary, but keep them under scheduler core application management read models.
|
||||||
|
|
||||||
|
Required models:
|
||||||
|
|
||||||
|
1. `BacklogBoardQueryResult`
|
||||||
|
2. `BacklogBoardColumnReadModel`
|
||||||
|
3. `BacklogBoardItemReadModel`
|
||||||
|
4. `BacklogBoardSummaryReadModel`
|
||||||
|
5. `BacklogDistributionReadModel`
|
||||||
|
6. `BacklogDistributionEntryReadModel`
|
||||||
|
7. `BacklogChildPreviewReadModel`
|
||||||
|
8. `BacklogTaskDetailReadModel`
|
||||||
|
9. `SuggestedSlotReadModel`
|
||||||
|
10. `ProjectOptionReadModel` if not already available.
|
||||||
|
|
||||||
|
Required summary fields:
|
||||||
|
|
||||||
|
- total task count,
|
||||||
|
- total estimated minutes,
|
||||||
|
- count by priority,
|
||||||
|
- count by project,
|
||||||
|
- count and percentage by duration bucket,
|
||||||
|
- planning tip copy.
|
||||||
|
|
||||||
|
Required card fields:
|
||||||
|
|
||||||
|
- task id,
|
||||||
|
- title,
|
||||||
|
- subtitle/notes preview,
|
||||||
|
- project id/name/color token,
|
||||||
|
- duration,
|
||||||
|
- priority,
|
||||||
|
- reward,
|
||||||
|
- difficulty,
|
||||||
|
- bucket,
|
||||||
|
- bucket reason,
|
||||||
|
- created/updated timestamps,
|
||||||
|
- child previews,
|
||||||
|
- tag strings.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Read models are immutable where repo conventions expect immutability.
|
||||||
|
- Read models expose display-ready values only where appropriate; do not bury domain objects inside the UI-only result if that would leak unnecessary mutation surface.
|
||||||
|
- Existing `BacklogQueryResult` tests remain passing.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 2.4 — Add notes and freeform tags metadata if absent
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Current `Task` appears to lack freeform notes and general tags. Add the minimal V1 metadata needed by the drawer:
|
||||||
|
|
||||||
|
- `String? notes`
|
||||||
|
- `Set<String> tags` or a small `TaskTag` value object if repo style requires validation.
|
||||||
|
|
||||||
|
Validation rules:
|
||||||
|
|
||||||
|
- notes may be null or non-empty trimmed string; blank notes normalize to null if the repo has normalization helpers.
|
||||||
|
- tag labels are trimmed.
|
||||||
|
- blank tags are rejected or filtered consistently.
|
||||||
|
- duplicate tags collapse case-insensitively if repo conventions support that; otherwise preserve normalized unique strings.
|
||||||
|
- impose a safe maximum count/length consistent with existing persistence payload guards.
|
||||||
|
|
||||||
|
Update all affected layers:
|
||||||
|
|
||||||
|
- `Task` constructor and `copyWith`.
|
||||||
|
- quick capture/create paths where tags/notes are supported.
|
||||||
|
- document mapping.
|
||||||
|
- persistence contract fields.
|
||||||
|
- SQLite task table and DAO/repository mapping.
|
||||||
|
- in-memory repository if it stores full domain objects.
|
||||||
|
- tests.
|
||||||
|
|
||||||
|
If adding persistence migration is required, keep it within SQLite/Drift V1 conventions and add migration tests if existing schema tooling supports them.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Existing tasks still construct without notes/tags.
|
||||||
|
- Notes/tags round-trip through repository mappings.
|
||||||
|
- Flutter receives notes/tags from public read models.
|
||||||
|
- No direct SQLite/Drift import leaks into Flutter.
|
||||||
|
|
||||||
|
BREAKPOINT: Stop here if notes/tags would require a broad migration beyond the current plan. Ask Ashley whether drawer tags should be read-only placeholders or true V1 metadata.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 2.5 — Add board query use case
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Add a method to `V1ApplicationManagementUseCases`, such as:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
Future<ApplicationResult<BacklogBoardQueryResult>> getBacklogBoard(
|
||||||
|
GetBacklogBoardRequest request,
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Request should include:
|
||||||
|
|
||||||
|
- `ApplicationOperationContext context`,
|
||||||
|
- selected `CivilDate localDate` for slot suggestions,
|
||||||
|
- optional search text,
|
||||||
|
- optional filters,
|
||||||
|
- sort key,
|
||||||
|
- group mode.
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
1. Load backlog tasks through repositories.
|
||||||
|
2. Load projects for display names/colors.
|
||||||
|
3. Load child relationships/previews as needed.
|
||||||
|
4. Apply search/filter/sort/group using application/core policies.
|
||||||
|
5. Resolve board bucket for every item.
|
||||||
|
6. Build summary from the same filtered item set.
|
||||||
|
7. Return stable column order: Do Next, Need Time Block, Break Up First, Not Now.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Query does not mutate repositories.
|
||||||
|
- Query returns all four columns even when empty.
|
||||||
|
- Counts match filtered item set.
|
||||||
|
- Summary and board columns use the same source task list.
|
||||||
|
- Unit tests cover empty backlog, default seed-like backlog, search/filter, and summaries.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 2.6 — Add task detail query and suggested slot preview
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Add a detail query method, such as:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
Future<ApplicationResult<BacklogTaskDetailReadModel>> getBacklogTaskDetail(
|
||||||
|
GetBacklogTaskDetailRequest request,
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
1. Load selected backlog task.
|
||||||
|
2. Load project options.
|
||||||
|
3. Load notes/tags/duration/reward/difficulty/project.
|
||||||
|
4. Generate suggested slots without mutating state.
|
||||||
|
5. Suggested slots should respect locked/required time by using scheduler/application services or cloned scheduler input.
|
||||||
|
6. If exact slot-specific scheduling is not supported, return preview rows and mark which one corresponds to `next available`.
|
||||||
|
|
||||||
|
Suggested slot labels for demo should support:
|
||||||
|
|
||||||
|
- `Great Fit`
|
||||||
|
- `Okay`
|
||||||
|
- no-fit or conflict copy if applicable.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Detail query returns not found if selected task no longer exists.
|
||||||
|
- Suggested slots do not write snapshots/tasks.
|
||||||
|
- Missing duration returns an empty suggestions list plus a display reason instead of crashing.
|
||||||
|
- Unit tests prove the query is read-only.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 2.7 — Expand demo seed data for Backlog board
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Create or extend app demo seed files under `apps/focus_flow_flutter/lib/app/demo/`.
|
||||||
|
|
||||||
|
Seed must include enough data to match the mockup:
|
||||||
|
|
||||||
|
- 24 backlog tasks total.
|
||||||
|
- Column counts:
|
||||||
|
- Do Next: 5
|
||||||
|
- Need Time Block: 6
|
||||||
|
- Break Up First: 6
|
||||||
|
- Not Now: 5
|
||||||
|
- Projects:
|
||||||
|
- Home: 5
|
||||||
|
- Work: 8
|
||||||
|
- Personal: 5
|
||||||
|
- Learning: 4
|
||||||
|
- Side Project: 2
|
||||||
|
- Priorities:
|
||||||
|
- High: 7
|
||||||
|
- Medium: 9
|
||||||
|
- Low: 8
|
||||||
|
- Total estimated time: 12h 15m.
|
||||||
|
- Include visible mockup tasks:
|
||||||
|
- Reply to 3 emails
|
||||||
|
- Update project status
|
||||||
|
- Schedule dentist appt
|
||||||
|
- Clean up downloads folder
|
||||||
|
- Plan tomorrow
|
||||||
|
- Review Q3 budget
|
||||||
|
- Plan next week
|
||||||
|
- Define weekly goals
|
||||||
|
- Time block schedule
|
||||||
|
- Organize kitchen drawers
|
||||||
|
- Build analytics dashboard
|
||||||
|
- Write marketing strategy
|
||||||
|
- Complete online course
|
||||||
|
- Module 1: Foundations
|
||||||
|
- Module 2: Deep Dive
|
||||||
|
- Module 3: Practice
|
||||||
|
- Learn guitar
|
||||||
|
- Start YouTube channel
|
||||||
|
- Travel to Japan
|
||||||
|
- Home office upgrade
|
||||||
|
- Read 2 books
|
||||||
|
- `Review Q3 budget` must have:
|
||||||
|
- duration 60 min,
|
||||||
|
- Work project,
|
||||||
|
- High priority,
|
||||||
|
- reward 3/5 equivalent,
|
||||||
|
- difficulty 2/5 equivalent,
|
||||||
|
- notes shown in drawer,
|
||||||
|
- tags `finance` and `review`,
|
||||||
|
- suggested slots matching the drawer mockup labels.
|
||||||
|
|
||||||
|
The remaining 3 tasks may be seed-only hidden lower in scroll or included below the fold.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Seed data is domain/application data, not a hardcoded widget list.
|
||||||
|
- Default board can render from public read models.
|
||||||
|
- Summary totals match the mockup.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Block acceptance criteria
|
||||||
|
|
||||||
|
- Public application/read models can produce the Backlog board, summary, and detail drawer data.
|
||||||
|
- Notes/tags support is either implemented end-to-end or explicitly deferred at the breakpoint with Ashley’s approval.
|
||||||
|
- Core/application tests cover bucket policy, summary, detail, and read-only suggested slots.
|
||||||
|
- Flutter code still does not know scheduler internals.
|
||||||
|
|
||||||
|
## Validation after block
|
||||||
|
|
||||||
|
```sh
|
||||||
|
dart analyze
|
||||||
|
dart test
|
||||||
|
cd apps/focus_flow_flutter
|
||||||
|
flutter analyze
|
||||||
|
flutter test
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,162 @@
|
||||||
|
<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
|
||||||
|
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
|
||||||
|
|
||||||
|
# UI Plan 2 Block 03 — Navigation and Backlog Screen Shell
|
||||||
|
|
||||||
|
**Goal:** Add the Backlog tab route/screen shell and make the sidebar navigation render `Backlog` as active.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Block outcome
|
||||||
|
|
||||||
|
After this block, the app can switch between the existing Today screen and the new Backlog screen shell. The Backlog shell matches the finalized header/control layout but may still use placeholder board content until later blocks fill it in.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 3.1 — Introduce app section navigation state
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
1. Add an app-level enum/model such as `FocusFlowSection` with values:
|
||||||
|
- `today`
|
||||||
|
- `backlog`
|
||||||
|
- `projects`
|
||||||
|
- `reports`
|
||||||
|
- `settings`
|
||||||
|
2. Move the currently hardcoded active `Today` sidebar state into `FocusFlowHome` or a small shell controller.
|
||||||
|
3. Update `Sidebar` to accept:
|
||||||
|
- `activeSection`,
|
||||||
|
- `onSectionSelected` callback.
|
||||||
|
4. Keep Projects/Reports/Settings visible. They may switch to placeholder empty screens or remain inert, but Today and Backlog must work.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Today still renders as before when active.
|
||||||
|
- Backlog nav item can become active.
|
||||||
|
- Sidebar widget tests can verify active styling for Today and Backlog.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 3.2 — Add Backlog screen controller skeleton
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Add controller/read-state classes under app conventions, for example:
|
||||||
|
|
||||||
|
```text
|
||||||
|
apps/focus_flow_flutter/lib/controllers/backlog_board_controller.dart
|
||||||
|
apps/focus_flow_flutter/lib/models/backlog/backlog_board_screen_data.dart
|
||||||
|
```
|
||||||
|
|
||||||
|
Controller responsibilities:
|
||||||
|
|
||||||
|
- load `BacklogBoardQueryResult`,
|
||||||
|
- track loading/ready/empty/failure states,
|
||||||
|
- track selected task id for drawer,
|
||||||
|
- track search/filter/sort/group UI values,
|
||||||
|
- request detail data for selected task,
|
||||||
|
- expose reload method after commands.
|
||||||
|
|
||||||
|
Avoid canonical scheduling state in the controller.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Controller can load the demo/app composition read model.
|
||||||
|
- Controller has no direct persistence dependency.
|
||||||
|
- Selection is UI-local and not persisted.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 3.3 — Extend composition factory
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Update `DemoSchedulerComposition` or the current app composition to create:
|
||||||
|
|
||||||
|
- Backlog board controller,
|
||||||
|
- Backlog command controller if needed,
|
||||||
|
- any date/context provider needed for suggestions.
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
- Use same owner/timezone/date context style as Today.
|
||||||
|
- Reuse existing in-memory application store seeded by domain objects.
|
||||||
|
- Ensure Today and Backlog share the same underlying demo store so commands can refresh both later.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Backlog can load without constructing a separate unrelated fake app state.
|
||||||
|
- Existing Today seed still works.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 3.4 — Build Backlog screen shell
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Create `BacklogBoardScreen` or equivalent under a feature folder such as:
|
||||||
|
|
||||||
|
```text
|
||||||
|
apps/focus_flow_flutter/lib/widgets/backlog/backlog_board_screen.dart
|
||||||
|
```
|
||||||
|
|
||||||
|
Screen sections:
|
||||||
|
|
||||||
|
1. Header title/subtitle row.
|
||||||
|
2. Header mode/settings row.
|
||||||
|
3. Search/filter/sort/group/new-task control row.
|
||||||
|
4. Content body with board region and summary panel slot.
|
||||||
|
5. Drawer overlay slot above content.
|
||||||
|
|
||||||
|
Use mockup spacing:
|
||||||
|
|
||||||
|
- main left/top padding close to current app gutter,
|
||||||
|
- title around 32–36 px,
|
||||||
|
- dark navy/black background,
|
||||||
|
- controls height around 40–44 px,
|
||||||
|
- right summary panel around 285–300 px wide.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Backlog shell visually resembles the default mockup header/control skeleton.
|
||||||
|
- Summary panel area exists but may display placeholder data until Block 6.
|
||||||
|
- Board area exists but may display placeholder columns until Block 4.
|
||||||
|
- No white Material surfaces.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 3.5 — Implement loading/empty/error states
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Use existing `ReadStateView` patterns only if they can match the mockup. Otherwise build Backlog-specific states:
|
||||||
|
|
||||||
|
- Loading: subtle centered progress or skeleton columns.
|
||||||
|
- Empty: calm empty board with new-task CTA.
|
||||||
|
- Failure: compact error panel with retry.
|
||||||
|
|
||||||
|
Do not show blame language.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Controller state maps to UI states.
|
||||||
|
- Tests can render loading, empty, failure, and ready states.
|
||||||
|
|
||||||
|
BREAKPOINT: Stop here for visual review if the shell deviates from the default mockup header/sidebar layout.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Block acceptance criteria
|
||||||
|
|
||||||
|
- Backlog nav is functional.
|
||||||
|
- Backlog shell renders without board details.
|
||||||
|
- Today screen remains functional and visually unchanged except sidebar now supports active state.
|
||||||
|
- App still passes Flutter analyze/test.
|
||||||
|
|
||||||
|
## Validation after block
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd apps/focus_flow_flutter
|
||||||
|
flutter analyze
|
||||||
|
flutter test
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,231 @@
|
||||||
|
<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
|
||||||
|
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
|
||||||
|
|
||||||
|
# UI Plan 2 Block 04 — Board Columns and Task Cards
|
||||||
|
|
||||||
|
**Goal:** Render the four finalized Backlog board columns and task cards from Backlog board read models.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Block outcome
|
||||||
|
|
||||||
|
After this block, the default Backlog board displays all four columns, counts, visible tasks, card metadata, child previews, and add-task footers.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 4.1 — Add board visual tokens
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Add or extend Flutter visual tokens for Backlog-specific accents:
|
||||||
|
|
||||||
|
- Do Next green.
|
||||||
|
- Need Time Block orange/yellow.
|
||||||
|
- Break Up First purple.
|
||||||
|
- Not Now blue.
|
||||||
|
- High priority red flag.
|
||||||
|
- Medium priority yellow/orange flag.
|
||||||
|
- Low priority green flag.
|
||||||
|
- Project dot colors matching seed projects.
|
||||||
|
- Tag chip colors for drawer later.
|
||||||
|
|
||||||
|
Prefer central token/mapping files over inline colors.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Colors are centralized.
|
||||||
|
- Existing Today color mappings remain unchanged.
|
||||||
|
- No one-off hardcoded color scatter in card widgets.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 4.2 — Build column header widget
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Create a reusable `BacklogBoardColumn` and `BacklogColumnHeader`.
|
||||||
|
|
||||||
|
Header content:
|
||||||
|
|
||||||
|
- bucket icon,
|
||||||
|
- bucket title,
|
||||||
|
- count pill,
|
||||||
|
- add icon button on the far right,
|
||||||
|
- subtitle line.
|
||||||
|
|
||||||
|
Icon suggestions:
|
||||||
|
|
||||||
|
- Do Next: check circle.
|
||||||
|
- Need Time Block: clock.
|
||||||
|
- Break Up First: target/radio button/segmented circle.
|
||||||
|
- Not Now: cloud outline.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Header count is read from `BacklogBoardColumnReadModel.count`.
|
||||||
|
- Header add icon calls the same create-task flow as the footer with bucket preselection if available.
|
||||||
|
- Header does not compute bucket counts in Flutter.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 4.3 — Build board layout
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
1. Render columns in stable order:
|
||||||
|
- Do Next
|
||||||
|
- Need Time Block
|
||||||
|
- Break Up First
|
||||||
|
- Not Now
|
||||||
|
2. Use horizontal layout at desktop width.
|
||||||
|
3. Make board horizontally scrollable if width becomes constrained.
|
||||||
|
4. Make column card stacks vertically scrollable or allow the whole board body to scroll, whichever best matches current app ergonomics.
|
||||||
|
5. Keep the summary panel fixed on the right in default state.
|
||||||
|
|
||||||
|
Sizing guidance at 1672 px mockup width:
|
||||||
|
|
||||||
|
- board starts after left content gutter,
|
||||||
|
- 4 columns fit before summary panel,
|
||||||
|
- column width around 270–300 px,
|
||||||
|
- column gap around 8–12 px,
|
||||||
|
- column border/fill tinted by bucket accent.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Four columns are visible at mockup-like desktop width.
|
||||||
|
- Board can be used at narrower desktop widths without overflow exceptions.
|
||||||
|
- Summary panel does not overlap default board state.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 4.4 — Build backlog task card widget
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Create `BacklogTaskCard` with:
|
||||||
|
|
||||||
|
- leading checkbox/selection square,
|
||||||
|
- title,
|
||||||
|
- subtitle/notes preview,
|
||||||
|
- metadata row:
|
||||||
|
- duration icon and minutes,
|
||||||
|
- project color dot/name,
|
||||||
|
- priority flag/label,
|
||||||
|
- footer:
|
||||||
|
- difficulty label and five bars,
|
||||||
|
- reward label and solid reward icons.
|
||||||
|
|
||||||
|
Use existing `DifficultyBars` and reward icon widgets where possible. If existing widgets are Today-specific, extract reusable versions without breaking Today.
|
||||||
|
|
||||||
|
Difficulty requirements:
|
||||||
|
|
||||||
|
- exactly five bars,
|
||||||
|
- `veryEasy` = 1 filled,
|
||||||
|
- `easy` = 2 filled,
|
||||||
|
- `medium` = 3 filled,
|
||||||
|
- `hard` = 4 filled,
|
||||||
|
- `veryHard` = 5 filled,
|
||||||
|
- unfilled bars are outline/subtle.
|
||||||
|
|
||||||
|
Reward requirements:
|
||||||
|
|
||||||
|
- display 1–5 solid sparkle/bolt-style marks matching the mockup language,
|
||||||
|
- no line-only star outlines.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Card content is read from `BacklogBoardItemReadModel`.
|
||||||
|
- Card supports selected state with magenta outline.
|
||||||
|
- Card click selects task and opens drawer in Block 7.
|
||||||
|
- Card does not mutate task status by itself.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 4.5 — Build child preview card section
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
For tasks with child previews, render nested child rows inside the parent card, as shown under:
|
||||||
|
|
||||||
|
- `Plan next week`
|
||||||
|
- `Complete online course`
|
||||||
|
|
||||||
|
Child row content:
|
||||||
|
|
||||||
|
- checkbox-like icon,
|
||||||
|
- child title,
|
||||||
|
- optional duration at right.
|
||||||
|
|
||||||
|
Interaction for this block:
|
||||||
|
|
||||||
|
- Child rows may be non-interactive or select the parent unless a public child-detail model already exists.
|
||||||
|
- Do not implement child completion from the Backlog board unless command wiring is explicitly available and tested.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Parent card remains visually coherent with child preview rows.
|
||||||
|
- Child previews come from read model, not title parsing.
|
||||||
|
- No scheduling/child completion rules are duplicated in Flutter.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 4.6 — Add column footer Add Task buttons
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Footer content:
|
||||||
|
|
||||||
|
- `+ Add task`, colored by bucket accent.
|
||||||
|
|
||||||
|
Behavior for this block:
|
||||||
|
|
||||||
|
- Calls a callback with intended bucket.
|
||||||
|
- Actual create drawer/command wiring happens in Block 8.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Footer is visible in every column.
|
||||||
|
- Footer does not throw when pressed before Block 8 wiring; it can open a placeholder or no-op with a TODO callback in tests.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 4.7 — Tune board visuals against default mockup
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Tune:
|
||||||
|
|
||||||
|
- background fills,
|
||||||
|
- border opacities,
|
||||||
|
- column corner radius,
|
||||||
|
- card height,
|
||||||
|
- card vertical spacing,
|
||||||
|
- title and metadata font sizes,
|
||||||
|
- count pill styling,
|
||||||
|
- icon sizes,
|
||||||
|
- card selected/hover states.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Default board content closely matches `mockups/backlog_board_default.png`.
|
||||||
|
- Visible mockup tasks are present in the expected columns.
|
||||||
|
- No white surfaces or accidental Material default cards.
|
||||||
|
|
||||||
|
BREAKPOINT: Stop here for visual review if card density or column spacing is substantially off.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Block acceptance criteria
|
||||||
|
|
||||||
|
- Backlog board renders from read models.
|
||||||
|
- All four columns, counts, visible task cards, child previews, difficulty bars, reward icons, and add footers are present.
|
||||||
|
- Board layout is responsive enough for desktop width changes.
|
||||||
|
- No domain mutations happen from basic card rendering.
|
||||||
|
|
||||||
|
## Validation after block
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd apps/focus_flow_flutter
|
||||||
|
flutter analyze
|
||||||
|
flutter test
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,189 @@
|
||||||
|
<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
|
||||||
|
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
|
||||||
|
|
||||||
|
# UI Plan 2 Block 05 — Search, Filter, Sort, Group, and Mode Controls
|
||||||
|
|
||||||
|
**Goal:** Implement the Backlog top controls shown in the finalized default mockup with safe, deterministic behavior.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Block outcome
|
||||||
|
|
||||||
|
After this block, the Backlog screen has working search/filter/sort/group controls that reload or transform the Backlog board without duplicating scheduling rules.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 5.1 — Search field
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Add search field matching the mockup:
|
||||||
|
|
||||||
|
- leading search icon,
|
||||||
|
- placeholder `Search backlog...`,
|
||||||
|
- dark outlined field,
|
||||||
|
- clear affordance when text is non-empty if it fits cleanly.
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
- Debounce user input lightly or trigger search on change if current data size is small.
|
||||||
|
- Search across title, subtitle/notes preview, project name, and tags.
|
||||||
|
- Prefer passing `searchText` into the board query so search is part of the read-model request.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Typing filters cards and updates summary counts.
|
||||||
|
- Clearing search restores all tasks.
|
||||||
|
- Search does not alter persisted task data.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 5.2 — Filter menu
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Implement `Filters` button and popover/menu.
|
||||||
|
|
||||||
|
Minimum filters:
|
||||||
|
|
||||||
|
- priority: High, Medium, Low,
|
||||||
|
- project,
|
||||||
|
- duration bucket,
|
||||||
|
- bucket/column,
|
||||||
|
- missing duration,
|
||||||
|
- no reward set if existing backlog filter supports it.
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
- Multi-select where useful.
|
||||||
|
- Apply and clear controls.
|
||||||
|
- Active filter count may be shown as a small badge if it does not clutter the mockup.
|
||||||
|
- Filter state should update board columns and summary from the same result set.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Filter button opens a dark popover.
|
||||||
|
- Applying filters updates columns and summary.
|
||||||
|
- Clearing filters restores default board.
|
||||||
|
- Filter logic lives in application read policy or safe query layer, not widget-only scheduling logic.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 5.3 — Sort dropdown
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Implement `Sort: Custom` dropdown.
|
||||||
|
|
||||||
|
Sort options:
|
||||||
|
|
||||||
|
- Custom/default.
|
||||||
|
- Priority.
|
||||||
|
- Reward vs Effort.
|
||||||
|
- Age.
|
||||||
|
- Project.
|
||||||
|
- Times Pushed if available.
|
||||||
|
- Duration if added to board sorting.
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
- Sort applies inside each bucket by default.
|
||||||
|
- Do not reorder bucket columns.
|
||||||
|
- Stable tie-breaker preserves source/read-model order.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Sort selection updates card order.
|
||||||
|
- `Custom` default matches mockup seed ordering.
|
||||||
|
- Sort state is visible in the control label.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 5.4 — Group dropdown
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Implement `Group: None` dropdown.
|
||||||
|
|
||||||
|
Group options:
|
||||||
|
|
||||||
|
- None.
|
||||||
|
- Project.
|
||||||
|
- Priority.
|
||||||
|
- Duration.
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
- `None` is default and matches mockup.
|
||||||
|
- Non-none group mode adds compact section dividers inside each column or transforms card ordering only if section dividers are visually too disruptive.
|
||||||
|
- Summary panel remains based on filtered item set, not group sections.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Group dropdown opens and changes state.
|
||||||
|
- Group none returns the exact default visual organization.
|
||||||
|
- No overflow or large layout jump when grouping.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 5.5 — Compact/Board toggle and Settings button
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Implement the upper-right controls:
|
||||||
|
|
||||||
|
- `Compact` segment.
|
||||||
|
- `Board` segment active.
|
||||||
|
- `Settings` button.
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
- Board is active by default.
|
||||||
|
- If an existing compact backlog list can be safely reused, clicking Compact may swap to that list. Otherwise, keep Compact inert for this plan and document it in the widget callback TODO.
|
||||||
|
- Settings remains visible and inert unless there is an existing settings screen.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Toggle visually matches mockup.
|
||||||
|
- Board remains active by default.
|
||||||
|
- Pressing Compact/Settings does not throw.
|
||||||
|
- Tests assert Board selected state.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 5.6 — New Task button shell
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Add magenta `+ New Task` button with trailing chevron.
|
||||||
|
|
||||||
|
Behavior for this block:
|
||||||
|
|
||||||
|
- Button calls a callback or opens a placeholder drawer shell.
|
||||||
|
- Full create task wiring happens in Block 8.
|
||||||
|
- Dropdown chevron may later expose quick destination choices; do not implement a broad menu unless already designed.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Button matches the mockup visually.
|
||||||
|
- Button has a stable key for tests.
|
||||||
|
- Button press is safe before full Block 8 wiring.
|
||||||
|
|
||||||
|
BREAKPOINT: Stop here if control behavior requires unresolved product decisions about compact mode or filter semantics.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Block acceptance criteria
|
||||||
|
|
||||||
|
- Search/filter/sort/group controls are present and safe.
|
||||||
|
- Default state matches mockup.
|
||||||
|
- Interactions update or preserve board data predictably.
|
||||||
|
- No scheduling rules are duplicated in Flutter.
|
||||||
|
|
||||||
|
## Validation after block
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd apps/focus_flow_flutter
|
||||||
|
flutter analyze
|
||||||
|
flutter test
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,176 @@
|
||||||
|
<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
|
||||||
|
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
|
||||||
|
|
||||||
|
# UI Plan 2 Block 06 — Backlog Summary Panel
|
||||||
|
|
||||||
|
**Goal:** Implement the right-side default Backlog summary panel from the finalized mockup.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Block outcome
|
||||||
|
|
||||||
|
After this block, the default Backlog state includes a data-driven summary panel with totals, distributions, duration donut, and planning tip.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 6.1 — Build summary panel structure
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Create `BacklogSummaryPanel` under the backlog feature widgets.
|
||||||
|
|
||||||
|
Panel sections:
|
||||||
|
|
||||||
|
1. Header:
|
||||||
|
- sparkle icon,
|
||||||
|
- `Backlog summary`,
|
||||||
|
- collapse chevron.
|
||||||
|
2. Totals:
|
||||||
|
- total tasks,
|
||||||
|
- total estimated time.
|
||||||
|
3. Priority distribution.
|
||||||
|
4. Project distribution.
|
||||||
|
5. Duration distribution.
|
||||||
|
6. Planning tip card.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Panel consumes `BacklogBoardSummaryReadModel`.
|
||||||
|
- No summary value is hardcoded in the widget.
|
||||||
|
- Panel aligns to the right of the default board layout.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 6.2 — Totals and distribution rows
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Implement reusable compact distribution rows:
|
||||||
|
|
||||||
|
- icon/dot/flag at left,
|
||||||
|
- label,
|
||||||
|
- count at right.
|
||||||
|
|
||||||
|
Priority rows:
|
||||||
|
|
||||||
|
- High: red flag.
|
||||||
|
- Medium: yellow flag.
|
||||||
|
- Low: green flag.
|
||||||
|
|
||||||
|
Project rows:
|
||||||
|
|
||||||
|
- colored dot.
|
||||||
|
- project name.
|
||||||
|
- count.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Distribution rows match mockup density.
|
||||||
|
- Counts come from summary read model.
|
||||||
|
- Project colors use centralized visual token mapping.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 6.3 — Duration donut chart
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Implement a small donut chart using Flutter painting, not external chart dependencies unless already present.
|
||||||
|
|
||||||
|
Segments:
|
||||||
|
|
||||||
|
- `0–30 min`
|
||||||
|
- `30–60 min`
|
||||||
|
- `60–120 min`
|
||||||
|
- `120+ min`
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
- Use read-model percentages/counts.
|
||||||
|
- Show legend at right with count and percentage.
|
||||||
|
- Handle zero-task state gracefully.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Donut is visually similar to mockup.
|
||||||
|
- Widget does not crash for empty or all-zero distribution.
|
||||||
|
- Tests can find legend labels/counts.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 6.4 — Planning tip card
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Render planning tip:
|
||||||
|
|
||||||
|
- sparkle icon,
|
||||||
|
- title `Planning tip`,
|
||||||
|
- copy: `Pick 2–4 tasks for today. Keep it realistic and leave space for focus.`
|
||||||
|
|
||||||
|
The initial tip may be static in read model. Later plans can make tips dynamic.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Tip card matches dark glass styling.
|
||||||
|
- Text uses calm product language.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 6.5 — Collapse behavior
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Implement chevron behavior:
|
||||||
|
|
||||||
|
- Expanded by default.
|
||||||
|
- Clicking collapse hides body sections and leaves a compact header or narrow rail if it fits the design.
|
||||||
|
- Collapsed state is UI-local only.
|
||||||
|
|
||||||
|
If collapse visual is not in mockup beyond chevron, simple body hide is enough.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Collapse/expand works.
|
||||||
|
- Board widens or summary area reduces only in default summary mode; drawer overlay behavior remains unchanged.
|
||||||
|
- No persisted state change.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 6.6 — Tune panel visuals
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Tune:
|
||||||
|
|
||||||
|
- panel width,
|
||||||
|
- border opacity,
|
||||||
|
- header spacing,
|
||||||
|
- section dividers,
|
||||||
|
- row heights,
|
||||||
|
- donut size,
|
||||||
|
- planning tip background.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Panel closely matches `mockups/backlog_board_default.png`.
|
||||||
|
- At mockup width, panel is fully visible and does not scroll independently unless content exceeds height.
|
||||||
|
|
||||||
|
BREAKPOINT: Stop here for visual review if donut or summary spacing substantially differs from the mockup.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Block acceptance criteria
|
||||||
|
|
||||||
|
- Default Backlog screen includes summary panel.
|
||||||
|
- All panel values come from read model.
|
||||||
|
- Collapse state works.
|
||||||
|
- Search/filter changes update summary values.
|
||||||
|
|
||||||
|
## Validation after block
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd apps/focus_flow_flutter
|
||||||
|
flutter analyze
|
||||||
|
flutter test
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,272 @@
|
||||||
|
<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
|
||||||
|
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
|
||||||
|
|
||||||
|
# UI Plan 2 Block 07 — Right-Anchored Task Detail Drawer
|
||||||
|
|
||||||
|
**Goal:** Implement the selected-task drawer shown in the finalized drawer mockup.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Block outcome
|
||||||
|
|
||||||
|
After this block, selecting a backlog card opens a right-side drawer that overlays the board without shifting any existing elements.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 7.1 — Add selection and detail loading behavior
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
1. Store selected task id in `BacklogBoardController`.
|
||||||
|
2. On card click:
|
||||||
|
- set selected task id,
|
||||||
|
- request `BacklogTaskDetailReadModel`,
|
||||||
|
- keep current board data unchanged.
|
||||||
|
3. If another card is selected while drawer is open, replace detail content without closing first.
|
||||||
|
4. If selected task disappears after a command/reload, close drawer and show quiet status if appropriate.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Card click opens drawer.
|
||||||
|
- Selecting another card changes drawer content.
|
||||||
|
- Selection is UI-local.
|
||||||
|
- Detail query failures are rendered as drawer-local error, not full screen crash.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 7.2 — Implement drawer overlay anchoring
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Use a `Stack` at the Backlog screen body level.
|
||||||
|
|
||||||
|
Drawer layout:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
Positioned(
|
||||||
|
top: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
width: drawerWidth,
|
||||||
|
child: BacklogTaskDrawer(...),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Sizing:
|
||||||
|
|
||||||
|
- Preferred width: 460–470 px.
|
||||||
|
- Clamp to available width minus safe left minimum for small desktop windows.
|
||||||
|
- Drawer height fills content area inside app frame.
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
- Do not shift columns or summary panel.
|
||||||
|
- Do not use a heavy scrim.
|
||||||
|
- Board remains visible behind/left of drawer.
|
||||||
|
- Close icon closes drawer.
|
||||||
|
- Escape key may close drawer if easy and testable.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Drawer overlays content without moving board columns.
|
||||||
|
- No layout jump occurs when drawer opens/closes.
|
||||||
|
- Drawer remains attached to right edge during window resize.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 7.3 — Drawer header
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Header content:
|
||||||
|
|
||||||
|
- bucket/status icon with accent color,
|
||||||
|
- selected task title,
|
||||||
|
- sparkle icon at right of title area if available,
|
||||||
|
- close icon button in top-right,
|
||||||
|
- subtitle/description,
|
||||||
|
- age metadata such as `Added 2h ago (Jul 3, 2024 • 6:17 AM)`.
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
- Metadata should be display-ready from read model or a UI formatter that only formats dates/times.
|
||||||
|
- Title wraps at sensible line count.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- `Review Q3 budget` header matches drawer mockup for seeded task.
|
||||||
|
- Close button works.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 7.4 — Notes, project, and tags sections
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Render:
|
||||||
|
|
||||||
|
1. Notes panel:
|
||||||
|
- label `Notes`,
|
||||||
|
- notes body.
|
||||||
|
2. Project selector:
|
||||||
|
- label `Project`,
|
||||||
|
- colored dot,
|
||||||
|
- project name,
|
||||||
|
- dropdown chevron.
|
||||||
|
3. Tags section:
|
||||||
|
- label `Tags`,
|
||||||
|
- tag chips,
|
||||||
|
- add button.
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
- If update commands exist by this block, project/tags can be editable.
|
||||||
|
- If update commands are deferred to Block 8, controls should call placeholder callbacks and not mutate state.
|
||||||
|
- Do not invent Flutter-only persisted tags.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Seeded `finance` and `review` chips display for `Review Q3 budget`.
|
||||||
|
- Empty notes/tags render calm empty states.
|
||||||
|
- Project and tag values come from detail read model.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 7.5 — Metric tiles
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Render three tiles:
|
||||||
|
|
||||||
|
1. Duration:
|
||||||
|
- clock icon,
|
||||||
|
- `60 min`,
|
||||||
|
- `Estimated`.
|
||||||
|
2. Reward:
|
||||||
|
- reward icon,
|
||||||
|
- `3/5`,
|
||||||
|
- `Satisfying` or equivalent label.
|
||||||
|
3. Difficulty:
|
||||||
|
- difficulty icon,
|
||||||
|
- `2/5`,
|
||||||
|
- `Easy` or equivalent label.
|
||||||
|
|
||||||
|
Use centralized mapping helpers for reward/difficulty numeric labels.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Tiles match drawer mockup density.
|
||||||
|
- Values update for different selected tasks.
|
||||||
|
- Missing values render `Not set` without throwing.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 7.6 — Suggested slots section
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Render:
|
||||||
|
|
||||||
|
- section title `Suggested slots`,
|
||||||
|
- `View day` button,
|
||||||
|
- rows with calendar icon, date label, time range, duration, fit badge, chevron.
|
||||||
|
|
||||||
|
Rows must support:
|
||||||
|
|
||||||
|
- green `Great Fit`,
|
||||||
|
- yellow/orange `Okay`,
|
||||||
|
- future/tomorrow labels.
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
- Rows may set a selected suggested slot id if slot-specific scheduling is implemented in Block 8.
|
||||||
|
- Otherwise rows are preview-only and pressing primary `Schedule` uses backend next-available command.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Seeded drawer shows three suggested slot rows similar to mockup.
|
||||||
|
- Missing duration or no-fit returns a calm explanation.
|
||||||
|
- Slot rows are generated by read model/scheduler preview, not widget-only calculations.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 7.7 — Drawer action buttons
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Render action buttons:
|
||||||
|
|
||||||
|
- Primary magenta `Schedule`.
|
||||||
|
- Secondary `Break Up`.
|
||||||
|
- Full-width `Push to Someday`.
|
||||||
|
- Full-width `Remove`.
|
||||||
|
|
||||||
|
Behavior in this block:
|
||||||
|
|
||||||
|
- Buttons call callbacks supplied by parent.
|
||||||
|
- Actual commands are finalized in Block 8.
|
||||||
|
- Disable only when the read model explicitly says the action is unavailable. Do not make them look disabled because wiring is pending; instead route callbacks safely.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Buttons visually match drawer mockup.
|
||||||
|
- Button presses do not throw before command wiring.
|
||||||
|
- Stable keys exist for widget tests.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 7.8 — Selected card styling behind drawer
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
When selected:
|
||||||
|
|
||||||
|
- card gets magenta border/outline,
|
||||||
|
- checkbox/leading control reflects selected/focused state if visually needed,
|
||||||
|
- underlying board remains scrollable if drawer does not cover that area.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- `Review Q3 budget` selected card matches drawer mockup highlight.
|
||||||
|
- Closing drawer clears selected styling.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 7.9 — Drawer polish and accessibility
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Polish:
|
||||||
|
|
||||||
|
- drawer background, border, radius,
|
||||||
|
- internal section spacing,
|
||||||
|
- text sizes,
|
||||||
|
- button heights,
|
||||||
|
- hover/focus states,
|
||||||
|
- semantic labels for close and action buttons.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Drawer closely matches `mockups/backlog_task_drawer.png`.
|
||||||
|
- Drawer is keyboard reachable enough for desktop tests.
|
||||||
|
- No white surfaces.
|
||||||
|
|
||||||
|
BREAKPOINT: Stop here for visual review if drawer is not right-anchored or if it shifts the board.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Block acceptance criteria
|
||||||
|
|
||||||
|
- Clicking a task opens the right drawer.
|
||||||
|
- Drawer overlays without shifting layout.
|
||||||
|
- Drawer content is data-driven.
|
||||||
|
- Close behavior works.
|
||||||
|
- Selected card styling works.
|
||||||
|
|
||||||
|
## Validation after block
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd apps/focus_flow_flutter
|
||||||
|
flutter analyze
|
||||||
|
flutter test
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,267 @@
|
||||||
|
<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
|
||||||
|
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
|
||||||
|
|
||||||
|
# UI Plan 2 Block 08 — Commands, New Task, Create/Edit Metadata, and Drawer Actions
|
||||||
|
|
||||||
|
**Goal:** Wire the Backlog tab’s visible actions to application commands while preserving backend/domain authority.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Block outcome
|
||||||
|
|
||||||
|
After this block, `New Task`, `Add task`, `Schedule`, `Break Up`, `Push to Someday`, `Remove`, and metadata edits are either implemented through application commands or explicitly left as safe non-mutating placeholders with tests and TODO notes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 8.1 — Add/update task metadata command
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Add an application command/use case such as `updateBacklogTaskDetails` or general `updateTaskDetails`.
|
||||||
|
|
||||||
|
Input fields:
|
||||||
|
|
||||||
|
- task id,
|
||||||
|
- expected updated timestamp/revision if available,
|
||||||
|
- title,
|
||||||
|
- notes,
|
||||||
|
- project id,
|
||||||
|
- duration minutes,
|
||||||
|
- priority,
|
||||||
|
- reward,
|
||||||
|
- difficulty,
|
||||||
|
- tags,
|
||||||
|
- backlog tags.
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
- Validate task exists.
|
||||||
|
- Validate stale update guard using existing `expectedUpdatedAt` style or repository revision style.
|
||||||
|
- Preserve schedule/source-of-truth rules.
|
||||||
|
- For backlog tasks, metadata changes should not schedule the task.
|
||||||
|
- For planned tasks, do not use this command from Backlog UI.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Metadata update command is tested.
|
||||||
|
- Notes/tags/project edits persist through repository layer.
|
||||||
|
- Flutter calls command controller, not repositories.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 8.2 — New Task drawer/create flow
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Implement reusable task editor drawer/sheet for Backlog create mode.
|
||||||
|
|
||||||
|
Open from:
|
||||||
|
|
||||||
|
- top `+ New Task`,
|
||||||
|
- column header add icon,
|
||||||
|
- column footer `+ Add task`.
|
||||||
|
|
||||||
|
Fields:
|
||||||
|
|
||||||
|
- title required,
|
||||||
|
- notes optional,
|
||||||
|
- project optional/default Inbox or selected bucket/project default,
|
||||||
|
- duration optional,
|
||||||
|
- priority default Medium,
|
||||||
|
- reward optional/not set,
|
||||||
|
- difficulty optional/not set,
|
||||||
|
- tags optional.
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
- Create through `quickCaptureToBacklog` or a new richer create command if notes/tags are required.
|
||||||
|
- Do not force scheduling.
|
||||||
|
- On success:
|
||||||
|
- close create drawer,
|
||||||
|
- refresh Backlog board,
|
||||||
|
- show quiet success text if existing command banner pattern supports it.
|
||||||
|
- Empty title validation stays inline and preserves input.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- `New Task` creates a backlog task.
|
||||||
|
- Column Add Task can preselect or hint bucket defaults without writing a fake bucket field.
|
||||||
|
- Created task appears in board after refresh according to bucket policy.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 8.3 — Schedule selected backlog task
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Wire drawer `Schedule` to existing command:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
scheduleBacklogItem(
|
||||||
|
taskId: selectedTaskId,
|
||||||
|
durationMinutes: optionalDurationIfEdited,
|
||||||
|
expectedUpdatedAt: selectedUpdatedAt,
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
- If duration is missing, focus/show duration requirement instead of discarding task.
|
||||||
|
- If scheduling succeeds:
|
||||||
|
- task leaves Backlog board if its status changes to planned,
|
||||||
|
- drawer closes,
|
||||||
|
- summary and counts refresh,
|
||||||
|
- command status shows calm success.
|
||||||
|
- If no fit/conflict:
|
||||||
|
- keep task in Backlog,
|
||||||
|
- show drawer-local or command-banner explanation.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- UI does not choose canonical time slot by itself.
|
||||||
|
- Schedule command handles stale updates.
|
||||||
|
- Tests verify success callback and failure display with fake command controller.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 8.4 — Break Up flow
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Use existing `breakUpTask` command if possible.
|
||||||
|
|
||||||
|
Minimum V1 UI:
|
||||||
|
|
||||||
|
- Pressing `Break Up` opens a focused child-task drawer/dialog.
|
||||||
|
- User can add at least two child rows with title and optional duration.
|
||||||
|
- Saving calls `breakUpTask` with `ApplicationChildTaskDraft` entries.
|
||||||
|
- On success:
|
||||||
|
- refresh board,
|
||||||
|
- selected detail updates or drawer closes,
|
||||||
|
- child previews appear under parent.
|
||||||
|
|
||||||
|
If full child-entry UI is too large for this plan, implement a safe placeholder that opens a drawer-local message: `Break-up flow is coming next` and do not mutate state. Only use placeholder if Ashley approves at breakpoint.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- No child tasks are created in Flutter-only state.
|
||||||
|
- Break-up command path is covered by tests if implemented.
|
||||||
|
|
||||||
|
BREAKPOINT: Stop before using a placeholder for Break Up. Ask Ashley whether to include full child-entry UI now or defer.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 8.5 — Push to Someday command
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Add/wire application command such as `pushBacklogTaskToSomeday`.
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
- Task remains backlog.
|
||||||
|
- Add `BacklogTag.wishlist` or equivalent someday metadata.
|
||||||
|
- Clear any selected scheduling preview if needed.
|
||||||
|
- Refresh board so task appears in `Not Now`.
|
||||||
|
- Record task activity/statistics if existing lifecycle service supports it.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Command is tested.
|
||||||
|
- It is non-destructive.
|
||||||
|
- It does not schedule or delete the task.
|
||||||
|
- UI refreshes board and drawer content.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 8.6 — Remove/archive command
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Add/wire application command such as `removeBacklogTask`.
|
||||||
|
|
||||||
|
Assumed behavior:
|
||||||
|
|
||||||
|
- non-destructive archive from active backlog,
|
||||||
|
- prefer `TaskStatus.noLongerRelevant` unless repo conventions define `cancelled` or a separate archive flag,
|
||||||
|
- require confirmation before applying,
|
||||||
|
- close drawer on success,
|
||||||
|
- refresh board/summary.
|
||||||
|
|
||||||
|
Confirmation copy:
|
||||||
|
|
||||||
|
- Title: `Remove from Backlog?`
|
||||||
|
- Body: `This hides the task from active planning. It will not schedule anything.`
|
||||||
|
- Actions: `Cancel`, `Remove`.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Remove does not physically delete repository data unless Ashley explicitly changed the product decision.
|
||||||
|
- User can cancel confirmation.
|
||||||
|
- Success refreshes the board.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 8.7 — Project and tags inline edits
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Once update command exists:
|
||||||
|
|
||||||
|
- Project dropdown updates project id.
|
||||||
|
- Tag add button opens small input or menu.
|
||||||
|
- Tag chip can be removed if design supports it.
|
||||||
|
- Use optimistic UI only if command result can reconcile cleanly; otherwise reload after save.
|
||||||
|
|
||||||
|
If inline autosave feels too chatty, use a small `Save changes` action inside the drawer only when fields are dirty. The mockup does not show a save button, so prefer careful inline save with visible running/success/failure states.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Project/tags update through command controller.
|
||||||
|
- Stale/failure result is visible and does not lose local input.
|
||||||
|
- Tests cover project/tag command callback.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 8.8 — Command state feedback
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Add a Backlog command status pattern:
|
||||||
|
|
||||||
|
- running state near top controls or drawer action area,
|
||||||
|
- success state quiet and auto-dismissable if existing app pattern supports it,
|
||||||
|
- failure state calm and specific.
|
||||||
|
|
||||||
|
Messages:
|
||||||
|
|
||||||
|
- `Added to Backlog.`
|
||||||
|
- `Scheduled.`
|
||||||
|
- `Kept in Backlog — no fitting slot found.`
|
||||||
|
- `Moved to Someday.`
|
||||||
|
- `Removed from active Backlog.`
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Failures do not crash screen.
|
||||||
|
- User input is not lost on validation failure.
|
||||||
|
- Command controller reloads board on success.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Block acceptance criteria
|
||||||
|
|
||||||
|
- Visible Backlog actions either work through application commands or have explicit Ashley-approved deferral.
|
||||||
|
- Create/schedule/someday/remove paths are implemented and tested.
|
||||||
|
- Break Up is implemented or explicitly deferred at its breakpoint.
|
||||||
|
- No Flutter widget mutates domain state directly.
|
||||||
|
|
||||||
|
## Validation after block
|
||||||
|
|
||||||
|
```sh
|
||||||
|
dart analyze
|
||||||
|
dart test
|
||||||
|
cd apps/focus_flow_flutter
|
||||||
|
flutter analyze
|
||||||
|
flutter test
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,263 @@
|
||||||
|
<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
|
||||||
|
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
|
||||||
|
|
||||||
|
# UI Plan 2 Block 09 — Testing, Validation, Polish, and Handoff
|
||||||
|
|
||||||
|
**Goal:** Complete tests, final visual polish, validation commands, and handoff notes for the Backlog tab.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Block outcome
|
||||||
|
|
||||||
|
After this block, the Backlog board implementation is tested, validated, documented, and ready for Ashley review or the next implementation plan.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 9.1 — Core/application tests
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
Add or update tests for:
|
||||||
|
|
||||||
|
1. Backlog bucket policy:
|
||||||
|
- Do Next,
|
||||||
|
- Need Time Block,
|
||||||
|
- Break Up First,
|
||||||
|
- Not Now,
|
||||||
|
- precedence/tie-breaking.
|
||||||
|
2. Backlog board query:
|
||||||
|
- empty state,
|
||||||
|
- 24-task seed-like board,
|
||||||
|
- search,
|
||||||
|
- filters,
|
||||||
|
- sort,
|
||||||
|
- group none/default,
|
||||||
|
- summary totals.
|
||||||
|
3. Backlog detail query:
|
||||||
|
- selected task detail,
|
||||||
|
- notes/tags/project metadata,
|
||||||
|
- suggested slots,
|
||||||
|
- missing duration/no-fit.
|
||||||
|
4. Commands:
|
||||||
|
- create backlog task,
|
||||||
|
- update metadata,
|
||||||
|
- schedule backlog item,
|
||||||
|
- push to someday,
|
||||||
|
- remove/archive,
|
||||||
|
- break up if implemented.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Tests are deterministic.
|
||||||
|
- Tests do not require Flutter.
|
||||||
|
- Tests do not depend on wall-clock time without injected context.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 9.2 — Flutter widget tests
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
Add tests under `apps/focus_flow_flutter/test/` that verify:
|
||||||
|
|
||||||
|
1. Sidebar renders `Backlog` active on Backlog screen.
|
||||||
|
2. Default Backlog screen shows:
|
||||||
|
- `Backlog`,
|
||||||
|
- `24 tasks`,
|
||||||
|
- search placeholder,
|
||||||
|
- `Filters`,
|
||||||
|
- `Sort: Custom`,
|
||||||
|
- `Group: None`,
|
||||||
|
- `New Task`,
|
||||||
|
- all four column names,
|
||||||
|
- `Backlog summary`.
|
||||||
|
3. Visible seed cards render in expected columns.
|
||||||
|
4. `Review Q3 budget` card opens drawer.
|
||||||
|
5. Drawer shows:
|
||||||
|
- title,
|
||||||
|
- notes,
|
||||||
|
- Work project,
|
||||||
|
- `finance`,
|
||||||
|
- `review`,
|
||||||
|
- `60 min`,
|
||||||
|
- reward/difficulty labels,
|
||||||
|
- suggested slots,
|
||||||
|
- all action buttons.
|
||||||
|
6. Close button closes drawer and clears selected styling.
|
||||||
|
7. Search narrows visible cards and updates state.
|
||||||
|
8. Filter/sort/group menus open without throwing.
|
||||||
|
9. New Task opens create drawer; empty title validation works.
|
||||||
|
10. Command callbacks are invoked for Schedule/Someday/Remove using fakes/mocks.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Widget tests avoid brittle pixel assertions.
|
||||||
|
- Stable keys are used for important controls.
|
||||||
|
- Tests remain readable and scoped.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 9.3 — Forbidden import and boundary tests
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Update or preserve `test/forbidden_imports_test.dart` so app still cannot import:
|
||||||
|
|
||||||
|
- `scheduler_core/src`,
|
||||||
|
- Drift/SQLite adapters,
|
||||||
|
- backup/export internals,
|
||||||
|
- notification platform internals,
|
||||||
|
- direct OS APIs for this UI slice.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Boundary test passes.
|
||||||
|
- Any new controller/widget files are covered by forbidden import scan.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 9.4 — Responsive and overflow validation
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Manually or via widget tests inspect Backlog layout at widths:
|
||||||
|
|
||||||
|
- 1672 px reference width,
|
||||||
|
- 1440 px,
|
||||||
|
- 1280 px,
|
||||||
|
- 1100 px if supported.
|
||||||
|
|
||||||
|
Expected behavior:
|
||||||
|
|
||||||
|
- desktop reference matches mockup closely,
|
||||||
|
- narrower widths use horizontal board scroll or reduce column widths without overflow,
|
||||||
|
- drawer remains anchored right,
|
||||||
|
- drawer never shifts board elements,
|
||||||
|
- summary can collapse or be hidden below a sensible width if needed.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- No RenderFlex overflow in tested widths.
|
||||||
|
- Drawer overlay behavior remains correct.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 9.5 — Final visual polish pass
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Compare against both mockups and tune:
|
||||||
|
|
||||||
|
- sidebar active state,
|
||||||
|
- main gutters,
|
||||||
|
- title/count pill,
|
||||||
|
- controls spacing,
|
||||||
|
- column widths/heights,
|
||||||
|
- card density,
|
||||||
|
- icons,
|
||||||
|
- difficulty/reward indicators,
|
||||||
|
- summary panel,
|
||||||
|
- drawer width/spacing,
|
||||||
|
- selected card highlight,
|
||||||
|
- button heights.
|
||||||
|
|
||||||
|
Allowed deviations:
|
||||||
|
|
||||||
|
- minor font metric differences,
|
||||||
|
- safe hit target sizing,
|
||||||
|
- small responsive adjustments,
|
||||||
|
- platform-specific rendering differences.
|
||||||
|
|
||||||
|
Not allowed:
|
||||||
|
|
||||||
|
- white backgrounds,
|
||||||
|
- drawer shifting columns,
|
||||||
|
- cards not data-driven,
|
||||||
|
- missing summary panel,
|
||||||
|
- missing visible action buttons.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Backlog default state and drawer state are close enough for Ashley review.
|
||||||
|
|
||||||
|
BREAKPOINT: Stop here for visual review if any major visual section is missing.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 9.6 — Run validation commands
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
From repo root:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
dart format --set-exit-if-changed .
|
||||||
|
dart analyze
|
||||||
|
dart test
|
||||||
|
```
|
||||||
|
|
||||||
|
From Flutter app:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd apps/focus_flow_flutter
|
||||||
|
flutter analyze
|
||||||
|
flutter test
|
||||||
|
```
|
||||||
|
|
||||||
|
If supported by environment:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scripts/test.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- Validation passes, or exact environment-related blockers are documented.
|
||||||
|
- New failures are fixed before handoff unless Ashley approves deferral.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chunk 9.7 — Update docs and handoff
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
Update relevant docs:
|
||||||
|
|
||||||
|
- `apps/focus_flow_flutter/README.md` current scope.
|
||||||
|
- `Codex Documentation/Current Software Plan/README.md` if this plan becomes the active plan.
|
||||||
|
- Optional implementation summary in completed plans if the repo tracks completed plan copies after execution.
|
||||||
|
|
||||||
|
Handoff summary must include:
|
||||||
|
|
||||||
|
- files changed,
|
||||||
|
- implementation decisions,
|
||||||
|
- commands run and results,
|
||||||
|
- features implemented,
|
||||||
|
- deferred items,
|
||||||
|
- known risks,
|
||||||
|
- next recommended plan.
|
||||||
|
|
||||||
|
### Acceptance criteria
|
||||||
|
|
||||||
|
- A new developer/Codex run can understand what changed.
|
||||||
|
- Deferred items are explicit, not hidden.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Final acceptance checklist
|
||||||
|
|
||||||
|
- [ ] Backlog navigation works.
|
||||||
|
- [ ] Default board matches mockup.
|
||||||
|
- [ ] Drawer state matches mockup.
|
||||||
|
- [ ] Drawer overlays and does not shift layout.
|
||||||
|
- [ ] Four board buckets and counts are data-driven.
|
||||||
|
- [ ] Summary panel is data-driven.
|
||||||
|
- [ ] Search/filter/sort/group controls are safe.
|
||||||
|
- [ ] New Task/Add Task create backlog tasks.
|
||||||
|
- [ ] Schedule uses backend/application command.
|
||||||
|
- [ ] Push to Someday is non-destructive.
|
||||||
|
- [ ] Remove is non-destructive unless Ashley explicitly changed this.
|
||||||
|
- [ ] Break Up works or is explicitly deferred with approval.
|
||||||
|
- [ ] Notes/tags/project metadata is either implemented end-to-end or explicitly deferred with approval.
|
||||||
|
- [ ] Flutter app avoids forbidden imports.
|
||||||
|
- [ ] Tests pass or blockers are documented.
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
|
||||||
|
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
|
||||||
|
|
||||||
|
# UI Plan 2 — Execution Order
|
||||||
|
|
||||||
|
Follow this order exactly. Stop at each `BREAKPOINT` if Codex is operating in an interactive repo session.
|
||||||
|
|
||||||
|
1. `UI_PLAN_2_BLOCK_01_REPO_SCOPE_AND_ASSETS.md`
|
||||||
|
2. `UI_PLAN_2_BLOCK_02_BACKLOG_READ_MODELS_AND_METADATA.md`
|
||||||
|
3. `UI_PLAN_2_BLOCK_03_NAVIGATION_AND_SCREEN_SHELL.md`
|
||||||
|
4. `UI_PLAN_2_BLOCK_04_BOARD_COLUMNS_AND_CARDS.md`
|
||||||
|
5. `UI_PLAN_2_BLOCK_05_SEARCH_FILTER_SORT_GROUP.md`
|
||||||
|
6. `UI_PLAN_2_BLOCK_06_SUMMARY_PANEL.md`
|
||||||
|
7. `UI_PLAN_2_BLOCK_07_TASK_DETAIL_DRAWER.md`
|
||||||
|
8. `UI_PLAN_2_BLOCK_08_COMMANDS_CREATE_AND_ACTIONS.md`
|
||||||
|
9. `UI_PLAN_2_BLOCK_09_TESTING_VALIDATION_HANDOFF.md`
|
||||||
|
|
||||||
|
Minimum validation after each block:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd apps/focus_flow_flutter
|
||||||
|
flutter analyze
|
||||||
|
flutter test
|
||||||
|
```
|
||||||
|
|
||||||
|
Additional validation after blocks that touch packages:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
dart analyze
|
||||||
|
dart test
|
||||||
|
```
|
||||||
|
|
||||||
|
Full project validation at the end, if available in the working environment:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scripts/test.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Commit guidance:
|
||||||
|
|
||||||
|
- Commit after each completed block.
|
||||||
|
- Use conventional commit style.
|
||||||
|
- Example block commits:
|
||||||
|
- `feat(backlog): add board read models`
|
||||||
|
- `feat(ui): add backlog navigation shell`
|
||||||
|
- `feat(ui): render backlog board cards`
|
||||||
|
- `feat(ui): add backlog detail drawer`
|
||||||
|
- `test(ui): cover backlog board interactions`
|
||||||
|
|
@ -0,0 +1,345 @@
|
||||||
|
<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
|
||||||
|
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
|
||||||
|
|
||||||
|
# UI Plan 2 — Backlog Board Tab Implementation
|
||||||
|
|
||||||
|
**Status:** Proposed plan.
|
||||||
|
**Primary target:** Implement the finalized Backlog tab shown in the two supplied mockups.
|
||||||
|
**Default mockup:** `mockups/backlog_board_default.png`.
|
||||||
|
**Drawer mockup:** `mockups/backlog_task_drawer.png`.
|
||||||
|
**Execution mode:** Feed this folder to Codex and execute block files in numeric order. Use `xhigh` reasoning for all chunks unless Ashley explicitly says otherwise.
|
||||||
|
**Implementation branch suggestion:** `block-ui-backlog-board` or the repo’s closest existing branch convention.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Purpose
|
||||||
|
|
||||||
|
Build the desktop-first Backlog tab for FocusFlow as a real Flutter screen, not a throwaway static mockup. The final state should provide:
|
||||||
|
|
||||||
|
1. Sidebar navigation with `Backlog` active.
|
||||||
|
2. Backlog title, task count, search, filters, sort, group, board/compact toggle, settings button, and `New Task` primary action.
|
||||||
|
3. Four-column backlog board:
|
||||||
|
- `Do Next`
|
||||||
|
- `Need Time Block`
|
||||||
|
- `Break Up First`
|
||||||
|
- `Not Now`
|
||||||
|
4. Backlog task cards with project, priority, duration, difficulty bars, reward icons, child-task previews, and selection styling.
|
||||||
|
5. Right-side Backlog summary panel in the default state.
|
||||||
|
6. Right-anchored task detail drawer when a backlog card is selected.
|
||||||
|
7. Suggested slots and task actions in the drawer.
|
||||||
|
8. New task / add task entry points wired to backlog-safe capture.
|
||||||
|
9. Tests and validation that preserve the existing backend-source-of-truth rule.
|
||||||
|
|
||||||
|
This plan intentionally treats the mockups as finalized visual direction and uses the current repo architecture as implementation truth.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Source truth and constraints
|
||||||
|
|
||||||
|
Use sources in this order:
|
||||||
|
|
||||||
|
1. Repo files, especially `AGENTS.md`, package boundaries, existing app structure, and tests.
|
||||||
|
2. This plan folder.
|
||||||
|
3. The two mockups in `mockups/`.
|
||||||
|
4. Existing completed UI Plan 1 files.
|
||||||
|
5. Human documentation and UX flow documents already in the repo.
|
||||||
|
|
||||||
|
Hard constraints:
|
||||||
|
|
||||||
|
- V1 is SQLite-first. Do not add MongoDB runtime work.
|
||||||
|
- `scheduler_core` remains pure Dart and is the scheduling/application source of truth.
|
||||||
|
- Flutter must not import scheduler `src/`, Drift/SQLite adapters, notification platform packages, backup/export internals, or OS APIs directly.
|
||||||
|
- UI may own local visual selection state, menu open/closed state, scroll position, text controller state, and drawer open/closed state.
|
||||||
|
- UI must not own canonical scheduling rules, placement rules, task lifecycle rules, or persistence mutations.
|
||||||
|
- Any scheduling/task mutation must go through public scheduler application commands/controllers.
|
||||||
|
- New Dart files require file-level Dartdoc library docs plus Dartdoc for every public/private class, enum, enum value, constructor, method, field, and top-level declaration, following `AGENTS.md`.
|
||||||
|
- New project files require SPDX metadata.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Confirmed repo observations from this planning pass
|
||||||
|
|
||||||
|
The supplied repo already contains:
|
||||||
|
|
||||||
|
- Flutter app target: `apps/focus_flow_flutter/`.
|
||||||
|
- Current provisional/Plan 1 Today UI with sidebar, app shell, theme tokens, top bar, timeline cards, difficulty bars, reward icons, and selected-task modal pieces.
|
||||||
|
- Current simple `BacklogPane` and `BacklogRow` that are not visually aligned with the finalized board mockup.
|
||||||
|
- Existing public scheduler application/query concepts:
|
||||||
|
- `V1ApplicationManagementUseCases.getBacklog`.
|
||||||
|
- `BacklogQueryResult`.
|
||||||
|
- `BacklogItemReadModel`.
|
||||||
|
- `GetBacklogRequest`.
|
||||||
|
- `BacklogView`, `BacklogFilter`, and `BacklogSortKey`.
|
||||||
|
- `V1ApplicationCommandUseCases.quickCaptureToBacklog`.
|
||||||
|
- `V1ApplicationCommandUseCases.scheduleBacklogItemToNextAvailableSlot`.
|
||||||
|
- `V1ApplicationCommandUseCases.breakUpTask`.
|
||||||
|
- Existing domain `Task` supports core scheduling fields, project id, duration, priority, reward, difficulty, backlog tags, parent task id, stats, timestamps, scheduled/actual/completed intervals, status, and type.
|
||||||
|
- Current domain `Task` does **not** appear to include freeform notes or general tags, which the drawer mockup shows.
|
||||||
|
- Current application commands do **not** appear to include a general update/edit-backlog-task command, push-to-someday command, or remove/archive backlog command.
|
||||||
|
|
||||||
|
Plan implication: this is a UI implementation plus a small application/domain read-model expansion, not only a widget rewrite.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Product assumptions to implement unless Ashley changes them
|
||||||
|
|
||||||
|
These assumptions unblock Codex without inventing broad product scope:
|
||||||
|
|
||||||
|
1. **Backlog columns are a V1 read-model policy.** The Flutter board consumes a `BacklogBoardReadModel`; it does not independently decide canonical task grouping.
|
||||||
|
2. **Column assignment is deterministic and explainable.** Each item exposes `bucket`, `bucketReason`, and optional `reasonMetadata` so the UI can show why it is in that column.
|
||||||
|
3. **General tags and notes are V1 task metadata.** Add minimal domain/persistence/application support needed for the drawer and create/edit flows.
|
||||||
|
4. **Remove means archive from active backlog, not physical delete.** Use an application-level remove/archive transition that hides the task from backlog. Prefer `TaskStatus.noLongerRelevant` unless a repo-local convention already says otherwise.
|
||||||
|
5. **Push to Someday means mark the task as a someday/wishlist backlog item.** Use existing `BacklogTag.wishlist` where possible. This should move or keep the task in `Not Now`.
|
||||||
|
6. **Suggested slots are non-mutating previews.** They must be generated by application/core read logic or by calling scheduler logic against cloned/current state. They must not save anything until the user presses `Schedule`.
|
||||||
|
7. **Schedule button chooses a suggested slot only through backend intent.** If the current command only supports “next available slot,” wire the primary button to that command and label suggested rows as preview-only until a slot-specific command exists.
|
||||||
|
8. **Compact mode can remain a non-primary visual affordance.** Board mode is the acceptance target because only Board has a finalized mockup. If a low-risk compact list already exists, it may be reused behind the toggle, but do not invent a second finalized design.
|
||||||
|
9. **Settings remains visible and inert for this plan** unless a settings surface already exists.
|
||||||
|
10. **Project dropdown and tag controls in the drawer should support inline edits only after the relevant update command exists.** If the command is not completed in the same block, render them as disabled/read-only with active visual styling deferred only at the final polish pass.
|
||||||
|
|
||||||
|
Non-blocking clarification items for Ashley after plan review:
|
||||||
|
|
||||||
|
- Exact board bucket policy thresholds for `Do Next`, `Need Time Block`, `Break Up First`, and `Not Now`.
|
||||||
|
- Whether `Remove` should be reversible archive, cancellation, no-longer-relevant, or hard delete.
|
||||||
|
- Whether slot rows should support picking a specific slot in V1 or only preview the result of next-available scheduling.
|
||||||
|
- Whether freeform tags should be global reusable tags or simple task-local strings in V1.
|
||||||
|
|
||||||
|
Do not stop implementation on those questions unless Ashley explicitly requests a policy change before coding.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Visual target summary
|
||||||
|
|
||||||
|
### App shell and sidebar
|
||||||
|
|
||||||
|
- Keep the dark rounded app frame and left sidebar style from UI Plan 1.
|
||||||
|
- Sidebar width remains approximately 250 px.
|
||||||
|
- `Backlog` nav item is active with magenta-tinted fill and outline.
|
||||||
|
- `Today`, `Projects`, `Reports`, and `Settings` remain visible.
|
||||||
|
- Bottom-left status card shows:
|
||||||
|
- green check icon,
|
||||||
|
- `Schedule up to date`,
|
||||||
|
- `All changes are saved.`
|
||||||
|
|
||||||
|
### Backlog default state
|
||||||
|
|
||||||
|
At desktop width around 1672×941:
|
||||||
|
|
||||||
|
- Main content has a left board region and a right summary panel.
|
||||||
|
- Header row:
|
||||||
|
- `Backlog` title,
|
||||||
|
- `24 tasks` count pill,
|
||||||
|
- subtitle: `Choose work that fits your current energy.`
|
||||||
|
- right controls: `Compact`, `Board` active, `Settings`.
|
||||||
|
- Control row:
|
||||||
|
- search field with placeholder `Search backlog...`,
|
||||||
|
- `Filters` button,
|
||||||
|
- `Sort: Custom` dropdown,
|
||||||
|
- `Group: None` dropdown,
|
||||||
|
- magenta `+ New Task` button with trailing chevron.
|
||||||
|
- Board columns:
|
||||||
|
- each column has an icon, title, count pill, subtitle, add icon, card stack, and `+ Add task` footer.
|
||||||
|
- Summary panel:
|
||||||
|
- `Backlog summary` header with sparkle icon and collapse chevron,
|
||||||
|
- total tasks and total estimated time,
|
||||||
|
- priority counts,
|
||||||
|
- project counts,
|
||||||
|
- duration distribution donut/list,
|
||||||
|
- planning tip card.
|
||||||
|
|
||||||
|
### Selected-card drawer state
|
||||||
|
|
||||||
|
- Selecting/clicking a backlog card opens a right-side drawer.
|
||||||
|
- Drawer is anchored to the right edge of the app content/window.
|
||||||
|
- Drawer overlays existing content and does **not** shift columns, header controls, or summary panel.
|
||||||
|
- No heavy scrim; underlying board remains visible.
|
||||||
|
- Selected card remains highlighted with magenta outline behind the drawer.
|
||||||
|
- Drawer width should be approximately 460–470 px at mockup width, clamped for smaller desktop windows.
|
||||||
|
- Drawer sections:
|
||||||
|
- header with bucket/status icon, title, sparkle icon, close icon,
|
||||||
|
- subtitle and age/created metadata,
|
||||||
|
- notes panel,
|
||||||
|
- project selector and tag chips,
|
||||||
|
- duration/reward/difficulty metric tiles,
|
||||||
|
- suggested slots list,
|
||||||
|
- action buttons: `Schedule`, `Break Up`, `Push to Someday`, `Remove`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Feature scope
|
||||||
|
|
||||||
|
### In scope
|
||||||
|
|
||||||
|
- Backlog route/tab under current Flutter app.
|
||||||
|
- Sidebar nav state and Backlog active rendering.
|
||||||
|
- Backlog-specific controllers/read state.
|
||||||
|
- Backlog board read models in public scheduler/application API.
|
||||||
|
- Demo seed data sufficient to render the exact mockup composition.
|
||||||
|
- Four board columns with counts and card ordering.
|
||||||
|
- Default summary panel.
|
||||||
|
- Drawer open/close/select-another behavior.
|
||||||
|
- Search/filter/sort/group controls with at least deterministic basic behavior.
|
||||||
|
- New Task and Add Task entry points with backlog-safe capture.
|
||||||
|
- Schedule action for a selected backlog item.
|
||||||
|
- Break Up action path if the existing `breakUpTask` command can be surfaced safely; otherwise the drawer button may open a non-persisting placeholder form until Block 8 completes the command wiring.
|
||||||
|
- Push to Someday command using `BacklogTag.wishlist` or equivalent.
|
||||||
|
- Remove/archive command using the chosen non-destructive lifecycle transition.
|
||||||
|
- Notes and tags support needed for drawer/create/edit read and persistence.
|
||||||
|
- Responsive handling for desktop width reductions.
|
||||||
|
- Widget tests and core/application tests.
|
||||||
|
|
||||||
|
### Out of scope
|
||||||
|
|
||||||
|
- Week/month views.
|
||||||
|
- Drag-and-drop card movement.
|
||||||
|
- Reports implementation.
|
||||||
|
- Shield/Recovery flows.
|
||||||
|
- Calendar sync.
|
||||||
|
- OS notifications.
|
||||||
|
- Backup/restore UI.
|
||||||
|
- Export/import UI.
|
||||||
|
- Full settings implementation.
|
||||||
|
- Perfect pixel golden tests.
|
||||||
|
- Mobile-first layout.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Target data/read-model shape
|
||||||
|
|
||||||
|
Codex may adjust exact names to match repo conventions, but preserve the information architecture.
|
||||||
|
|
||||||
|
```dart
|
||||||
|
enum BacklogBoardBucket {
|
||||||
|
doNext,
|
||||||
|
needTimeBlock,
|
||||||
|
breakUpFirst,
|
||||||
|
notNow,
|
||||||
|
}
|
||||||
|
|
||||||
|
class BacklogBoardQueryResult {
|
||||||
|
final String ownerId;
|
||||||
|
final CivilDate localDate;
|
||||||
|
final BacklogBoardSummaryReadModel summary;
|
||||||
|
final List<BacklogBoardColumnReadModel> columns;
|
||||||
|
final List<ProjectOptionReadModel> projectOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
class BacklogBoardColumnReadModel {
|
||||||
|
final BacklogBoardBucket bucket;
|
||||||
|
final String title;
|
||||||
|
final String subtitle;
|
||||||
|
final String accentToken;
|
||||||
|
final int count;
|
||||||
|
final List<BacklogBoardItemReadModel> items;
|
||||||
|
}
|
||||||
|
|
||||||
|
class BacklogBoardItemReadModel {
|
||||||
|
final String taskId;
|
||||||
|
final String title;
|
||||||
|
final String? subtitle;
|
||||||
|
final String projectId;
|
||||||
|
final String projectName;
|
||||||
|
final String projectColorToken;
|
||||||
|
final int? durationMinutes;
|
||||||
|
final PriorityLevel? priority;
|
||||||
|
final RewardLevel reward;
|
||||||
|
final DifficultyLevel difficulty;
|
||||||
|
final BacklogBoardBucket bucket;
|
||||||
|
final String bucketReason;
|
||||||
|
final DateTime createdAt;
|
||||||
|
final DateTime updatedAt;
|
||||||
|
final bool hasChildren;
|
||||||
|
final List<BacklogChildPreviewReadModel> childPreview;
|
||||||
|
final List<String> tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
class BacklogTaskDetailReadModel {
|
||||||
|
final BacklogBoardItemReadModel item;
|
||||||
|
final String? notes;
|
||||||
|
final String addedLabel;
|
||||||
|
final List<String> tags;
|
||||||
|
final List<ProjectOptionReadModel> projectOptions;
|
||||||
|
final List<SuggestedSlotReadModel> suggestedSlots;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Summary should include:
|
||||||
|
|
||||||
|
- total tasks,
|
||||||
|
- total estimated minutes,
|
||||||
|
- priority distribution,
|
||||||
|
- project distribution,
|
||||||
|
- duration distribution buckets: `0–30`, `30–60`, `60–120`, `120+`,
|
||||||
|
- planning tip string.
|
||||||
|
|
||||||
|
Suggested slots should include:
|
||||||
|
|
||||||
|
- stable id,
|
||||||
|
- local date label,
|
||||||
|
- start/end display text,
|
||||||
|
- duration minutes,
|
||||||
|
- fit label (`Great Fit`, `Okay`, no-fit/conflict if relevant),
|
||||||
|
- fit severity token,
|
||||||
|
- whether it is the primary/default scheduling target.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Block list
|
||||||
|
|
||||||
|
Execute these files in order:
|
||||||
|
|
||||||
|
1. `UI_PLAN_2_BLOCK_01_REPO_SCOPE_AND_ASSETS.md`
|
||||||
|
2. `UI_PLAN_2_BLOCK_02_BACKLOG_READ_MODELS_AND_METADATA.md`
|
||||||
|
3. `UI_PLAN_2_BLOCK_03_NAVIGATION_AND_SCREEN_SHELL.md`
|
||||||
|
4. `UI_PLAN_2_BLOCK_04_BOARD_COLUMNS_AND_CARDS.md`
|
||||||
|
5. `UI_PLAN_2_BLOCK_05_SEARCH_FILTER_SORT_GROUP.md`
|
||||||
|
6. `UI_PLAN_2_BLOCK_06_SUMMARY_PANEL.md`
|
||||||
|
7. `UI_PLAN_2_BLOCK_07_TASK_DETAIL_DRAWER.md`
|
||||||
|
8. `UI_PLAN_2_BLOCK_08_COMMANDS_CREATE_AND_ACTIONS.md`
|
||||||
|
9. `UI_PLAN_2_BLOCK_09_TESTING_VALIDATION_HANDOFF.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Expected final changed areas
|
||||||
|
|
||||||
|
Likely changed or added areas:
|
||||||
|
|
||||||
|
```text
|
||||||
|
packages/scheduler_core/lib/src/domain/models/entities/task.dart
|
||||||
|
packages/scheduler_core/lib/src/application/application_management/**
|
||||||
|
packages/scheduler_core/lib/src/application/application_commands/**
|
||||||
|
packages/scheduler_core/lib/src/persistence/document_mapping/tasks/**
|
||||||
|
packages/scheduler_core/lib/src/persistence/persistence_contract/fields/tasks/**
|
||||||
|
packages/scheduler_persistence/lib/persistence/repositories/task_repository.dart
|
||||||
|
packages/scheduler_persistence_memory/**
|
||||||
|
packages/scheduler_persistence_sqlite/lib/src/scheduler_db/tables/tasks/tasks.dart
|
||||||
|
packages/scheduler_persistence_sqlite/lib/src/scheduler_db/daos/task_dao.dart
|
||||||
|
packages/scheduler_persistence_sqlite/lib/src/sqlite_repositories/sqlite_task_repository.dart
|
||||||
|
apps/focus_flow_flutter/lib/app/**
|
||||||
|
apps/focus_flow_flutter/lib/controllers/**
|
||||||
|
apps/focus_flow_flutter/lib/models/backlog/**
|
||||||
|
apps/focus_flow_flutter/lib/widgets/backlog/**
|
||||||
|
apps/focus_flow_flutter/lib/widgets/sidebar.dart
|
||||||
|
apps/focus_flow_flutter/lib/theme/**
|
||||||
|
apps/focus_flow_flutter/test/**
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not modify unrelated packages unless tests prove a required boundary update.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Final acceptance criteria
|
||||||
|
|
||||||
|
The plan is complete when:
|
||||||
|
|
||||||
|
- Backlog sidebar item opens/renders the Backlog tab and is visually active.
|
||||||
|
- Default Backlog board state closely matches `backlog_board_default.png`.
|
||||||
|
- Selecting `Review Q3 budget` or any task card opens a right-side drawer matching `backlog_task_drawer.png`.
|
||||||
|
- Drawer overlays content without moving columns or summary.
|
||||||
|
- Search/filter/sort/group controls are visible and do not break board state.
|
||||||
|
- Board columns, cards, summary, and drawer are all driven by scheduler/application read models or controller-level display models derived from those read models.
|
||||||
|
- Schedule action uses scheduler application command(s); UI does not compute canonical placement.
|
||||||
|
- New task capture creates backlog tasks through scheduler application command(s).
|
||||||
|
- Push to Someday and Remove are non-destructive domain/application commands, not Flutter-only state deletion.
|
||||||
|
- Tests cover default render, navigation, controls, card selection, drawer close, summary data, and command callbacks.
|
||||||
|
- `flutter analyze` and `flutter test` pass under `apps/focus_flow_flutter`.
|
||||||
|
- Root/package tests touched by domain/persistence changes pass or are explicitly reported if environment prevents full validation.
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
|
||||||
|
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
|
||||||
|
|
||||||
|
# Backlog Board Mockups
|
||||||
|
|
||||||
|
These images are the visual references for UI Plan 2.
|
||||||
|
|
||||||
|
- `backlog_board_default.png` — finalized default Backlog board state with summary panel.
|
||||||
|
- `backlog_task_drawer.png` — finalized selected-task state with right-anchored drawer.
|
||||||
|
|
||||||
|
Implementation notes:
|
||||||
|
|
||||||
|
- Treat these as semi-strict visual references.
|
||||||
|
- Preserve the dark theme, board density, summary panel, and drawer anchoring.
|
||||||
|
- The drawer must overlay existing content and must not move board columns or summary layout.
|
||||||
|
- Do not introduce a white app background.
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.1 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.2 MiB |
Binary file not shown.
|
|
@ -1,13 +0,0 @@
|
||||||
# ADHD-Friendly Scheduling Application
|
|
||||||
|
|
||||||
Unified Product and Design Specification
|
|
||||||
|
|
||||||
Draft compiled from user requirements - June 19, 2026
|
|
||||||
|
|
||||||
## Executive Summary
|
|
||||||
|
|
||||||
This application is a failure-tolerant scheduling system for people who struggle with executive dysfunction, task migration, reminders, volatile schedules, and missed logging. It is not intended to be a generic productivity app. Its core job is to preserve intent when the plan breaks: move flexible tasks forward, protect required commitments, keep locked unavailable time out of the way visually, and make recovery simple instead of punitive.
|
|
||||||
|
|
||||||
The MVP focuses on Today, Backlog, recurring hidden locked blocks, push/rollover behavior, task capture, and simple state management. Version 2.0 adds week/month views, reports, drag-and-drop, task history, and the full overwhelm shield/recovery system.
|
|
||||||
|
|
||||||
See the DOCX file for the complete formatted specification.
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
# Human Documentation
|
|
||||||
|
|
||||||
This folder contains human-facing product documentation.
|
|
||||||
|
|
||||||
Start with:
|
|
||||||
|
|
||||||
- `Overall App Design Spec.docx`
|
|
||||||
- `Original Chat-Compiled Design Spec.md`
|
|
||||||
|
|
||||||
These documents define the product intent, terminology, major features, and version boundaries. Codex should use these files for product context but should execute from the files in `Codex Documentation/Current Software Plan/`.
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
|
||||||
|
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
|
||||||
|
|
||||||
|
# Backlog Notes and Freeform Tags Metadata
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
Deferred from UI Plan 2 on 2026-07-07.
|
||||||
|
|
||||||
|
For the current Backlog board implementation, notes and freeform tags are
|
||||||
|
read-only presentation placeholders. Do not expand the current UI Plan 2 scope
|
||||||
|
to add persisted task notes or general-purpose tags.
|
||||||
|
|
||||||
|
## Why this is deferred
|
||||||
|
|
||||||
|
The drawer mockup includes notes and tag chips, but the current V1 `Task` domain
|
||||||
|
model only has narrow `BacklogTag` flags such as `wishlist`. It does not yet
|
||||||
|
have general freeform notes or user-defined task tags.
|
||||||
|
|
||||||
|
Adding those fields correctly is not a local widget change. It is a real V1
|
||||||
|
metadata and persistence feature with schema, migration, command, and test
|
||||||
|
impact.
|
||||||
|
|
||||||
|
## Work left for the future feature
|
||||||
|
|
||||||
|
When this feature is resumed, decide the exact product behavior first:
|
||||||
|
|
||||||
|
1. Whether notes are plain text only or support lightweight formatting later.
|
||||||
|
2. Whether tags are task-local strings or reusable global tag records.
|
||||||
|
3. Maximum note length.
|
||||||
|
4. Maximum tag count per task.
|
||||||
|
5. Maximum tag label length.
|
||||||
|
6. Case and duplicate handling for tags.
|
||||||
|
7. Whether tag edits are allowed in quick capture, the Backlog drawer, or both.
|
||||||
|
8. Whether existing imports/exports should include notes and tags immediately.
|
||||||
|
|
||||||
|
Expected implementation areas:
|
||||||
|
|
||||||
|
1. Add `String? notes` and either `Set<String> tags` or a small validated tag
|
||||||
|
value object to `Task`.
|
||||||
|
2. Update `Task.quickCapture`, `Task.copyWith`, and domain invariant tests.
|
||||||
|
3. Add validation and normalization for blank notes, blank tags, duplicate tags,
|
||||||
|
and safe payload limits.
|
||||||
|
4. Extend task document fields and `TaskDocumentMapping`.
|
||||||
|
5. Update document mapping, migration, and persistence field coverage tests.
|
||||||
|
6. Update repository conformance expectations so notes/tags round-trip through
|
||||||
|
every adapter.
|
||||||
|
7. Add SQLite Drift task columns or a normalized tag table, depending on the
|
||||||
|
chosen tag model.
|
||||||
|
8. Bump or migrate SQLite schema as required and add migration tests for old
|
||||||
|
databases.
|
||||||
|
9. Regenerate Drift code.
|
||||||
|
10. Update SQLite application and repository task row mappers.
|
||||||
|
11. Extend quick-capture/create/update command surfaces if users can write notes
|
||||||
|
or tags.
|
||||||
|
12. Update readable export/import behavior if these fields are part of user data
|
||||||
|
portability.
|
||||||
|
|
||||||
|
## Current UI Plan 2 handling
|
||||||
|
|
||||||
|
For UI Plan 2, the Backlog board and drawer may display placeholder or derived
|
||||||
|
read-only tag text where useful, but Flutter must not pretend those values are
|
||||||
|
persisted editable task metadata. Editing controls should remain disabled,
|
||||||
|
hidden, or clearly non-editing until the future metadata feature lands.
|
||||||
Loading…
Reference in a new issue