v0.9.159
Patch Changes
-
#928
f119fe4Fix a deadlock that wedged the deferred-prompt store, and with it every task deletion.discard()returned the in-flight claim's promise bare from inside the store's write queue.serialized()runstail.then(fn), so the queue slot ADOPTED that promise: the slot could not settle until the claim did, while the claim's ownreleaseClaim/markDeliveredwere queued behind that same slot. A dismiss arriving during a delivery closed the cycle and no later operation on the store ever ran —deleteTask(and sotask.delete) sat atphase=runningindefinitely, androve api deferred-listtimed out.The wait now happens outside the queue, exactly as
waitForClaimsalready did: the enqueued callback hands the promise back wrapped and the wait runs after the slot has settled. Discard semantics are unchanged — it still waits for an in-flight claim before dropping the record. — @Sma1lboy -
#928
f119fe4Bound thepsprobe that every engine-presence check runs, and stop a failed probe from reading as "no engine".psSnapshotawaitedps -Awith no deadline and no kill. Every caller wraps the probe in try/catch, which catches a throw and never a hang, so apsthat did not exit froze whichever gate asked it — including prompt delivery, which sits between a deferred prompt'sbeginDeliverymarker and its release. It now gives up after 5s (ps -Aanswers in ~20ms) and kills the child rather than leaving it holding a pipe nobody reads.Failure is also an answer now.
enginePresencereports"engine" | "none" | "unknown", andsendrefuses an unreadable probe withENGINE_PROBE_FAILEDinstead of telling you a running tab "has no live engine process — it is a plain shell right now". The write gate itself is unchanged:sessionHasEnginestill refuses on anything but a positive walk, because a prompt pasted into a bare shell is executed. — @Sma1lboy -
#928
f119fe4The delivery guard is now switchable, legible, and forgiving of a mis-hitd.- Settings → Dev replaces the composer-gate checkbox with a three-position
delivery.guard:on(both checks),screen off(drop the engine-layout
read only),off(drop both). The keystroke window was previously not
switchable at all — it lived in the pty host's spawn-time environment, so
changing it meant restarting the host. Both checks now resolve per delivery,
andROVE_DELIVERY_GUARDoverrides the setting for one session. An existing
delivery.composerGate=falsereads asscreen off. - Inbox cards for a queued message name the sender, which check held it,
and how long the text survives —from kobe · composer had text · expires in 23h— instead ofmessage queuedand a countdown.don one asks first. - Dismissing keeps the text. A dismissed message leaves the queue (its tab
accepts new sends immediately) but stays on disk until its ordinary 24h
expiry:rove api deferred-list --include-dismissedfinds it and
deferred-releasestill delivers it. Dismiss used to destroy a message the
sender had already been told was accepted. - Every deferral, release and dismiss is now a line in
daemon.log; only drops
were recorded before. — @Sma1lboy
- Settings → Dev replaces the composer-gate checkbox with a three-position