Skip to content

Shift workflow

A shift groups its deliveries, pauses and recorded route. Expenses have their own dates and remain independent. This page follows one from the driver's side; the implementation is described under Architecture.

flowchart TD
    A[Root screen] -->|Start shift| B[Shift running]
    B --> C{Recording started with DashPilot open?}
    C -->|Yes, and location usable| D[Positions recorded, in the app and off screen]
    C -->|Started off screen| E[Recording paused, shift keeps running]
    C -->|Permission lost| F[Recording unavailable, shift keeps running]
    D -->|iOS suspends or ends the app| E
    D --> J[Record deliveries, one tap per event]
    E --> J
    F --> J
    J --> M{Pause shift?}
    M -->|Delivery in progress| N[Pause refused: deliver or cancel it first]
    N --> J
    M -->|Yes| P[Shift paused: recording stopped, working time held]
    P -->|Resume| Q[New recording session, shift running again]
    Q --> J
    P -->|End| G
    M -->|No| K{Delivery in progress?}
    K -->|Yes| L[End refused: deliver or cancel it first]
    L --> J
    K -->|No| G[End shift]
    G --> H[Completed shift in history]
    H --> I[Detail: earnings, route, rates, deliveries, delete]

Starting a shift

Work with a running shift and no delivery yet

Home and Work offer a start control while no shift is running. Starting from Home opens Work. The panel answers what starting now would record: a quiet No shift in progress, then Next shift records with the selected vehicle's name and, under it, its fuel economy and the current gas price, then Start Shift. With nothing selected it says No vehicle selected in the quieter style and still starts a shift. Starting records a start timestamp and copies the driver's current vehicle and gas price onto the new shift, which owns that copy from then on (see Settings and vehicles). At most one shift may be unfinished at a time, and the rule is checked against the store, so the absence of the button is presentation and not the protection.

Which vehicle the next shift will record

Above Start Shift, one short line says which vehicle the shift about to be started will record, with its miles per gallon and the current gas price under it where those are set: 2020 Honda Civic, then 34 MPG · Gas $3.29/gal. A driver with two vehicles can see before the tap whether they forgot to switch.

It is read through the same rule the start copies from, so what it says is what the shift records. Changing the selected vehicle in Settings and coming back changes it, because no shift exists yet. Once the shift starts, this line is gone and the running shift's own line takes its place, read from the shift's snapshot (see Which vehicle the shift is using).

Nothing selected reads No vehicle selected. A missing figure is left out rather than written as 0 MPG or $0.00, no vehicle is chosen on the driver's behalf, and none of this refuses a start: a shift started with nothing to copy records no assumptions. Looking at the line writes nothing.

VoiceOver reads it as a separate element from the button: Next shift vehicle, 2020 Honda Civic, 34 miles per gallon, gas $3.29 per gallon, or No vehicle selected for the next shift. It wraps at large text sizes rather than truncating the vehicle's name.

A shift can also be started by voice, without opening the app: see Voice and system actions. The rule is the same either way, because the same service enforces it, and the spoken confirmation states that recording begins when the app is opened.

Starting a shift also puts one Live Activity on the Lock Screen, which is where the rest of the shift can be watched and controlled without unlocking the phone. See The shift on the Lock Screen.

If the app is terminated while a shift is running, the next launch finds the same unfinished shift and resumes it with its original start time. Nothing synthesises a replacement shift, and no recovery step is asked of the driver.

While a shift runs

The running shift shows a working timer derived from the recorded timestamps, and one line describing route capture:

State What it means
Location tracking active Positions are being recorded, and go on being recorded in another app or behind a locked screen
Route recording stopped The driver paused the shift, so nothing is being recorded until they resume
Route recording stopped while parked The driver recorded the vehicle as parked; the shift is still running
Route recording paused The shift began with DashPilot off screen, so there is nothing recording yet
Permission required Location permission has not been granted, so nothing is being recorded
Unavailable Location Services is off, access is restricted, or the store refused a write

The active line carries a sentence of its own rather than a green label and silence. Recording continuing off screen is the useful half; that iOS can still stop it, and that it does not restart on its own once DashPilot is closed, is the half a driver has to know before trusting the total.

While paused or parked, the line under the state says only what the rest of the panel does not: that resuming starts a new recording, and that the distance across the break is not counted. The shift's status row already says it is paused, and the parked notice already says the route stopped while the shift keeps running, so neither is repeated there.

Losing location never ends a shift. Capture becomes unavailable, the shift keeps running, and the driver decides when it ends.

The timer counts working time, which is the whole shift less the stretches the driver paused it. For a shift that was never paused that is the same figure the timer always showed. It is the number every rate the shift produces divides by, so the figure watched during the shift and the figure read afterwards are the same one.

The screen reads top to bottom in the order a driver needs it: which state the shift is in, the working clock as the one large figure, a row of figures, and Park; then the deliveries, each with its next step; and only then the once-a-shift controls and the context. Recording a newly accepted order is not in that list at all: it is a bar pinned to the bottom of the screen, reachable from wherever the list has been scrolled to:

