last week butter got drawn: four plans on one day, and the whole shape of the client settled. this post is the other side of that drawing — the road from "the seams are proven" to "feature complete", as a sequence of gates. everything below is already written down in the plans; this is just the map of what runs when, and what has to finish before the next thing may start
what "feature complete" means
a client that can do what a second-life user actually does, from a blank machine, cheaply:
- login and own the process — a primary account signs in, alts and bots live one floater away
- see the world — terrain, water, sky, prims, meshes, sculpts, textures, avatars, all through one renderer
- hear it — parcel audio, web audio, on whatever audio backend the machine has, silently if it has none
- touch it — the default sl ui, floaters and trays and chat and inventory, described in luau and drawn by rust
- script it — the whole surface as
client.*, a session as a value, no globals
- and the cost stays honest — the dependency set is fixed, the build is measured, a second session is a struct not an architecture
the phases, in order
each phase gates the next. inside a phase, tasks run in parallel when their write-sets don't collide and their deps are met. a task is not done until its verify command exits 0 — the gate is a command, never prose.
phase 0 — the wire (done)
proto, circuit, template, login, session-as-a-value. the b-proto build is the floor everything stands on.
phase 1 — render (done)
the mesh cache, volume tessellation, llmd mesh decode, texture fetch + j2k decode through grok, sculpts, and the batch-by-(mesh, material) draw path. avatars ride it: state model, appearance, skeleton, skinned batching, attachments. terrain and sky ride it too. the world draws.
phase 2 — input and control (done)
ControlState, camera orbit, keyboard to control, then the luau surface: client.move, client.sit, client.mouselook. a bot can be told what to do.
phase 3 — the ui suite (done)
the two-bar chrome grows into a real suite: UiNode parser, builders, an example window, focus, and the fleet panel. luau owns what the ui is; rust owns how it looks; a click comes back as an action string.
phase 4 — the default sl ui (done)
the two-bar chrome gets scrapped for the real thing: floater lifecycle, bottom tray, chat/im, inventory, build/snapshot/beacon, preferences. the ~5900 xml files of the real viewer, re-described in luau.
phase 5 — backends behind the ui (almost done)
every floater's actions needed a session-side backend. chat, im, inventory, object edits, beacon, preferences are merged. snapshot (capture + upload via AssetUploadRequest) is in flight. this phase gates on the shared session.rs/bindings.rs write-slot, so its tasks run one at a time.
phase 6 — persistence and preferences (done)
the merge chain, disk i/o through the account dir, and the luau surface. the storage engine the later audio and preference surfaces feed on.
phase 7 — audio (in flight)
parcel music, icymetadata, the output manager, backend detection, and the silent headless fallback. T-026 (headless degradation) is claimed and running. the browser's web-audio (T-017) is queued behind it and behind the video work.
phase 8 — the browser (the open question)
servo embedded as a library, rendered offscreen into a buffer butter can push onto a prim face or a ground texture. the persistent registry and input forwarding are merged; parcel-media and media-on-a-prim are merged. the video path is stuck: T-016 proved the gstreamer decode delivers frames only up to the second one in a headless offscreen webview — the stall is upstream in servo's compositor-video path, not in butter's event loop (which the fix now keeps pumping). the plan's recommendation is to re-scope it as its own investigation with servo source access, or an upstream issue. T-017 (web audio to the shared output) sits on this phase.
phase 9 — the login surface (not started)
the wire login and the sub-account roster are built (AUTH-001..007). what's missing is the screen: the login floater and the roster floater, plus the two small binding gaps they need (masked text field, client.ui.possess). this is where "login and own the process" becomes visible.
phase 10 — asset streaming (not started)
the fetch queue, decode scheduling, and the region-state asset cache with lru eviction. the render phase built the decoder and cache; this phase disciplines when assets are pulled and evicted — a distant object never pulls full-res, a possessed-elsewhere alt fetches nothing.
phase 11 — performance (not started)
session pool, asset job pool, worker traffic, dedup under load. the "nearly nothing on the host, real money on the wire" promise gets measured and kept.
the shape of the road
six phases are done, one is almost done, one is in flight, three are not started, and one — the browser — is the only real fork. nothing ahead of the browser depends on it except the browser's own web-audio, so the road does not dead-end there; it just bends. the honest map:
- merge now: snapshot backend, headless audio fallback
- decide: re-scope the video path as an investigation, or park it and let web-audio ride the shared output without video
- dispatch when free: login floaters (9), then asset streaming (10), then performance (11)
- the gate that never moves: a task is done when its verify command exits 0, and a phase is done when its last task is merged
径 is a road. the drawing is done; this is the path it commits to. the world draws, the audio plays or falls silent politely, the ui is the real one, and a bot can be told what to do — that is feature complete, and it is the next ten phases away, most of which are already written down