Skip to content

design

Who: the department head over Vehicle Ops Co, which is about each individual tricycle from the moment it arrives from Rider Ops Co. Catalog category: Vehicle Operations — uat merged the old tricycle-hardware and maintenance groups into it while this branch was open, and that group is exactly this domain, so the console joined it rather than keeping a category of its own that meant the same thing. The sidebar wordmark names the group a reader navigated from; the department’s own name, Vehicle Ops Co, stays in the job title and in this document. The flow opens on the Command centre; there is no login screen.

The four functions are Conversion, Field support and retrieval, Maintenance, and Parts repair. This corrects the first draft, which had R&D as the fourth. R&D remains one of the five personas in the department but is not a function the dashboard reports on: its insight appears as the L4 cadre on a case. Never a function row.

Sidebar: four items, flat, in his order. Command centre · Vehicle cases · Retrievals · Inventory. The groups went with the pages they grouped — see “Four pages, and what came off them” below for what came off and why the numbers that survived it still add up.

There is no Targets page. It came from the base template, measured production delivery goals this department does not own, and has been removed along with its whole engine.

In order: quick find beside the RadR launcher, the two loud alerts, a global date window over nine slim figures, the release trend, then seven cards each with a window of its own.

Quick find and the god view sit side by side: they are the two controls that answer a question about a specific vehicle, and the launcher used to be a screen away from the search box.

One fleet register, which is what makes the rest possible

Section titled “One fleet register, which is what makes the rest possible”

Until this pass every list minted its own plate, so the same keke could not appear in two places and “which vehicle has the most issues” was unanswerable. Cases, field jobs, bay jobs, the conversion queue and the retrieval queue all draw their vehicle from one register of 140 now. That single change is what makes quick find, most/least issues, longest running and the cost of delay real rather than decorative.

The two alerts are a sticky strip on every page

Section titled “The two alerts are a sticky strip on every page”

They were on the command centre only, which is the one page he is not on when he is working a queue. The oldest thing running on each of the two clocks now sits under the topbar on every page, sticks there as the document scrolls, and opens its record on click.

The zero KPI · no keke off the road because something broke

Section titled “The zero KPI · no keke off the road because something broke”

The one he is chasing, and it needed a definition before it needed a chart.

Preventive and predictive work is PLANNED: the keke goes in on a schedule and the rider knows. Corrective work is UNPLANNED: it broke, and it is off the road without warning. So the number to drive to zero is unplanned admissions, not maintenance work in general — a bay doing more planned work is a bay doing its job, and a KPI that punished that would be the wrong KPI.

Three readings, because no one of them answers it alone:

Reading Why it is there
Unplanned admissions against a target of 0 the number itself, with the window before it beside it so it has a direction
Current clean run, with the best run and 28 day-blocks a zero target is measured in how long you have gone without one. A percentage never reaches zero convincingly; a run of clean days does, and it is the form every safety board already uses. One block a day, oldest on the left: green is a day nothing broke, red is a day at least one keke came in unplanned. The strip carries that key on its face — it shipped with only a hover title and the colours had to be guessed
Unplanned share of bay work says whether the mix is improving even in a week where volume moved

One window for the whole section. Every reading on this card used to carry its own period — admissions over a fixed 7 days, the share over the card’s selector, the strip over a fixed 28 — so three numbers on one card were measuring three different stretches of time and the selector only moved one of them. The card’s own date filter now drives all three, the comparison, the strip and the chart. The strip caps at 60 blocks so they stay readable, and says so when it does.

Each block carries the real date. Hovering one gives the day (Sat 26 Sep 2026), the unplanned count and the planned count, through the canonical .chart-tip rather than a browser title. The legend swatches are deliberately not hoverable — they are a key, not data.

The chart is counts, not a share. 20% of a quiet week and 20% of a busy one are different numbers of stranded riders. Two lines — unplanned in red, planned in green — and the goal is stated plainly under it: the red line on the axis. Every keke that goes into a bay goes in because it was booked in, not because it stopped.

“At the bay 42” sat beside Conversions and Released, which are throughput, and read as throughput when it was a standing population. It is Fixed at the bay now, and Completed field support cases, with the open counts moved into the parts where they belong.

Releases are a shape, and it reads three ways

Section titled “Releases are a shape, and it reads three ways”

