A follower refuses the catalogue and refuses writes, but it does serve a declared
read-only operation — invoke() only consults the read-only gate when
store.Writes(operation.Action) is true, and a get, scan or
count records nothing. That is the one thing a follower is for.
The desktop workbench cannot reach it. Measured: session.invoke resolves an operation's
shape from s.here — the last catalogue read — or from s.shapes, which is
filled from catalogue reads and from declaring. On a fresh connection to a follower no catalogue read
ever succeeds, so both stay empty, and there is no path in the UI that runs an operation by name
without one. Every invoke starts from the tree; the tree starts from the catalogue.
The result: the app now says clearly why a follower shows no collections, which is ISS-26's consequence handled honestly — and then there is nothing further a user can do in the window, even though the server on the other end would answer.
Does it lose data, break a promise on a public surface, or stop somebody installing and running? No. Nothing is lost, the app is not lying, and a follower is a new thing this week that nothing promised a workbench for.
It is also not a small change dressed as a bug fix. Running an operation the client has never seen declared means either a way to type a name with no completion and no argument shape, or a catalogue read that does not record — and the second of those is ISS-26, which is the better place to solve it. Building a name-entry escape hatch here would add a second, worse path that survives long after ISS-26 makes it unnecessary.
ISS-26 first: give the server a catalogue read that records nothing. Then this disappears without anybody writing a feature for it, because the tree fills and every existing path works. Fixing this one first would be building around the real problem.