DutyGuard
Can I take this overtime shift — and what does it do to my week?

Independent tool — not affiliated with, or endorsed by, Royal Mail. The public app runs on a fictional depot; every duty code, time and route shown is invented. DutyGuard is a planning assistant, not a compliance guarantee.
The problem
I drive at a mail centre. Overtime there is driver-led: you put your own name in a book for the duties you want, and management may approve them without recalculating everyone’s previous week. The expectation is that you already know whether you are able to work it.
So every driver is doing the same arithmetic in their head, against rules most of us have never been sat down and taught — daily rest, weekly rest, driving limits, working time. Get it wrong and you can end up over a limit you did not know you were near. The safe move is to take less overtime than you could. The tempting move is to take more than you should.
Nobody wants to do this maths at half past midnight to find out whether they can work on Wednesday.
Research
The research was the job. I photographed what is actually on the wall: the late duty roughs, the distribution scheduled attendance, the Saturday and Sunday sheets, and one real duty card. Then I transcribed them into a duty pack — 89 duties at one site.
Three things fell out of that, and all three shaped the product:
Hours on site are not driving hours
One duty card documents eight hours of attendance, forty-five minutes of meal relief and three hours fifty of driving. The rest is loading, collections and travel. Any tool that treats a shift length as a driving figure is wrong before it starts — so attendance, working time and driving time are three separate fields that are never derived from one another.
Half the data does not exist
The late rough publishes start times and no finishes. 43 of the 89 duties have a start and nothing else. A planner that quietly assumed “start plus eight hours” would be confidently wrong — real duties at this site run from 4h25 to 10h30.
Duties are not all the same shape
Some are fixed rounds with a documented route. Some are pooled attendances — twelve identical slots where the number is a slot, not a round, and the work is whatever needs doing. One is a split duty with two blocks in a day and a gap that is not a rest period. Several cross midnight into the following regulatory week.
The design approach
The app answers one question — can I take this? — and a second one behind it: how much more could I take? Everything else is in service of those.
The decisions that mattered:
Never say legal or illegal
Three things sit on top of each other: the regulations, the employer’s own rules, and what a driver personally wants. Collapsing them into one verdict would be dishonest, so the app reports no conflict identified, check before accepting, or potential conflict — and always says why. Breaching your own preference is amber. It is never red, because it is not that kind of problem.
“I don’t know” is a first-class answer
Where a finish time or a driving figure is missing, the app says so rather than passing. A silent green on missing data is the one outcome that could actually get someone in trouble, because that is the one they would act on. Propose a duty with no published finish and twelve of twenty-two checks return unknown, each naming the gap.
What you were rostered is not what you worked
Every shift holds scheduled and actual times separately. Before the duty, projections use the roster; afterwards the app asks what you really finished, and uses that. A third of my own contracted week is pooled work with no predictable driving figure, which makes recording actuals the main way data gets in, not an afterthought.
A pass should say how much room it passed by
My Saturday finishes 18:00 and my Sunday starts 05:30. That is eleven and a half hours against an eleven hour floor — a pass, with thirty minutes of slack. A green tick alone hides that. So green now carries its margin, and the tightest gap of the week is surfaced on the home screen.
Technical implementation
The compliance rules are pure TypeScript functions with no knowledge of React, storage or the network, so every rule can be tested against a hand-built week. The regulatory thresholds are versioned configuration rather than code, because which rules govern a given duty is a question the app is not entitled to settle on its own.
A rules engine, not rules scattered through screens
Daily rest, weekly rest, driving time, working time and the employer or personal layer are separate modules behind one interface. Every verdict is stamped with the rule set and version that produced it, and every threshold ships flagged as needing confirmation — because it does.
Adversarially reviewed, and it needed to be
The suite runs to 379 tests, but the useful pass was an adversarial one hunting for a single failure: green where the app should hesitate. It found two. One returned a pass on a week the same engine called a conflict when asked differently; the other split a Sunday-night-into-Monday driving period in half so a breach was invisible from both weeks. Both were reproduced with runnable tests before anything was changed.
The real duty pack is encrypted, not hidden
The depot’s sheets are internal documents, so the public app ships a fictional depot instead. My own pack travels inside the same build under AES-256-GCM with a key stretched 600,000 times, and decrypts onto my phone when I enter a passphrase. An unlisted URL would not have been enough — certificate transparency logs make those findable.
One depot, behind an interface any depot could use
Nothing in the engine knows about mail. A duty pack is data: codes, categories, times where they are published, and honest nulls where they are not. Another driver at another operator can import their own and get the same checks.
Outcome
DutyGuard is a working, installable app that I use for my own duties. It tells me before I write my name in the overtime book whether a duty conflicts with the rest I have had, what it does to my week, and — just as often — which parts of that it cannot answer yet.
It has not been given to other drivers. The honest position is that it needs its remaining unknowns closed first: which hours regime governs my duties is a question for the depot, not for me, and 43 duties still have no published finish time.
What I learned
The hardest part was not the regulations. It was deciding what to do when the data runs out — and the answer, every time, was to say so. It is tempting to fill a gap with a reasonable assumption, because the screen looks better. But a tool that guesses teaches you to trust it, and then it is worse than nothing.
The other lesson was that domain knowledge is what makes the model right. I knew attendance was not driving time because I had a duty card in my hand showing eight hours and three-fifty. Without doing the job, I would have built something that looked correct and was quietly wrong.