# Feature: Chore Completion Confirmation + Task Refactor

## Overview

**Goal:**
Refactor the "task" concept into three distinct entity types — **Chore**, **Kindness**, and **Penalty** — and implement a chore completion confirmation flow where children can confirm chores and parents approve them.

**User Stories:**

- As a **child**, I can click on a chore and confirm that I completed it. I see a **PENDING** banner (yellow) until a parent confirms.
- As a **child**, I can click an already PENDING chore and cancel my confirmation.
- As a **child**, I see a **COMPLETED** banner (green) on a chore that a parent has approved. That chore is disabled for the rest of the day.
- As a **parent**, I see pending chore confirmations in the **Notifications** tab alongside pending reward requests.
- As a **parent**, I can click a PENDING chore to **approve** it (awarding points) or **reject** it (resetting to available).
- As a **parent**, I can click a non-pending/non-completed chore and award points directly (current behavior). The child view then shows the COMPLETED banner.
- As a **parent**, I can **reset** a completed chore from the kebab menu so the child can confirm it again (points are kept).
- As an **admin**, I can view full tracking history in the database/logs for all confirmation lifecycle events.

**Rules:**
.github/copilot-instructions.md

---

## Design Decisions (Resolved)

### Task Refactor → Chore / Kindness / Penalty

**Decision: Full refactor.**

| Old Concept                                                    | New Concept  | Behavior                                   |
| -------------------------------------------------------------- | ------------ | ------------------------------------------ |
| Task with `is_good=true` (schedulable)                         | **Chore**    | Scheduled, expirable, confirmable by child |
| Task with `is_good=true` (ad-hoc, e.g. "Child was good today") | **Kindness** | Parent-only award, not confirmable         |
| Task with `is_good=false`                                      | **Penalty**  | Parent-only deduction                      |

- The `is_good` field is **removed**. Entity type itself determines point direction.
- The `Task` model is retained in the backend but gains a `type` field: `'chore' | 'kindness' | 'penalty'`.
- `task_api.py` is split into `chore_api.py`, `kindness_api.py`, `penalty_api.py`.
- Existing `is_good=true` tasks are auto-classified as **chore**; `is_good=false` as **penalty**.
- Kindness items must be manually created post-migration (acceptable).

### Merged Pending Table

**Decision: Single `PendingConfirmation` model replaces `PendingReward`.**

- Both pending reward requests and pending chore confirmations live in one `pending_confirmations` table, differentiated by `entity_type`.
- The `/pending-rewards` endpoint is replaced by `/pending-confirmations`.
- `pending_rewards.json` DB file is replaced by `pending_confirmations.json`.

### "Completed Today" Tracking

**Decision: `PendingConfirmation` record with `status='approved'` + `approved_at` timestamp.**

- An approved `PendingConfirmation` record persists (DB-backed, survives restart) and serves as the "completed today" marker.
- The frontend checks if `approved_at` is today to determine the COMPLETED state.
- On **reset**, the record is deleted (status returns to available).
- **Multi-completion history** is preserved via `TrackingEvent` — each confirm/approve/reset cycle generates tracking entries. Query `TrackingEvent` by `child_id + entity_id + date + action='approved'` to count completions per day.

### Navigation

**Decision: Sub-nav under "Tasks" tab.**

- Top-level nav stays 4 items: **Children | Tasks | Rewards | Notifications**
- The "Tasks" tab opens a view with 3 sub-tabs: **Chores | Kindness | Penalties**
- Each sub-tab has its own list view, edit view, and assign view.
- No mobile layout changes needed to the top bar.

### Chore Confirmation Scoping

- Each `PendingConfirmation` is scoped to a **single child**. If a chore is assigned to multiple children, each confirms independently.
- Expired chores **cannot** be confirmed.
- A chore that is already PENDING or COMPLETED today **cannot** be confirmed again (unless reset by parent).

---

## Data Model Changes

### Backend Models

#### `Task` Model (Modified)

File: `backend/models/task.py`

```python
@dataclass
class Task(BaseModel):
    name: str
    points: int
    type: Literal['chore', 'kindness', 'penalty']  # replaces is_good
    image_id: str | None = None
    user_id: str | None = None
```

- `is_good: bool` → **removed**
- `type: Literal['chore', 'kindness', 'penalty']` → **added**
- Migration: `is_good=True` → `type='chore'`, `is_good=False` → `type='penalty'`

