18 KiB
phase, verified, status, score, human_verification
| phase | verified | status | score | human_verification | |||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 02-rooms-and-tasks | 2026-03-15T22:00:00Z | human_needed | 15/15 must-haves verified |
|
Phase 2: Rooms and Tasks Verification Report
Phase Goal: Users can create and manage rooms and tasks, mark tasks done, and trust the app to schedule the next occurrence automatically Verified: 2026-03-15T22:00:00Z Status: human_needed (all automated checks pass; 5 UI behaviors require running device confirmation) Re-verification: No — initial verification
Goal Achievement
Observable Truths
| # | Truth | Status | Evidence |
|---|---|---|---|
| 1 | Room CRUD operations work correctly at the database layer | VERIFIED | rooms_dao.dart: insert, update, deleteRoom (transaction with cascade), reorderRooms all implemented; 6 DAO tests green |
| 2 | Task CRUD operations work correctly at the database layer | VERIFIED | tasks_dao.dart: insert, update, deleteTask (transaction), watchTasksInRoom ordered by nextDueDate; 7 DAO tests green |
| 3 | Task completion records timestamp and auto-calculates next due date | VERIFIED | tasks_dao.dart lines 42-81: transaction inserts TaskCompletion, calls calculateNextDueDate then catchUpToPresent, writes updated nextDueDate |
| 4 | All 8 interval types and custom intervals produce correct next due dates | VERIFIED | scheduling.dart: all 8 IntervalType cases handled via switch; 17 scheduling tests green |
| 5 | Calendar-anchored intervals clamp to last day of month with anchor memory | VERIFIED | scheduling.dart _addMonths() helper uses anchorDay parameter; test "monthly from Jan 31 gives Feb 28, then Mar 31" in scheduling_test.dart |
| 6 | Catch-up logic advances past-due dates to next future occurrence | VERIFIED | catchUpToPresent while loop in scheduling.dart lines 50-66; test coverage confirms |
| 7 | All 14 room types have bundled German-language task templates | VERIFIED | task_templates.dart: 14 keys present (kueche through garten), 3-5 templates each; 11 template tests green |
| 8 | Overdue detection correctly identifies tasks with nextDueDate before today | VERIFIED | tasks_dao.dart getOverdueTaskCount(), rooms_dao.dart watchRoomWithStats(), task_row.dart isOverdue check — all use dueDate.isBefore(today) logic |
| 9 | User can create/edit a room with name and icon from curated picker | VERIFIED | room_form_screen.dart 272 lines: full form with validation, icon_picker_sheet.dart 94 lines: 5-column grid of 25 icons |
| 10 | User can see rooms as 2-column card grid with icon, name, due count, cleanliness bar | VERIFIED | rooms_screen.dart: ReorderableBuilder + GridView.count(crossAxisCount:2); room_card.dart: LinearProgressIndicator(minHeight:3) with Color.lerp sage-to-coral |
| 11 | User can reorder rooms via drag-and-drop | VERIFIED | rooms_screen.dart lines 133-155: ReorderableBuilder.onReorder calls roomActionsProvider.notifier.reorderRooms() |
| 12 | User can see all tasks in a room sorted by due date | VERIFIED | task_list_screen.dart watches tasksInRoomProvider(roomId); DAO orders by nextDueDate ASC |
| 13 | User can create/edit/delete tasks with frequency and effort selectors | VERIFIED | task_form_screen.dart 442 lines: ChoiceChip wrap for 10 presets + custom, SegmentedButton for effort, date picker; delete via long-press confirmation dialog |
| 14 | User can mark task done, which triggers auto-rescheduling | VERIFIED | task_row.dart line 61: checkbox calls taskActionsProvider.notifier.completeTask(task.id), which calls tasks_dao.completeTask() transaction |
| 15 | Template picker shows after room creation for matched room names | VERIFIED | room_form_screen.dart lines 86-101: detectRoomType(name) → showTemplatePickerSheet() → _createTasksFromTemplates() |
Score: 15/15 truths verified
Required Artifacts
| Artifact | Min Lines | Actual Lines | Status | Details |
|---|---|---|---|---|
lib/core/database/database.dart |
— | 83 | VERIFIED | schemaVersion=2, 3 tables, daos:[RoomsDao,TasksDao], MigrationStrategy with PRAGMA foreign_keys |
lib/features/rooms/data/rooms_dao.dart |
— | 127 | VERIFIED | All 6 CRUD methods + watchAllRooms + watchRoomWithStats + cascade delete transaction |
lib/features/tasks/data/tasks_dao.dart |
— | 102 | VERIFIED | All 5 CRUD methods + completeTask transaction + getOverdueTaskCount |
lib/features/tasks/domain/scheduling.dart |
— | 66 | VERIFIED | calculateNextDueDate (8 cases) + catchUpToPresent |
lib/features/tasks/domain/frequency.dart |
— | 62 | VERIFIED | IntervalType enum (8 values, indexed), FrequencyInterval with presets (10) and German labels |
lib/features/tasks/domain/effort_level.dart |
— | 23 | VERIFIED | EffortLevel enum (3 values, indexed), EffortLevelLabel extension with German labels |
lib/features/tasks/domain/relative_date.dart |
— | 18 | VERIFIED | formatRelativeDate returns Heute/Morgen/in X Tagen/Uberfaellig |
lib/features/rooms/domain/room_icons.dart |
— | 40 | VERIFIED | curatedRoomIcons (25 entries), mapIconName with fallback |
lib/features/templates/data/task_templates.dart |
— | 371 | VERIFIED | TaskTemplate class, roomTemplates (14 types, 3-5 each), detectRoomType with alias map |
lib/features/rooms/presentation/rooms_screen.dart |
50 | 188 | VERIFIED | ConsumerWidget, AsyncValue.when, ReorderableBuilder grid, empty state, FAB, delete dialog |
lib/features/rooms/presentation/room_card.dart |
40 | 123 | VERIFIED | InkWell→/rooms/{id}, icon, name, dueTasks badge, LinearProgressIndicator(minHeight:3), long-press menu |
lib/features/rooms/presentation/room_form_screen.dart |
50 | 272 | VERIFIED | ConsumerStatefulWidget, create+edit modes, name validation, icon picker, detectRoomType+template flow |
lib/features/rooms/presentation/icon_picker_sheet.dart |
30 | 94 | VERIFIED | showIconPickerSheet helper, GridView.count(5), selected highlight with primaryContainer |
lib/features/rooms/presentation/room_providers.dart |
— | 48 | VERIFIED | roomWithStatsListProvider stream, RoomActions notifier (create/update/delete/reorder) |
lib/features/tasks/presentation/task_list_screen.dart |
50 | 228 | VERIFIED | ConsumerWidget, tasksInRoomProvider, empty state, ListView, FAB, AppBar with edit/delete |
lib/features/tasks/presentation/task_row.dart |
40 | 106 | VERIFIED | ListTile, Checkbox→completeTask, formatRelativeDate, isOverdue coral color, onTap→edit, onLongPress→delete |
lib/features/tasks/presentation/task_form_screen.dart |
80 | 442 | VERIFIED | ConsumerStatefulWidget, ChoiceChip frequency wrap, SegmentedButton effort, date picker, create+edit |
lib/features/tasks/presentation/task_providers.dart |
— | 65 | VERIFIED | tasksInRoomProvider (manual StreamProvider.family), TaskActions notifier (CRUD + completeTask) |
lib/features/templates/presentation/template_picker_sheet.dart |
40 | 198 | VERIFIED | TemplatePickerSheet StatefulWidget, DraggableScrollableSheet, CheckboxListTile, skip/add buttons |
lib/core/router/router.dart |
— | 85 | VERIFIED | /rooms/new, /rooms/:roomId, /rooms/:roomId/edit, /rooms/:roomId/tasks/new, /rooms/:roomId/tasks/:taskId |
Key Link Verification
| From | To | Via | Status | Details |
|---|---|---|---|---|
tasks_dao.dart |
scheduling.dart |
completeTask calls calculateNextDueDate + catchUpToPresent | WIRED | Lines 57, 70: both functions called in transaction |
database.dart |
rooms_dao.dart |
daos: [RoomsDao, TasksDao] annotation | WIRED | Line 47: daos: [RoomsDao, TasksDao] |
database.dart |
tasks_dao.dart |
daos annotation | WIRED | Line 47: confirmed |
database.dart |
frequency.dart |
intEnum column | WIRED | Line 28: intEnum<IntervalType>()() on intervalType column |
room_providers.dart |
rooms_dao.dart |
ref.watch(appDatabaseProvider) | WIRED | Line 12: ref.watch(appDatabaseProvider) then db.roomsDao.watchRoomWithStats() |
rooms_screen.dart |
room_providers.dart |
ref.watch(roomWithStatsListProvider) | WIRED | Line 21: ref.watch(roomWithStatsListProvider) |
room_card.dart |
router.dart |
context.go('/rooms/…') | WIRED | Line 43: context.go('/rooms/${room.id}') |
task_providers.dart |
tasks_dao.dart |
ref.watch(appDatabaseProvider) | WIRED | Line 18: ref.watch(appDatabaseProvider) then db.tasksDao.watchTasksInRoom(roomId) |
task_list_screen.dart |
task_providers.dart |
ref.watch(tasksInRoomProvider(roomId)) | WIRED | Line 24: ref.watch(tasksInRoomProvider(roomId)) |
task_row.dart |
relative_date.dart |
formatRelativeDate for German labels | WIRED | Line 47: formatRelativeDate(task.nextDueDate, now) |
task_row.dart |
task_providers.dart |
checkbox onChanged calls taskActions.completeTask | WIRED | Line 61: ref.read(taskActionsProvider.notifier).completeTask(task.id) |
room_form_screen.dart |
task_templates.dart |
detectRoomType on room name after save | WIRED | Line 86: detectRoomType(name) |
room_form_screen.dart |
template_picker_sheet.dart |
showTemplatePickerSheet on match | WIRED | Line 90: showTemplatePickerSheet(context: context, ...) |
room_form_screen.dart |
task_providers.dart |
_createTasksFromTemplates calls taskActions.createTask | WIRED | Line 123: taskActions.createTask(...) inside _createTasksFromTemplates |
All 14 key links: WIRED
Requirements Coverage
| Requirement | Source Plan | Description | Status | Evidence |
|---|---|---|---|---|
| ROOM-01 | 02-01, 02-02 | Create room with name and curated icon | SATISFIED | RoomFormScreen + IconPickerSheet + RoomsDao.insertRoom |
| ROOM-02 | 02-01, 02-02 | Edit room name and icon | SATISFIED | RoomFormScreen(roomId:) edit mode + RoomsDao.updateRoom |
| ROOM-03 | 02-01, 02-02 | Delete room with confirmation (cascade) | SATISFIED | Confirmation dialog + RoomsDao.deleteRoom (transaction cascade) |
| ROOM-04 | 02-01, 02-02 | Reorder rooms via drag-and-drop | SATISFIED | ReorderableBuilder in RoomsScreen + RoomsDao.reorderRooms |
| ROOM-05 | 02-01, 02-02 | Room cards with icon, name, due count, cleanliness indicator | SATISFIED | RoomCard: icon, name, dueTasks badge, LinearProgressIndicator with Color.lerp |
| TASK-01 | 02-01, 02-03 | Create task with name, description, frequency, effort | SATISFIED | TaskFormScreen (create mode) + TaskActions.createTask |
| TASK-02 | 02-01, 02-03 | Edit task name, description, frequency, effort | SATISFIED | TaskFormScreen (edit mode): loads existing task, all fields editable |
| TASK-03 | 02-01, 02-03 | Delete task with confirmation | SATISFIED | TaskRow long-press → confirmation dialog → TaskActions.deleteTask |
| TASK-04 | 02-01, 02-03 | Frequency interval presets (10 options) + custom | SATISFIED | FrequencyInterval.presets (10 entries: daily through yearly) + custom ChoiceChip + number/unit picker |
| TASK-05 | 02-01, 02-03 | Effort level (low/medium/high) | SATISFIED | EffortLevel enum + SegmentedButton in TaskFormScreen |
| TASK-06 | 02-01, 02-03 | Tasks sorted by due date | SATISFIED | watchTasksInRoom orders by nextDueDate ASC at DAO level |
| TASK-07 | 02-01, 02-03 | Mark task done, records completion, auto-schedules | SATISFIED | Checkbox → completeTask → TasksDao transaction (insert completion + calculateNextDueDate + catchUpToPresent + update) |
| TASK-08 | 02-01, 02-03 | Overdue tasks visually highlighted | SATISFIED | task_row.dart: isOverdue → _overdueColor (0xFFE07A5F) on due date text; room_card.dart: cleanlinessRatio → red progress bar |
| TMPL-01 | 02-01, 02-04 | Template selection prompt after room creation | SATISFIED | room_form_screen.dart: detectRoomType → showTemplatePickerSheet → _createTasksFromTemplates |
| TMPL-02 | 02-01, 02-04 | 14 preset room types with German templates | SATISFIED | task_templates.dart: kueche, badezimmer, schlafzimmer, wohnzimmer, flur, buero, garage, balkon, waschkueche, keller, kinderzimmer, gaestezimmer, esszimmer, garten (14 confirmed) |
15/15 requirements satisfied. No orphaned requirements.
Anti-Patterns Found
| File | Line | Pattern | Severity | Impact |
|---|---|---|---|---|
| None | — | — | — | — |
No TODO/FIXME comments, no placeholder bodies, no empty implementations found. dart analyze lib/ reports zero issues.
Human Verification Required
The following items require a running device. All automated checks pass (59/59 tests green, dart analyze clean), but these visual and interaction behaviors cannot be confirmed programmatically:
1. Template Picker Appearance and Selection
Test: Run the app. Tap FAB on the Rooms screen. Enter "Kueche" as room name. Select any icon. Tap the check button. Expected: A bottom sheet slides up showing 5 task templates (Abspuelen, Herd reinigen, Kuehlschrank reinigen, Backofen reinigen, Muell rausbringen) as CheckboxListTiles, all unchecked. Each shows frequency and effort label. Tapping "Uberspringen" navigates to the room without tasks. Checking templates and tapping "Hinzufuegen" creates those tasks and navigates to the room. Why human: Modal bottom sheet rendering and CheckboxListTile state cannot be exercised without a real Flutter runtime.
2. Task Completion and Auto-Rescheduling Feel
Test: Open any room with tasks. Tap the leading checkbox on a task. Expected: The task's due date updates immediately (reactive stream). The task may re-sort in the list. No undo prompt. For a weekly task, the new due date is exactly 7 days from the original due date (not from today). Why human: Real-time stream propagation and sort-order change require observing a running UI.
3. Drag-and-Drop Reorder Persistence
Test: Create 3+ rooms. Long-press a room card and drag it to a new position. Navigate to Settings and back to Rooms. Expected: The new room order persists after navigation. Why human: Drag gesture, onReorder callback, and persistence across navigation require device interaction.
4. Overdue Highlighting Visual Rendering
Test: Create a task and manually set its initial due date to yesterday (or two days ago). Navigate back to the task list. Expected: The due date text on that task row is warm coral (0xFFE07A5F). The room card's cleanliness bar shifts toward red. Why human: Color rendering values and gradient interpolation require visual inspection.
5. Custom Room Without Template Prompt
Test: Create a room named "Mein Hobbyraum". Expected: No template picker bottom sheet appears. The app navigates directly to the (empty) task list for the new room. Why human: Confirming absence of UI elements requires running device observation.
Summary
Phase 2 is fully implemented at the code level. The goal — "Users can create and manage rooms and tasks, mark tasks done, and trust the app to schedule the next occurrence automatically" — is achieved by the codebase:
- Data layer (Plan 02-01): Drift schema v2 with Rooms/Tasks/TaskCompletions tables, RoomsDao and TasksDao with all CRUD operations, pure scheduling utility handling all 8 interval types with calendar anchoring and catch-up logic, and German task templates for all 14 room types.
- Room UI (Plan 02-02): 2-column reorderable card grid, create/edit form with icon picker, cascade-warning delete dialog, cleanliness progress bar.
- Task UI (Plan 02-03): Task list screen with sorted rows, checkbox completion, overdue coral highlighting, create/edit form with frequency presets and custom interval, effort selector.
- Template flow (Plan 02-04): Room creation detects room type, shows checklist bottom sheet, creates selected tasks atomically.
All 59 unit tests pass. All 14 key links are wired. All 15 requirements are satisfied. Zero placeholder code or dart analysis issues detected.
The remaining items flagged for human verification are purely visual or interaction behaviors that cannot be confirmed without a running device.
Verified: 2026-03-15T22:00:00Z Verifier: Claude (gsd-verifier)