Highlights
The Superintendent's six action chips are gone, and nothing they did went with them
The floating panel carried a row of six chips — Toolbelt, Manifests, Draft Manifest, Assign seat, Pause run, Terminate run. They were honest when they shipped: each was a typed route into the live runtime rather than a label, two firing a real hm call on click and four staging a command the runtime must not invent an argument for. What they were not was the catalog. They were a hand-written list of six commands sitting above a menu that reads the whole catalog from the session itself.
The / menu is tools/list — the same list hm workflow show renders, grouped by its own lifecycle phases and described by its own guidance. Every command a chip named is in it (workflow show, manifest list, manifest create, latch assign, run pause, run terminate), and so is every command no chip ever named. Mid-run steer has a better home than either: the run card for a dispatched ticket, which sends the id it is already drilled into instead of asking the Principal to type one back. Its Hold and Terminate are unchanged.
So the row is deleted — actions.ts, ActionChips.svelte and their test — and the panel is left with the surfaces that cannot fall behind the runtime: a composer, a catalog menu that grows on its own, and a run card that knows which run it is looking at. (#330)
The slot the chips left holds the agent's own configuration
The header chip has always named which runtime hosts the chat. It never said how that runtime was configured — and in this Works it was already running --model claude-opus-5 off the Superintendent seat, with nothing on the panel saying so. Under the approval cards there is now a row that does: Model, Level where the runtime has a flag for one, Posture, and a quiet Save as seat default.
It is the second axis of the same switcher, not a second switcher. The chip picks the CLI; the row picks how that CLI is configured, and it re-reads when the chip changes — each runtime has its own model namespace and its own knobs, and Cursor has no Level control at all because its level rides inside the model slug.
A pick is a session override, remembered per runtime so a relaunch comes back on it, and it never touches org/executors.toml — that seat is shared with decompose, and one model string cannot hold five namespaces. Claude takes a model or posture change hot, on the same stdin the stop button already writes to, so the conversation is not restarted to change what is answering it. A level is a spawn flag, so it re-opens on the same conversation and says so before it does.
Posture is hm's own, not a vendor's permission list: it is the class gate that decides whether a write raises a card, the bridge re-reads it on every held call, and it applies on every runtime rather than only on the one that takes a flag for it.
Every value on the row is what the host reported it resolved, never the pick that was asked for — a change that failed leaves the live value standing. (#331)
The row is now true on every runtime, not just the two that read a model
Codex, Pi and Opencode each spawned the Superintendent on a model written into their host module, and read neither the row above them nor the seat below it. A Model pick there was a label — so the row disabled it and said why. That is gone, because the reason is: all three hosts now build their argv from the one resolution the panel writes to, on the open path and the per-turn path alike.
A level travels with it, in each CLI's own vocabulary rather than a word hm invented — Claude --effort, Codex model_reasoning_effort, Pi --thinking, Opencode --variant. It is passed only when one is set: an unset level means the CLI's own default answers, never hm's idea of a middle setting. Cursor still has no Level control, for the reason it never had one — its level rides inside the model slug.
The seat row grew the matching homes, so a session pick has somewhere durable to be promoted to on every runtime: effort under [seat.claude] and variant under [seat.opencode] join the model_reasoning_effort and thinking their Codex and Pi siblings already carried. Unset stays unwritten — a seat that names no level materializes no table.
None of it widens a sandbox. Codex still runs read-only with approvals never, Pi still excludes the three mutating built-ins, Opencode still ships its posture in opencode.json, and the guards that assert so are unchanged. (#332)
Every Line's Superintendent arrives with a row to be addressed at
Save as seat default writes hm executor set --seat superintendent-<line> with no --provider in it, because the row it is updating is supposed to already be there. Only hm works wire ever authored that pair, so a Line that arrived any other way answered the Principal's Model pick with an error about a flag they were never shown.
The pair is now seeded with the Line itself: works init, works line add, and works onboard for any Line the roster carries and the executors file does not. Seeding is an address and not a wiring — the script provider and nothing else — and it is additive, so a seat already answering on claude keeps its model, posture and toolbelt when a Line is added beside it. org apply-template stays roster-only on purpose, and the runbook says so rather than leaving it as an inconsistency to rediscover. Doctor's line.executor_mismatch was the same gap read from the other side, and it goes quiet for a seeded Line. (#333)
A ticket's Mail box takes an @, and the panel's @ knows what is open
The Detail's Mail composer now spends the same sigil the Superintendent's does, on the same authority — list_agent_mentions for the rows and address_agent_mentions, with this ticket as the mention's work unit, before the body travels. The write underneath is the one it already had: a single hm ticket mail through the write hand, QUEUED until the hand pulls it. The trigger, the rows in flight, the highlight and the dismissal moved into one module, so the two menus cannot disagree about what @ means. (#335)
The floating panel needed the other half of that. It resolved a mention with no work unit at all, which let the seat's own latch answer precisely when the Principal was looking at a ticket that seat is not latched to. The shell now says what is open and the store hands it along — leaving the Detail takes the Given unit away — and both mention paths, the pre-send guard and the rewrite that travels, go through one address. With nothing open, the latch fills the target exactly as before. (#336)
Where a mention resolves onto a ticket, the panel can carry the whole write itself, because a mail body rides argv where a call's body rides stdin. So it does, and it stages it: the composer pre-fills the command and the Principal reads it and sends. Naming a seat queues nothing by itself. Where there is no ticket, nothing is staged and the panel says which miss it was — several latches, no latch, a manifest with no queue at its address, or two names and two queues — and the line travels to the agent instead, which reaches the same command over MCP. Neither route paints a dispatch: QUEUED is the ceiling both stop at. (#337)
The menu draws its superintendent-… rows rather than filtering them out, and says what they are: mail lands on a ticket, and that ticket's queue is read by the hand latched to it. Hiding was the worse half of the trade — the resolve rules on the roster and not on this menu, so a hidden row is a name that still resolves when it is typed, with the explanation taken away. (#338)
The ticket says who has worked it, and the rail's Roster row opens
The composer answers "who am I naming". Nothing on screen answered the other half: who has already worked this ticket, and could any of them be reached about it now. hm-core has had that answer since hm listen — the latch holder plus every seat whose runs left events on the ticket, each resolved through the same router the composer reads — and no surface asked it. One read is added and one row under the Tickets tree draws it, in the host's order and with the host's own sentence per row. Three reach states rather than two, because whether anything is listening now and whether there is anywhere to listen at are different facts, and one grey chip over both would be the lie the row exists to avoid. Display-only, and that is a decision: un-reaching a seat is not a verb hm has. (#339)
The nav rail has carried a disabled Roster row since the shell's first draft, with a tooltip saying it would land with its own row of work. This is that row: one read of the roster, and one screen that draws what it answers. A seat is an id, a Line, a role, a mandate and the hats it stacks — so there are no standing or one-off chips, no per-seat spend bar and no create or retire control, because none of those are objects the model has. Delivery and spend go where they live: two header links open Overview's own agent health and spend regions rather than restating a figure per row, since those rows are keyed by a different id and that panel is a Works-wide aggregate. The one affordance a row carries hands the composer the catalog's own latch assign line with the seat named and the ticket left for the Principal. The list is the roster's, whole and in its order. (#340)
The Superintendent's belt is MCP-only, and the runtime now enforces it
Super is an hm entry point rather than a shell, and that was held by convention. It is now held by the argv: a Claude Super session filters Bash and Agent out of the tools it registers, a Super seat refuses --toolbelt instead of quietly accepting a second one, and Opencode's webfetch is an explicit off rather than an unstated default. (#342)
Reads stop asking. The class gate already knew which verbs only read, so Super's reads travel without raising a card — the Principal was approving a list and a show one at a time on the way to the call that mattered. The wait on a card is bounded, so a deny that never comes back names the argv it was holding instead of hanging with nothing on screen. (#343)
Burst work has a path that does not invent a seat. A Super that needs a Hand to take a repair opens a maintenance manifest and dispatches one Principal card — a Repair title and its acceptance — and run status lists every live Hand on the Line, so the choice is made against what is actually running. The Works-side MCP wiring a Hand needs in order to pull its mail is recorded in the runbook. (#344)
Super reads the public web host by host, and none of it opens a file write: Claude registers WebFetch and WebSearch behind the same belt filter, and Opencode sets webfetch true explicitly. Cursor, Codex and Pi stay documented and unverified, and are named as such. (#345)
A completed ticket's leftover latched_seat is history, not a live latch. Mention, listen and mail read it the same way now, so all three agree the Hand is gone rather than one of them offering to reach a seat whose work is over. (#346)