"Two seams were reserved for video. One was a field in a request; the other was a class in a hierarchy. When video finally came, it walked through the field and around the class."
The Day the Reservation Came Due
On 2026-09-21 the engine shipped local video: three open-weight video families, generated on the engine's own machines. This quest had been waiting for that day in two different places. The ceiling matrix reserved video in the request contract — a modality field that could say video from the engine's first generated image. And the lesson before this one leaned the whole adapter spine on a second reservation: a VideoAdapter, named in the engine's notes as the next implementation of its one abstraction. Both were bets on the same future. They did not pay out the same way.
What the Wire Did
The request contract held exactly as designed. The same generate endpoint now accepts either an image request or a video request, and the modality value decides which shape the body is read as. A video request carries what video needs: a frame count, a frame rate, and references with roles — a first frame, a last frame, a reference image, clip, or audio track. No image caller changed a byte. The image schema still refuses any other modality at the boundary; its refusal now points at the video request instead of calling the value unimplemented. A field that cost one line on the first day carried a whole new kind of work four months later, and no client had to notice.
What the Class Did
The class hierarchy was routed around. The thing that runs local video is even called VideoAdapter — the reserved name, spent — but it does not implement Adapter. It is a separate class. It takes the local image adapter as a collaborator, so it can clear the image models out of memory before a video job needs the room. It launches each video family's native runtime as a child process and holds the device gate until that child's whole process group has been reaped. It writes a video file, with a record beside it, into an archive of its own. That same evening upscaling became a queued job with a modality of its own and took the same shape: another class called an adapter that is not an Adapter. The abstract base class, four months old, still has exactly one implementation — and its docstring still names two futures: an API implementation for a version number the engine has already passed, and a video implementation that shipped somewhere else.
Why Video Couldn't Wear the Signature
The previous lesson showed what the interface asks for: a model row, a progress emitter, and a job record to write the resolved seed back into — the nouns of an in-process image job. Video shares some of that. It is queued, it reports progress, it resolves a seed. The rest differs all the way down. Its request has frames and roles where an image has a denoise and a sampler. Its work happens in a separate process, not in this one. Its output is a video file and a sidecar record, not image bytes. And its first move is to push the image models out of memory, which means it has to hold the image adapter, not be one. What the three kinds of work genuinely share lives below any class: one queue, one device gate, one progress channel, one registry, and now one placement step that picks a machine. The engine's real shared abstraction turned out to be the job — a typed request on one queue — not the adapter.
A Correction About the Router
This track's second lesson drew a dumb router that reads which adapter owns a model from the model's registry row. That router was the design document's. In code, from the engine's first generated image until 2026-09-21, there was no router at all: every job went straight to the one adapter, and no registry row ever recorded an owner. A router finally appeared when video did, and it is dumb in exactly the sense that lesson praised — no branch per model, no name patterns — but it reads the request's kind, not a registry column: image, video, or upscale selects the runner. It branches on the axis that moves when a new kind of work arrives, never on the axis that moves every week.
Meanwhile, the Other Axis Became Data
The bet the adapter was built on — generation happens in different places — did come true, just not as subclasses. The closed-weight subsystem that went out its own door in the first place grew into the engine's Pro workflow. Local instruction-editing models now appear in its catalog beside the vendor providers, and every row in that catalog states where it executes and how it bills: included for the local models, a subscription for the Codex provider that became the default, metered credits for the vendor APIs. Location turned into a column. The local rows still run through the spine — queue, placement, local adapter, possibly on another machine — while the other rows run inline. So the variation the abstraction was meant to absorb is absorbed, by a catalog the engine serves, and the class it was meant to live in still has one member.
So Is It Dead Surface Now?
Apply the rule from the narrow-boundary lesson, and from the concrete-first lesson in the last track, honestly. One implementation. Two named second cases: one expired, one shipped as a different class. No named, maintained second case stands behind the abstraction anymore. By this quest's own discriminator, the Adapter base class is now a deletion candidate. The engine has not taken that step — the base class and its docstring are still there, a small monument to two futures that happened somewhere else. Saying so is not a verdict on the engine. It is the audit this track taught you to run, run on the track's own spine.
VideoAdapter, so a search for the name finds it and the searcher concludes the reservation was honored. Only its first line — what it inherits from — says otherwise. Audit a reservation by what the code inherits and implements, never by what it is called.