#### `PendingConfirmation` Model (New — replaces `PendingReward`)

File: `backend/models/pending_confirmation.py`

```python
@dataclass
class PendingConfirmation(BaseModel):
    child_id: str
    entity_id: str            # task_id or reward_id
    entity_type: str           # 'chore' | 'reward'
    user_id: str
    status: str = "pending"    # 'pending' | 'approved' | 'rejected'
    approved_at: str | None = None  # ISO 8601 UTC timestamp, set on approval
```

- Replaces `PendingReward` (which had `child_id`, `reward_id`, `user_id`, `status`)
- `entity_id` generalizes `reward_id` to work for both chores and rewards
- `entity_type` differentiates between chore confirmations and reward requests
- `approved_at` enables "completed today" checks

#### `TrackingEvent` Model (Extended Types)

File: `backend/models/tracking_event.py`

```python
EntityType = Literal['task', 'reward', 'penalty', 'chore', 'kindness']
ActionType = Literal['activated', 'requested', 'redeemed', 'cancelled', 'confirmed', 'approved', 'rejected', 'reset']
```

New actions:

- `confirmed` — child marks chore as done
- `approved` — parent approves chore completion (points awarded)
- `rejected` — parent rejects chore completion (no point change)
- `reset` — parent resets a completed chore (no point change)

#### `ChildOverride` Model (Extended Types)

File: `backend/models/child_override.py`

```python
entity_type: Literal['task', 'reward']  # → Literal['chore', 'kindness', 'penalty', 'reward']
```

#### `ChildTask` DTO (Modified)

File: `backend/api/child_tasks.py`

```python
class ChildTask:
    def __init__(self, name, type, points, image_id, id):
        self.id = id
        self.name = name
        self.type = type        # replaces is_good
        self.points = points
        self.image_id = image_id
```

#### SSE Event Types (New)

File: `backend/events/types/event_types.py`

```python
class EventType(Enum):
    # ... existing ...
    CHILD_CHORE_CONFIRMATION = "child_chore_confirmation"
```

New payload class — File: `backend/events/types/child_chore_confirmation.py`

```python
class ChildChoreConfirmation(Payload):
    # child_id: str
    # task_id: str
    # operation: 'CONFIRMED' | 'APPROVED' | 'REJECTED' | 'CANCELLED' | 'RESET'
```

#### Error Codes (New)

File: `backend/api/error_codes.py`

```python
class ErrorCodes:
    # ... existing ...
    CHORE_EXPIRED = "CHORE_EXPIRED"
    CHORE_ALREADY_PENDING = "CHORE_ALREADY_PENDING"
    CHORE_ALREADY_COMPLETED = "CHORE_ALREADY_COMPLETED"
    PENDING_NOT_FOUND = "PENDING_NOT_FOUND"
    INSUFFICIENT_POINTS = "INSUFFICIENT_POINTS"
```

### Frontend Models

File: `frontend/vue-app/src/common/models.ts`

```typescript
// Task — modified
export interface Task {
  id: string;
  name: string;
  points: number;
  type: "chore" | "kindness" | "penalty"; // replaces is_good
  image_id: string | null;
  image_url?: string | null;
}

// ChildTask — modified
export interface ChildTask {
  id: string;
  name: string;
  type: "chore" | "kindness" | "penalty"; // replaces is_good
  points: number;
  image_id: string | null;
  image_url?: string | null;
  custom_value?: number | null;
  schedule?: ChoreSchedule | null;
  extension_date?: string | null;
}

// PendingConfirmation — new (replaces PendingReward)
export interface PendingConfirmation {
  id: string;
  child_id: string;
  child_name: string;
  child_image_id: string | null;
  child_image_url?: string | null;
  entity_id: string;
  entity_type: "chore" | "reward";
  entity_name: string;
  entity_image_id: string | null;
  entity_image_url?: string | null;
  status: "pending" | "approved" | "rejected";
  approved_at: string | null;
}

// EntityType — extended
export type EntityType = "chore" | "kindness" | "penalty" | "reward";

// ActionType — extended
export type ActionType =
  | "activated"
  | "requested"
  | "redeemed"
  | "cancelled"
  | "confirmed"
  | "approved"
  | "rejected"
  | "reset";

// SSE event payload — new
export interface ChildChoreConfirmationPayload {
  child_id: string;
  task_id: string;
  operation: "CONFIRMED" | "APPROVED" | "REJECTED" | "CANCELLED" | "RESET";
}
```

