It sat in world.go, which is about the workstation model; it is a phrasing
error and belongs in llmphraser.go. Also trims the PhraseQuery doc.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
PhraseChat and PhraseQuery returned canned text with a nil error, so a dead
or OOM-killed server was indistinguishable from bad phrasing — "не знаю." is
also a legitimate answer.
Both now return the fallback text AND the error. The daemon keeps using the
text, so the turn still survives; a measuring caller counts a real failure.
An empty response is its own error: the model is up and said nothing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The naming half of the degradation rule in docs/offload.md. PhraseWorld has
three outcomes: no workstation configured means the resident model answers
exactly as today, a workstation that is taking work answers, and one that is
asleep returns ErrNoWorldModel so the caller can say so. Naming a gap
requires a gap — on a box that never had a second model, refusing every
world question would remove a capability he has now.
Both prompts move into knowledgePrompt and evidencePrompt, shared by
PhraseQuery and PhraseWorld, because prompt parity across two models stops
holding the moment there are two copies of a prompt.
The silent half comes with it: chatWithSystem and chatWithMessages prefer
the workstation when it will take work, at the same 0.7 the resident
transport samples at, and say nothing when it will not. That covers the
digestion worker's nudge and reminder phrasing without touching tick.go.
Only Available and CompleteRemote are in the Remote interface. Pair.Complete
has its own floor and the phraser already owns one; two floors under a
single call is one too many.