● Shift in Progress                    Started 5:46 PM

2:14:07
Worked so far

4.5 mi              3            2
Recorded miles      Delivered    In progress
partial route · 2 capture segments · 1 capture gap

[ Parked for a Pickup ]

DELIVERIES
  (2) Delivery 2                                   (each card: marker, track,
      ●──○┄┄○┄┄○                                    state, Next step)
      Heading to the pickup · 12 min
      Next  [ Arrived at Pickup ]

SHIFT
  [ Pause Shift ]  [ End Shift ]
  This shift is still running. Rates are worked out once it ends.
  2020 Honda Civic · 34 MPG                       Change
  Location tracking active
───────────────────────────────────────────────── (pinned)
  [ Add Delivery ]                     [ Several ]

The entry bar holds Start Delivery (Add Delivery once one is in progress) and, narrower beside it, Several for an offer of more than one delivery. It sits in the screen's bottom safe area rather than over the list, so the list is inset by its height and its last row always scrolls fully above it. It is the prominent control only when nothing is in progress and the vehicle is not parked; otherwise the prominent control is a delivery's next step or Resume Driving, and the bar is bordered. It is not shown while the shift is paused, when no delivery can be started, and its text stops growing at the first accessibility size so Start Delivery stays whole on one row.

Pause and End sit below the deliveries because each is tapped once a shift, while a delivery's next step is tapped many times; that keeps the first delivery's step on the first screen.

The working clock leads, not earnings, because it is the one figure that exists and moves while a shift runs; a running shift cannot record an amount, so an earnings headline would be a permanent absence. The row of figures becomes a column whenever it cannot hold them side by side, and always at accessibility text sizes, so no figure is ever shortened to fit beside another. The clock is set in tabular figures so it does not move sideways as it ticks, and it is never scaled down to fit.

Running, paused and parked each have their own symbol, word and tint, and the tint is never the only signal. Paused replaces the status with an orange banner that says working time stopped, with Resume Shift directly under it. Parked is not a third status: a parked shift is still running and still counting working time, so it is a blue banner about the route under a status that still says the shift is in progress, saying working time is still counting, with Resume Driving directly under it. Pause and End share one row where they fit and stack where they do not.

The mileage is recorded mileage, in the same words and from the same calculation the finished shift uses, and it grows only while positions are being accepted. A pause stops it, and resuming never adds the distance covered during the break. The segment and gap counts under it are what make the partiality concrete without a paragraph a driver in a cradle would not read; the sentence that explains what a partial route means is on the finished shift's own screen.

No earnings and no rates appear on a running shift, and the screen says why rather than showing a dash or a zero. A shift's gross earnings cannot be recorded until it has finished, so every rate derived from them is withheld: This shift is still running. Rates are worked out once it ends. That sentence is with the shift's context below the deliveries, so it never stands between the clock and a delivery's step. Nothing is worked out from the amounts recorded against individual deliveries, which are a separate fact and never a shift total.

Still deliberately absent: a map, coordinates, a sample count, an earnings projection, a target, a goal and any comparison with another shift.

Which vehicle the shift is using

The vehicle line under Pause and End is the vehicle assumptions this shift recorded when it started, so a driver with two vehicles who forgot to switch can see it without leaving the screen. It answers which vehicle is this shift using?; Settings answers a different question, which is what the next shift will record.

It reads the shift's own snapshot and nothing else. Changing the selected vehicle, renaming a profile, correcting its miles per gallon, deleting it or changing the current gas price all leave this row exactly where it is. A shift that recorded nothing says No vehicle recorded rather than borrowing what is selected today, which would claim the shift was worked in a vehicle nobody recorded.

The gas price is deliberately not here. It is an input to the fuel estimate a finished shift reports, and the one screen a driver reads while working is not where a price belongs. See Estimated fuel and net and Settings and vehicles.

Correcting the vehicle, before any driving is recorded

Beside the vehicle lines there is a small Change, and it is offered only while the shift's route has recorded no distance. A driver who notices at the kerb that they started the shift in the wrong vehicle, or under a gas price they have since seen is wrong, can correct this shift's own snapshot there and then.

The sheet is two explicit choices, each defaulting to keeping what the shift already recorded: which vehicle, and whether to take the gas price currently in Settings. Nothing is written until Save, and Save is unavailable until something differs from what is recorded. Choosing a vehicle copies its current name and miles per gallon onto this shift: nothing in Settings is changed, the selection is not moved, and renaming or deleting that vehicle afterwards leaves this shift saying what it recorded.

Once the route has measured a distance the control is gone, and the vehicle lines stay readable without it. Changing what a mile is assumed to cost after the miles are recorded would restate what those miles are estimated to have consumed, with nothing to point at, so the correction closes rather than being offered and refused. The rule is measured distance and never elapsed time: a driver who has been sitting still for an hour can still correct, and one who has driven ten miles in five minutes cannot.

