<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
<!-- SPDX-License-Identifier: AGPL-3.0-only -->

# UI Plan 2 Implementation Notes

## Block 01 Baseline Map

1. Sidebar and app shell currently render through
   `apps/focus_flow_flutter/lib/widgets/sidebar.dart`,
   `apps/focus_flow_flutter/lib/widgets/app_shell.dart`, and the
   `FocusFlowHome` parts under `apps/focus_flow_flutter/lib/app/home/`.
2. Navigation state is not implemented yet. `Sidebar` hard-codes Today as
   active, and `FocusFlowHome` owns only Today controllers. UI Plan 2 should add
   app-level section state in the home/composition layer before rendering the
   Backlog board.
3. Backlog board data needs new public scheduler application read models. The
   current `BacklogQueryResult` is list-shaped and returns raw `Task` values via
   `BacklogItemReadModel`, which is not enough for board columns, summary,
   detail drawer metadata, or suggested slot previews.
4. Existing commands include quick capture to backlog, schedule backlog item to
   next available slot, move flexible tasks to backlog, remove task, and break
   up task. Push-to-Someday and non-destructive backlog archive still need
   command-level decisions before the drawer actions can be final.
5. UI Plan 1 components to reuse include `FocusFlowTokens`, the dark shell,
   timeline reward icon, difficulty bars, selected overlay patterns, and the
   top-bar icon/segmented-control styling conventions.

## Block 01 Validation

- `scripts/bootstrap_dev.sh`: passed.
- `dart analyze`: passed.
- `dart test`: passed.
- `flutter analyze` in `apps/focus_flow_flutter`: passed.
- `flutter test` in `apps/focus_flow_flutter`: passed.

## Block 02 Audit

1. `GetBacklogRequest`, `BacklogQueryResult`, and `BacklogItemReadModel` remain
   the compatibility path for the existing simple backlog pane.
2. UI Plan 2 should add board-specific public read models instead of extending
   `BacklogQueryResult`, because the board needs columns, summary
   distributions, child previews, detail rows, and suggested slots while the
   current list result intentionally exposes raw tasks plus staleness markers.
3. The board bucket policy belongs in pure scheduler backlog code under
   `packages/scheduler_core/lib/src/scheduling/backlog/`, with Flutter consuming
   only public `scheduler_core.dart` exports.

## Block 02 Notes/Tags Breakpoint

Adding real V1 task notes and freeform tags is a broad persistence change, not
only a drawer read-model change. It would touch at least:

1. `Task`, `Task.quickCapture`, and `Task.copyWith`.
2. Task document fields and `TaskDocumentMapping`.
3. Persistence contract field sets and document field coverage tests.
4. In-memory application/repository round trips through the full domain object.
5. SQLite Drift task table columns, generated database code, schema versioning,
   migration strategy, migration tests, and both SQLite task mappers.
6. Command/capture surfaces if the UI can create or edit notes/tags.

Per `UI_PLAN_2_BLOCK_02_BACKLOG_READ_MODELS_AND_METADATA.md`, this is the
breakpoint where Ashley needs to choose whether drawer tags should be read-only
placeholders for now or true V1 metadata with a schema migration.

Ashley chose the read-only path for UI Plan 2. Backlog drawer notes remain
`null`, and tags are derived only from existing narrow backlog metadata for now
(`BacklogTag.wishlist` displays as `someday`). True notes and freeform tags are
tracked in `Human Documentation/Things to consider todo/Backlog Notes and
Freeform Tags Metadata.md` for a later migration-backed feature.

## Block 02 Board and Detail Queries

1. `GetBacklogBoardRequest` and `GetBacklogTaskDetailRequest` now expose the
   public query inputs needed by Flutter without importing scheduler `src/`.
2. `V1ApplicationManagementUseCases.getBacklogBoard` loads backlog candidates,
   project display metadata, direct child previews, search/filter/sort/group
   state, bucket policy results, and summary distributions through repository
   read boundaries only.
3. `V1ApplicationManagementUseCases.getBacklogTaskDetail` returns the selected
   backlog task drawer model, read-only derived tags, project options, and
   non-mutating suggested slot previews. Missing duration returns a display
   reason instead of attempting scheduling.
