Milestones
List view
Riders meet beyond their crew on shared roads, never in an open world. Every ride still builds its own world from its own GPX, and a climb belongs to the map (ADR-0082), so riders can meet in two ways, each its own part of Jan's shared-roads answer: 1. Across time, part (c): an opt-in, unnamed board of ten per Category on each library climb over 90 days (ADR-0083), 'race one of them' as a ghost, and 'flag this time' into the operator's private queue from day one. Nobody's home road ever gets a board. 2. Live, part (d), only where a time and a place concentrate them: open rides (ADR-0076). An open ride is a crew's planned session opened to everyone, on a library road at a set time. v1 is the group ride, a keep-together bunch at prescribed %FTP. Each crew rides from its own voice channel; strangers are unnamed markers in a coarse kit; no name, number, voice or free text crosses a crew, beyond a listed crew's name and mark. The operator's own crew hosts a couple a week and gathers nobody. Under every answer, ADR-0076 records that there is no open world and parks the always-on open road behind a measured, id-free condition. The block list (M11) comes first; report ships with open rides. The crew stays the social unit. Exit: Under every answer, ADR-0076 is merged: no open world, and the always-on road parked with its measured condition. Beyond that, each approved part meets its own conditions. The road board: - Only opted-in, board_ok, timeable efforts from hub-streamed rides on library climbs appear; a home-road segment has no board; a zone-near effort never appears. - No response field could link two entries to one rider, and a deleted effort's token resolves to nothing. - A flagged time reaches the operator's private queue, and the operator can clear its board_ok. - Each seen red first. Open rides: - Riders from 3 crews and one solo rider ride one group ride, each crew in its own voice channel. - No stranger frame, roster or closing carries a name, id, crew, channel, number, zone ring or look hash. - The ride id changes between rides, and the id map is gone 24 h after the ride. - Blocked pairs never see each other, and a marker-origin block's export names no stranger. - A private, crew-owned or Strava-origin route cannot become an open ride's road. - An unlisted host crew's name and image never reach a stranger, and an open ride stores no timeable effort. - Reports reach the operator's private queue and are gone after 30 days. - Each of these was seen red first.
No due date•23/23 issues closedIn Switzerland the world stands on real ground: - swisstopo heights; - the real skyline, with its peak names; - trees where the canopy model says trees stand; - ground coloured from graded SWISSIMAGE; - a scattering sky. Everything is baked and served by place, never along a route: crowns over the whole area, the road network burned in at bake time, the skyline from stations on a global grid, and the ground in place tiles cached across routes. The generator stays outside the look pack and inside every privacy zone. A quality ladder under the World control picks the tier at the count-in and only ever steps down during a ride. Gated on Jan's realism decision (ADR-0078). Exit: All of these hold: - A one-canton pilot of the look pack is measured, and its extrapolation is under ADR-0078's ceiling, or the 0.5 m imagery layer has given way to 2 m. - The bake reads no route table. - The operator's host serves the pack, baked from STAC downloads and never from WMTS. - Ground arrives in place tiles cut per audience, with lossless heights, and two routes sharing a stretch receive byte-identical tiles there. - A zone tile carries no raster, tree or building bytes, and no URL carries a tile address; both were seen red first. - On the synthetic fixture, and on the maintainer's reference loop (checked by hand, never committed), L2 and L3 hold their measured budgets on #2998's rig and on the low-tier rig through a 60-minute soak. - The ladder steps down without a frame over 50 ms and never steps up mid-ride. - Every data source is credited where it shows.
No due date•15/16 issues closedA Wednesday alone becomes a crew thing. A rider who rides solo can: - ride in the crew's lounge, where anyone can drop in; - cheer a crewmate who rides in another channel, and be cheered; - play Watt Golf, Floor is Lava or Backyard Ramp in the lounge, alone unless someone joins; - if they opted in, move the crew's Tour forward with every ride. Tour metres pay the same for the same %FTP, whatever the rider weighs. - climb the col of the month, whole or its top half; - race a crewmate's best on any climb, from any route, if Jan approves crew lines (shared roads part (b): the crew's switch, off by default); - chase a pacer, if Jan agrees. Nothing is ranked, nothing ordered is stored, and no daily quest nudges anyone off a rest day. The block list ships earlier, in M11, because it is needed today. Exit: All of these hold: - An opted-in member's solo route ride on the SimulatedTrainer adds tour metres inside the ride's own transaction. - A member who has not opted in adds none. - Home names only opted-in contributors, without a number. - Deleting a ride keeps its metres in the tour's unattributed total and leaves no row about the ride. - A cheer from afar reaches a crewmate in another voice channel, and past its budget it is refused with rate_limited. - A one-rider Watt Golf starts from /ride in the lounge and saves as a game ride. - The col of the month stamps the col book for the whole climb and for its top half, and its crew count leaves out rides on Strava-origin routes. - A boundary test proves no tour row orders members. - If crew lines are approved: a line reaches only members of a crew its rider switched lines on for, only the rider's 90-day best per stretch, and a private, near_private_end, zone-near, Strava-origin or not board_ok effort is never a line (seen red first).
No due date•11/13 issues closedA world the crew grows together. Parked until M13 and M14 ship. It needs its own ADR, weighed against ADR-0010 and ADR-0022. Exit: All of these hold: - ADR-0075 is accepted. - The Crew Atlas lights only tiles that at least two members rode together outside every zone. - The valley shows the crew's roads and cairns.
No due date•5/5 issues closedThe world feels alive and Swiss: - real villages on real footprints; - water, and Alpine features; - herds and birds; - an ambient sound bed; - seasons, the fog sea and weather. All of it stays inside the world budget, and none of it ever touches resistance. Exit: On the synthetic Alpine fixture, all of these hold: - Buildings stand on the fixture's footprints. - An open bridge and a culvert render where they are. - Herds keep to pasture. - The fog sea is crossed in season. - Ambient sound plays under the cues fader. - All dressing fits the gate: 24 draws and 180k triangles on the high tier, 12 and 70k on the low tier. The maintainer's reference loop is checked by hand.
No due date•18/20 issues closedRace a real road, fairly. Races are opt-in and run on W/kg physics. Results are bracketed by Category D–A and appear on the closing card only. Race weight is frozen and checked. Races never mix with riding together. Exit: All of these hold: - Chase the Devil, Last Light and Wheelrace each run end to end with four riders in a Go WS e2e with an injected clock. - The Col runs inside a bunch ride, with an opt-out for each rider. - Results appear per Category. - A rider with a default weight or FTP, or a weight changed within 14 days, rides unranked. - A restart voids the race. - No placing is persisted.
No due date•25/32 issues closedEarned, never bought. Riding fills a wallet, and the garage turns it into looks that never change a number on the ride: bikes, wheels, kits, helmets and colours. Build, height and skin tone are free. Items come from what you rode or what you did. Crew kits belong to the crew, and seasonal items come back every year. Exit: All of these hold: - A saved ride mints into the wallet inside the ride's own transaction. - A rider buys a helmet shape, undoes it within 10 min, buys it again, and crewmates see it at the next session. - The guard tests that forbid hub and race code from importing wardrobe are green. - The colour guard refuses a watt-coloured kit in the viewer's own theme. - The garage works without WebGL through a 2D figure. - The export and the purge carry the wallet and the wardrobe.
No due date•32/32 issues closedThe real world, in depth. Routes carry their real villages, passes and landmarks from WattRoom's own copy of OpenStreetMap, served from its own origin. Climbs get real names, and one climb is recognised whichever file you rode it from. What riders get: - Their own climb times. - The road on the ride page and on the closing card. - Private collections: the col book, the Everest ladder and explorer tiles. - Cooperative crew climbing. The rules: - Location-derived data is owner-only. - No browser request goes to a third party. - OSM, swisstopo and Copernicus are credited wherever their data shows. Exit: All of these hold: - The operator's host serves the geo pack. - A synthetic corridor fixture places village signs and a named pass at their metres. - The climb card names the pass. - A solo route ride stores per-climb efforts keyed to one climb identity across two different files. - The col book stamps the pass. - Crew Home shows Everest together. - No point, heading, height or name ins A climb belongs to the map: roads are keyed strokes, a climb is one chain of them from foot to summit, and over a matched span every file rides the map's line and the climb's frozen profile. Your ghost rides beside you on that climb from any route. The map reaches the client in world tiles cut per audience, with the crew's coverage clamped to a corridor that stops at the anchor; every ride and session pins its data snapshot. With place keys (shared roads, decided 2026-09-28), the world walks the map's strokes, and zones meet real ground through a membrane.
No due date•52/54 issues closedGroup ERG in the world. A crew rides any workout together on a real road: - The workout sets the bunch's pace, and each rider's legs set their place in it. Nobody is ever removed. - Roadside v1 happens on the road: stand, paint, a Prime, back a rider and call the weather. None of it touches a trainer. - KOM sprints, the seven games and the jukebox all live in the same world. Exit: A Go WS e2e with an injected clock has four riders (two on the SimulatedTrainer in the web e2e) ride a synthetic workout on the synthetic Alpine fixture, started at Terrain Match's metre. All of these hold: - One hub bunch position. - Offsets are clamped to −10…+25 m. - A coasting descent never marks anyone Resting. - Gates land where blocks start. - A KOM sprint arms. - A spectator's Prime leaves every trainer's mode unchanged. - A late joiner lands within 25 m. - A restart resumes within 25 m.
No due date•68/72 issues closedWhen a ride has a road, the 3D world becomes slot 2. The other four slots dock around it: a Garmin-style bike computer, the climb card, the workout header and the Skyline. The ride falls back to the Skyline once per ride, and says why, when: - it runs on a phone; - reduced motion is on; - frames are missed; - the WebGL context is lost; - the desktop window is hidden. Figures and bikes look like athletes on real bikes and move naturally. The world stays behind a flag until it is measured on a fast rig and a slow one. Exit: All of these hold: - The synthetic Alpine fixture renders a solo route ride and a road workout within the world budget: at most 60 draws and 400k triangles on the high tier, at most 30 draws and 150k on the low tier, paced at 30 fps. - The budget is inside the GPU gate on #2998's rig and on a low-tier rig, with a 60-minute soak. - The 51 animation gates run in the required web job. - rideView() falls back on a forced context loss and on missed frames, and never fla The generator is written key-agnostic (#3224): it walks strokes and never reads the route's name, frame or bounding box, and its salts are secrets served by the server (#3225). Until M14's map data, each road still builds its own world, keyed by its own secret in its own frame; the same-road gate holds on a synthetic network. A route's hidden ends are keyed by owner-only secrets from the start.
No due date•216/227 issues closedBring your own road. A rider imports a GPX, TCX or FIT course and rides it solo, either in SIM as a route ride or in ERG as a road workout compiled from it. Slot 5 shows the road ahead as the Skyline, with its climbs. The ride keeps its distance and climbing. Coordinates are sealed on the server for the owner. A workout carries its road only by reference, cut to each audience. No route name travels further than its audience. Roadside v0 and the XP bound ship alongside. Exit: All of these hold: - A synthetic Alpine fixture imports and rides end to end on the SimulatedTrainer in e2e. - The maintainer's reference loop (kept out of the repo) imports in two clicks as a manual check. - Kickr Core and Kickr Core v2 sessions sign off rideGrade() and measure the Cw factor. - A solo route ride and a road workout save with route_id, ride_mode, distance_m and climbed_m. - A 10-minute coasting descent at 0 W neither pauses nor ends the ride. - Boundary tests prove that no coordinate, zone point or
No due date•74/76 issues closedThe visual finish: spacing, separation and what each theme is.
No due date•113/115 issues closed**The room dissolves into the crew.** A crew owns identity: members, roles, bans, board, schedule, streak, medals, ride history, invite code, directory listing. Below it, furniture: **text channels** (a name, a gate, a scrollback), **voice channels** (a name, a gate, a deck, who is in it) and **sessions** (a workout on a timeline, running *in* a voice channel, one per channel at a time, any member may start one and is its coach until they hand off). Decisions (2026-09-22, Jan): session runs in a voice channel · one deck per voice channel, playlists crew-owned · crew text channels only, no text-in-voice · "You" is the first entry of the crew switcher · **big bang**: PRs to `main` in dependency order, CI green is the bar, no release until the milestone closes · every room → one text + one voice channel of the same name · crew roles + a channel may be private (admins + named members) · streak, medals, weekly board, sessions-this-month all port to the crew · words: text channel / voice channel / session · any member starts a session · channels have no owner; crew owner/admins manage them. Numbers proposed here are **defaults — tune in alpha** and land in SPEC via #2426: 20 text + 10 voice channels per crew · one session per voice channel · 100 planned sessions per crew · 500 messages per text channel · recaps 90 days · a rider founds at most 3 crews. URLs: `/crew/[id]` home · `/crew/[id]/c/[channel]` text · `/crew/[id]/v/[channel]` voice · `/crew/[id]/s/[session]` session (`/watch` to spectate) · `/crew/[id]/schedule|workouts|board|members|settings`. `/c/[code]` stays the door. Sizing from the research: 45 `/api/rooms` routes, 11 tables with `room_id`, `hub` 6.4k LOC keyed by slug (221 tests), `rooms` pkg 4.2k LOC (127 tests), `web/src/lib/room` 188 files / 28k LOC, 32 web files linking `/r/`, 16 e2e specs. Repo velocity: 300+ merged PRs in the last 14 days. Order of work: #2425 (the ADR) first; then any issue whose **Depends on** line is fully merged. #2433 stays blocked until the release after M9. Nothing outside this milestone lands until it closes.
No due date•269/272 issues closedWattRoom outside a browser tab: the Electron desktop shell and the OS capabilities the web can't grant (system audio, keep-awake, HUD, tray). Amends ADR-0004. The browser stays a first-class surface — every share/spectator link keeps working without the app.
No due date•34/39 issues closed