Skip to content

changelog

All notable changes to this product are documented here. The format is based on Keep a Changelog, and this product adheres to Semantic Versioning.

  • Energy capture no longer depends on the AI extraction model. The module was built on the premise that OCR always works: photograph a meter and the model reads the label, the numbers and the date off it and files the reading itself, with a bulk upload doing a whole pile at once on the same assumption. The model has real downtime, and an experience welded to an automation fails exactly as hard as the automation does — with extraction down, nothing could be recorded at all. Extraction is now an enhancement, never a dependency:

    • Bulk upload is gone, with its review screen, its per-row fix flow and its styles. Nothing now assumes a pile of photos can be read, dated and filed unattended.

    • Work runs meter point by meter point. Each round offers exactly three things: photograph it now, upload one from the phone, or mark it faulty.

    • A photo always lands and the value fields are always editable. Extraction fills them when it is up; the manager types them when it is not. Values save as they are entered. Daily takes watt-hours because that is what the controller glass shows, and converts internally.

    • Every reading says where its number came from — read from the photo, typed, or edited after an auto-read — so a wrong auto-read is visibly an auto-read and not something the manager appears to have typed. A failed read offers a retry on the row.

    • Upload and extraction report on the meter card, not on a page of their own, so a photo going up never blocks working the next point. A failed upload keeps the photo and offers Try upload again — the send failed, not the capture, and offering a retake first would throw away a good photo.

    • The in-app gallery grid is gone. Choosing a photo is the operating system’s job; the grid only existed to multi-select for a bulk run. Upload attaches exactly one image to exactly one round.

    • The summary card answers the day in two blocks, morning and evening, each stating how far it got and whether it is finished. Faulty counts as settled rather than outstanding. The old combined Captured / Not captured row mixed both rounds into one number, which is what obscured whether the morning was done.

    • The clock-driven round override is gone, along with the “set by the clock” strip that was its only way in. The round is chosen by tapping its row, and the camera lists every meter and round behind Change.

    • The top capture button is retired for a greeting that says which round is in front of you. Jumping to “the next open slot” only made sense while capture was a page-level batch.

    • The generator is once a day, and reports a total. Output and load are gone: a snapshot of load is not a reading anybody can add up. The genset round photographs the energy page and records a lifetime Total in kWh, and it is read once a day rather than twice, because a cumulative total does not say anything different in the morning than it does in the evening. The morning round therefore counts 12 points and the evening 13 — every count, filter, denominator and navigation now asks roundsOf(point) instead of assuming two. This resolves the open question logged as C14 in docs/dev-handoff-removals.md. G1’s seeded figures still need one real reading off the genset energy page.

    • The day’s kWh total is off the summary.

    Applied to prototypes/swap-station-manager.html. The charge station manager and the swap PM still carry the previous model.

  • Prototypes consolidated into ROLES. The swap app had seven overlapping prototypes and now has three, one per role, each a standalone app rather than a feature demo:

    • prototypes/swap-station-manager.html — the reference build. Dashboard, the end-to-end swap (fee + VAT, two-stage unlock, production Report Issue) and the full energy module. Renamed from swap-energy-capture-v1.html.
    • prototypes/charge-station-manager.html — the energy module, profile and sign in, and nothing else. A charge station runs no swaps, so every swap screen and its logic are absent rather than sitting behind a dead nav item: 13 screens, two tabs.
    • prototypes/swap-pm.html — the station manager plus a station switcher over the five operating stations. The register and the readings are keyed by station and day together, so labels (which are only unique inside a station) can repeat without one station’s readings ever appearing under another’s. Switching resets the day, the filter and any pending upload.

    A ROLE config block at the top of each file is the only thing that differs structurally — the bottom nav renders from a NAV array rather than duplicated markup, so a role is a config change and not a rebuild. Profile and sign in were added to all three; every one boots to its app screen, never to a sign-in screen.

  • Removed index.html, old-vcu.html, swap-energy-capture-v2.html, swap-prod-v1.html, swap-roles-v1.html and swap-support-basic.html, along with the broken screens/Rechaj-Swap-Prototype.html symlink that pointed at old-vcu.html. DESIGN.md and the swap-app DESIGN.md now cite the station manager as the swap reference implementation; the product thumb follows. Changelog and spec mentions are left alone as historical record.

  • Meter register is the real one. The invented SOL-TG-45 / “Solar String 45” scheme and the invented “72 meter points” are gone. Points carry the label printed above each controller (M9, M76, G1), which is the identity extraction reads off the photo and is only unique inside a station. Every value is anchored to a photographed reading. An MPPT reports Daily in watt-hours (resets overnight, reads the generation for the day by the evening round) and a lifetime Total in whole kilowatt-hours, plus the date and time on its own display; the genset controller reports instantaneous output and load and carries no energy counter and no date, so its round is a snapshot dated by the phone. See docs/dev-handoff-removals.md C14 for the open question this raises about generator energy.

  • Station named on the station-manager prototype moved from Toll Gate Mega (shut down) to Metro Swap Station.

  • The three undesigned roles are now blank placeholders. flows/battery-handler and flows/cluster-manager were 503 KB copies of an older role prototype that no longer described anything real. Each is now a 2.6 KB “Coming soon” card following the repo’s existing placeholder convention (products/atlas/flows/pm-battery/index.html) — no shell, so detectPlatform reports unknown and the platform-scoped canon rules skip it. Removed flows/support-cases/ and flows/station-manager/ entirely, along with all four canon-baseline entries — the station-manager surface is the Swap Station Manager prototype, so a second flow of the same name was a duplicate.

  • Energy: filter and photo preview. A chip track over the meter points — All / Not captured / Captured / Faulty with live counts, using the same test as the summary above it so the two can never disagree. Every logged round carries a thumbnail of the photo it came off, one tap from a full preview showing the image and everything read off it.
  • Bare-bones in-app support at prototypes/swap-support-basic.html — a deliberate reset from the sophisticated support-cases-v3 direction, taking the current WhatsApp support model straight to the app on top of the unchanged production UI (swap-prod-v1). Two moves managers make today: Get help and Park swap. Get help (on the dashboard for out-of-swap issues; in a bar on Swap Payment / Complete Swap for in-swap issues) opens a uniform flow — pick the exact issue from the shared, grouped list → attach a screenshot + photos → describe → submit. One flow for every issue; no per-issue-type capture screens, no auto-population (that comes later). Submitting creates one support ticket + a two-way thread (manager ↔ Rechaj support, with photo attachments). An in-swap ticket auto-parks the swap so the rider queue moves on; Park swap parks manually. Parked swaps and support tickets live on the home screen (parked = oldest-first with a count badge; resume-in-place when resolved). Report a new issue lets a manager name an issue that isn’t listed, pick its area, and add it to the company-wide shared taxonomy so support and other managers reuse the same type — keeping one clean issues table. Escalation targets are named (Revenue Assurance for special cases, Hardware for keke breakdowns) as tags on the relevant issues; their downstream is intentionally a stub for now. Registered in site/src/data/products.ts with side-panel scenarios (home · get-help · in-swap · report · new-issue · thread).
  • Reconcile sheet pruned — removed the “Capture every transfer claimed” subtitle, the context recap card, and the “If it’s still slow…” overdraft note. Sheet now goes straight from the title to the payment-count chooser and the payment rows.
  • Rider authentication form (perm-station-change lookup) — QR scan returns plate and phone number. Manual entry replaced with two inputs (plate + phone) instead of a single licence-number input.
  • Old-battery reassignment scenario rebuilt and shipped (WIP tag removed). After unlocking a keke with no record of the current battery, the manager scans or types the serial. Three outcomes interactively branchable on-screen: (a) logged → continue to new-battery, (b) serial in use on another battery in the field → opens “Report to support” sheet, parks swap, (c) serial unknown → opens “Request new serial from backoffice” sheet, parks swap. Parked-swap copy + notification banners added for both new wait states.
  • Terminology — “battery cycle” replaced with “swap” everywhere user-visible. Battery profile rows now read “Last swapped” / “612 swaps” (was “Last cycled” / “612 cycles”). Applies across swap-app prototypes v1/v2/v3, Atlas v1 & v2 dashboards, and the swap-support-resolution prototype.
  • Battery serial format — adopted production pattern BP-YYMMDD-NNNNNNNN (e.g. BP-251022-23910847) everywhere a battery serial is shown. Replaces the legacy BAT-#### mock format in all prototypes + Atlas references. Ticket IDs (#BAT-####) intentionally left untouched — those are audit case numbers, not battery serials.
  • v3 final-step (Set next milestone) — adds a manual Voltage input (the manager reads off the new battery’s display before handing it over) and pre-fills “Current mileage” with the value from the rider’s last swap. A hint below the mileage input notes “From last swap (07:14 today). Edit if the dashboard reads differently.” — manual override stays available. Voltage flows through to the swap-complete receipt.
  • Voltage everywhere — the metric Rechaj actually records is voltage, not state-of-charge. Every percentage-based charge reading across the app was renamed and recalibrated: 98% → 67.2V, 12% → 50.4V. Labels updated: “Charge” / “Charge level” / “State of charge” → “Voltage”; “Charge given” → “Voltage given”; “Return charge” → “Return voltage”. Hits v2 + v3 swap-app prototypes, Atlas v1 + v2 dashboards, and the swap-support-resolution prototype.
  • v3 rider-profile wallet hero — adds a circular refresh affordance at the top-right (idempotent re-pull of balance from backend, with a 900ms spin animation) and a View history link in the footer that opens a new sheet-wallet-history bottom sheet. Sheet groups top-ups and daily-fee debits by day, with credit (green) / debit (red) iconography.
  • Production swap-flow replica + battery-compartment unlock: prototypes/swap-prod-v1.html. Faithful rebuild of the currently-live swap app (the role-split update has not shipped) across five screens — dashboard, Initiate-swap sheet (plate + phone), Swap Payment (session timer, rider wallet + refresh, swap fee, rider/keke details, Sango Reward, VCU status card, station balance), Transaction-history sheet, and Complete Swap with the “Keke compartment control” green lock button. The compartment unlock wires the full Bluetooth → internet → OTP cascade onto the production UI (logic ported from support-cases-v3.html): the VCU card’s Bluetooth enabled / Recently streamed diagnostic drives the path. Deep-linkable scenarios: default (BT/internet reachable → direct unlock) and ?scenario=bt-fail (No/No → 5s BT timeout → Try internet fails at 3s → OTP fallback: 6-digit, 15s window, blurs on expiry, regenerable). Also supports ?screen=<id> direct deep-links.
  • New v3 of the support-cases prototype: prototypes/support-cases-v3.html. Captures the full set of swap-app support scenarios — a 3-step happy path (drops the obligatory old-battery scan because the depleted battery is held in-memory), wallet not loading, battery not yet transferred to the station, temporary vs permanent station change, insufficient balance with three funding accounts (Opay / Paystack / Sterling, Opay highlighted), manager→rider transfer failure, funding-not-reflecting reconciliation, funds held with another station manager, battery serial conflict (kept + polished), old-battery reassignment, and a three-rung VCU fallback ladder (Bluetooth → internet → manual unlock). v3 lives alongside v2 until approved.
  • Six new patterns surfaced inside v3 — reassign-banner, va-tabs (virtual-account picker), action-strip (subtle inline action), psc-station-list (radio-select), vcu-ladder (progress strip), manual-unlock (numeric code entry).
  • Five new scenario groups in the /flows sidebar — station, wallet, battery, vcu (in addition to the existing flows / scenarios / end-states). Six new sidebar icons (map-pin, shuffle, key, wifi, clock) added to site/src/pages/flows.astro.
  • New v2 of the support-cases prototype: prototypes/support-cases-v2.html. Covers the full station-manager support flow — station mismatch, first-swap-unpaid (Opay funding), battery conflict (duplicate serial), the parked-swap queue with live update banner, and a redesigned support log. Lives alongside the v1 prototypes/support-cases.html until v2 is approved, at which point v1 will be removed.
  • Seven new entries in patterns/: prototype-scenarios, parked-queue, notification-banner, inline-alert, status-card, captured-context, timer-band — extracted from the new prototype for cross-product reuse.
  • New Scenario data shape in site/src/data/products.ts lets a flow declare captured scenarios. The /flows page renders them as a 3-column grid panel beside the iframe; clicks update ?scenario=<slug> on the iframe, which the prototype reads at init to set up the captured state.
  • v2 swap-flow now models the full happy path leadership called out: rider-details card surfaces wallet balance + active subscription + station match alongside the existing identification fields, and a new Connect & unlock step (#screen-vcu-unlock) sits between rider details and battery return. The step has four captured states (vcu-connected, battery-locked, battery-unlocked, vcu-failed) driven by data-state on the screen, with auto-progression on entry and on tapping Unlock battery lock.
  • Four standalone keke illustrations at prototypes/assets/keke-{connected,locked,unlocked,issue}.svg — used as hero artwork on the four VCU states.
  • Progress bar across the swap rebalanced to 4 steps: Identify · Connect · Return · Out.
  • Scenario list grew to 16 + Reset, with five new captured states: rider-details-ok, vcu-connected, battery-locked, battery-unlocked, vcu-failed. Three new scenario icons (bluetooth, lock, lock-open) added to site/src/pages/flows.astro.
  • “Rider wallet not loading” scenario removed — the new wallet-hero refresh button on the rider profile handles this inline. Dropped the alert-wallet-fail inline alert, sheet-wallet-fail bottom sheet, retryWalletLoad / submitWalletFail JS, the wallet-fail scenario mode, and the scenario entries in site/src/data/products.ts (both swap-app and Atlas swap-support-resolution). Also removed the corresponding Atlas resolution screen + queue row.