---

## Backend Implementation

### API Changes

#### New Files

| File                                               | Description                                                                                                                                           |
| -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `backend/api/chore_api.py`                         | CRUD for chores (type='chore'). Routes: `/chore/add`, `/chore/<id>`, `/chore/<id>/edit`, `/chore/list`, `DELETE /chore/<id>`                          |
| `backend/api/kindness_api.py`                      | CRUD for kindness acts (type='kindness'). Routes: `/kindness/add`, `/kindness/<id>`, `/kindness/<id>/edit`, `/kindness/list`, `DELETE /kindness/<id>` |
| `backend/api/penalty_api.py`                       | CRUD for penalties (type='penalty'). Routes: `/penalty/add`, `/penalty/<id>`, `/penalty/<id>/edit`, `/penalty/list`, `DELETE /penalty/<id>`           |
| `backend/models/pending_confirmation.py`           | `PendingConfirmation` dataclass                                                                                                                       |
| `backend/events/types/child_chore_confirmation.py` | SSE payload class                                                                                                                                     |
| `backend/api/pending_confirmation.py`              | Response DTO for hydrated pending confirmation                                                                                                        |

#### Modified Files

| File                                  | Changes                                                                                                                                                                           |
| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `backend/models/task.py`              | `is_good` → `type` field                                                                                                                                                          |
| `backend/models/tracking_event.py`    | Extend `EntityType` and `ActionType` literals                                                                                                                                     |
| `backend/models/child_override.py`    | Extend `entity_type` literal                                                                                                                                                      |
| `backend/api/child_tasks.py`          | `is_good` → `type` field in DTO                                                                                                                                                   |
| `backend/api/child_api.py`            | Add chore confirmation endpoints, replace `/pending-rewards` with `/pending-confirmations`, update trigger-task to set COMPLETED state, update all `is_good` references to `type` |
| `backend/api/task_api.py`             | Deprecate/remove — logic moves to entity-specific API files                                                                                                                       |
| `backend/api/error_codes.py`          | Add new error codes                                                                                                                                                               |
| `backend/events/types/event_types.py` | Add `CHILD_CHORE_CONFIRMATION`                                                                                                                                                    |
| `backend/db/db.py`                    | Add `pending_confirmations_db`, remove `pending_reward_db`                                                                                                                        |
| `backend/main.py`                     | Register new blueprints, remove `task_api` blueprint                                                                                                                              |

#### New Endpoints (on `child_api.py`)

| Method | Route                              | Actor  | Description                                                                                                                                                                                                                                                     |
| ------ | ---------------------------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `POST` | `/child/<id>/confirm-chore`        | Child  | Body: `{ task_id }`. Creates `PendingConfirmation(entity_type='chore', status='pending')`. Validates: chore assigned, not expired, not already pending/completed today. Tracking: `action='confirmed'`, `delta=0`. SSE: `CHILD_CHORE_CONFIRMATION` (CONFIRMED). |
| `POST` | `/child/<id>/cancel-confirm-chore` | Child  | Body: `{ task_id }`. Deletes the pending confirmation. Tracking: `action='cancelled'`, `delta=0`. SSE: `CHILD_CHORE_CONFIRMATION` (CANCELLED).                                                                                                                  |
| `POST` | `/child/<id>/approve-chore`        | Parent | Body: `{ task_id }`. Sets `status='approved'`, `approved_at=now()`. Awards points (respects overrides). Tracking: `action='approved'`, `delta=+points`. SSE: `CHILD_CHORE_CONFIRMATION` (APPROVED) + `CHILD_TASK_TRIGGERED`.                                    |
| `POST` | `/child/<id>/reject-chore`         | Parent | Body: `{ task_id }`. Deletes the pending confirmation. Tracking: `action='rejected'`, `delta=0`. SSE: `CHILD_CHORE_CONFIRMATION` (REJECTED).                                                                                                                    |
| `POST` | `/child/<id>/reset-chore`          | Parent | Body: `{ task_id }`. Deletes the approved confirmation record. Tracking: `action='reset'`, `delta=0`. SSE: `CHILD_CHORE_CONFIRMATION` (RESET).                                                                                                                  |
| `GET`  | `/pending-confirmations`           | Parent | Returns all pending `PendingConfirmation` records for the user, hydrated with child/entity names and images. Replaces `/pending-rewards`.                                                                                                                       |