A matrix of counts made him read six columns to find a peak. It is a line now, with daily / weekly / monthly granularity and a custom range, and the badge names the peak and the trough.

Three views, because one line answers a different question from six. A line per station answers which station is busiest; it cannot answer are we releasing more than we were, because the eye cannot add six lines.

View What it draws
All stations · total one line, the network total. The summary trend
Every station a line each, with a clickable key to mute one. The comparison
A named station that station alone, with its own peak, trough and note

In a single-station view the badge and the note describe that station’s peak and trough, not the network’s, or they would be captioning a line that is not on screen.

Every trend here was labelled in distance from now: 1w, 2w, now. His objection, and it is the right one: “What does 1w represent? which date period does it represent? i don’t know and as a result, its not very useful for me.”

A bucket is a span of days-ago, so it has real dates and now shows them. The axis gets the short form and the hover gets the whole span, which is why lineChart takes tipLabels separately from labels — the axis has room for 5–11 Oct and the tip has room for the year.

Grain Axis Hover
Daily 2 Oct Fri 2 Oct 2026
Weekly 27 Jul 27 Jul – 2 Aug 2026
Monthly 28 Jun 28 Jun – 27 Jul 2026

The note under the chart names the span too, and says which bucket was busiest by date rather than by position. The same fix went to vehicle issues over time, which had the identical labels.

Quick find opens a vehicle RECORD, not a dialog

Section titled “Quick find opens a vehicle RECORD, not a dialog”

A plate or a rider name, and it opens the vehicle’s own page. A dialog with ten rows in it could say a keke was at a bay but not which work order, who signed its QA, which station it was released to — and it let him open none of its cases.

The record carries four tabs:

Tab What is on it
Overview the rider and where they ride · where the VCU puts it right now, under RadR’s honesty bands · what its downtime has cost, at ₦12,900 and ₦40,000 a day · and everything against this vehicle in one list, newest first
Field support every job on the road and every field case, each opening its own record
Maintenance every bay visit and every bay case, each opening its own record
Conversion & QA the work order, the station, when it was released and to which swap station, against the 2-week clock · and the QA report: the six steps of the retrofit procedure with the result, who signed it and the note on anything that went to rework

Every row opens something. Nothing on the page is a summary that dead-ends, which is the whole difference from the dialog it replaced.

A case opened from a vehicle goes back to that vehicle, not to the Cases list — otherwise following one keke’s history throws you out of it at the first case you open.

A keke on the road for 110 days was obviously released at some point, even though only the live pipeline is in the conversion queue. Saying “no record” was true of the queue and useless to the reader, so a vehicle outside the pipeline carries its historic release instead: it went out when it entered service, to one of the real destination stations.

The oldest thing still running on each of the two clocks he follows up on — the bay and field support — stated loudly at the top with the plate, the rider, the fault and how long it has been going. Clicking one opens the record. No side stripe: a card carries no stroke, single-side accents included, so the urgency is said by the tonal icon, a badge and the red figure.

Nine figures, slim, in three rows of three

Section titled “Nine figures, slim, in three rows of three”

Each row is one comparable set — the pipeline, the work, then the rest — because a row that wraps is no longer a set at all, which is what the layout probe checks.

Figure Its parts
Conversions still pending
Tricycles released completed, not released yet
Retrievals still to do
At the bay open cases · past the 24-hour SLA · done, waiting to be picked up
Field support cases open cases · battery rescues · electrical cases
Blocked work in conversion · at the bay · on field support
Kits back, not placed whole, ready to reassign · no longer whole
Cost of delay · company vehicle-days off the road · vehicles at a bay
Cost of delay · riders what a rider loses each day · riders carrying it

The parts run on one line. Stacked, three of them added ~45px to every card and pushed the charts under the fold; the card is now 137px rather than 190.

Released is not the same as conversion done

Section titled “Released is not the same as conversion done”

A keke can be finished and still sitting at the retrofit station, because the onboarding team has not sent it out to its swap station yet. That gap is its own number, so Released is a stage after Retrofit completed rather than the same thing, and the figure carries “completed, not released yet” as its part.

The release itself is a trend worth reading per station, so it gets a table of its own: releases by swap station, six buckets at a granularity you choose — daily, weekly or monthly — with each station’s total. Six buckets whatever the grain, because six plus the station and the total is exactly the eight columns past which a table’s type shrinks until it stops being readable.