The remedy after that is the finished shift's own fuel editor, on its detail screen. Correcting the assumptions of shifts already recorded is not a feature DashPilot has.

Pausing a shift

A driver who stops for a meal, an errand or the end of a busy block can pause the shift instead of ending it. Pausing is a real recorded state rather than something the screen remembers: it is a row with a start timestamp, it survives the app being terminated, and the shift stays the unfinished shift throughout.

Three things happen, and nothing else:

  • Working time stops accumulating. The timer holds at whatever it read, and the paused stretch is excluded from the shift's working duration and from every hourly figure derived from it. The shift's elapsed duration still covers the whole span, and both are shown on the finished shift.
  • Route recording stops immediately. Nothing is recorded for as long as the shift is paused.
  • Deliveries cannot be started. The delivery control is replaced by the reason.

Pausing is refused while a delivery is in progress, with a message naming how many. Pausing says the driver stopped working and an open delivery says they had not, and a shift holding both would report delivery active time running through hours it also reports as not worked.

Resuming closes the pause and starts a new recording session. The distance between where the driver paused and where they resumed is never counted: nothing was recorded across that stretch, so nothing is measured across it. The shift's route carries the break, and the mileage is a floor as it always is.

Pause and Resume can also be spoken, without opening the app, and both are on the shift's Lock Screen card: see Voice and system actions and The shift on the Lock Screen. A shift resumed by either records no route until DashPilot is opened, for the same reason a shift started by voice does not, and the spoken confirmation says so.

A shift left paused when the app is terminated is still paused on the next launch, with its pause intact and nothing recording.

Parking for a pickup

A driver who parks and walks into a shop to collect an order can record the vehicle as parked. It exists because walking around a shop inflates a recorded route, and DashPilot has no way to tell a walk from a drive: a stored position carries no speed, and the rule that keeps a route free of noise treats a walk across a car park exactly as it treats a crawl through traffic. Rather than guess, the app lets the driver say it and records that they said it.

Like a pause, it is a row with a start timestamp rather than something the screen remembers, so a shift left parked when the app is terminated comes back parked with nothing to recover.

Unlike a pause, it subtracts nothing. Shopping is working:

Pause Parked
Working time Stops accumulating Keeps counting
Hourly rates Divide by less Unchanged
Deliveries Cannot be started, none may be open Unaffected, any number may be open
Route recording Stops Stops

The one consequence is to the route. Recording stops, so the walk is never written down; driving again starts a new recording session, so the distance between where the vehicle was parked and where it is driven off from is never counted. See Parked for a pickup.

Parking is refused while the shift is paused. Pausing says the driver stopped working and parking says they are working on foot, and a shift holding both would be claiming two things about the same minutes. Resuming the shift first is one tap.

It belongs to the shift, never to a delivery. Whether the vehicle is moving is a fact about the driver and their vehicle: a driver shopping for one order while carrying another has one vehicle and it is parked. There is one stretch at a time however many deliveries are open. Neither delivery records nor stacked deliveries divide it.

Leaving the state is always explicit. Resume Driving is one tap, pausing the shift closes it, and ending the shift closes it at the end instant. Movement never resumes recording. With Resume driving after delivery progress enabled, recording Picked Up or Delivered can close the parked stretch once that stop has nothing left to do. The setting is off by default and never resumes a paused shift.

The running shift and the shift's Lock Screen card both say Parked for as long as the state lasts, and both say plainly that the shift is still running, because forgetting to leave the state is the expensive way this goes wrong.

Both halves can be recorded without opening the app. Park my vehicle in DashPilot and Resume driving in DashPilot are App Shortcuts, and the shift's Lock Screen card offers the matching button: whichever of the pair applies, never both. A driver with two bags in their hands cannot unlock a phone, and a state nobody can enter or leave hands-free is a state that gets forgotten. Every rule above applies to all three ways of saying it, because all three call the same two service operations. See Voice and system actions and The shift on the Lock Screen.

Park and Resume as the pickup steps

A driver who turns on Pick up orders with Park & Resume in Settings can let Park record Arrived at Pickup and Resume Driving record Picked Up, for the delivery being picked up. It is off by default, and with it off nothing above changes.

Each is one operation behind all three surfaces, so the app's buttons, the spoken actions and the Lock Screen's controls behave identically. The vehicle state is recorded first, and always stands; the delivery step follows through the delivery's own operation, at the same instant. The app then says so, under the parked notice after Park and in a line below the list after Resume Driving (so its leaving moves no delivery card), for example Delivery 3 marked Arrived at Pickup with Recorded automatically when you parked. beneath it and an Undo beside it for a few seconds. Undo takes back that delivery step only: the vehicle stays parked, or driving. There is no confirmation to answer first, because the point is fewer taps at a door.

