Skip to content
Kinetic Melbourne OCC User manual

Manual / Operations analysis

Punctuality, and what it does not prove

For
a planner localising where a route loses time, and anyone shown one of its numbers
Status
current
Covers
the Punctuality view — the sixth view of the Timetable tab
Last checked against the app
6f7727e (2026-08-19)

Punctuality is a view of the Timetable tab, not of Operations Analysis. Its button sits with the other five, after Headway, and it appears only on a deployment where observed running times have been loaded. It is written up here because what it measures belongs with the rest of the operational analysis.

It answers one question, for one route: where does this route lose its time, and is the timetable or the road the reason?

This is the page in the manual where "what a number does not mean" matters most, because the numbers here look like a performance report and are not one.

What you are looking at

Pick a route — and, if you want, a direction — and the view lists every stop-to-stop segment along it.

At the top, three things: a short note saying what the numbers measure, a Worst segment line naming the segment to look at first and why it is the one, and a coverage line saying how many observed days are behind all of it and which dates they run between.

Column What it is
Segment From one stop to the next
Median The time a run typically loses, or gains, on that hop against what the timetable allowed for it. Shaded by size
p85 The 85th percentile — the bad days
Lose >1m The share of runs that lose more than a minute here
Allocated What the timetable gives the hop
Observed What it typically takes
km/h Scheduled speed against observed speed
Diagnosis What the app makes of it, with its reasoning on hover
n How many observations the row rests on. Hover for how many separate days

The one idea the whole view rests on

Every figure here is about one stretch of road, not about the journey.

The Median column is the time a run typically loses — or gains — between those two stops, measured against the time the timetable gave it for that hop. It is not how late the bus is.

That distinction is the point of the view, and it is worth working through once:

  • a bus that left the terminus ten minutes down and then held its time on every hop reads as 0, or close to it, the whole way along this table. That is correct. Its problem is at the start, and nothing on this road will fix it;
  • a bus that left on time and bled four minutes between two stops reads as +4m on that one row, and near enough nothing everywhere else. Its problem is exactly there.

The first is a departure problem. The second is a corridor problem. They need different fixes, and a single "this route runs late" figure cannot tell them apart — which is why this view exists and why it does not report lateness.

The note the app prints above the table says the same thing, and labels the quantity with an internal name the rest of the app never uses. The name does not matter; the sentence after it does.

The six diagnoses

Badge What it means What it points at
Under-allocated The hop typically loses a minute or more, and the timetable's own implied speed for it is faster than a bus does here The timetable. No amount of driving fixes a stretch scheduled at 45 km/h through the suburbs
Traffic / boarding It loses a minute or more, at a speed the timetable could plausibly expect The road. A retime here just bakes the loss in
Occasional incidents Typically fine, but the worst 15% of runs lose two minutes or more Buffer, rather than retime
Inherited delay It arrives already late but holds its own time Upstream — the origin departure, or the hop before
Holding time None of the above Nothing
No observations Nothing was recorded for this hop Nothing to read

The order those are tested in is deliberate: what does this segment do comes before what did it inherit. A segment that occasionally loses five minutes is reported as doing that, even when it happens to sit downstream of a slow one.

Where the observations come from

An official export, loaded by an administrator. The times are measured by the authority that runs the network, not collected by this app watching the live feed. The app does not keep a record of what it saw yesterday, and nothing on this view is built from one.

That is why the view is absent rather than empty on most deployments: with no export loaded there is nothing to show, and a button that opens a question with no answer is worse than no button.

What it does not prove

It proves nothing whatever about a driver. There is no driver in this data. Every figure is pooled across every run of that route over every observed day. It cannot be broken down by person, it is not broken down by person anywhere in the app, and a number from this view used to describe an individual would be describing a road.

It is not on-time running. The five bands the bus dots and the timetable cells wear — very early, early, on time, late, very late — measure one bus against its own timetable, journey by journey, and are the shape a published performance figure takes. This view measures segments, and deliberately does not use them.

The Median column's shading is relative to this route. It is scaled to the worst segment on the route in front of you. The same number on a different route may be a different colour, and a route where nothing much goes wrong will still have a darkest row.

Time gained is not shaded as good. A hop that typically runs faster than allowed falls to the neutral end of the scale rather than being coloured for it.

The diagnosis is an interpretation, made from three thresholds. A minute of typical loss, a scheduled speed of 32 km/h, and two minutes at the 85th percentile. Those are sensible lines and they are this app's lines. The badge is a planning aid; it is not a finding, a determination, or anything anybody has to accept.

Under-allocated and Traffic / boarding point at opposite fixes, which is the reason the view separates them at all. Retiming a corridor whose problem is traffic bakes the loss into the timetable permanently. Adding drivers or pressure to a corridor whose problem is the allocation changes nothing at all.

n is observations, not days. Eight observations can all be from one Tuesday. Hover the number for how many separate days are behind it.

A ! beside n means the row is too thin to rely on — fewer than eight observations. Those rows are still shown, because hiding them would be worse, but they are left out of the ranking that produces the Worst segment line.

A dash is not a zero. Where an allocated time, an observed time, a share or a speed could not be computed, the cell is a dash. Printing a zero would claim a bus did 0 km/h.

The coverage line is the honest scope of everything above it. Four observed days is four days. The view will still draw a full table off them, and the diagnoses will still read confidently; the coverage line is the thing that says how much weight they carry.

The coverage count stops at 60 days. A route with two years of observations behind it still reads "60 observed days", and the dates beside it are the most recent sixty. The table itself is built from everything that has been loaded, so the line understates the depth rather than the table overstating it — but it is not a total, and it should not be quoted as one.

It is one route and one direction at a time. There is no network-wide worst-segments board, and no date filter on screen — the figures are the whole of what has been loaded, rolled up.

The time slider does not scope it. The Timetable tab's window narrows the Table, the String-line, Allocation and Headway; it does not touch this view. The Both / Outbound / Inbound buttons do, and they are the only control here that changes what is counted.

It says nothing about whether the timetable is achievable overall. A route can hold its time on every segment and still be undeliverable, if the problem is at the terminus or in the turnaround. That question is Allocation's, and the timetable's own budget is the Allocation view's.

When it looks wrong

The button is not there at all. No observed running times have been loaded on this deployment. That is the normal state, and there is nothing to switch on from the app.

You reached the view from an old link and it is one paragraph. The paragraph reads:

No observed running times are loaded. Once an official export is ingested (python backend/actuals.py load …) this view shows where each segment of the route loses time, and why.

The bracketed part is an instruction for whoever runs the server. The part that concerns you is the first sentence: there is nothing loaded here yet.

"No observations for this route yet." Something has been loaded, but nothing covering this route — or, with a direction selected, this direction. Where nothing at all has been loaded that covers it, the message says so as well.

"Failed to load observed performance." The request did not come back. Switch away and back to retry.