Skip to content

v0.5.1 — nothing left to configure

Choose a tag to compare

@amyodov amyodov released this 30 Aug 08:09
· 10 commits to main since this release

Everything a user had to write down by hand is now discovered. Both of the failures behind this release were
reported from the wild by a user running YAAC on Windows under Codex.

YAAC_SESSION is gone, and so is the arithmetic behind it. The notice socket takes whatever port the kernel
offers and says so in hello; the hat keeps a directory of who is out there and answers sessions to anyone
who asks at the one address every participant already agrees on. A Codex hook finds its own session there — by
the name its client gave both halves, by the working directory, or by the process line it shares with its
server. The derivation it replaces was wrong three ways: Codex keeps one configuration block for a whole
machine, so every session derived the same port and answered for each other's inboxes; the digest could not be
reproduced in Node, which declines to truncate blake2s; and a connect to a closed local port does not fail fast
on Windows, so walking eight candidates cost 8.2 seconds on every hook event. Codex now needs one hooks file
and nothing in config.toml.

YAAC_WAKE is gone too, which leaves YAAC with no environment variables at all. The app-server is the
process that starts the MCP server — the tree reads codex app-server --listen ws://… → uv run … yaac → python … yaac — so its address is read off the command line of the forebear that has it. That answers which
app-server is running this session rather than which ones are listening, so several at once are no more
ambiguous than one, and the permanent codex app-server daemon, which every Codex install runs and which
listens on nothing, is never mistaken for a door.

The wake knocks on thread/queue/add instead of turn/start. On an idle thread the queue drains at once
and a whole turn runs, and on a thread already working it takes its place in line — where turn/start does not
refuse but opens a second turn beside the first. So waking a busy session used to interrupt it. turn/start
remains the fallback for an app-server too old to know the queue. Found by Vadim, who had it working before it
was in YAAC.

A compaction no longer strands a session. Losing the peer_secret left a session on the air, holding a
name, and unable to say a word: the other tools refused it, and so did rejoining. Three answers, because no one
of them reaches every client. join_channel now says in its own description that the pair must survive a
compaction and what to do when it did not — a description rides in every request, where the tool result that
used to carry this is summarised away. On Claude Code the plugin also fires on a post-compaction SessionStart
and hands the session its connections straight back, from the process that has held them all along. And a
rejoin no longer asks for the secret the caller just lost: any part of the pair, or none of it, leads back to
the same membership.

PYTHONUTF8=1 is no longer needed. The hook reads its payload as UTF-8 bytes rather than through the
console's encoding, where a Russian Windows turned a working directory into a different string and matched no
session at all, silently; and the log handler writes UTF-8 over stderr's buffer instead of losing whole lines to
--- Logging error ---.

Also: Hat._send never saw EHOSTUNREACH on an asyncio socket, because the send is a future and the error
arrives after the except has returned — so a departed participant was never evicted on that path, which is the
likely source of a name reported as taken by nobody. leave_channel now asks for the secret like the other
three, so a session that cannot prove who it is can no longer strand itself by leaving. CI checks formatting.

Two things a 0.5.0 user may trip on: leave_channel wants a peer_secret, and yaac-hook no longer takes
--key.