SkipOps

Plain English, start here

What SkipOps does — and exactly where we are

SkipOps runs the day for a UK rubbish-clearance firm, entirely through Telegram. The boss texts jobs in plain words. The system works out the smartest route for every van. The crew get tap-by-tap job cards on their phones. The boss watches it happen live and ends up with a photo-proof record of every job. No money or pricing anywhere in version 1 — the win is told in saved fuel, time and wages.

5+1set-up wizard built + on-brand (Your firm · Vans · Crew · Disposal Sites · Checklist) in amber-on-tarmac dark mode; Disposal rebuilt to waste-type tabs + vector map. Going to 6 steps — a new Operations step (yard hub / "full load" rules) is planned, awaiting Alex's nod
1route planner: a working core that needs a rework
7stages designed and waiting to be built
built & tested part-built to build

The whole thing on one page

The loop, top to bottom

Five moving parts. Set the firm up once, then the same loop repeats every working day.

flowchart LR
  A["① Set the firm up
(once)"] --> B["② & ③ Boss texts
jobs"] B --> C["④ System plans the
smartest day"] C --> D["⑤–⑦ Crew get job cards
+ post photos"] D --> E["⑥ ⑧ ⑨ Boss watches live +
gets the record"] E -. "new job or change
→ re-plan" .-> C classDef here fill:#eef2ff,stroke:#4f46e5,stroke-width:2px,color:#3730a3; class A here;
We are here — stage ① calibration wizard is built + on-brand (amber-on-tarmac dark mode) (27 Jun): the 5 steps walk start→finish with no dead ends, the Disposal step is rebuilt (waste-type tabs + vector map + per-type real sites), and contrast is AA-checked by a test. Now adding a 6th "Operations" step (yard hub / "full load" rules — plan opened, awaiting Alex's nod). Then Alex walks the whole 6-step wizard live. No stage ②+ bot work until calibration is concrete.

Every stage — what it's for, and where we are

The 9 stages in detail

Each one: the plain-English objective (what we're trying to achieve), a quick picture, and an honest done / still-to-do.

Set the firm up

5 steps built end-to-end + on-brand (amber-on-tarmac) · live phone gate the one thing owed · v1 actively excludes a calibration-time working window

The objective: before SkipOps can run anyone's day, it has to learn how that firm works — the five things its features need. The boss fills in a quick 5-step setup wizard + a review — one simple screen per thing (yard address, vans, crew, disposal sites, checklist), tap and type, then Next. No AI, no guessing in setup: each step is a plain form with the right controls. Our own code checks a step is complete before it lets you advance, and the firm is saved at the end. Hours are deliberately not asked here — they flex day to day, so the day's working window is captured when the crew share live location to sign in (kicked off by the gaffer's "kick off the day" command, built in stage ②).

What we gather from the firm → what it powers: the yard/base address (anchor for routing + the centre we search around for nearby tips and scrapyards), their vans & how much each holds, their crew (names — daily availability comes from sign-in, not here), which materials they handle + where each one goes (powers the smart-route consolidation runs), and the standard job checklist. Every answer feeds a feature — nothing is asked "just in case".
flowchart LR
  subgraph G ["What we gather"]
    V["Vans + capacity"]
    M["Materials + drop sites
per material"] S["Yard address
(the hub)"] C["Crew (names only —
hours come from sign-in)"] K["Job checklist"] end subgraph P ["What it powers"] R["Smart routes +
full-van trips"] J["Crew job cards"] D["Boss live map"] Pr["Photo-proof
record"] end V --> R M --> R S --> R S --> D C --> J K --> J K --> Pr

Done

  • The data shapes + strict validation — each step's "is it complete?" check, reused as-is by the form wizard (100 worker tests + 59 web tests green)
  • The manual wizard — all 5 step forms, the "step N of 5" strip, Back/Next, review + save-the-firm step. Live in prod.
  • Step 1 — Yard / base address: live Google autocomplete as you type, geocode on pick/blur, has-yard toggle (yard vs business address). The geocode anchor is what powers Step 4's nearby-search.
  • Step 2 — Vans: add-a-van list (name required, reg optional); last row can't be removed (≥1-van floor); Next gates on every row having a name.
  • Step 3 — Crew: add-a-person list (name required); same floor pattern. Names only — daily availability comes from sign-in, not here.
  • Step 4 — Disposal Sites (the map renders correctly — dark CartoDB tiles + amber pulsing-beacon markers; ≤30 mi haversine cap; refuses to ship unverified sites). Boss-eyes confirmation of the whole flow working end-to-end still owed — see Still to do.
  • Step 5 — Checklist: pre-seeded per-job tick-list (Before photo · Load in · Site swept · After photo); editable, add/remove rows; Next gates on ≥1 non-blank item.
  • Hours removed from calibration — the day's working window will come from the crew sharing live location to sign in (kicked off by the gaffer in stage ②). Worker schema + DB column made nullable; wizard no longer asks.

Still to do — calibration isn't concrete until this is all done

  • UI / brand pass — DONE (27 Jun). Re-skinned to the SkipOps amber-on-tarmac brand (dark header + hazard stripe, amber action colour with dark text, deep-amber links); WCAG AA enforced by a test that parses the real CSS (Alex's hard rule).
  • End-to-end function — DONE (27 Jun). Captured the firm's name on Step 1 (was missing → Save would 422); fixed the progress strip's ghost "Hours" step; a full headed walk proves all 5 steps + Review run with no dead ends.
  • Walk it live on a real phone — the one thing left: Alex walks the whole wizard end-to-end on his phone (real WDI suggestions on the dark map + the new brand look) and signs it off. No Console key needed — Step 4 is keyless WDI suggestions since the 26 Jun pivot.
  • End-to-end save path — walk the wizard, hit "Save the firm", verify a tenant lands in dev Supabase with working_hours: null and every other row clean (needs the dev Supabase project + creds).
①·5

Disposal Sites — how it works (PIVOTED 26 Jun)

the firm declares its OWN sites per material (routing truth) · the regulatory research now powers low-friction suggestions, NOT auto-discovery

The objective: for each waste type, capture the disposal site(s) the firm itself uses — the places it actually has access to and an account with. That list is what routing trusts. Why not just auto-find sites for them? Because no data can tell us whether a site will take a crew that turns up unannounced — many require a trade account; some (like Robins) don't. Sending a van somewhere it gets turned away is unacceptable. So the firm names its own (it only ever uses 4–5) — and our whole job is to make that entry effortless: we suggest the real sites near their yard and let them tap to add, instead of making them type everything from scratch.

What we gather → what it powers: the firm's own disposal sites, per material (tapped from suggestions or typed once) → the routing truth (each load goes to a site the firm knows it can use) → and the regulatory data (Environment Agency Waste Data Interrogator — every licensed site near the yard and what it actually received last year) → becomes the suggestion engine that makes that entry a few taps, not a chore.
flowchart LR
  A["Yard postcode"] --> B["Suggest real sites
near you, by material
(from EA data)"] B --> C["Firm taps to add
· or types its own"] C --> D["The firm's sites,
per material"] D --> E["Routing only ever
uses these"]

Done

  • The pivot is decided + de-risked. Proved (26 Jun) that auto-qualifying "where waste can go" is too risky — a site can pass every check and still refuse a no-account crew. So routing uses only what the firm declares.
  • Suggestion index ingested nationally → D1. The EA Waste Data Interrogator (free, keyless) is materialised into a disposal_suggestions table — 7,107 real commercial sites (household-only HWRCs excluded), each with what it received by the tonne. Built + loaded local + remote (26 Jun). Live Brighton query surfaces the web-quiet sites the old gate missed (Newtimber/Robins → 24,000t hardcore; OLUS → 36,000t wood).
  • Runtime suggestion query built. GET /suggestions turns the yard's location into nearest sites per material (keyless OS-grid maths, £0/zero-token) — proven live end-to-end.
  • Step 5 re-pointed — tap-to-add suggestion chips (real EA data) + a keyless "add a site you use" (address autocomplete + a draggable map pin) + the honest dynamic disclaimer (phone ahead before adding) + idiot-proof gating. Built + smoke-passed; headed test dry-run twice.
  • Auto-qualify path retired — the website-scrape + LLM "does it take commercial X?" gate and its whole module are deleted (the risky part is gone).

Still to do

  • ◐ The live gate — walk it on a real phone. Everything above is built + smoke-passed (worker 116 + web 64 tests green) and the headed test passes headless, but Alex hasn't yet walked Step 5 live and tapped real suggestions on screen. This is the one thing left before it's signed off ✓.
  • WDI licence — confirm the commercial-use terms (currently "conditional/internal-use") before it underpins the product nationally.

Give the firm its two chats

to build

The objective: every firm gets two Telegram chats — a private one for the boss (the "Gaffer" chat) and a group for the crew (the "Dispatch" group). And a hard wall so one firm can never see another firm's jobs.

flowchart LR
  A["Firm set up"] --> B["Gaffer chat
(boss only)"] A --> C["Dispatch group
(the crew)"] B --> D["Each firm's data
walled off"] C --> D

Done

  • Nothing yet — the design is set

Still to do

  • Wire up the two bots + lock each to its firm
  • Switch on the data walls (security rules) before any real firm's data lands

Boss drops a job

to build

The objective: the boss texts a job the way he'd say it out loud — "clear a garage on Dyke Road tomorrow morning, half a load, before-and-after pics." The system turns that into a proper job (where, how big, when, what photos) and reads it back so any misread is caught on the spot.

flowchart LR
  A["Boss texts it
in plain words"] --> B["System understands:
where, size, when"] B --> C["Job created"] C --> D["Reads it back
to confirm"]

Done

  • Skeleton only

Still to do

  • The "understand the text" step, save the job, and the read-back

Plan the smartest day

core built · rework owed

The objective: given the day's jobs, work out the most efficient round for every van — fewest miles, fullest loads — including nipping back to the yard to empty when a van fills up, then carrying on. This saving (fuel, time, wages) is the whole pitch.

flowchart LR
  A["The day's jobs"] --> C["The planner"]
  B["The vans + capacity"] --> C
  C --> D["Most-efficient
route per van"] D -. "van full →" .-> E["empty at the yard,
then carry on"] E -.-> D

Done

  • The core planner works and is tested (routes, time windows, empty-and-continue)

Still to do

  • It currently plans around cost (money) — rework it to plan around distance + load (no money in v1)
  • Wire in the yard-hub + the per-waste-type consolidation trips

Tell each crew their route

to build

The objective: once the day's planned, each van gets one clear, friendly message — their stops in order, what to expect, and a tap-to-navigate link for each stop that opens their own phone's maps. Nothing new to learn.

flowchart LR
  A["The day's plan"] --> B["Friendly message
per van"] B --> C["Stops in order"] B --> D["Tap-to-navigate
per stop"]

Done

  • Skeleton only

Still to do

  • Turn the cold route into a readable message + the per-stop map links

See where the vans are

to build

The objective: each driver taps "share live location" in Telegram once at the start of the day. That's it — the system now knows where every van is, with no app and no tracking box to fit.

flowchart LR
  A["Driver taps
'share location'"] --> B["System knows
where each van is"] B --> C["Feeds the
boss's live map"]

Done

  • Nothing to build on Telegram's side — by design

Still to do

  • Store the shared location + a morning "share it again" nudge

Photo-proof every job

to build

The objective: the crew snap a before and an after photo and tick the job checklist. The system files them against the job, so there's a permanent, proof-backed record of every clearance — plus a note of exactly who was on that team that day.

flowchart LR
  A["Crew: before +
after photos"] --> C["Filed against
the job"] B["Checklist ticked"] --> C C --> D["Permanent
proof record"]

Done

  • Skeleton only

Still to do

  • Photo capture + storage, checklist tick, the crew snapshot on finish

Re-plan when things change

planner ready · trigger left

The objective: jobs change all day — a new one comes in, one's cancelled, a van finishes early. When that happens the system quietly re-plans the rest of the day and re-sends the routes, without anyone asking.

flowchart LR
  A["New / cancelled job,
or van free early"] --> B["Re-plan the
rest of the day"] B --> C["Re-send the
updated routes"]

Done

  • The planner can already re-plan on demand

Still to do

  • The automatic trigger that fires it the moment something changes

The boss's live dashboard

to build

The objective: one screen for the boss — a live map of his vans and jobs, a list he can filter, and a tap into any job to see its photos, crew, checklist and timings. His whole operation at a glance.

flowchart LR
  A["Live van pins"] --> C["Boss dashboard"]
  B["All the jobs"] --> C
  C --> D["Tap a job → photos,
crew, checklist, times"]

Done

  • Folder is a placeholder

Still to do

  • All of it — the map, the list, the job detail

Staying on track

What's next, in order

Calibration wizard is done. Rewrite the docs for the new sign-in strategy, then build the daily loop in the order the day actually runs.

1
Docs rewrite for "kick off the day · share location to sign in" next
CLAUDE.md + docs/HANDOFF.md updated to spell out the v1 sign-in strategy that replaces calibration-time working hours, ahead of stage ② bot work. STATE.html already reflects it.
2
Build the new "Operations" step + sign off the wizard live at the gate
The wizard is built + on-brand in dark mode (5 steps incl. the rebuilt Disposal step — waste-type tabs + vector map + per-type real sites, no "keep at yard"). Next: a 6th "Operations" step — per waste type, straight-to-tip vs store-at-yard-until-full + how-many-loads-is-full (the optimiser's trigger_loads). Plan explainer opened (docs/operations-step-plan.html); awaiting Alex's nod on the design + ordering, then build it and walk the whole 6-step wizard live.
3
Rework the route planner's goal
Stage ④ — switch it from "cheapest" to "fewest miles + fullest loads", and wire in the yard-hub + per-material consolidation trips. The hard maths already works.
4
Build the daily loop (stage ② onwards)
Stages ②③⑤⑥⑦ — the two chats, the gaffer's "kick off the day" + crew share-location sign-in, dropping a job, sending routes, live location, and photo-proof. This is the bulk of the remaining build.
5
Auto re-plan + the boss dashboard
Stages ⑧⑨ — fire the re-plan on any change, and give the boss his live oversight screen.

Mission: 20 paying firms at £75/mo by 5 Nov 2026. Roughly the first stretch is finishing the build; the rest is selling it.