Skip to content

v0.217.0 — Windows and Linux, measured

Choose a tag to compare

@sergezuber sergezuber released this 09 Aug 18:47
· 6 commits to main since this release

Windows and Linux are first-class: the whole matrix is green on all three platforms, the
application starts on a clean Windows machine, and the model list now reflects what is
actually running rather than what the config declares.

0.217.0 — 2026-08-09

  • Two log entries carried ONE number. The change of 7 August was labelled 0.209.0 while it actually shipped as 0.210.0 — the version was bumped that time and the entry kept the previous number, colliding with the genuine 0.209.0 of the 6th. The log is what release notes are assembled from: two different changes under one number means one of them is either lost from the notes or attributed to the wrong release. The number is corrected against what the version REALLY was at that commit, not against what the entry claimed.

0.216.0 — 2026-08-09

  • The model list is shown by SIX different places, and all six now re-ask it. The change had been written three times before, each time in the wrong file: what was on screen was the home page menu while the session composer's picker was being edited. No test failed, because the route and the filter both answered correctly; the untrue thing was the surface nobody was measuring. It was found by a counter placed in the code, not by reasoning about it.
  • The rule is pinned by an enumeration rather than by memory: a check reads the sources and requires that EVERY interface file reading the model list also re-asks it. The first version of the check tried to separate showing from counting and found three of the six surfaces — half of them wrap the call across a line break. A rule with exceptions rots; the first-run screen shows how many models there are, and that number has to be true when it is shown too.

0.213.0 — 2026-08-09

  • The model list stops offering what is not running on this machine, and "nobody is there" is now asked of the KERNEL rather than read out of an error message. The rule "offer only what a provider really serves" used to rest on the provider ANSWERING, and a closed port did not count as an answer — so every model of such a provider stayed in the menu. Now a failed request to a local address opens a plain connection to the port: a refusal from the kernel, and only that, means nobody is listening. Open, timed out, any other error, any remote address — nothing is hidden.
  • The first version read the error text, and that was a costly mistake: with HTTP_PROXY set in the environment, even a loopback request travels through the proxy, and an unreachable proxy answers with a message byte-identical to a closed port. A live runtime answering 200 was hidden entirely — precisely what this mechanism exists to prevent. The hostname cannot settle it: whether to use a proxy is decided by the transport, not by the address. A direct socket to the port is something a proxy cannot spoof: either something accepts, or nothing does.
  • A hiding that was true for one instant is no longer a verdict for the whole session. The map was asked once per launch, so an owner who starts the application before the runtime — the ordinary order — would see no models until the window was reloaded. Now exactly one answer is re-asked, the single one that is not fail-open, and only while it stands: when nothing is hidden there is no polling at all.
  • A hidden model no longer breaks model selection. A candidate's fitness was checked against the configuration while the model was then looked up in the FILTERED list — so a declared-but-unserved candidate was accepted and then lost, and selection returned nothing instead of trying the next one. "Can this be used?" is now asked of the same list the menu shows, and the default scan walks all of a provider's models rather than only its first. Onboarding's model count moved to the same source: two different answers to "how many models do you have" were contradicting each other.
  • An empty model list now says WHY it is empty and names the runtime that is not running — that state simply did not exist before, and "No model results" tells nothing to someone whose runtime is off.

0.212.0 — 2026-08-09

  • Template parsing understands the generation extension. It is a real chat-template extension, not a typo: it marks which span of the text belongs to the assistant. A plain environment does not know the tag and REFUSES to compile the template — so the audit called a perfectly ordinary model a layout violation, a statement about our parser dressed as a statement about the model. Once the template could be read, the honest answer was different: that model is not tools-first. Three of the four on this disk are; one is not.
  • The sweep over installed models REPORTS their layout and asserts only what is ours: the template was readable and the probe answered. What the layout is, for a model this project neither writes nor ships, is that author's decision and not a defect here; the invariant FABULA depends on is asserted separately, against the model in the socket.
  • The production model is DERIVED from the same file the engine reads instead of being written down as a path. The path was written down, the model it named had long been replaced — and the invariant this very file calls design-critical was skipped in silence on the owner's machine for as long as it had been gone. A fact about a moving thing, recorded once, stops being a fact and nothing says when. And a sweep that examined nothing now says so: absence and success look identical in a count.

0.211.0 — 2026-08-09

  • The rule "a name that resolves to an internal address is refused" is finally TESTED. The resolver is injectable, so the verdict comes from this code and from nothing else. The real network cannot produce that case at all — no public name resolves to a loopback address — and it is precisely why the async check exists beside the synchronous one; until now nothing tested the anti-rebinding floor. It also removes a verdict that depended on whether DNS answered: on another machine two checks failed on resolution timeouts while the code was fine. One live check remains, asking a different question — that the default path is wired to a resolver at all — and on a silent network it reports a SKIP that names itself.