With one delivery in progress it is that delivery. With several, nothing is recorded unless Handle stacked orders in order is also on, and then Park takes the lowest-numbered delivery still waiting for its pickup; Resume Driving always finishes the one Park took. Deliveries the driver marked Same pickup move together, and one Undo takes back all of them. The stretch parked still belongs to the shift; it stores which delivery it was for and joins none. See Pick up orders with Park & Resume.

Driving again after the last step at a stop

With Resume driving after delivery progress on in Settings, the driver's own Picked Up or Delivered, recorded while parked, records driving again once that stop has nothing left: no order marked Same pickup (for a pickup) or Same drop-off (for a drop-off) still waiting there, and no other order still needing that kind of stop. It is the same Resume Driving the button records, and it never resumes a paused shift. Parking and pausing stay different statements: a pause stops working time and is left only by Resume Shift; parking stops the route and is left by Resume Driving, by this setting, by pausing or by ending. See Resume driving after delivery progress.

Correcting a recorded pause

A pause is two taps made at a kerb, and it is the easiest thing in DashPilot to record at the wrong moment: pausing on arriving at a restaurant rather than on leaving it, forgetting to resume until the next offer arrives, or forgetting to pause at all. Until the pauses of a finished shift became correctable, the only remedy was deleting the whole shift, which threw away its route, its deliveries and its amounts to fix one timestamp.

The corrections live on the finished shift's own detail screen, in a Pauses section beside the paused and working figures they feed:

Correction What it records
Edit Pause This pause began, ended, or both, at times other than the ones recorded
Delete Pause This pause was recorded by mistake and did not happen
Add Missed Pause A pause was taken and never recorded

Each opens two date and time pickers with the shift's own start and end as their bounds. Nothing is written while the pickers move, Cancel leaves the pause exactly as it was, and the screen states what the shift's working time would become before anything is saved.

What a correction is refused for

A stretch is named and refused, never quietly clamped, swapped or nudged into the nearest acceptable one:

  • it has to end after it starts, so a pause of no length or of negative length is refused; deleting a pause is the separate action for a pause that should not exist
  • both times have to be inside the shift
  • it may not overlap another pause the shift records, because two pauses covering the same minutes are one pause recorded twice, and combining them would delete a row the driver can still see
  • it may not overlap a stretch a delivery was open for, which is the same fact the live lifecycle already keeps from both directions, and it is refused rather than resolved by moving the delivery

Two pauses may touch: one beginning exactly where another ended is two adjacent breaks, not one claim made twice.

What a correction never touches

  • The shift's own start and end times. Its elapsed duration is the same afterwards.
  • The route. No recorded position is added, moved, deleted or reassigned to another capture session, so the recorded mileage, the capture segments and the gaps are all exactly as they were. A pause recorded live left a real break in the route and that break stays.
  • Deliveries. No lifecycle timestamp moves, so the shift's delivery active time does not either.
  • Amounts. The shift's gross earnings and every delivery's stay as entered.

What does move is what a pause is subtracted from: the shift's paused time, its working duration, its gross per shift hour, and the period totals and rates that sum working durations.

A pause added afterwards does not rewrite the route

A pause recorded during the shift stopped recording, so the route has a real gap across it. A pause added afterwards does not: DashPilot never deletes positions it recorded, so a shift can record mileage inside a stretch it also records as paused. The alternatives were both dishonest, and the detail screen's route section says so rather than smoothing it over.

What is not correctable here

The open pause of a shift that is paused right now. It is ended by resuming or by ending the shift, both of which reconcile route capture and the Lock Screen card as they close it, and this editor does neither. The same rule is why none of these corrections appear on a running shift at all: choosing two times from two pickers is the sustained attention DashPilot keeps away from a driver who may be at a wheel.

Nothing is detected. No pause is inferred from a stationary stretch, a gap in the route or a quiet hour, and none is proposed when one is added. Every timestamp here was typed by the driver.

Correcting a shift's end time

A shift's end is the one lifecycle timestamp DashPilot itself can get wrong. If the app is evicted under memory pressure, crashes, or is simply not something a driver will stop to open in the last minutes of a shift, the end is recorded whenever they next get to it. The shift then reports working time nobody worked, an hourly figure that is too low, and, if recording was still running, the mileage of the drive home.

Correct End Time is on the finished shift's own detail screen, in the Shift section beside the times it changes. It opens a picker on the end the shift records, states what the elapsed and working times would become, and writes nothing until Save. Cancel leaves the shift exactly as it was.

Moving the end earlier deletes the route recorded after it

Route recorded after the moment the driver stopped is not part of that shift, so it is deleted. This is the one destructive correction in DashPilot that is not a deletion of a whole record, and it is confirmed in an alert that says how many positions go.

The recorded mileage is then measured again from the positions that remain, by the same calculation every other shift is measured by:

Mileage is re-measured, never scaled

A shift shortened by a fifth does not lose a fifth of its miles. It loses whichever positions were fixed after the corrected end, and what is left is measured from its own coordinates. A shift that recorded three equal stretches and loses one reports two thirds of the distance, whatever share of the time went with it.