The grain control is a .filt-select, not a .pseg: a tab strip in a table card head is a filter, and canon reserves .pseg for detail-page sub-sections.

₦12,900 to the company and about ₦40,000 to the rider, for every day a keke sits at a bay. The total is days-down times the rate, never an estimate, and the riders carrying the most of it get their own ranked card. The cost card carries one currency symbol, because two in a card is indistinguishable from the formatter bug that ships “₦297.02M ₦” — the riders’ figure lives on the card built for it.

Every card below the figures has a window of its own

Section titled “Every card below the figures has a window of its own”

Because the question each one answers has its own natural period: vehicle issues over time (a line, not bars — the question is whether a fault type is rising), work mix at the bay (preventive / predictive / corrective, which replaced the why-defaulted donut), parts replaced most, vehicles with the most issues, vehicles with the fewest issues, longest running open work, riders losing the most, and where it is happening.

The work mix outlived the Maintenance page. It is counted off the bay population and the scheduled plans, both of which are still registers here, and it is the card that makes the zero KPI readable — the corrective share is the unplanned half. A page was never what it needed.

Parts replaced is a donut, with the total in it

Section titled “Parts replaced is a donut, with the total in it”

It was a ranked bar list. His objection: it made him add the bars up in his head to know the total, and it never said what share of all replacements one part was, which is the question “which part is consuming the most” actually asks.

So it is the canonical donut: the total sits in the middle, every row carries its count and its percentage, and the note names the biggest single draw and its share in words. Everything past the top six folds into one Everything else slice rather than a ring of slivers, and the total still counts every part.

A donut tip carries no data-tip-l. Its single row already names the segment, and carrying both printed “Engine oilEngine oil 19 (26%)”. A line chart still needs the label, because its rows are series and the label is the x value.

Fewest issues is not the bottom of the most-issues list. A keke with nothing recorded against it would never appear in an issue list at all, so the universe is the whole fleet and the rank is days on the road with a clean sheet.

“Everything at a glance” is gone. It restated what the figures above it already said.

His ask, in his words: “beyond what is being reported to me, I can see a real feed from VCU telemetry of what is happening out in the world. I need that.” It is the first thing on the Command centre, above the KPI cards, because it is what he logs in to look at.

It is a floating panel. It used to sit at the top of the command centre and push everything below it down, so reading the trends meant scrolling past a map every time. It opens over the page now and closes again without moving anything; it is deliberately not a .dlg, because a dialog takes the page away and the ask was the opposite. Leaflet builds on first open, not at load, because a map built into a hidden container measures 0 and paints a quarter tile. The launcher it left behind carries the live counts, so closing the map costs him nothing.

It is a real map. Leaflet, as products/atlas/screens/kaag-hermes-map.html already uses it, with the keke marker lifted verbatim from RadR’s own KekeIcon in products/hermes-web-app/flows/god-view/hermes-map.jsx and RadR’s own five status colours from hermes-core.css. Status reads off a coloured dot pinned to the mark rather than the icon fill, which is how RadR does it.

The basemap is Esri’s Dark Gray Canvas, not Carto. RadR’s architecture doc names Carto and kaag-hermes-map.html still points at it, but basemaps.cartocdn.com now returns a watermark tile reading “API KEY REQUIRED” on HTTP 200 — a status check passes and the map renders covered in watermarks. Measured, not assumed. Esri’s canvas is keyless, is the same dark cartography, and splits labels into a reference layer drawn on top. Note the {z}/{y}/{x} order: Esri puts y before x.

A tricycle is on this map only once it is completed and its VCU is live. Units still in conversion have no live VCU, so plotting them would be a drawing, not a feed. The conversion pipeline is therefore deliberately absent from the map and the card says so on its face; conversion is measured on its own page, off work orders and pre-assembly. The three tabs are what RadR genuinely carries:

  • Everything RadR sees — the whole completed fleet it can place
  • Down · needs rescue — the ones stopped and waiting, against the 15-minute reach SLA, with the swap stations field support draws rescue batteries from
  • At the maintenance bays — the ones parked at a bay, with each bay’s pin, lead and load

The flow’s own unit states map onto RadR’s vocabulary rather than inventing a second one: past an SLA becomes Offline, waiting on a part or still inside the 15 minutes becomes Warning, parked and not moving becomes Known, out working becomes Active. Immobilized is a command state — nothing in this flow issues that command, so it is never painted on a unit here.

