journeys walkthroughs 03 focus session - fahadahmed/jamaal-app GitHub Wiki
Journey 3 โ A focus session
Status: done โ gaps G-21 โฆ G-26 raised, decided and applied (see the gap log). The text below is the walkthrough as first written, with the proposals it raised. Register flow F05, screens FS-01 โฆ FS-07 (and TD-06). Behaviour is in Task โ Focus sessions, Habit โ Timed habits and Rules engine โ module 8; this page tests it against the schema and engine.
FS-08(Lock Screen activity) is v1.1 and out of scope.
In one line: the user taps Begin on a task, a quiet chip follows them around the app while they work, they pause, overrun, finish or stop, and the real time is recorded so Night Planning and the load can be honest.
Preconditions: Journey 2 is done. Example: today holds "Draft the architecture review" (60 min, due today) and a timed habit "Qur'an reading" (15 min target).
Entry points
A session starts from three places: the Begin button on the "Start here" guidance card on Today (TD-01), Begin in the task detail (TK-02), and Begin on a timed habit's row (HB).
- Writes (every Begin): a
WorkSessionโstartedAt = now,day = logicalDate(now),estimateMinutes(a snapshot ofTaskItem.effortMinutes, ornil),outcome = running, andtaskorhabitWindow. - Reads: whether a session is already live (
outcome = running,endedAt = nil). - Assumes:
- Begin needs nothing else โ โ (a task that is live; completed and dropped tasks don't offer Begin);
- Begin on a task that is not due today is fine โ โ (it counts toward today once completed today; while running it simply isn't yet in "due today");
- a second Begin is handled โ โ (
FS-07).
- Read-only state: Begin is always allowed after the trial (Journey 9, G-70).
FS-01 The session chip
- Sees: a slim chip above the tab bar on every tab: the task title and a count-up timer (monospaced digits, so the numerals don't jitter). It is filled only while a session is live. On regular width and Duo it sits in the right-hand panel.
- Reads: the live
WorkSession(elapsed is(endedAt ?? now) โ startedAt โ pausedSeconds โ (paused so far)), and nearby Anchors (module 8). - Does: taps it to open
FS-02. - Assumes:
- the chip survives a killed app and another device โ โ (everything derives from
startedAt; the session syncs, so the chip also appears on the user's iPad); - the chip can warn about an approaching Anchor without blocking โ โ G-21 (which events surface is under-specified: the docs say "Maghrib in 12 min", but the costly moment is an open window that is about to close).
- the chip survives a killed app and another device โ โ (everything derives from
- Copy to respect: neutral always. No red, no alarm, no "you're over".
FS-02 The focus screen
- Sees: the timer numeral (display face, monospaced digits), the task title, "of 60 min", the task's note as a tappable checklist beneath it, and Pause and Finish. A habit session shows the habit and its target, with no note.
- Does: ticks checklist items; taps Pause, Finish, or closes it (the session keeps running).
- Writes: ticking a box edits
TaskItem.notes(the markdown text); Pause setspausedAt; Resume addsnow โ pausedAttopausedSecondsand clearspausedAt. - Assumes:
- elapsed ignores paused time โ โ;
- a session left paused or running overnight is closed โ โ (auto-closed at the day rollover, with the partial time logged);
- a manual change of the device clock can't corrupt a session โ โ with care (elapsed clamps at zero; time zones don't matter because the fields are instants).
FS-03 Overrun and FS-04 Paused
- Overrun: the same screen, the timer still counting ("75 of 60 min"); nothing changes โ no colour, alarm, nudge or haptic. Reads:
elapsed > estimateMinutes. - Paused: the same screen with the timer held and Resume in place of Pause; only an explicit Pause pauses (backgrounding never does).
- Assumes: no estimate โ no "overrun" โ โ (the state only exists when
estimateMinutesis set; a task with no estimate just counts up).
FS-05 Finish โ and stopping without finishing
- Sees: a sheet showing actual against estimate ("74 min ยท estimated 60"), an optional one-line note, and the choices. The current docs give it a single outcome, Finish, plus abandon in the state machine โ but no screen reaches abandon (โ G-22). The proposal: the sheet has two buttons โ Done (the task is complete) and Stop for now (time logged, task stays live) โ because being interrupted is the commonest way a session ends.
- Writes โ Done:
outcome = finished,endedAt,actualSeconds(elapsed minus pauses);TaskItem.isCompleted,completedAt = endedAt; an optional timestamped line appended toTaskItem.notes; for a repeating task the next instance is created. Stop for now:outcome = abandoned,endedAt,actualSeconds; the task is untouched. - Assumes:
- the partial time is kept either way โ โ ("abandoning is not failing");
- finishing or stopping from the chip, the screen or (v1.1) the Lock Screen all do the same โ โ.
FS-06 Undo toast
- Sees: "Done ยท Undo" for five seconds.
- Writes (Undo): reopens the session (
endedAt = nil,outcome = running) and un-completes the task (and, for a repeating task, removes the untouched next instance โ rule). - Assumes: the five seconds of the toast don't count as work โ โ G-23 (reopening as written would count them as running time; they should be added to
pausedSeconds).
FS-07 Switching task while one is running
- Sees: tapping Begin on a second task raises a sheet naming the running one: "You're timing 'Draft the architecture review'. Settle it first." โ Done ยท Defer to tomorrow ยท Drop (for a habit session, only Log it). Today's docs omit the Stop for now choice that interruptions need (G-22).
- Writes:
finished,deferred(a normal deferral with its count and record),dropped(droppedAt), or โ with G-22 โabandoned. The elapsed time is logged whichever is chosen; the new session only starts afterwards. - Assumes:
- only one session is ever live โ โ (engine-enforced; on a cross-device clash the later-started session is closed as
abandonedand its time logged); - the user learns of that clash โ โ G-26 (nothing tells them the other device's timer was stopped).
- only one session is ever live โ โ (engine-enforced; on a cross-device clash the later-started session is closed as
Resolving a task while it is being timed
- Does: ticks the check on the running task on Today, or taps Mark done, Defer or Drop in its detail while its session is live.
- Assumes: the session and the task can't disagree โ โ G-25 (nothing says what happens to the live session; left running it would outlast a completed task).
TD-06 After a session is auto-closed
- Sees: at the day rollover a session still running is closed at the boundary instant; the next day's Today opens with one row offering to pick the task back up ("Pick up 'Draft the architecture review'").
- Reads: yesterday's
autoClosedsession whose task is still live; no storage is needed (the row is derived, and disappears once the task is acted on or the day ends). - Writes (tap): a new
WorkSessionfor the same task. The earlier session stays as history. - Assumes: the task isn't charged a deferral โ โ (carried over without counting one).
A timed habit's session
- Begin / chip / focus screen / finish work the same way. Finish adds the minutes to that day's
HabitEntry.amountfor the window (creating the entry, with itstargetsnapshot, if none exists). - Assumes:
- several sessions in a day accumulate โ โ;
- minutes can also be added by hand โ โ (
HB-09); - the entry's
amountis exact โ โ G-24 (rounding each session to whole minutes drifts; and a hand-added figure and timed figures both land in one integer, so neither can be recomputed).
What the user sees at each point
At Begin the chip appears "Draft the architecture review ยท 0:00". Twenty minutes in, after a pause, it reads "0:20" and the meter on Today is unchanged (the load counts the task, not the clock). After 60 minutes the chip keeps counting with no change in look. Finishing at 74 minutes shows "74 min ยท estimated 60"; Done marks the task complete, and the meter now uses 74 minutes for that task instead of the 60-minute estimate (the load rule counts actual focus time once a session exists).
Data that exists afterwards (end-state check)
| Model | Change |
|---|---|
WorkSession |
+ 1 per Begin: startedAt, day, estimateMinutes, pausedSeconds, endedAt, actualSeconds, outcome (finished / abandoned / deferred / dropped / autoClosed) |
TaskItem |
isCompleted / completedAt on Done; a timestamped line appended to notes; deferralCount on Defer; droppedAt on Drop |
HabitEntry |
timed habit: amount (minutes) for that day and window |
DeferralRecord |
+ 1 when a session is settled with Defer |
Every row is storable now. One small additive change is proposed (G-24): a new raw value for WorkSession.outcome.
Rules and changes this journey implies
If the proposals are accepted:
- Chip messages (G-21): the chip shows the single most urgent line โ an open, pending Anchor closing soon ("Asr closes in 10 min") takes priority over a fixed Anchor's window opening within 30 minutes ("Maghrib in 12 min"). Flexible Anchors (bin night and the like) never appear. Neither blocks anything.
- Finish sheet and settle sheet (G-22): Done and Stop for now (and, on the settle sheet, Defer and Drop for a task); a habit's settle sheet is Log it / Stop for now.
- Undo (G-23): reopening a finished session adds the time since
endedAttopausedSeconds. - Timed habit minutes (G-24): the day's
HabitEntry.amountis recomputed from that window's sessions โround(total seconds รท 60), never per-session โ and minutes added by hand are stored as a finished session with a new raw valueWorkSession.outcome = manual(no start or end time of its own). Everything that feeds the entry is then a session, it can be recomputed at any time, and two devices converge by summing rows instead of overwriting a counter. - Resolving a task with a live session (G-25): the session closes with the matching outcome โ done โ
finished, defer โdeferred, drop โdroppedโ and its time is logged. - Conflict notice (G-26): if a session was closed as
abandonedbecause another device started one first, the user sees a single quiet line on next open โ "Two timers were running; the later one was stopped and its time logged."