Nothing is invented to reach the new boundary either. If the last retained position was fixed thirteen minutes before the corrected end, that position is still the last one, and those thirteen minutes are counted as a capture gap like any other.

Positions recorded at or before the corrected end are kept, coordinate, timestamp and capture session unchanged. A capture session the boundary falls inside keeps the part that is still inside the shift and stays one session.

Moving the end later adds nothing

No position and no mile is created for the stretch gained. The route simply no longer reaches the end of the shift, which DashPilot already counts as a capture gap and already reports as a partial route — so a lengthened shift says plainly that part of it has no recording behind it rather than claiming coverage it does not have.

What a correction is refused for

An instant is named and refused, never quietly clamped or nudged into the nearest acceptable one:

  • it has to be after the shift's own start; a shift of no length is not a correction anybody means
  • it may not precede anything the shift's deliveries recorded — an acceptance, an arrival, a pickup, a completion or a cancellation, because recorded work cannot fall outside the shift that holds it. The refusal names the blocking delivery and event: Delivery 1 has Delivered recorded at 9:47 PM, after the proposed shift end, so the driver knows which record to open. Nothing here corrects that delivery on their behalf. See the recovery below
  • it may not leave a recorded pause outside the shift; the pause is corrected or deleted first, through its own editor, and nothing here shortens one to fit
  • it may not leave a recorded stretch parked outside the shift either, for the same reason and with the same refusal: that stretch is what explains a gap in the shift's route, and an end moved back through it would leave the gap with its recorded reason outside the shift. A shift recording a stretch parked that was never ended is refused outright, exactly as one holding an unended pause is
  • it may not reach into a shift recorded after this one, because two overlapping shifts would each contribute their whole working duration to the same period
  • a shift recording a pause that was never ended is refused outright, in both directions: that pause has no recorded end, so every figure derived from it would move with the correction

What a correction never touches

  • The shift's own start time, so the day, week and period it belongs to do not change.
  • Amounts. The shift's gross earnings, every delivery's recorded amount, every additional tip and every expected amount stay exactly as entered.
  • Deliveries, pauses and stretches recorded parked. No lifecycle timestamp, no pause timestamp and no parked timestamp moves.
  • Route recorded at or before the corrected end. Nothing is added, moved, retimed or reassigned to another capture session.

What does move is everything derived from the boundary: the shift's elapsed and working durations, its three rates, its recorded mileage with its segments and gaps, and the period totals and rates that sum those.

When a delivery recorded late blocks an earlier end

This is the case the refusal above exists for. DashPilot became unreachable near the end of a shift, the driver kept delivering, and both the remaining deliveries and the shift's own end were recorded much later than they happened. Correcting the end alone is refused, because the delivery now records work after the end being proposed.

The recovery is five steps, and each one is the driver's:

  1. Correct End Time refuses the earlier end.
  2. It names the delivery and the event that block it.
  3. The driver opens that delivery in the shift's own record.
  4. They correct its recorded times. See Correcting the times a delivery recorded.
  5. They retry the same end correction, which is then accepted and trims the route as it always does.

Nothing corrects a delivery from the shift editor. A delivery's times and a shift's end are two records with two sets of collisions, and an editor that moved both would be writing a fact the driver never looked at.

What is not correctable here

A running shift's end, because it has none: End is what records one, and it stops recording and reconciles the Lock Screen card as it does. The shift's start: it is what decides the day, week and period a shift is reported in, and it is not editable anywhere. A delivery's own lifecycle times are corrected on the delivery, never here.

Nothing is detected. DashPilot does not infer when a driver stopped from the last position it holds or the last delivery they completed. The instant was typed by the driver.

Deleted route positions do not come back

Correcting the end later again does not restore positions an earlier correction removed. The confirmation says so before anything is deleted.

Location permission

Permission is never requested at launch. iOS shows the prompt once, and a prompt that appears before the driver has any reason to grant it is the surest way to have it declined permanently, so the request is always a tap.

DashPilot asks for When In Use only. That is not a restriction it works around: paired with the location background mode, it is exactly what lets recording started with the app open carry on while the driver is elsewhere. Always would buy starting a recording from the background and being relaunched into one, and DashPilot does neither.

The authorization panel states the current condition and offers only a recovery that actually works: the prompt when permission has not been decided, the app's Settings page when it was denied, a description of where the Location Services switch lives when the system-wide switch is off, and nothing at all when access is restricted or already granted.

Recording deliveries

A running shift offers one primary delivery control, and what it says depends on what the driver has already recorded: Start Delivery, then Arrived at Pickup, Picked Up and Delivered. Nothing is typed and nothing is detected. The full lifecycle, its rules and its limits are on Delivery lifecycle.

Ending a shift

A shift cannot be ended while one of its deliveries is in progress. The end is refused with a message saying to mark the delivery delivered or cancel it first — silently completing it would record a delivery the driver never made, and silently discarding it would erase one they did.