Positions are the real towns the bay and cluster registers name, to about a street, plus a seeded scatter so the fleet renders identically on every load. A board that moves between loads reads as reflow to the layout probe.

The map depends on a CDN. If Leaflet does not load, the card hides the map and shows a unit board in its place — the same rows, marks, counts, legend and note, all computed off UNITS rather than off the map, so the numbers are identical either way. A flow that renders a dark rectangle because a CDN is slow is not a flow. This path is tested by aborting the Leaflet request, not assumed.

Classes: .rdr-card · .rdr-wrap · .rdr-map · .rdr-mk + .rdr-dot · .rdr-pin · .rdr-legend · .rdr-counts, with RadR’s palette under --radr-* names so it can never collide with a DS token. The fallback board keeps .vb-board · .vb-row · .vb-marks · .vb-mk · .vb-legend, re-inked for the dark card it now sits on.

He pared the sidebar himself: “i want to strip out the things that don’t yet matter to me right now.” What is left is Command centre · Vehicle cases · Retrievals · Inventory, in his order.

Page What it shows and does
Command centre The data summary. The RadR god view and quick find at the top, the two sticky alerts, the zero-unplanned-downtime KPI, nine slim figures over a date window you choose, the release trend, then the ranked and trend cards each with a window of its own.
Vehicle cases Everything after conversion in one register. Tabs: By case · By vehicle · The five cadres · Routing by type.
Retrievals Tabs: Pending · Done. Revenue assurance approves; we execute.
Inventory Tabs: Draws and returns · Repair-level routing · Stock by condition · Item requests. The layer that was missing.

Inner pages, reached by clicking rather than by the sidebar: the vehicle record, the case record, an item-request detail, Notifications and Settings.

Seven pages came off, with every renderer, register and CSS rule behind them: Pre-assembly, Conversion, Field support, Maintenance, Parts repair, KaaG and Schedule and recalls. The work those pages described has not stopped — Conversion still feeds the released figure, the bay still feeds the work mix, scheduled plans still feed the planned half of the zero KPI — but none of it has a page to stand on, so none of it claims one.

Two command-centre figures went with their pages. KaaG inverters active and Pre-assembly done both opened a page that no longer exists, and a number he cannot open is worse than no number. What replaced them is retrieval’s own backlog (kits back, not placed, split whole against no-longer-whole) and the second half of the figure he gave us: the riders’ cost of delay beside the company’s, one currency symbol per card because two in one card is indistinguishable from the formatter bug that ships “₦297.02M ₦”.

Blocked work lost its pre-assembly part for the same reason. It now counts only what the surviving pages can explain: conversion, the bay, field support.

Nothing was left pointing at a deleted page. Every KPI that linked to one now links to Vehicle cases or Inventory, and a card with no surviving target lost its link rather than keeping a dead one. Verified mechanically: every goPanel target resolves to a view that exists, every getElementById resolves to markup that exists, and the dead-code sweep ran to a fixed point — twenty-five declarations, one register, one icon and nine CSS rules had no reader left.

He called this out specifically: every function draws from one inventory and returns to it, and that layer had never been designed. It is one row per function — what it takes out, what it puts back, and what it is waiting on.

Function Draws Returns
Conversion components for pre-assembly, then the full kit the three assembled bundles
Field support and retrieval rescue batteries from the swap stations, throttle and gear selector for roadside swaps the removed part, and the whole retrieved system
Maintenance bay oil, differential, MCU, VCU every part it takes off
Parts repair the returned items, to assess repaired parts, graded by life

Waiting is counted, never typed — a unit on a line whose kit has not been drawn is the same unit the god view marks amber.

Nothing in this repo models a repair level. The warehouse’s four buckets (Unused good, Refurbished, Used serviceable, Faulty) are a disposition, not a grade: the lifecycle they describe is Faulty, then held for repair, then Refurbished, with no record of how many times that has already happened to the part in your hand. So a life number sits beside the bucket rather than replacing it, and the life is what decides which function may draw the part back out.

Life May be drawn by Why
First life Conversion only a new tricycle leaves with new parts, or the 3-month promise is being made on a repaired one
Second life Maintenance bay fitted on a lift, with the bay’s own 24-hour check behind it
Third life Field support a roadside replacement that gets the rider earning today, seen again at the next service
No further life Scrapped assessed and refused; it does not go back on a shelf