4. Focused application-management tests cover stable empty columns, bucket and
   summary consistency, search/filter behavior, child previews, not-found detail
   responses, read-only slot suggestions, and missing-duration handling.

## Block 02 Demo Seed Data

1. The Flutter demo composition now seeds Backlog board data as real scheduler
   `Task` and `ProjectProfile` records, not widget-local mock rows.
2. The seed matches the feasible textual targets from Chunk 2.7: 24 backlog
   tasks, project counts of Home 5 / Work 8 / Personal 5 / Learning 4 / Side
   Project 2, priority counts of High 7 / Medium 9 / Low 8, and 12h 15m total
   estimated time.
3. The plan/mockup contains a count conflict: the mockup summary says 24 tasks,
   while the listed column badge counts add to 22. The current seed keeps 24
   repository-backed backlog tasks so the summary target stays truthful through
   public read models.
4. `Review Q3 budget` is seeded with Work, 60 minutes, High priority,
   medium reward, and easy difficulty. Finance/review freeform tags, notes text,
   and exact drawer slot copy remain deferred with the approved metadata scope
   decision above.

## Block 03 Navigation and Screen Shell

1. `FocusFlowSection` now owns app-level navigation state for Today, Backlog,
   Projects, Reports, and Settings. The sidebar is controlled by this state and
   exposes stable active keys for Today and Backlog tests.
2. `BacklogBoardController` loads `BacklogBoardQueryResult`, tracks local
   search/filter/sort/group values, and keeps selected task detail as UI-local
   state. It uses only public scheduler application read models.
3. Demo and persistent compositions both create the Backlog controller from the
   same underlying application store used by Today, so future commands can
   refresh both surfaces without creating separate fake state.
4. `BacklogBoardScreen` renders the desktop Backlog header, controls, column
   shells, loading/empty/failure states, and a compact summary panel shell.
   Detailed cards, charts, and drawer contents remain for later UI Plan 2
   blocks.

## Block 04 Board Columns and Cards

1. Backlog bucket, priority, project, reward, and future tag-chip colors now
   live in `apps/focus_flow_flutter/lib/theme/backlog_board_visual_tokens.dart`
   instead of inline card mappings.
2. `BacklogBoardScreen` delegates column rendering to reusable board column and
   task card widgets. The board keeps the summary panel fixed on the right and
   horizontally scrolls the four-column board if the available desktop width is
   constrained.
3. `BacklogTaskCard` renders only public `BacklogBoardItemReadModel` data:
   title, subtitle or bucket reason, duration, project dot/name, priority flag,
   difficulty bars, solid reward marks, selected outline, and direct child
   previews.
4. Add-task controls intentionally call a no-op bucket callback until Block 8
   wires the create-task command flow. Card taps select through
   `BacklogBoardController.selectTask`, which performs a read-only detail query.
5. The current demo seed still represents mockup child rows as normal backlog
   tasks rather than parent-child relationships. Child preview rendering is
   covered by a focused widget test using handcrafted public read models so the
   seed scope does not expand in this block.

## Block 05 Search, Filter, Sort, and Group Controls

1. The board request now has `BacklogBoardFilterSelection` for board-only
   filters: priority group, project, duration bucket, board bucket, and missing
   duration. Legacy `BacklogFilter.noRewardSet` remains the cleanup filter for
   no-reward tasks.
2. `BacklogSortKey.custom` preserves source/read-model order for the board
   default, and `BacklogSortKey.duration` supports duration ordering. The simple
   backlog list still keeps its existing priority default.
3. `BacklogBoardGroupMode` now supports project, priority, and duration
   grouping as stable ordering inside the existing four bucket columns. The UI
   does not add section dividers in this block.
4. The Backlog control row lives in
   `apps/focus_flow_flutter/lib/widgets/backlog/backlog_board_controls.dart`.
   Search reloads through the board query, filters apply through the public
   request object, sort/group menus update controller state, and Compact,
   Settings, and New Task remain safe inert shells until later blocks.

## Block 06 Summary Panel

1. `BacklogSummaryPanel` now owns the right-side summary surface and consumes
   only `BacklogBoardSummaryReadModel` data from the public scheduler API.
2. The panel renders total tasks, total estimated time, priority distribution,
   project distribution, a custom-painted duration donut with legend rows, and
   the planning tip card without hardcoded summary values.