#### Modified Endpoints

| Endpoint                                 | Change                                                                                                                                                                                        |
| ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| `POST /child/<id>/trigger-task`          | When a parent triggers a chore directly (no pending), create an approved `PendingConfirmation` so child view shows COMPLETED. Update entity_type references from `'task'` to the actual type. |
| `POST /child/<id>/request-reward`        | Create `PendingConfirmation(entity_type='reward')` instead of `PendingReward`.                                                                                                                |
| `POST /child/<id>/cancel-request-reward` | Query `PendingConfirmation` by `entity_type='reward'` instead of `PendingReward`.                                                                                                             |
| `POST /child/<id>/trigger-reward`        | Query/remove `PendingConfirmation` by `entity_type='reward'` instead of `PendingReward`.                                                                                                      |
| `GET /child/<id>/list-tasks`             | Add `pending_status` and `approved_at` fields to each chore in the response (from `PendingConfirmation` lookup).                                                                              |
| `PUT /child/<id>/set-tasks`              | Accept `type` parameter instead of `type: 'good'                                                                                                                                              | 'bad'`. |

#### Database Migration

A one-time migration script (`backend/scripts/migrate_tasks_to_types.py`):

1. For each record in `tasks.json`: if `is_good=True` → set `type='chore'`, if `is_good=False` → set `type='penalty'`. Remove `is_good` field.
2. For each record in `pending_rewards.json`: convert to `PendingConfirmation` format with `entity_type='reward'`, `entity_id=reward_id`. Write to `pending_confirmations.json`.
3. For each record in `tracking_events.json`: update `entity_type='task'` → `'chore'` or `'penalty'` based on the referenced task's old `is_good` value.
4. For each record in `child_overrides.json`: update `entity_type='task'` → `'chore'` or `'penalty'` based on the referenced task's old `is_good` value.

---

## Backend Tests

### Test File: `backend/tests/test_chore_api.py` (New)

- [ ] `test_add_chore` — PUT `/chore/add` with `name`, `points` → 201, type auto-set to `'chore'`
- [ ] `test_add_chore_missing_fields` — 400 with `MISSING_FIELDS`
- [ ] `test_list_chores` — GET `/chore/list` returns only `type='chore'` tasks
- [ ] `test_get_chore` — GET `/chore/<id>` → 200
- [ ] `test_get_chore_not_found` — 404
- [ ] `test_edit_chore` — PUT `/chore/<id>/edit` → 200
- [ ] `test_edit_system_chore_clones_to_user` — editing a `user_id=None` chore creates a user copy
- [ ] `test_delete_chore` — DELETE `/chore/<id>` → 200, removed from children's task lists
- [ ] `test_delete_chore_not_found` — 404
- [ ] `test_delete_chore_removes_from_assigned_children` — cascade cleanup

### Test File: `backend/tests/test_kindness_api.py` (New)

- [ ] `test_add_kindness` — PUT `/kindness/add` → 201, type auto-set to `'kindness'`
- [ ] `test_list_kindness` — returns only `type='kindness'` tasks
- [ ] `test_edit_kindness` — PUT `/kindness/<id>/edit` → 200
- [ ] `test_delete_kindness` — cascade removal

### Test File: `backend/tests/test_penalty_api.py` (New)

- [ ] `test_add_penalty` — PUT `/penalty/add` → 201, type auto-set to `'penalty'`
- [ ] `test_list_penalties` — returns only `type='penalty'` tasks
- [ ] `test_edit_penalty` — PUT `/penalty/<id>/edit` → 200
- [ ] `test_delete_penalty` — cascade removal

### Test File: `backend/tests/test_chore_confirmation.py` (New)

#### Child Confirm Flow