The grading happens in Parts repair; the routing rule lives in Inventory. That is an act and a rule, not a duplicate. The rule is written as data and rendered as a table so it can be argued with on screen, and the page says plainly that it is a proposal rather than a readout. Chips are .life with .life-1/.life-2/.life-3/.life-x.

A case used to open a six-row dialog: a type, a cadre, an age. That told him nothing he could act on. A case is a rich record, so canon gives it a details page.

It carries two figures, not one — how long the case has been open, and how long the holder has actually had it — then the case facts with its class and affected part, the triage, why it took longer where a clock was missed, and six tabs: Timeline · Where the time went · Who worked it · Parts · Photos · Other cases.

The record is built from a stamp chain, not from fractions of the case age. See “Every case is a sequence of legs” below: that one change is what makes every other answer on this page true rather than drawn.

A bay job opens the same record. It is the same tricycle, the same fault, held at L2, so it is shaped into a case rather than duplicated into CASES — the god view and the bay board both count off UNITS and must keep doing so. The three tables sit behind one page-level .pseg, which is both what web-stacked-tables-not-tabbed asks for and one question at a time instead of three cards to scroll past.

The chain is seeded deterministically, so the same case always produces the same history, and Back returns to whichever page he opened it from.

The record used to derive its timeline from fractions of the case age: c.mins*0.62 was “arrived at the bay”. That is a drawing of a timeline rather than one. It could not say a tow took 52 minutes, it could not say who held the keke between two stamps, and it could not answer the question he actually asked, which is where the time went.

So every case now carries an explicit, ordered chain of stamps, each with the minute it happened, who held it and what they did:

Stamp What it ends
Opened the RM raises it
Assigned routed automatically on the case type
Arrived at the rider ends the 15-minute reach clock
Triaged on the road what the agent found once it was open
Resolved on the road ends the 45 minutes, measured from arrived
Sent to the bay the lead’s verdict: the road cannot fix it
Tow started it cannot move under its own power
Arrived at the bay ends the 15-minute tow clock, and STARTS the 24-hour bay clock
Triaged at the bay on a lift, fault confirmed
Parts drawn off the bay store, against this case
Taken over on the next shift a second technician, which is normal
Resolved at the bay / Escalated to R&D
Triaged at R&D the defect is the design, not the unit

Legs are built forward and the total becomes the case age, so the short clocks stay literally true: a 22-minute reach is 22 minutes, not 22% of something. Deriving the other way round is what made every interval a fraction of the whole.

⛔ THE BAY CLOCK RUNS FROM ARRIVAL, and that is a production defect being fixed here

Section titled “⛔ THE BAY CLOCK RUNS FROM ARRIVAL, and that is a production defect being fixed here”

His words: “a case is created about a rider but they haven’t arrived at the maintenance bay. The RMs think they have and start to calculate from the time they opened the case, rather than from the time they got to the maintenance bay.”

So nothing on this console measures a bay case from when it was opened. caseClock() asks which leg the clock starts at; bayMins() measures from arrived_bay and returns null when the keke is not there. The consequences, all deliberate:

  • The case record’s head shows two figures side by side — “Open for 2d 6h” and “At the bay 21h 14m”. Both are true about one case and only the second is on the 24 hours.
  • Where the time went marks the leg that ends at the bay door and is on no clock of its own as before the bay had it · NOT on the bay clock, and it is tinted so the eye finds it first. On the measured fixture that leg is 61% of the case.
  • A case whose keke has not arrived shows Not at the bay yet and “the 24 hours has not started” — never a breach. The Resolution card says the clock is Not started, not that there is no clock: the cadre has one, it has not begun.
  • A KPI counts “Would read as breached”: cases that a board counting from the case age paints red today, for a bay that has not been handed the keke.

A road leg is not marked as dead time even though it is also not bay time: it carries the 15-minute reach clock, and labelling it clockless while a green SLA badge sat in the same row was two statements contradicting each other.

His instruction: if it takes longer than 15 minutes to reach the rider, or longer than 15 minutes to tow the tricycle in, the system should ask why, “maybe traffic, police arrest, etc. Just so that we can have the full picture.”

Two closed lists, not one, because the reasons a van is late to a rider are not the reasons a tow is slow:

