clikae v0.23.0 — the waiter worked, nothing ever started it
The waiter worked. Nothing ever started it.
v0.18.0 shipped a session that waits out its usage limit and picks itself back up.
Last night a real limit arrived and nothing happened.
The evidence, all four parts of it: the tank went dry at 21:57 with "resets 12am
(Asia/Tokyo)"; the phrase parsed correctly to midnight; the preference was still
unset, meaning nothing had ever asked; and no wake window had ever existed.
Detection lived in two places and the limit walked past both — clikae watch,
which nobody runs in order to be interrupted later, and the supervised launch,
which only fires once the engine has exited. Sitting in a live session that
hits its limit is the ordinary case and the only one that matters at 3am, and it
reached neither. The release notes had promised something that, on the path
people actually take, could not happen.
So the session watches itself. Every session clikae starts now carries a
wake window that asks the same question the board asks — is this tank dry? —
once a minute, and hands over to the countdown in place.
One window, two phases. Bare wake while watching, wake 13h38m once
counting down. A session gains one extra window, not two, and the "only one
waiter per session" guard already covers both phases because it matches
^wake( |$). No daemon, no state file, no model of anybody's quota: it asks a
question that reads the transcript and self-clears, and it dies with the session.
The question moved to launch
Asking when the limit arrives was the original design, and it cannot work: the
question would be posed by a watcher in a window nobody is looking at. That is a
deadlock, not consent — and it is exactly why the preference was still unset
last night.
At launch a human is demonstrably present: they just typed the command. The
friction is still paid exactly once. Where there is nobody to ask — a pipe, CI, a
headless run — it stays silent and schedules nothing, which is the safe direction
for a feature that types into a live session.
Also fixed
Shift+Enter inserts a newline again. tmux defaults to extended-keys off,
which flattens a modifier onto the key it modifies before the application sees
it — so Shift+Enter arrived as a plain Enter and an engine that treats Enter as
"send" submitted instead of adding a line. Adding tmux had put a translator in the
middle of the keyboard.
Two settings, because they answer different questions: whether tmux forwards
the extended encoding to the application, and whether it asks the outer
terminal for those sequences at all. Without the second there is nothing to
forward.
Only a NEW client picks this up — terminal features are resolved when a client
attaches, so a session you are already inside keeps the old behaviour until you
detach and come back.
Five assertions that could not fail
Every defect found while building this was the same species, and none of them was
in the feature:
run wait "$pid"runs in a bats subshell, where the background job is not
a child — sowaitalways failed, and an assertion of "non-zero" was satisfied
no matter what the code did. Two tests had been passing that way.- A watcher test asserted on a window named
wake <time>in a setup that never
creates a wake window at all. Forcing the watcher to ignore dryness entirely
left it green. It asserts on what reaches the pane now. local rc=1; wait || rc=$?reports failure when the wait succeeds.- roam.bats' long-running intermittency was never timing. It passed the stub
engine's log path through an exported variable, and tmux passes only its
update-environmentlist into a session — everything else is inherited from the
server's process environment, which belongs to whoever started the server.
So the variable arrived only when that test happened to start the server itself.
The engine ran, the roaming assertions passed, and the count of engine starts
was zero because nothing could be written. - Both test harnesses had to learn to answer the new question: a pty-driven test
is a terminal, so every launch test sat at the prompt and reported the
engine's output as missing.
brew upgrade clikae · CHANGELOG