- [ ] `test_child_confirm_chore_success` — POST `/child/<id>/confirm-chore` with `{ task_id }` → 200, `PendingConfirmation` record created with `status='pending'`, `entity_type='chore'`
- [ ] `test_child_confirm_chore_not_assigned` — 400 `ENTITY_NOT_ASSIGNED` when chore is not in child's task list
- [ ] `test_child_confirm_chore_not_found` — 404 `TASK_NOT_FOUND` when task_id doesn't exist
- [ ] `test_child_confirm_chore_child_not_found` — 404 `CHILD_NOT_FOUND`
- [ ] `test_child_confirm_chore_already_pending` — 400 `CHORE_ALREADY_PENDING` when a pending confirmation already exists
- [ ] `test_child_confirm_chore_already_completed_today` — 400 `CHORE_ALREADY_COMPLETED` when an approved confirmation exists for today
- [ ] `test_child_confirm_chore_expired` — 400 `CHORE_EXPIRED` when chore is past its deadline
- [ ] `test_child_confirm_chore_creates_tracking_event` — TrackingEvent with `action='confirmed'`, `delta=0`, `entity_type='chore'`
- [ ] `test_child_confirm_chore_wrong_type` — 400 when task is kindness or penalty (not confirmable)

#### Child Cancel Flow

- [ ] `test_child_cancel_confirm_success` — POST `/child/<id>/cancel-confirm-chore` → 200, pending record deleted
- [ ] `test_child_cancel_confirm_not_pending` — 400 `PENDING_NOT_FOUND`
- [ ] `test_child_cancel_confirm_creates_tracking_event` — TrackingEvent with `action='cancelled'`, `delta=0`

#### Parent Approve Flow

- [ ] `test_parent_approve_chore_success` — POST `/child/<id>/approve-chore` → 200, points increased, `status='approved'`, `approved_at` set
- [ ] `test_parent_approve_chore_with_override` — uses `custom_value` from override instead of base points
- [ ] `test_parent_approve_chore_not_pending` — 400 `PENDING_NOT_FOUND`
- [ ] `test_parent_approve_chore_creates_tracking_event` — TrackingEvent with `action='approved'`, `delta=+points`
- [ ] `test_parent_approve_chore_points_correct` — `points_before` + task points == `points_after` on child

#### Parent Reject Flow

- [ ] `test_parent_reject_chore_success` — POST `/child/<id>/reject-chore` → 200, pending record deleted, points unchanged
- [ ] `test_parent_reject_chore_not_pending` — 400 `PENDING_NOT_FOUND`
- [ ] `test_parent_reject_chore_creates_tracking_event` — TrackingEvent with `action='rejected'`, `delta=0`

#### Parent Reset Flow

- [ ] `test_parent_reset_chore_success` — POST `/child/<id>/reset-chore` → 200, approved record deleted, points unchanged
- [ ] `test_parent_reset_chore_not_completed` — 400 when no approved record exists
- [ ] `test_parent_reset_chore_creates_tracking_event` — TrackingEvent with `action='reset'`, `delta=0`
- [ ] `test_parent_reset_then_child_confirm_again` — full cycle: confirm → approve → reset → confirm → approve (two approvals tracked)

#### Parent Direct Trigger

- [ ] `test_parent_trigger_chore_directly_creates_approved_confirmation` — POST `/child/<id>/trigger-task` with a chore → creates approved PendingConfirmation so child view shows COMPLETED

#### Pending Confirmations List

- [ ] `test_list_pending_confirmations_returns_chores_and_rewards` — GET `/pending-confirmations` returns both types
- [ ] `test_list_pending_confirmations_empty` — returns empty list when none exist
- [ ] `test_list_pending_confirmations_hydrates_names_and_images` — response includes `child_name`, `entity_name`, image IDs
- [ ] `test_list_pending_confirmations_excludes_approved` — only pending status returned
- [ ] `test_list_pending_confirmations_filters_by_user` — only returns confirmations for the authenticated user's children

### Test File: `backend/tests/test_task_api.py` (Modified)

- [ ] Update all existing tests that use `is_good` to use `type` instead
- [ ] `test_add_task` → split into `test_add_chore`, `test_add_kindness`, `test_add_penalty` (or remove if fully migrated to entity-specific APIs)
- [ ] `test_list_tasks_sorted` → update sort expectations for `type` field

### Test File: `backend/tests/test_child_api.py` (Modified)

- [ ] Update tests referencing `is_good` to use `type`
- [ ] Update `set-tasks` tests for new `type` parameter values (`'chore'`, `'kindness'`, `'penalty'`)
- [ ] Update `list-tasks` response assertions to check for `pending_status` and `approved_at` fields on chores
- [ ] Update `trigger-task` tests to verify `PendingConfirmation` creation for chores
- [ ] Update `request-reward` / `cancel-request-reward` / `trigger-reward` tests to use `PendingConfirmation` model
- [ ] Replace `pending-rewards` endpoint tests with `pending-confirmations`