Clock Reasons
Reaching the rider Traffic · Police or agency stop · Rider could not be found · Wrong location given · Van broke down
Towing it to the bay Traffic · Police or agency stop · No tow available · Could not lift it alone · Bay had no space

⚠ Both lists are a PROPOSAL. He gave two examples and an “etc.”, and nothing in the repo holds a delay-reason taxonomy. Worth settling with him before it is built for real.

The important half is the state below the lists. A breach with no reason given is Not explained, and it is counted on its own: “No reason given” is a KPI and a filter, because it is the difference between a department that knows why it is slow and one that only knows that it is. The record’s Why it took longer card only appears when a clock was missed, and says plainly when nobody answered.

Cases: RMs raise them, five cadres hold them

Section titled “Cases: RMs raise them, five cadres hold them”

Relationship Managers interface directly with riders and are the ones who raise the case. By type it is routed automatically; the RM picks a type, never a destination. The cadre names who is holding it, and a case enters at a cadre and escalates upward when the tier below cannot resolve it.

Cadre Who holds it Clock
L0 Relationship Manager, resolved with the rider, no dispatch no clock
L1 Field support 15m to reach · 45m to resolve
L2 Maintenance bay 24h to resolve
L3 Parts repair, the kit is assessed and the part graded no clock, graded not timed
L4 R&D, the defect is the design and not the unit no clock, may raise a recall

L0 is on the board deliberately. Those are the cases the RM contained, and a department that only ever sees what it failed to contain cannot tell whether containment is working.

Every table on this console opens a record on row click, and the record is sized to what it holds: a centred .dlg for a compact one, a full details page for a rich one. Work orders carry Forge’s own progress sentence rather than a bare built-count; an assignment carries its 2-week clock; a post-conversion failure opens the case behind it rather than a summary of it, because the point of that tab is to ask why a unit we had just built came back.

SLA state is a filter, not just a badge. The vocabulary is taken verbatim from facilities-vp: Breached / At risk / Within SLA — three states, not two, because at risk is the one he can still do something about. At risk is the last fifth of the window.

Past three dropdowns the filters collapse into a dialog. Vehicle cases carries nine; six in a row crowd the page title and wrap. The selects keep their ids inside the dialog, so every renderer reads them unchanged, and a count badge on the button says a filter is on while the dialog is shut.

Battery rescues, parts replaced and parts repaired on site. The Field support page is gone, but the distinction is not cosmetic and it survives on the case record, where the triage is read: each job carries it as the canon keeps it, in three separate lists, deliberately not merged.

Layer What it is Example
Reported what the rider or RM says down a phone Battery tripped off · Draining too fast
Discovered what the agent finds once the keke is open Tripped off · Loose connector · Voltage drop under load
Done what was actually done, following the lead’s verdict Battery swapped · Part replaced · Repaired on site

Merging them, in the canon’s own words, “would let a case be filed with a diagnosis nobody made”.

⚠ “The rider ran it down” does not exist in the canon. The reported list has Battery tripped off and Draining too fast; there is no rider-caused-discharge symptom anywhere in the repo. Rather than invent one, the discovered list carries Discharged in service for the case where the agent finds no fault at all. That is the one word on this page with no precedent behind it, and it is flagged here rather than passed off as canon.

Field support and the bay share ONE case register

Section titled “Field support and the bay share ONE case register”

They are two sides of the same coin: both handle cases against a vehicle, differing in type — and a case that starts on the road often ends at a bay when the road cannot fix it. Two separate tables made that journey invisible and made “every case against this keke” unanswerable.

So there is one register, VCASES, holding everything after conversion. origin is where the case started, to is who holds it now, and escalated is the difference between them. A case worked on the road keeps its field triage — reported, discovered, done — whether or not it later moved to a bay. Six of the fifty-four have moved from the road to a bay, and the page has a figure for exactly that.

CASES and FSJOBS survive as views over the register, so the seventeen functions that already read them kept working without a rewrite.

  • By case — eight columns: case, tricycle, fault and the affected part, class, status, assignee, open for, and the clock. Nine filters behind the dialog: cadre, where it is, status, class, part, who worked it, delay past the 15 minutes, SLA state and rider area.
  • By vehicle — the same register grouped: open count, all-time count, where its open cases are, and its oldest. Opening one goes to the vehicle record, where every case against it is already listed.

