Build

The Screen That Never Asks — What Is Bolted to a Wall Must Not Ask

By makemind · Jul 20, 2026

At the end of The Line Outside we wrote this.

There is no push. The door did follow when the counter called, but only because the harness put the same state into both runtimes. This sample did not do that.

This piece does it.

A screen in your hand and a screen on a wall

Every sample so far learned by asking. The screen calls a tool, gets an answer, draws.

A screen you are holding can do that. The moment a person presses is the moment to ask.

A screen bolted to a wall is different. Nobody presses a kitchen display. So it becomes one of two things.

  • It asks constantly — once a second is 86,400 times a day. A few hundred of those answers mean anything
  • It is late — every ten seconds means an order can appear up to ten seconds late

Both options are bad, and the second is especially bad. Ten seconds is long in a kitchen.

The queue as a resource, not a tool result

server.addResource(
  uri: _queueUri,
  name: 'Kitchen queue',
  description: 'Tickets the kitchen still has to make',
  mimeType: 'application/json',
  handler: (uri, params) async => ReadResourceResult(...),
);

And when the queue moves, the server says so.

_tickets.add(_Ticket(_next++, _incoming[i++]));
// The whole point. Nobody asked; the server says the queue moved.
server.notifyResourceUpdated(_queueUri);

The screen side subscribes once and is done.

client.onResourceUpdated((uri) async { ... });
await client.subscribeResource(_queueUri);

The call count is the evidence

A claim like this cannot be verified in words. Code that says "it uses push" and polls behind the scenes is common.

So the harness counts the tools it called.

subscribed to orders://queue — from here the screen asks for nothing
--- window opens: tool calls so far 1 ---
told: orders://queue changed (notification 1)
told: orders://queue changed (notification 2)
told: orders://queue changed (notification 3)
--- window closes ---
notifications received: 3
screen updates: 3
tool calls made by the screen inside the window: 0

Zero. While three orders arrived, the screen asked for nothing.

SUBSCRIBED — 3 to make. #71 Bibimbap / #72 Cold noodles / #73 Pork cutlet. made 0 · waiting 3
SUBSCRIBED — 3 to make. #71 Bibimbap / #72 Cold noodles / #73 Pork cutlet. made 0 · waiting 3

The verification protects that zero.

grep -q "tool calls made by the screen inside the window: 0" captures/run.log \
  || { echo "   the screen asked for something — this is polling, not push"; exit 1; }

And the screen definition must not poll either.

if grep -RIqiE '"(poll|interval|refresh|timer)"' kitchen.mbd; then
  echo "   the screen definition is polling"; exit 1
fi

The notification says only "it changed"

This is the confusing point when you first build it. The notification does not carry the new content.

// The notification says *that* it changed, not what to. So the screen
// reads the resource — one read per change, never on a timer.
final r = await client.readResource(uri);

So it is one read per notification. How that differs from polling: polling reads even when nothing changed; this reads only when something did. The number of arrivals is the number of changes.

You can also carry the content in the notification (notifyResourceUpdated(uri, content: ...)). We did not. As the queue grows you would send the whole thing with every notification, and with several screens attached that traffic multiplies by the number of screens. Send only "it changed" and a screen nobody is watching does not read.

This content requires Developer or above

Sign in and upgrade your plan to continue reading.

View Plans
Twitter