3. Summary panel color decisions use
   `apps/focus_flow_flutter/lib/theme/backlog_board_visual_tokens.dart` for
   priority, project, and duration colors so board cards and summary rows share
   the same visual mapping.
4. Collapse and expand state is local to the Flutter widget. It hides body
   sections while leaving the summary header visible and does not write any
   scheduler state.

## Block 07 Task Detail Drawer

1. `BacklogBoardController` now keeps selected-task id, detail loading state,
   and detail-read failures as UI-local state. Detail failures render in the
   drawer and no longer replace the whole Backlog screen.
2. `BacklogBoardScreen` renders `BacklogTaskDrawer` in a right-anchored
   `Stack` overlay. The board and summary row stay in their original layout, so
   opening and closing the drawer does not shift cards.
3. `BacklogTaskDrawer` renders header metadata, empty or read-only notes,
   project display, read-only tags, duration/reward/difficulty metrics,
   suggested slot previews, and Block-8-ready action buttons from public
   `BacklogTaskDetailReadModel` data.
4. Real notes and freeform tags remain deferred per the Block 02 metadata
   decision. The drawer shows calm empty states when the read model has no
   notes or tags instead of inventing Flutter-only persisted metadata.

## Block 08 Commands Through Drawer Actions

1. Metadata edit controls remain safe non-mutating placeholders at this point
   because real notes and freeform tags were explicitly deferred in Block 02.
   Project and tag editing should be revisited with a migration-backed metadata
   command rather than Flutter-only state.
2. `BacklogBoardScreen` now accepts the app `SchedulerCommandController`.
   Backlog command state is rendered in a compact status banner below the
   controls.
3. Top-level `New Task` and column `Add task` open a title-first creation
   dialog. Successful submission calls the existing `quickCaptureToBacklog`
   command and refreshes Backlog through the shared command controller.
4. Drawer `Schedule` calls the existing
   `scheduleBacklogItemToNextAvailableSlot` command through
   `SchedulerCommandController.scheduleBacklogItem`. Missing duration shows a
   drawer-local message and does not start a command.
5. Drawer `Break Up` opens a focused child-entry dialog with two initial rows.
   The dialog validates at least two titled rows, optional whole-minute
   estimates, and submits `ApplicationChildTaskDraft` values through the
   existing `breakUpTask` application command. Successful saves refresh the
   board and selected detail so child previews come from scheduler read models.
6. Drawer `Push to Someday` now uses a Backlog-specific application command
   that adds the existing `BacklogTag.wishlist` flag without scheduling or
   deleting the task. The selected detail and board refresh into the `Not Now`
   bucket.
7. Drawer `Remove` now confirms with the requested copy and archives the task
   through a Backlog-specific application command. It marks the task
   `TaskStatus.noLongerRelevant`, clears active Backlog selection on success,
   and does not physically delete repository data.
8. The shared application-command change detector now includes Backlog metadata
   such as `backlogTags`, so metadata-only commands are persisted even when the
   command clock equals the task's previous `updatedAt`.

## Block 09 Validation and Handoff

1. Added final widget coverage for the default Backlog shell controls, empty
   New Task title validation, and responsive no-overflow smoke checks at 1672,
   1440, 1280, and 1100 px desktop widths.
2. Added a SQLite schema-column regression test and kept Drift table DSL input
   files out of the custom runtime coverage denominator. The fresh coverage
   gate reports 80.34% package `lib/` line coverage.
3. Preserved the forbidden-import boundary test so Flutter widgets and
   controllers continue to use public scheduler APIs instead of scheduler
   internals, Drift, SQLite adapters, notification internals, backup/export
   internals, or direct OS APIs outside approved runtime boundaries.
4. Final validation passed with:
   - `scripts/test.sh`
   - `cd apps/focus_flow_flutter && flutter analyze`
   - `cd apps/focus_flow_flutter && flutter test`
5. Manual live UI review was not possible in this session because the local X11
   display was refusing new clients with `Maximum number of clients reached`.
   The diagnosed cause was many duplicate `xbindkeys` clients, not a Flutter
   build failure.
6. Deferred items remain limited to the approved metadata scope: real notes,
   freeform tags, project edits, and the Backlog drawer `View day` shortcut.