A paused shift can be ended without resuming it first. The pause is closed at the same instant the shift ends, which is the truthful reading of what happened: the driver was paused right up to the moment they stopped. Its full length therefore stays out of the working duration, and a shift paused and then ended can have a working duration well short of its elapsed one. Refusing would make a driver who has finished resume a shift they are not working in order to end it, which would record work that did not happen.

Ending records an end timestamp. Capture is stopped and any pending positions are written before the end is recorded, so no position is judged against a shift the store has already closed. If ending fails, capture restarts rather than staying off.

If the device clock has moved behind the recorded start, the end is clamped to the start, and to an open pause's start if there is one. Recording a zero-length shift or a zero-length pause is preferable to leaving a driver unable to end their shift until the clock catches up.

After a shift ends

Once an end has been recorded, the app offers a short recap: recorded gross earnings, working time, gross per working hour, recorded mileage with its partial-route qualification, and an estimated fuel cost labelled as an estimate. A value that was not recorded says Not recorded or Not available, never zero, and an unavailable rate or estimate says why. Done closes it; View Shift Details opens the shift.

Every figure comes from the calculators the shift's own detail screen uses. Nothing is stored for the recap. Recorded expenses are not shown beside the estimate, and delivery earnings are never read as the shift's gross. A refused end offers no recap, and a recap waiting for a shift ended from the Live Activity is dropped once another shift starts.

An end recorded later than the driver actually stopped — because DashPilot was not reachable at the time — can be corrected afterwards. See Correcting a shift's end time.

History

Work contains History; Home's View Work History action opens it directly. History shows the week the driver is in, Monday through Sunday, and nothing else. The heading says which week, the section opens with that week's own figures, and the footer under the list says which days:

HISTORY · THIS WEEK

$482.40
Recorded earnings
6 of 6 shifts

21 hr, 34 min        286.4 mi
Working time         Recorded miles
6 of 6 shifts        6 of 6 shifts measured
Per working hour                    $22.37
Every shift this week
Per recorded mile                    $1.68
Every shift this week
------------------------------------------
6 shifts · 31 deliveries completed · 2 cancelled