---

## Frontend Implementation

### New Files

| File                                          | Description                                                                                                              |
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `src/components/task/ChoreView.vue`           | Admin list of chores (type='chore'). Same pattern as current `TaskView.vue` with blue theme.                             |
| `src/components/task/KindnessView.vue`        | Admin list of kindness acts (type='kindness'). Yellow theme.                                                             |
| `src/components/task/PenaltyView.vue`         | Admin list of penalties (type='penalty'). Red theme.                                                                     |
| `src/components/task/ChoreEditView.vue`       | Create/edit chore form. Fields: name, points, image. No `is_good` toggle.                                                |
| `src/components/task/KindnessEditView.vue`    | Create/edit kindness form. Fields: name, points, image.                                                                  |
| `src/components/task/PenaltyEditView.vue`     | Create/edit penalty form. Fields: name, points, image.                                                                   |
| `src/components/task/TaskSubNav.vue`          | Sub-nav component with Chores / Kindness / Penalties tabs. Renders as a tab bar within the Tasks view area.              |
| `src/components/child/ChoreAssignView.vue`    | Assign chores to child (replaces `TaskAssignView` with `type='good'`).                                                   |
| `src/components/child/KindnessAssignView.vue` | Assign kindness acts to child.                                                                                           |
| `src/components/child/PenaltyAssignView.vue`  | Assign penalties to child (replaces `TaskAssignView` with `type='bad'`).                                                 |
| `src/components/child/ChoreConfirmDialog.vue` | Modal dialog for child to confirm chore completion. "Did you finish [chore name]?" with Confirm / Cancel buttons.        |
| `src/components/child/ChoreApproveDialog.vue` | Modal dialog for parent to approve/reject pending chore. Shows chore name, child name, points. Approve / Reject buttons. |

### Modified Files

| File                                               | Changes                                                                                                                                                                                                                                                                                                                   |
| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `src/common/models.ts`                             | Replace `Task.is_good` with `Task.type`, add `PendingConfirmation` interface, extend `EntityType`/`ActionType`, add `ChildChoreConfirmationPayload`, replace `PendingReward` with `PendingConfirmation`. Add `pending_status` and `approved_at` to `ChildTask`.                                                           |
| `src/common/backendEvents.ts`                      | Add `child_chore_confirmation` event listener pattern.                                                                                                                                                                                                                                                                    |
| `src/common/api.ts`                                | Add `confirmChore()`, `cancelConfirmChore()`, `approveChore()`, `rejectChore()`, `resetChore()`, `fetchPendingConfirmations()`. Remove `fetchPendingRewards()`.                                                                                                                                                           |
| `src/components/child/ChildView.vue`               | Add chore tap handler → show `ChoreConfirmDialog`. Add PENDING (yellow) / COMPLETED (green) banner rendering. Handle cancel-confirm on PENDING tap. Filter kindness acts into new scrolling row. Listen for `child_chore_confirmation` SSE events.                                                                        |
| `src/components/child/ParentView.vue`              | Add PENDING/COMPLETED banners on chores. Handle approve/reject on PENDING chore tap. Add "Reset" to kebab menu for completed chores. Add "Assign Kindness" button. Update `trigger-task` to create approved confirmation. Replace `is_good` filters with `type` checks. Listen for `child_chore_confirmation` SSE events. |
| `src/components/notification/NotificationView.vue` | Fetch from `/api/pending-confirmations` instead of `/api/pending-rewards`. Render both pending chores and pending rewards with differentiation (icon/label). Listen for `child_chore_confirmation` events in addition to existing `child_reward_request`.                                                                 |
| `src/layout/ParentLayout.vue`                      | "Tasks" nav icon remains, routes to a view housing `TaskSubNav` with sub-tabs.                                                                                                                                                                                                                                            |
| `src/components/task/TaskEditView.vue`             | Remove or repurpose. Logic moves to entity-specific edit views (no `is_good` toggle).                                                                                                                                                                                                                                     |
| `src/components/task/TaskView.vue`                 | Remove or repurpose into the sub-nav container view.                                                                                                                                                                                                                                                                      |
| `src/components/child/TaskAssignView.vue`          | Remove. Replaced by `ChoreAssignView`, `KindnessAssignView`, `PenaltyAssignView`.                                                                                                                                                                                                                                         |
| Router config                                      | Add routes for new views. Update existing task routes to chore/kindness/penalty.                                                                                                                                                                                                                                          |