Four columns he asked for, and each is derived, never typed, so a column and the timeline can never disagree.

Column Values Where it comes from
Status Open · In progress · Resolved · Blocked where the chain stopped. Open genuinely means nobody has reached it, so the chain really does end at Assigned
Class Mechanical · Electrical · Battery the case type. It used to be set on field jobs only, so two thirds of the register had no class at all
Affected part Throttle, gear selector, buck converter, harness, differential, … the case type’s own part list
Assignee whoever holds it now, plus +N worked it the last leg in the chain

Blocked is not slow. A blocked case carries what it is blocked on — waiting on a part, a tow, a lift, or held at R&D — because a case nobody can move is a different problem from a case nobody has moved.

⚠ Three parts he named are not in the shared register. components/field-support-items.js is field support’s list, and a tow-in job is not a roadside job, so Differential, Brake assembly and Chassis are carried in this flow with a marker rather than quietly added to a file two other apps read. The record says “a bay part · not in the field support register” under the part name. Worth resolving properly: either the bay gets its own register, or that one grows a scope.

He was specific: “there will be multiple people working on a tricycle, especially at the maintenance bay… and even on field support, sometimes, both a rider that does battery swap and electrical that fixes electrical issues will work on a case, they all need to be captured.”

So the chain carries both:

  • On the road, a battery rescue and an electrical fix are two different people on one case, and the second agent’s leg says why they were called out.
  • At a bay, anything that runs past a shift carries the technician who diagnosed it, the one who took it over, and the bay lead who signed the QA gate. That is Forge’s per-step signer model, not a single “technician assigned” field.

Who worked it is one row per person, with every step they took, when they came on and how long they actually had it. The measured fixture runs up to six people on one case. Where the repo has no name for a bench — parts repair, R&D — the role stands in the Assignee column rather than the words “Not yet named”: the honesty belongs in the record, not in the column that is meant to say who to call.

The case record shows the vehicle’s other cases

Section titled “The case record shows the vehicle’s other cases”

A fifth tab on every case: everything else raised against the same keke, with a note when any of them is the same fault. A fault that keeps coming back on one keke is a different problem from a fault that happens once, and that is a question a single case page could never answer.

Revenue assurance approves a retrieval. Defaulting on the five-days-a-week rule is their call, not this department’s. The first build put an “awaiting your approval” state and an Approve button on this page — a decision on his desk that was never his. What lands here is the execution: field support goes and takes the kit back.

Two tabs: Pending and Done. Pending is what revenue assurance has approved and field support has not yet collected; Done is the kit back with us, whole or not.

The 2-day reassignment clock came off, on his instruction — “remove the 2 day SLA for now”. It is a real rule and it stays in the domain note, but it is not what he is working from, and a clock on a page is a thing the reader has to carry. What is left of it is honest and unclocked: the command centre counts kits back, not placed, split whole against no-longer-whole, so the backlog is still visible without a deadline nobody is yet holding anyone to.

Where is it? A keke in the retrieval queue still has a live VCU, so field support does not have to go looking. Each row carries its last fix, how old that fix is, and the rider area it sits in, under the same honesty bands RadR uses — Reporting now / Quiet / Silent — rather than a claim of live GPS.

The case record carries the people and the photographs

Section titled “The case record carries the people and the photographs”

One card at the top, not four. “Held at”, “with” and “hands on it” were three more 150px cards repeating what the badges in the title row and the Technicians tab already say, and together they pushed the record itself below the fold.

More than one technician works a tricycle, and the record says precisely who did what and when: each entry carries the minute it happened and how long that person had it. A bay job past a shift shows the diagnosing technician, the one who took it over on the next shift, and the bay lead who signed the final QA gate — that is Forge’s per-step signer model rather than a single “technician assigned” field.

Photos use the Atlas web evidence atom (.evi / .evi-thumb / .evi-cap, from head-of-maintenance), keyed to the record so a case shows the same photograph every time it is opened, and gated by topic so a battery photograph cannot turn up on an electrical case.

The bays tab no longer says “the four bays” — the count is read from the register, so it cannot go stale the day a fifth opens.

All bay work falls into three categories, with a donut showing the share of each:

Category What it is What drives it
Preventive scheduled service, done before anything fails the maintenance schedule
Predictive telemetry or a repeat pattern says it is about to fail RadR and the fault taxonomy
Corrective it has already failed and the keke is off the road cases from field support and RMs