(the week's shifts)

Showing Sep 14 – 20, 2026.

The figures are the same weekly summary each older week carries (see How a whole week went), with the week's recorded earnings as the largest figure in History. A figure that was never recorded is said in words, never drawn as a zero, and an empty week draws no summary at all: it says the week holds no completed shifts yet. The summary is worked out off the main actor from the week's own shifts, once for each change to what they record, so a shift running meanwhile restarts nothing.

Period Summaries and Export All History sit in a small section of their own above History, because they span every shift rather than this week's.

Completed shifts in the week appear under the summary, newest first, each row a compact summary and a single tap target:

Sat, Sep 19                              $86.25
5:46 PM - 8:46 PM · 3 hr
4.5 mi recorded · partial route · $28.75/hr

The duration on the second line is the working time, so it multiplies out against the rate on the third. A shift that was paused says so on the same line (· 1 pause), and the shorter figure is then not read as a mistake.

Three lines, no controls. Only figures that exist appear: an unavailable rate leaves nothing behind, no dash and no $0.00. At accessibility text sizes the date and the amount stack rather than share a line, and the summary wraps rather than truncating, because the first thing a truncation takes is the end of "recorded", which is the word that makes the mileage honest.

The week, and the weeks before it

A week runs from Monday 00:00 to the following Monday 00:00, in the driver's own time zone. The boundary is half-open, so a shift started at exactly Monday midnight belongs to the week that is beginning and to that week only. Which week a shift belongs to is decided by the same instant every other period in the app uses, its start: a shift worked from Sunday evening into Monday morning is a Sunday shift, and is not split.

The boundary comes from Calendar, never from a count of seconds. A week holding a daylight-saving change is 167 or 169 hours and is still one week, and a week running from December into January is one week in two years.

History, Home, Money, Insights and period summaries all use the same Monday-first reporting calendar, regardless of the device's preferred first weekday. Each screen names its dates. Changing the reporting timezone can change membership without changing a recorded timestamp.

Everything before this week is under View Older Weeks, a row at the end of the History section, present only when there is something older. It says how much is behind it (3 weeks · 3 shifts) and opens a screen of the same rows, grouped by the week they were worked in, newest week first, each group headed by the dates it covers and footed by how many shifts it holds. A week nobody worked is absent rather than shown empty.

How a whole week went

Each week on that screen opens with a summary of every shift in it, above the shifts themselves, so that the question a driver scrolls back with, what did this week look like?, is answered before they start opening rows. The week's recorded earnings lead, working time and recorded miles share a row under them (a column where the row cannot hold them, and always at accessibility sizes), the two rates follow, quieter, and the rest sit under a divider. The estimates are last, in a surface of their own under the heading Estimated from fuel assumptions, so they never read as recorded figures on position or tint alone:

Sep 14 - 20, 2026

$185.00
Recorded earnings
3 of 3 shifts

6 hr                 89.4 mi
Working time         Recorded miles
3 of 3 shifts        3 of 3 shifts measured
Per working hour                    $30.83
Every shift this week
Per recorded mile                    $2.07
Every shift this week
-------------------------------------------
3 shifts · 5 deliveries completed · 1 cancelled
┌ Estimated from fuel assumptions ─────────┐
│ Estimated fuel                     $4.77 │
│ 2 of 3 shifts · 59.6 of 89.4 recorded mi │
│ Estimated net after fuel         $120.23 │
│ 2 of 3 shifts · before recorded expenses │
└──────────────────────────────────────────┘

The heading of each week is drawn in the primary colour and a heavier weight than an ordinary section heading, so where one week ends and the next begins is the most obvious thing on the screen. The headings do not pin while scrolling, because the grouped list style does not support it.

Nothing is defined for History. Every figure is the period summary's, derived by the same aggregation over the week's own period, which is what keeps one definition of "what a week came to" in the app. A weekly total on this screen and a weekly total on the period summary cannot disagree, because they are the same calculation.

Coverage travels with every figure. A week's earnings are the subtotal of the shifts that recorded an amount, its working time the total of the shifts with a usable one, its mileage what the routes measured. None of those is necessarily every shift, so each line that can be short of its sources says how many shifts are behind it. 4 of 5 shifts under a subtotal is the difference between a subtotal and a claim about the week.

The rates are the period's own. Per working hour and per recorded mile are the period summary's gross rates over the week: the amounts of the shifts carrying both halves of a rate, divided by those same shifts' working time or recorded miles. Neither is the headline earnings divided by the headline hours or miles, because those can come from different shifts. Each says Every shift this week when every shift contributed, and otherwise the subset it was worked out over (Based on 2 of 3 shifts with both earnings and a measurable route). A rate no shift could contribute to is absent rather than $0.00, because the lines above already say which half is missing. Both are gross: nothing estimated is subtracted from either numerator.

Fuel is estimated only over the shifts that recorded enough to say, and says so in two units: how many of the week's shifts, and how many of its recorded miles. It is never scaled up to the whole week, and each shift is estimated under the economy and price it recorded, never today's. The estimated net after fuel is worked out over the shifts that recorded both an amount and an estimate, which is why its coverage can differ from the earnings line above it, and it is labelled as coming before recorded expenses. Where a route in the week is partial, the fuel line says the estimate is a floor and the net line says it is a ceiling. A week where no shift recorded fuel assumptions carries neither line, rather than two lines saying so on every week a driver scrolls past; the shift's own detail screen is where an absent estimate is explained.

Deliberately not on the card: elapsed time (working time is what every rate divides by), net after recorded expenses (an expense belongs to a date rather than to a shift, and one net on a small card cannot be mistaken for the other), and any vehicle. A week can hold shifts worked in different vehicles, and a vehicle's name is a label a shift recorded rather than an identity, so the card does not count or merge names. Each shift's detail says what that shift recorded. Delivery active time and its rate, pickup waits and the comparison with the week before are on the period summary, one tap from the root screen.

Missing is never a zero. A week where nobody recorded an amount says Not recorded, not $0.00; a week whose routes measured nothing says Not measured, not 0.0 mi. A recorded gas price of zero is a fact and is counted as one. A running shift is not in any of it, by the rule that keeps running shifts out of every historical aggregate.

For a listener the whole week is one element, spoken as one sentence: the week's name, then how many shifts, then each figure with every unit and every coverage said in full, because there is no caption in view to read afterwards. At large text sizes each figure stacks under its own label rather than being shortened to fit beside it, and nothing is shrunk to fit.

The summary is worked out when a week comes into view, on a context of its own off the main actor, because a week of ordinary shifts is about half a second of route walking and the list has to keep scrolling meanwhile. Nothing is stored: a week's totals are worked out from the same recorded facts every time they are shown, exactly as a shift's mileage is.

What History reads, and what it costs

The root screen reads the current week's shifts and nothing more, plus a count of every other completed shift, so that the list a driver reads while working does not grow with their history. How many weeks those other shifts fall in, for the 67 weeks · 69 shifts line under View Older Weeks, is worked out off the main actor. Opening Older Weeks is where the rest of the history is read, and that is the driver asking for it. Measured on a synthetic store holding five years of work (3,124 completed shifts), the root screen's refresh went from about 175 to 220 ms to about 1 ms, and opening Older Weeks costs about 80 to 100 ms once. Export All History still reads the whole store through its own fetch, never the screen's.

Rows never measure their routes on the main actor. Each week, the current one and every older one, measures its shifts' routes once, off the main actor, for its summary, and hands each row its recorded distance from the same pass. Before this, every row measured its own route on the main actor as it scrolled into view, by a fetch whose cost grew with every position the store held, and the summary measured the same routes again: on a simulator store holding six months of full shifts that was about 120 ms a row, a second for the first screen of Older Weeks and over half a minute to scroll every row once. A driver reported Older Weeks lagging on a real device on October 3, 2026. After the change the same first screen costs about 60 ms of main-actor work and scrolling every week about a quarter of a second; a row shows its mileage line a moment after its week appears. HistoryFetchScopeMeasurementTests reproduces both.

Nothing is deleted, archived or aged out. This is what is shown where, and nothing else: every completed shift is still in the store, still exported, still counted by every period summary, and still one tap from its own detail screen. A shift that leaves the current week at Monday midnight moves from one list to the other, and the app does not have to be relaunched for it to do so.

If the current week holds nothing, History says No completed shifts this week yet and leaves the older weeks where they are; a driver with no history at all reads No completed shifts yet and where one will come from. It does not reach back for the last shift worked to avoid an empty list: a week with no work in it is a fact, and filling it with the week before would be the screen answering a question nobody asked.

Shift detail

Tapping a row opens a screen for that shift alone. The row answers what shift is this and roughly how did it go; the detail screen answers what exactly happened and how trustworthy are these numbers.

Section What it holds
Summary The recorded amount as the headline, or "No amount recorded", with Add or Edit Earnings; working time and recorded miles under it
Performance Start and end times, elapsed duration, and, for a shift that was paused, its paused and working durations; delivery active and non-delivery time; all three derived gross rates, or the reason each could not be derived
Driving Recorded mileage, what qualifies it (a partial route, stretches recorded as parked), capture segments and capture gaps
Estimated Costs The estimated fuel cost over this shift's recorded mileage, the estimated gallons, the vehicle, fuel economy and gas price this shift recorded, Add or Edit Fuel Assumptions, and the estimated net ledger: recorded earnings, the estimated fuel being subtracted, the estimated net after fuel and the estimated net per working hour (where there is no estimate, the net says why once and the lines that would repeat it are left out)
Deliveries How many were completed and cancelled, and what each one recorded, with its own corrections under it
Pauses Each recorded pause with its times and length, Edit and Delete for each, and Add Missed Pause
Corrections Correct End Time, and Correct Grouping on a shift with more than one delivery
Export Export this shift
Delete Delete Shift, behind a confirmation, in a section of its own

Reading down, the screen goes from the figures a driver opens it for to the controls that change them. The first four sections summarise the shift in a fixed number of lines; the delivery log and the pause list come after them because they grow with the shift. Corrections that act on the whole shift are gathered in their own quiet section below every figure they change, and deletion stands apart at the foot. A correction that belongs to one delivery or one pause stays on that row, beside the fact it changes, under a rule and an Edit or correct label that separate it from the record.

A stretch recorded as parked is stated in Driving, in the route's words, and never beside a pause: parking stops the route and subtracts nothing from working time, pausing does both.

The estimates come after everything recorded, deliberately. What the driver recorded and what the route measured are the trustworthy part of this screen, and reading down it should go from the recorded to the estimated rather than mix them. A shift with no fuel estimate keeps every other figure exactly where it is, and only the Costs section says what is unavailable and why. See Estimated fuel and net.

It is a summary, not a dashboard: no chart, no map, no gauge and no score. Only completed shifts have a detail screen, because a running shift has no finalised duration, no earnings it may record and nothing that may be deleted.

Which vehicle a finished shift recorded

The Costs section's assumptions open with a Vehicle row, above the fuel economy and gas price it recorded, so the block reads as what this shift was estimated under:

Vehicle                   2020 Honda Civic
Miles per gallon                        34
Gas price per gallon                 $3.29

It is the shift's own snapshot and nothing else. Renaming or deleting that vehicle in Settings, selecting another one and changing the current gas price all leave it exactly as it is. A shift that recorded no vehicle name (one worked before vehicles existed, or whose economy was typed by hand) reads Not recorded, and nothing fills it from today's selection or guesses a vehicle from a matching economy. A missing economy or price says Not recorded rather than 0; a price recorded as zero reads $0.00, because that is what was recorded. VoiceOver hears the block as one sentence per row, the vehicle's row saying it was recorded with this shift.

Entering earnings

Earnings are entered from the detail screen, in a sheet with a field, Cancel and Save. Editing is a draft: the typed text is view state and the store is written once, on Save or Remove. Cancel leaves the recorded amount exactly as it was, and a refused amount keeps the sheet open with what was typed and says which rule it broke.

Removing an amount is its own action rather than an empty field, because an empty field would ambiguously mean both "invalid" and "delete". No amount recorded and an amount of zero are different facts everywhere in the app.

A running shift offers nothing to type into. Typing is a task for a parked car, and the model refuses an amount on an unfinished shift as well, because a screen that is merely never presented is not a rule.

Deleting a shift

Deletion is offered on the detail screen, behind an alert that names what it destroys, including the number of route positions that go with the shift. That count is the part a driver is least likely to have in mind and cannot re-enter by hand.

Deletion is permanent

A deleted shift is removed from the device's store together with its route positions, its recorded pauses and its recorded amount. There is no undo, no trash, no archive and no copy anywhere else. A shift that is still running cannot be deleted at all.