### Files to Remove

| File                                   | Reason                                    |
| -------------------------------------- | ----------------------------------------- |
| `backend/models/pending_reward.py`     | Replaced by `pending_confirmation.py`     |
| `backend/api/pending_reward.py`        | Replaced by `pending_confirmation.py` DTO |
| `backend/data/db/pending_rewards.json` | Replaced by `pending_confirmations.json`  |

### ChildView Chore Tap Flow

```
Child taps chore card
  ├─ Chore expired? → No action (grayed out, "TOO LATE" stamp)
  ├─ Chore COMPLETED today? → No action (grayed out, "COMPLETED" stamp)
  ├─ Chore PENDING? → Show ModalDialog "Cancel confirmation?"
  │    └─ Confirm → POST /child/<id>/cancel-confirm-chore
  └─ Chore available? → Show ChoreConfirmDialog "Did you finish [name]?"
       └─ Confirm → POST /child/<id>/confirm-chore
```

### ParentView Chore Tap Flow

```
Parent taps chore card
  ├─ Chore PENDING? → Show ChoreApproveDialog
  │    ├─ Approve → POST /child/<id>/approve-chore (awards points)
  │    └─ Reject → POST /child/<id>/reject-chore (resets to available)
  ├─ Chore COMPLETED today? → No tap action. Kebab menu has "Reset"
  │    └─ Reset → POST /child/<id>/reset-chore
  └─ Chore available? → Show TaskConfirmDialog (current behavior)
       └─ Confirm → POST /child/<id>/trigger-task (sets COMPLETED)
```

### Banner Styling

| State     | Banner Text | Text Color                 | Background              | CSS Variable Suggestion |
| --------- | ----------- | -------------------------- | ----------------------- | ----------------------- |
| Pending   | `PENDING`   | Yellow (`--color-warning`) | Dark semi-transparent   | `--banner-bg-pending`   |
| Completed | `COMPLETED` | Green (`--color-success`)  | Dark semi-transparent   | `--banner-bg-completed` |
| Expired   | `TOO LATE`  | Red (existing)             | Gray overlay (existing) | (existing styles)       |

---

## Frontend Tests

### Test File: `components/__tests__/ChoreConfirmDialog.test.ts` (New)

- [ ] `renders chore name in dialog`
- [ ] `emits confirm event on confirm button click`
- [ ] `emits cancel event on cancel button click`

### Test File: `components/__tests__/ChoreApproveDialog.test.ts` (New)

- [ ] `renders chore name and points in dialog`
- [ ] `emits approve event on approve button click`
- [ ] `emits reject event on reject button click`

### Test File: `components/__tests__/TaskSubNav.test.ts` (New)

- [ ] `renders three sub-tabs: Chores, Kindness, Penalties`
- [ ] `highlights active tab based on route`
- [ ] `navigates on tab click`

### Test File: `components/__tests__/ChoreView.test.ts` (New)

- [ ] `fetches and renders chore list`
- [ ] `navigates to edit on item click`
- [ ] `shows delete confirmation modal`
- [ ] `refreshes on task_modified SSE event`

### Test File: `components/__tests__/NotificationView.test.ts` (Modified)

- [ ] `fetches from /api/pending-confirmations`
- [ ] `renders both pending chores and pending rewards`
- [ ] `differentiates chore vs reward with label/icon`
- [ ] `refreshes on child_chore_confirmation SSE event`
- [ ] `refreshes on child_reward_request SSE event`

### Test File: `components/__tests__/ChildView.test.ts` (Modified / New)

- [ ] `shows PENDING banner on chore with pending confirmation`
- [ ] `shows COMPLETED banner on chore completed today`
- [ ] `opens ChoreConfirmDialog on available chore tap`
- [ ] `opens cancel dialog on PENDING chore tap`
- [ ] `does not allow tap on expired chore`
- [ ] `does not allow tap on COMPLETED chore`
- [ ] `renders kindness scrolling row`
- [ ] `refreshes on child_chore_confirmation SSE event`

