← Commit history

1.33.0: a timed-out send may have delivered; never re-send, and never drive a send through a transport with a shorter timeout

John Lauer ·6665c60012 ·1mo ago ·parent 72b52d7
2 files changed +18−1
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "adom-ui-design",-  "version": "1.32.1",+  "version": "1.33.0",   "type": "skill",   "description": "The Adom UI Design System plus a bundle of focused UI skills (tooltips, floating-windows, toasts, responsive-ui, app-shell, ai-driven-apps, clickable-paths, dark-default, input-feedback, settings-layout). One install drops the whole set of skill files onto your container, plus shared icon assets (the settings cog) so every Adom app draws the same glyph.",   "dependencies": {},
skills/say-strip/SKILL.md+17
@@ -205,6 +205,23 @@ that then landed late and stacked orphan tabs.) A short client timeout turns a w into a spurious "could not reach the AI panel", which was half of the original bug. The copy-fallback covers genuine failure, so give the call room to succeed first. +**⛔ A TIMED-OUT SEND MAY HAVE DELIVERED. NEVER RE-SEND TO FIND OUT.** nb double-submitted+into John's thread on 2026-08-25 and the mechanism will catch anyone driving a send through a+short-timeout transport: it sent through `hd_api /eval-in`, which ABANDONS AFTER 5 SECONDS+while the send kept running server-side and delivered; it then checked the census for its+`dock:` tag, found none because the send had ADOPTED AN EMPTY TAB, concluded failure, and+sent again. The user got the same prompt twice.++Two rules fall out:++1. **After a timeout, the census can never clear you.** Only `delivered_to` or+   `inject.delivered_in_conversation` can. A tag lookup is exactly the check that lies when a+   send adopts an existing tab, which is the common case.+2. **Do not drive the send through a transport with a shorter timeout than the send.**+   `/eval-in` gives you 5s for a call that legitimately takes up to 120. Call your backend+   directly with a real timeout (e.g. `wsl_exec curl -m 180` inside the user's container) so+   the transport cannot abandon a call that is still working.+ **On a create timeout, DO NOT RETRY BLIND** — a blind retry duplicates the thread. Every `/ai-threads` response now carries `_hints` that teach the recovery: poll for your staged `name`/`tags` (the tab often lands late and they attach to it), then deliver by `tid`.