The share that is corrective is the number that matters: a bay that is mostly corrective is a bay chasing its fleet rather than staying ahead of it, and the badge turns amber past 40% and red past 55%.

Nobody is named who has not been named to us

Section titled “Nobody is named who has not been named to us”

The command centre used to carry a lead’s name under each function KPI, inherited from the first draft’s “four functions” table. Three of the four were real people in the repo doing different jobs — Ibrahim Yusuf and Grace Uche are field support technicians in the swap app, promoted here by accident to heads of Conversion and Maintenance; the fourth, the parts-repair lead, did not exist anywhere. The console also contradicted itself, since the bay pages correctly list the four real bay leads while the KPI card claimed a different person ran maintenance.

They are gone. The rule now: a name appears only where the repo supports it.

  • Gbenga Adisa stays on field-support triage, because that is exactly his role in products/rechaj-swap-app — Field Support Lead.
  • Bay triage names a real bay lead from the Head of Maintenance register.
  • Parts repair has no persona anywhere in the repo, so where its bench is named at all it is Not yet named.
  • The four KPI subs carry the actionable half instead: “16 of them waiting on a kit”, “3 past the 24-hour bay SLA”.

The four function heads have not been named to us. When they are, they go in — until then the cards say what is happening, not who to blame for it.

The design system ships no media queries at all — it is a fixed 1440 canvas — so every responsive rule here is the flow’s own, following the pattern the swept siblings already use.

The topbar was the break, and it was the profile. .user-name and .user-role carry no nowrap, so at 834 the name squeezed to 44px and wrapped onto two lines while the role ran to three, both spilling straight out of a pill that is a fixed 42px inside a 60px bar. Measured: the name is 14px tall at 1024 and 29px at 834. Both now nowrap, and below 1000 the text is dropped entirely — the avatar and chevron identify the signed-in persona on their own and the account menu still names them in full.

Breakpoint What changes
1200 KPI row steps 4 columns to 2
1000 sidebar collapses to the 68px icon rail (every item carries a title, so the rail is readable) · the profile drops to the avatar · the lens pill goes, being a filter rather than identity · topbar and page gutters tighten to 16px
900 record grid goes single column · the map shortens to 420px and its count panel hides
760 the RadR head stacks above its tab strip · .tbl-card-head is allowed to wrap · board rows go single column
640 KPI row goes to one column · a tab strip scrolls rather than taking the page sideways

Two of those were found by sweeping every view at every width rather than eyeballing the dashboard: a table card pushed its three filter selects 83px past the viewport below 768, because .filt-bar wraps internally but sits inside a .tbl-card-head that does not, and a flex item will not shrink below its content. A four-tab strip took the document sideways at 560. Both fixes are general, so they held when seven pages came off; re-verified on every surviving view from 480 to 1440.

Nothing is invented where the repo already holds the real thing. Bays come from the Head of Maintenance console, the richest and most authoritative of the three bay registers (the other two disagree with it and with each other): Metro, Honda, Alimosho, Ikotun, with their LGA, lead, technicians and bench capacity. Retrofit stations and the two conversion models (Bajaj RE, TVS King) come from the Head of Retrofit console. Parts come from components/field-support-items.js, the one shared and linted parts register, with its serialised codes MCU-22, VCU-18, EM-05, SHF-31, DU-44. Fault codes come from the Maintenance Supervisor’s taxonomy. Clusters come from the VP Swap console; swap stations from the Field Support Lead.

The unit feed is a deterministic fixture off a seeded generator, never Math.random: a board that renders differently on two loads reads as reflow to the layout probe, and a KPI that moves between renders cannot be checked against the page it opens. Ikotun Bay sits over capacity and three bay jobs are past the 24 hours on purpose, because a board on which nothing is wrong tells a head nothing.

  • The repair-level routing above is a proposal. It is the one thing on these pages with no precedent in the repo to copy.
  • Real LGA geometry for the god view. The board works without it; it would make the three tabs geographic rather than site-anchored.
  • The R&D persona has no flow, record or metric anywhere in the repo. It is named here only where it genuinely acts, as the L4 cadre on a case.
  • Batch recalls had a page and now have none. The register went with it, so the recall R&D triggers is currently nowhere on this console — the one piece of the domain the strip left unrepresented, and worth asking him whether it comes back when he is ready for it.