### Test File: `components/__tests__/ParentView.test.ts` (Modified / New)

- [ ] `shows PENDING banner on chore with pending confirmation`
- [ ] `shows COMPLETED banner on approved chore`
- [ ] `opens ChoreApproveDialog on PENDING chore tap`
- [ ] `opens TaskConfirmDialog on available chore tap`
- [ ] `shows Reset in kebab menu for completed chore`
- [ ] `renders kindness scrolling row`
- [ ] `shows Assign Kindness button`

---

## Future Considerations

- **Recurring chore auto-reset**: Automatically clear completed status on schedule rollover (e.g., daily chores reset at midnight).
- **Chore streaks**: Track consecutive days a child completes a chore using `TrackingEvent` history.
- **Multi-completion analytics dashboard**: Query `TrackingEvent` to show completion counts per chore per day/week.
- **Partial credit**: Allow parents to award fewer points than the chore's value when approving.
- **Chore delegation**: Allow one child to reassign a chore to a sibling.
- **Photo proof**: Child attaches a photo when confirming a chore.
- **Kindness auto-classification**: Suggested classification when creating new items based on name patterns.

---

## Acceptance Criteria (Definition of Done)

### Backend

- [ ] `Task` model uses `type: 'chore' | 'kindness' | 'penalty'` — `is_good` removed
- [ ] `PendingConfirmation` model created, `PendingReward` model removed
- [ ] `pending_confirmations_db` created in `db.py`, `pending_reward_db` removed
- [ ] Migration script converts existing tasks, pending rewards, tracking events, and overrides
- [ ] `chore_api.py`, `kindness_api.py`, `penalty_api.py` created with CRUD endpoints
- [ ] `task_api.py` removed or deprecated
- [ ] Child chore confirmation endpoints: `confirm-chore`, `cancel-confirm-chore`, `approve-chore`, `reject-chore`, `reset-chore`
- [ ] `GET /pending-confirmations` returns hydrated pending chores and rewards
- [ ] `trigger-task` creates approved `PendingConfirmation` when parent triggers a chore directly
- [ ] Reward request/cancel/trigger endpoints migrated to `PendingConfirmation`
- [ ] `list-tasks` response includes `pending_status` and `approved_at` for chores
- [ ] `TrackingEvent` created for every mutation: confirmed, cancelled, approved, rejected, reset
- [ ] Tracking events logged to rotating file logger
- [ ] SSE event `CHILD_CHORE_CONFIRMATION` sent for every confirmation lifecycle event
- [ ] All new error codes defined and returned with proper HTTP status codes
- [ ] All existing tests updated for `type` field (no `is_good` references)
- [ ] All new backend tests pass

### Frontend

- [ ] `Task` and `ChildTask` interfaces use `type` instead of `is_good`
- [ ] `PendingConfirmation` interface replaces `PendingReward`
- [ ] Sub-nav under "Tasks" with Chores / Kindness / Penalties tabs
- [ ] `ChoreView`, `KindnessView`, `PenaltyView` list views created
- [ ] `ChoreEditView`, `KindnessEditView`, `PenaltyEditView` edit/create views created
- [ ] `ChoreAssignView`, `KindnessAssignView`, `PenaltyAssignView` assign views created
- [ ] `TaskView`, `TaskEditView`, `TaskAssignView` removed or repurposed
- [ ] `ChoreConfirmDialog` — child confirmation modal
- [ ] `ChoreApproveDialog` — parent approve/reject modal
- [ ] `ChildView` — chore tap opens confirm dialog, cancel dialog for pending, banners render correctly
- [ ] `ChildView` — expired and completed chores are non-interactive
- [ ] `ChildView` — kindness scrolling row added
- [ ] `ParentView` — pending chore tap opens approve/reject dialog
- [ ] `ParentView` — available chore tap uses existing trigger flow + creates completion record
- [ ] `ParentView` — kebab menu "Reset" option for completed chores
- [ ] `ParentView` — "Assign Kindness" button added
- [ ] `NotificationView` — fetches from `/pending-confirmations`, renders both types
- [ ] SSE listeners for `child_chore_confirmation` in all relevant components
- [ ] Banner styles: yellow PENDING, green COMPLETED (using CSS variables)
- [ ] All `is_good` references removed from frontend code
- [ ] All frontend tests pass
- [ ] Router updated with new routes
