diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md
index 90f7550..1d8ba41 100644
--- a/.planning/ROADMAP.md
+++ b/.planning/ROADMAP.md
@@ -50,7 +50,9 @@ Plans:
1. Every task completion (tap done in any view) is recorded in the database with a precise timestamp — data persists across app restarts
2. From a task's detail or context menu the user can open a history view listing all past completion dates for that task in reverse-chronological order
3. The history view shows a meaningful empty state if the task has never been completed
-**Plans**: TBD
+**Plans:** 1 plan
+Plans:
+- [ ] 06-01-PLAN.md — DAO query + history bottom sheet + TaskFormScreen integration + CalendarTaskRow navigation
### Phase 7: Task Sorting
**Goal**: Users can reorder task lists by the dimension most useful to them — name, how often the task recurs, or how much effort it requires
@@ -72,5 +74,5 @@ Plans:
| 3. Daily Plan and Cleanliness | v1.0 | 3/3 | Complete | 2026-03-16 |
| 4. Notifications | v1.0 | 3/3 | Complete | 2026-03-16 |
| 5. Calendar Strip | 2/2 | Complete | 2026-03-16 | - |
-| 6. Task History | v1.1 | 0/? | Not started | - |
+| 6. Task History | v1.1 | 0/1 | Planned | - |
| 7. Task Sorting | v1.1 | 0/? | Not started | - |
diff --git a/.planning/phases/06-task-history/06-01-PLAN.md b/.planning/phases/06-task-history/06-01-PLAN.md
new file mode 100644
index 0000000..6bffe4d
--- /dev/null
+++ b/.planning/phases/06-task-history/06-01-PLAN.md
@@ -0,0 +1,312 @@
+---
+phase: 06-task-history
+plan: 01
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - lib/features/tasks/data/tasks_dao.dart
+ - lib/features/tasks/data/tasks_dao.g.dart
+ - lib/features/tasks/presentation/task_history_sheet.dart
+ - lib/features/tasks/presentation/task_form_screen.dart
+ - lib/features/home/presentation/calendar_task_row.dart
+ - lib/l10n/app_de.arb
+ - lib/l10n/app_localizations.dart
+ - lib/l10n/app_localizations_de.dart
+ - test/features/tasks/data/task_history_dao_test.dart
+autonomous: true
+requirements: [HIST-01, HIST-02]
+
+must_haves:
+ truths:
+ - "Every task completion is recorded with a timestamp and persists across app restarts"
+ - "User can open a history view from the task edit form showing all past completion dates in reverse-chronological order"
+ - "History view shows a meaningful empty state if the task has never been completed"
+ artifacts:
+ - path: "lib/features/tasks/data/tasks_dao.dart"
+ provides: "watchCompletionsForTask(int taskId) stream method"
+ contains: "watchCompletionsForTask"
+ - path: "lib/features/tasks/presentation/task_history_sheet.dart"
+ provides: "Bottom sheet displaying task completion history"
+ exports: ["showTaskHistorySheet"]
+ - path: "lib/features/tasks/presentation/task_form_screen.dart"
+ provides: "Verlauf button in edit mode opening history sheet"
+ contains: "showTaskHistorySheet"
+ - path: "lib/features/home/presentation/calendar_task_row.dart"
+ provides: "onTap navigation to task edit form"
+ contains: "context.go"
+ - path: "test/features/tasks/data/task_history_dao_test.dart"
+ provides: "Tests for completion history DAO query"
+ min_lines: 30
+ key_links:
+ - from: "lib/features/tasks/presentation/task_form_screen.dart"
+ to: "lib/features/tasks/presentation/task_history_sheet.dart"
+ via: "showTaskHistorySheet call in Verlauf button onTap"
+ pattern: "showTaskHistorySheet"
+ - from: "lib/features/tasks/presentation/task_history_sheet.dart"
+ to: "lib/features/tasks/data/tasks_dao.dart"
+ via: "watchCompletionsForTask stream consumption"
+ pattern: "watchCompletionsForTask"
+ - from: "lib/features/home/presentation/calendar_task_row.dart"
+ to: "TaskFormScreen"
+ via: "GoRouter navigation on row tap"
+ pattern: "context\\.go.*tasks"
+---
+
+
+Add task completion history: a DAO query to fetch completions, a bottom sheet to display them, integration into the task edit form, and CalendarTaskRow onTap navigation.
+
+Purpose: Users can see exactly when each task was completed in the past, building trust that the scheduling loop is working correctly.
+Output: Working history view accessible from task edit form, completion data surfaced from existing TaskCompletions table.
+
+
+
+@/home/jlmak/.claude/get-shit-done/workflows/execute-plan.md
+@/home/jlmak/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/STATE.md
+@.planning/phases/06-task-history/06-CONTEXT.md
+
+
+
+
+
+From lib/core/database/database.dart:
+```dart
+/// TaskCompletions table: records when a task was completed.
+class TaskCompletions extends Table {
+ IntColumn get id => integer().autoIncrement()();
+ IntColumn get taskId => integer().references(Tasks, #id)();
+ DateTimeColumn get completedAt => dateTime()();
+}
+
+@DriftDatabase(
+ tables: [Rooms, Tasks, TaskCompletions],
+ daos: [RoomsDao, TasksDao, DailyPlanDao, CalendarDao],
+)
+class AppDatabase extends _$AppDatabase { ... }
+```
+
+From lib/features/tasks/data/tasks_dao.dart:
+```dart
+@DriftAccessor(tables: [Tasks, TaskCompletions])
+class TasksDao extends DatabaseAccessor with _$TasksDaoMixin {
+ TasksDao(super.attachedDatabase);
+
+ Stream> watchTasksInRoom(int roomId) { ... }
+ Future insertTask(TasksCompanion task) => into(tasks).insert(task);
+ Future updateTask(Task task) => update(tasks).replace(task);
+ Future deleteTask(int taskId) { ... }
+ Future completeTask(int taskId, {DateTime? now}) { ... }
+ Future getOverdueTaskCount(int roomId, {DateTime? today}) { ... }
+}
+```
+
+From lib/features/tasks/presentation/task_form_screen.dart:
+```dart
+class TaskFormScreen extends ConsumerStatefulWidget {
+ final int? roomId;
+ final int? taskId;
+ const TaskFormScreen({super.key, this.roomId, this.taskId});
+ bool get isEditing => taskId != null;
+}
+// build() returns Scaffold with AppBar + Form > ListView with fields
+// In edit mode: _existingTask is loaded via _loadExistingTask()
+```
+
+From lib/features/home/presentation/calendar_task_row.dart:
+```dart
+class CalendarTaskRow extends StatelessWidget {
+ const CalendarTaskRow({
+ super.key,
+ required this.taskWithRoom,
+ required this.onCompleted,
+ this.isOverdue = false,
+ });
+ final TaskWithRoom taskWithRoom;
+ final VoidCallback onCompleted;
+ final bool isOverdue;
+}
+// TaskWithRoom has: task (Task), roomName (String), roomId (int)
+```
+
+From lib/features/home/domain/daily_plan_models.dart:
+```dart
+class TaskWithRoom {
+ final Task task;
+ final String roomName;
+ final int roomId;
+ const TaskWithRoom({required this.task, required this.roomName, required this.roomId});
+}
+```
+
+Bottom sheet pattern from lib/features/rooms/presentation/icon_picker_sheet.dart:
+```dart
+Future showIconPickerSheet({
+ required BuildContext context,
+ String? selectedIconName,
+}) {
+ return showModalBottomSheet(
+ context: context,
+ isScrollControlled: true,
+ builder: (context) => IconPickerSheet(...),
+ );
+}
+// Sheet uses SafeArea > Padding > Column(mainAxisSize: MainAxisSize.min) with drag handle
+```
+
+Router pattern from lib/core/router/router.dart:
+```dart
+// Task edit route: /rooms/:roomId/tasks/:taskId
+GoRoute(
+ path: 'tasks/:taskId',
+ builder: (context, state) {
+ final taskId = int.parse(state.pathParameters['taskId']!);
+ return TaskFormScreen(taskId: taskId);
+ },
+),
+```
+
+
+
+
+
+
+ Task 1: Add DAO query, provider, localization, and tests for completion history
+
+ lib/features/tasks/data/tasks_dao.dart,
+ lib/features/tasks/data/tasks_dao.g.dart,
+ lib/l10n/app_de.arb,
+ lib/l10n/app_localizations.dart,
+ lib/l10n/app_localizations_de.dart,
+ test/features/tasks/data/task_history_dao_test.dart
+
+
+ - watchCompletionsForTask(taskId) returns Stream of TaskCompletion list ordered by completedAt DESC (newest first)
+ - Empty list returned when no completions exist for a given taskId
+ - After completeTask(taskId) is called, watchCompletionsForTask(taskId) emits a list containing the new completion with correct timestamp
+ - Completions for different tasks are isolated (taskId=1 completions do not appear in taskId=2 stream)
+ - Multiple completions for the same task are all returned in reverse-chronological order
+
+
+ RED phase:
+ Create test/features/tasks/data/task_history_dao_test.dart with tests for the behaviors above.
+ Use the existing in-memory database test pattern: AppDatabase(NativeDatabase.memory()), get TasksDao, insert a room and tasks, then test.
+ Run tests -- they MUST fail (watchCompletionsForTask does not exist yet).
+
+ GREEN phase:
+ 1. In lib/features/tasks/data/tasks_dao.dart, add:
+ ```dart
+ /// Watch all completions for a task, newest first.
+ Stream> watchCompletionsForTask(int taskId) {
+ return (select(taskCompletions)
+ ..where((c) => c.taskId.equals(taskId))
+ ..orderBy([(c) => OrderingTerm.desc(c.completedAt)]))
+ .watch();
+ }
+ ```
+ 2. Run `dart run build_runner build --delete-conflicting-outputs` to regenerate tasks_dao.g.dart.
+ 3. Run tests -- they MUST pass.
+
+ Then add localization strings to lib/l10n/app_de.arb:
+ - "taskHistoryTitle": "Verlauf"
+ - "taskHistoryEmpty": "Noch nie erledigt"
+ - "taskHistoryCount": "{count} Mal erledigt" with @taskHistoryCount placeholder for count (int)
+
+ Run `flutter gen-l10n` to regenerate app_localizations.dart and app_localizations_de.dart.
+
+ NOTE: No separate Riverpod provider is needed -- the bottom sheet will access the DAO directly via appDatabaseProvider (same pattern as _loadExistingTask in TaskFormScreen). This keeps it simple since the sheet is a one-shot modal, not a long-lived screen.
+
+
+ cd /home/jlmak/Projects/jlmak/HouseHoldKeaper && flutter test test/features/tasks/data/task_history_dao_test.dart -r expanded && flutter analyze --no-fatal-infos
+
+
+ watchCompletionsForTask method exists on TasksDao, returns Stream of completions sorted newest-first.
+ All new DAO tests pass. All 101+ existing tests still pass.
+ Three German localization strings (taskHistoryTitle, taskHistoryEmpty, taskHistoryCount) are available via AppLocalizations.
+
+
+
+
+ Task 2: Build history bottom sheet, wire into TaskFormScreen, add CalendarTaskRow navigation
+
+ lib/features/tasks/presentation/task_history_sheet.dart,
+ lib/features/tasks/presentation/task_form_screen.dart,
+ lib/features/home/presentation/calendar_task_row.dart
+
+
+ 1. Create lib/features/tasks/presentation/task_history_sheet.dart:
+ - Export a top-level function: `Future<void> showTaskHistorySheet({required BuildContext context, required int taskId})`
+ - Uses `showModalBottomSheet` with `isScrollControlled: true` following icon_picker_sheet.dart pattern
+ - The sheet widget is a ConsumerWidget (needs ref to access DAO)
+ - Uses `ref.read(appDatabaseProvider).tasksDao.watchCompletionsForTask(taskId)` wrapped in a StreamBuilder
+ - Layout: SafeArea > Padding(16) > Column(mainAxisSize: min):
+ a. Drag handle (same as icon_picker_sheet: Container 32x4, onSurfaceVariant 0.4 alpha, rounded)
+ b. Title: AppLocalizations.of(context).taskHistoryTitle (i.e. "Verlauf"), titleMedium style
+ c. Optional: completion count summary below title using taskHistoryCount string -- show only when count > 0
+ d. SizedBox(height: 16)
+ e. StreamBuilder on watchCompletionsForTask:
+ - Loading: Center(CircularProgressIndicator())
+ - Empty data: centered Column with Icon(Icons.history, size: 48, color: onSurfaceVariant) + SizedBox(8) + Text(taskHistoryEmpty), style: bodyLarge, color: onSurfaceVariant
+ - Has data: ConstrainedBox(maxHeight: MediaQuery.of(context).size.height * 0.4) > ListView.builder:
+ Each item: ListTile with leading Icon(Icons.check_circle_outline, color: primary), title: DateFormat('dd.MM.yyyy', 'de').format(completion.completedAt), subtitle: DateFormat('HH:mm', 'de').format(completion.completedAt)
+ f. SizedBox(height: 8) at bottom
+
+ 2. Modify lib/features/tasks/presentation/task_form_screen.dart:
+ - Import task_history_sheet.dart
+ - In the build() method's ListView children, AFTER the due date picker section and ONLY when `widget.isEditing` is true, add:
+ ```
+ const SizedBox(height: 24),
+ const Divider(),
+ ListTile(
+ leading: const Icon(Icons.history),
+ title: Text(l10n.taskHistoryTitle),
+ trailing: const Icon(Icons.chevron_right),
+ onTap: () => showTaskHistorySheet(context: context, taskId: widget.taskId!),
+ ),
+ ```
+ - This adds a "Verlauf" row that opens the history bottom sheet
+
+ 3. Modify lib/features/home/presentation/calendar_task_row.dart:
+ - Add an onTap callback to the ListTile that navigates to the task edit form
+ - The CalendarTaskRow already has access to taskWithRoom.task.id and taskWithRoom.roomId
+ - Add to ListTile: `onTap: () => context.go('/rooms/${taskWithRoom.roomId}/tasks/${taskWithRoom.task.id}')`
+ - This enables: CalendarTaskRow tap -> TaskFormScreen (edit mode) -> "Verlauf" button -> history sheet
+ - Keep the existing onCompleted checkbox behavior unchanged
+
+
+ cd /home/jlmak/Projects/jlmak/HouseHoldKeaper && flutter test && flutter analyze --no-fatal-infos
+
+
+ History bottom sheet opens from TaskFormScreen in edit mode via "Verlauf" row.
+ Sheet shows completion dates in dd.MM.yyyy + HH:mm format, reverse-chronological.
+ Empty state shows Icons.history + "Noch nie erledigt" message.
+ CalendarTaskRow tapping navigates to TaskFormScreen for that task.
+ All existing tests still pass. dart analyze clean.
+
+
+
+
+
+
+Phase 6 verification checks:
+1. `flutter test` -- all tests pass (101 existing + new DAO tests)
+2. `flutter analyze --no-fatal-infos` -- zero issues
+3. Manual flow: Open app > tap a task in calendar > task edit form opens > "Verlauf" row visible > tap it > bottom sheet shows history or empty state
+4. Manual flow: Complete a task via checkbox > navigate to that task's edit form > tap "Verlauf" > new completion entry appears with timestamp
+
+
+
+- HIST-01: Task completion recording verified via DAO tests (completions already written by completeTask; new query surfaces them)
+- HIST-02: History bottom sheet accessible from task edit form, shows all past completions reverse-chronologically with German date/time formatting, shows meaningful empty state
+- CalendarTaskRow tapping navigates to task edit form (history one tap away)
+- Zero regressions: all existing tests pass, dart analyze clean
+
+
+