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


# Task Pushing 01 Block 02 — Past Task Read Model

**Status:** Complete.
**Goal:** Add presentation-model state that tells widgets when to show the full
Push button.

---

## Block outcome

After this block, `TimelineCardModel` or its successor exposes a clear push-state
field. Leaf widgets should not recompute past/incomplete scheduling conditions.

## Implementation notes

1. `TimelineItem` carries the source task `updatedAt` timestamp for stale-write
   protection.
2. `TodayScreenData` and `TimelineCardModel` receive an injected clock for
   deterministic past/incomplete detection.
3. `TimelineCardModel.showPastTaskPushButton` identifies past incomplete planned
   flexible cards and suppresses hover quick actions while true.
4. Mapper tests cover earlier today, previous day, future day, completed,
   unsupported task types, and missing schedule placement.

---

## Chunk 2.1 — Add push-state presentation fields

### Tasks

1. Add a compact, explicit card field such as:
   - `pastActionState`,
   - `showPastTaskPushButton`, or
   - `pushControlState`.
2. Include enough information for UI callbacks:
   - task id,
   - expected updated timestamp/revision input if available,
   - enabled/disabled state,
   - semantic label.
3. Keep the field false/null for completed tasks.
4. Keep the field false/null for unsupported task types.
5. Keep the field false/null for backlog/free-slot/locked cards.

### Acceptance criteria

- Widgets can render the Push button from presentation data alone.
- Presentation data does not expose Drift rows or repository records.
- Completed cards cannot accidentally show the Push button.

---

## Chunk 2.2 — Provide clock and selected-date context to the mapper

### Tasks

1. Update Today-state-to-card mapping to receive current owner-local clock
   context, if it does not already have it.
2. Avoid using `DateTime.now()` directly inside presentation mappers unless a
   testable clock is injected.
3. Compare scheduled instants with current owner-local time using existing time
   conversion utilities.
4. Make selected date available to the mapper only if needed for previous-day
   detection.

### Acceptance criteria

- Mapper tests can freeze time.
- Past detection is deterministic.
- UTC/local date boundaries are handled through project time semantics.

---

## Chunk 2.3 — Add mapper tests

### Required tests

1. Flexible planned task earlier today and incomplete shows Push state.
2. Flexible planned task later today does not show Push state.
3. Flexible planned task on a previous selected date and incomplete shows Push
   state.
4. Flexible planned task on a future selected date does not show Push state.
5. Completed flexible task in the past does not show Push state.
6. Required/locked/free-slot/surprise cards do not show Push state unless Block
   01 explicitly expanded support.
7. Task without valid schedule placement does not show Push state.

### Acceptance criteria

- Tests cover each state branch.
- No widget test is needed to prove core push-state calculation.

---

## Chunk 2.4 — Connect push state to quick-action suppression

### Tasks

1. Update `TimelineCardModel.showsQuickActions` or equivalent to return false
   when the full Push button should show.
2. Ensure hover actions remain available for normal planned flexible tasks.
3. Ensure completed cards continue to use completed behavior, not push behavior.
4. Keep the selected-task modal behavior unchanged unless the modal also needs a
   push menu later.

### Acceptance criteria

- Past incomplete cards expose Push state and suppress hover actions.
- Non-past flexible cards keep existing hover quick actions.
- Completed cards do not show push controls or hover quick actions intended for
  planned tasks.

---

## Block acceptance criteria

- Past-task push state exists in presentation models.
- Detection is deterministic and test-covered.
- Hover quick-action suppression is model-driven.

## Validation after block

```sh
cd apps/focus_flow_flutter
flutter test test/models
```
