fe Frontend38be Backend26dm Data-model11inf Infrastructure11A system of a different shape: periodic rather than event-triggered, long-running rather than single-transaction, notification-driven rather than session-driven, and rendered on surfaces the user visits intermittently rather than sits in for the duration of the operation.
Re-entry isn't a variant here. It's the default. A user tapping a push notification to mark a dose taken is re-entering the system every time.
A structural sentence about what the system is as an object that exists over time. The generative-ness of the sentence is the test.
A medication tracker is a time-indexed obligation ledger that reconciles scheduled doses against taken doses across varying adherence, delay, substitution, and prescription-change conditions, rendered on surfaces the user visits intermittently.
Highlighted terms are the structural pieces. Each one generates a cluster of states.
"A medication tracker helps people remember to take their pills on time and records whether they took them."
Names a beneficiary and a goal. The verbs (helps, records) describe what the product does for the user, not what it is. Derived states collapse into reminded and recorded, which are events, not conditions.
"A medication tracker is an app where the user sets up a schedule, receives reminders at scheduled times, and marks each dose as taken or missed."
Better. Contains nouns the system is made of (schedule, reminders, doses). Still inadequate: it describes a user sequence rather than the object's structure, and omits the conditions the system spends most of its time in (waiting between windows, accumulating state, reconciling against wall-clock time, rendering on surfaces the user doesn't open).
Every state the system can occupy, sorted into four categories. The number (52) is not a target; it's the point at which three successive additions were specialisations of states already named.
Operating normally
Something goes wrong
Time, context, or user leaving
Where the system presents itself
Hover or tap a state to see its description.
Assign every state a scope tag. Annotate layers and (for failure states) cause. For medication tracking, all active states are in-scope: the product's core value lives in the reconciliation of dose states.
fe Frontend38be Backend26dm Data-model11inf Infrastructure11user-input5system1external1policy1Re-entry is medication tracking's default, not its exception. Two in-scope active states are shown in full; the other in-scope active states have abbreviated specifications in the source.
A today surface showing the dose is due now, with a primary mark-as-taken action, secondary skip action, and context about the dose (medication name, strength, preconditions). Rendered on any of the in-scope surfaces (today view, widget, watch, push).
If the user returns mid-window, the rendering reflects current window status. If they return after the window closed, the state has transitioned: the dose is now overdue or missed. The return surface must show the transitioned state, not the state at leave-time.
Canonical arrival. A tap on the first-reminder notification opens this state directly, bypassing the today view. The surface must be self-sufficient: show which medication, which dose, take/skip actions. Arrival from another device requires an optimistic-then-reconciled flow.
The user may arrive at this state without having seen window pending — for example, when a notification fires while the app was backgrounded. This state must not assume the user had any warning; it is the user's first awareness of the dose.
Between the moment the window opened and the moment the user arrives, the medication may have been paused, discontinued, or had its schedule changed by the user on another device. The surface must revalidate against current configuration before accepting a mark-as-taken.
If the reminder did not fire (permission revoked, DND, battery saver) the window may be open without the user being aware. The today view must render the open dose prominently on re-open regardless of whether the reminder fired. Backend sync failure means a mark-as-taken may not persist; accept optimistically, queue it, reconcile.
Today's obligations, ordered by time, each dose shown in its current state (pending, open, overdue, missed, taken, skipped). Aggregate adherence summary for the day at the top or as a running score.
If the user returns later the same day, doses that were pending or open have transitioned; the rendering must reflect current state rather than cached state. If they return on a subsequent day, this surface is now rendering a new day and should show the new day's schedule; yesterday's ledger moves to the history view.
Most common arrival is from a notification tap into a specific dose; a return-to-home action then brings the user to this view. On a different device, the surface may render stale data briefly during sync; show a subtle updating affordance rather than blocking the view.
A new user lands on medication-list-empty rather than this view; this state is entered for the first time after a first medication is configured. Arrival without medications configured must route to the empty state.
Data commonly changes between visits: doses marked on another device, medications paused, schedules edited. The surface must reconcile on foreground and render current state. Changes that would surprise the user (an in-progress dose now marked taken) should surface a lightweight indication of the change.
If multiple reminders failed (e.g. after battery-saver suppressed background work), several doses may be overdue or missed on arrival. The surface must not hide this behind a today summary; overdue doses should be prominent, and the user's ability to mark them late should be preserved where the missed threshold has not been crossed.
Re-entry conditions compose. Arrival at a dose window from a notification, after the app has been backgrounded across a timezone change, during battery-saver suppression, and with pending sync failures is a plausible Tuesday.
The artefact. Every state with its description, layers, cause, renders-on surfaces, and re-entry variants. Click any cell to inspect.
First use, or the user has removed all medications. The home surface has no scheduled obligations.
Render faithfully rather than persisting a stale schedule view.
Arrival from an expired notification or share link should land here with a brief explanation of what happened.
Configuration flow for a new medication: name, strength, schedule, preconditions, duration.
Preserve partial configuration locally; on return, prompt to resume or discard.
A validation failure such as daily-dose-exceeds-safe-total must not clear entered fields.
Between dose windows for this medication; the obligation exists but is not yet due.
Next-dose time renders from absolute scheduled time, not a stale relative duration computed at leave-time.
On focus, re-fetch schedule and re-render the next-dose indicator.
The next dose is within view but the window has not opened. A "coming up" rendering, not an "act now".
Arrival from a pre-window reminder must show the same information as entering via the today view.
This view must render the upcoming dose even if a prior dose has not yet synced.
The dose is due now, within its acceptable window. The primary action, mark as taken, is available.
Render reflects the current window status; time-remaining indicator updates on focus.
The state has transitioned to dose-overdue or dose-missed; the return surface must show the transitioned state, not the state at leave-time.
Surface must be self-sufficient: show which medication, which dose, and the take/skip actions without assuming the user saw the today view first.
Render optimistically from local state, then reconcile with backend; if the dose was taken on the other device, transition to dose-taken-on-time and surface a lightweight confirmation.
Revalidate against current configuration before accepting mark-as-taken; if paused, route to medication-paused rendering rather than recording a dose.
If reminder failed (permission, DND, battery saver), the open dose must still render prominently on re-open regardless of reminder delivery.
The window has passed but not by enough to count as missed. Still takeable; the system prompts more urgently.
On return, check whether the missed threshold has been crossed and transition to dose-missed if so.
Deep-linked from push-overdue-escalation; render the dose with take-late and skip actions foregrounded.
Past the missed threshold. No longer takeable for this window; recorded as missed in the ledger.
If a schedule edit retroactively changes the missed status, the history rendering must reflect it coherently.
Recorded within the window. Terminal state for a successfully reconciled dose.
Safe to revisit; does not re-commit.
If the user reverses within a short window, the dose may return to dose-window-open; handle explicitly.
Recorded after the window but before the missed threshold. Distinct from on-time in the ledger.
User explicitly chose to skip. Optionally records a reason.
Recorded reason persists through history rendering.
System skipped because the medication is paused or discontinued during the window.
Rendered in history without the user having seen an in-app prompt. Copy must explain the skip cause (paused medication).
Aggregate rendering of today's obligations: taken, pending, overdue. Default home surface once medications are configured.
Reflect current state of all doses rather than cached state; doses that transitioned must render correctly.
Render the new day's schedule; previous day's ledger moves to history-view.
Notification taps typically deep-link to a specific dose; a return-to-home brings the user here.
May render stale data briefly; show a subtle 'updating' affordance rather than blocking the view.
Reconcile on foreground; surface a lightweight indication for surprising changes (e.g. a dose marked taken from elsewhere).
After battery-saver or similar suppression, several overdue doses must render prominently; the user's ability to mark them late where possible must be preserved.
Ledger view across days or weeks. Aggregates taken, late, skipped, missed.
Append-only from the user's perspective; revisiting shows the same data plus any new entries.
Arrival from a weekly summary or export link scrolls to the referenced date.
User or provider has paused this medication. Scheduled doses do not surface as obligations; configuration persists.
Rendering distinguishes pause cause; user-pause is editable, provider-pause (out of scope but retained as out-with-implication) is not.
Future doses are removed from the schedule; historical doses remain in the ledger.
Decision typically initiated from medication detail; deep links from external systems must explain the current state clearly.
The dose has a precondition (take with food, take on empty stomach) requiring user confirmation of context.
If the user confirms the precondition and then fails to complete (network drop), the confirmation must persist on retry.
At onboarding the user did not grant permission to send reminders.
Handled at onboarding by a permissions primer. Implication: the today view must render meaningfully without assuming reminders have fired.
User granted then revoked in OS settings. The app must detect this and surface it explicitly on foreground.
Two doses scheduled at identical times across different medications.
User configured a schedule whose daily sum exceeds a safety threshold for the medication. Policy reject at configuration time.
Push or local notification did not reach the device (service failure, device offline past TTL).
Not reliably detectable device-side. Implication: the today view must not assume a reminder fired; act-now affordances remain visible even when a reminder was expected.
User's actions (mark taken, skip) have not synced to backend. Local state diverges from remote.
User attempts to mark a dose taken that is more than a day old. Data-integrity policy.
System time disagrees with server time by more than a threshold.
Rare; no dedicated rendering. Implication: server-time reconciliation on sync; a generic 'something looks off with your device's time' surface reuses the sync-failure rendering.
Device timezone updated but schedule has not been reconciled against the new zone.
The DST transition either doubles a dose or skips one, depending on direction.
Handled by the schedule engine rather than by a rendered state. Implication: the engine's decision (skip vs double-dose) is baked into the data model, documented so it is not rediscovered later.
User marked the same dose taken twice within seconds, likely a double-tap.
Two medications scheduled within an unsafe window for a known interaction.
The user was not looking; several windows opened and some closed without action.
Device timezone changes between dose windows. Subsequent doses now computed against a different zone.
Device was off at reminder time. OS delivers on boot, possibly after the window has passed.
Notification suppressed by OS. App cannot distinguish 'user saw it' from 'OS withheld it'.
Local notifications fire but network sync is unavailable; remote state diverges.
Many dose windows have passed. Daily schedule view is showing history, not today.
Deep link into a specific dose. System must handle arrival at the dose without the preceding schedule-view context.
User marks a dose on one device; opens another device seconds later. Second device may not have synced yet.
Device OS has suppressed the app's background work. Reminders do not fire; sync lags.
User deletes a medication that has recorded doses. History must survive the deletion.
One-line summary: next dose name and time.
Today's schedule condensed, with a primary action.
Live activity surface (iOS) or persistent notification (Android) for an open dose window.
Smallest surface; typically a single next-dose indicator.
Initial reminder at the window open.
Follow-up reminder after a user-configured snooze.
Stronger reminder once the window has closed but the dose is not yet missed.
Canonical today surface within the app.
Ledger view.
Detail surface for a single medication: schedule, recent history, preconditions.
Semantic rendering of the today view; live-region announcements for dose-window transitions.
Printable summary for sharing with a clinician.
Not designed this iteration. Implication: data model must preserve enough history to support export later; per-dose entries must carry their medication name rather than an id that might later be deleted.
Assistant integration. Becomes in-scope when a specific integration is committed to.
Platform integrations deferred.
OS-default grouping is accepted for this iteration.