From 5e0c23b0b51219d53c3f8b9bd9f40eeeaaf28d34 Mon Sep 17 00:00:00 2001 From: Vuong Hoang Date: Wed, 2 Sep 2026 09:14:06 -0700 Subject: [PATCH] fix(statusline): ask the post office if this seat is reachable, not a lock file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bell reported 🔔 iff wake-listener-.lock named a live pid — one MECHANISM, not the property it stands for. Correct while the FIFO waiter was the only channel; wrong the moment 3.3.0 added `cc`. This seat is reachable over its Claude Code socket, has no waiter lock at all, and was rendering 🔕 while the post office reported push/reachable. Pane-routed seats were wrong the same way before that. It now reads `reachable` from the status payload it was already fetching and discarding, which means the segment knows nothing about althing's internals — no lock paths, no channel names — so a fourth channel cannot make it stale. Adds the third state: an unreachable post office rendered identically to a healthy seat with no mail. It is 📵 now. An outage is not an empty inbox, including on the status line. Also retires a `kill -0` liveness check, the third instance of liveness-standing-in-for-identity found on this object tonight. Verified in all three states: 🔔 on this seat, 📵 against a dead address, 📬 4 🔕 on a pull-only handle. --- scripts/claude-statusline-command.sh | 42 +++++++++++++++++++++------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/scripts/claude-statusline-command.sh b/scripts/claude-statusline-command.sh index 69b26ea..f4b30d0 100755 --- a/scripts/claude-statusline-command.sh +++ b/scripts/claude-statusline-command.sh @@ -126,7 +126,7 @@ if [ -n "$cwd" ]; then fi fi -# --- althing: unread count (📬 N) + waiter-armed (🔔 armed / 🔕 not) --- +# --- althing: unread count (📬 N) + reachability (🔔 / 🔕 / 📵 outage) --- # v3 (the post office, 2026-08-28). ⚠ This block used to gate on # `command -v althing-cli`, which the v3 cutover DELETED -- so the whole segment, # badge and bell both, silently disappeared for every session on this box. That is @@ -164,16 +164,38 @@ if command -v postbox >/dev/null 2>&1; then # `timeout` is load-bearing, not belt-and-braces: v2 read a local SQLite file, # v3 makes an HTTP call. An unreachable post office must cost this segment two # seconds and nothing else — a statusline that hangs blocks the whole prompt. - unread=$(timeout 2 postbox --handle "$h" status --json 2>/dev/null /dev/null) + # ONE call, both fields. The status payload already carries `reachable`; + # the previous version fetched it and threw it away. + st=$(timeout 2 postbox --handle "$h" status --json 2>/dev/null /dev/null) case "${unread:-0}" in ''|0|*[!0-9]*) : ;; *) althing="📬 $unread" ;; esac - # v3 has ONE arming mechanism where v2 had three: `althing-listen` takes - # wake-listener-.lock. monitor-*.lock and light-monitor-*.lock belonged - # to binaries that no longer exist. kill -0 discards a crashed listener's lock. - mon="🔕" - lk="$HOME/.althing/wake-listener-$h.lock" - if [ -f "$lk" ]; then - pid=$(tr -dc '0-9' < "$lk" 2>/dev/null) - [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null && mon="🔔" + + # ⚠ ASK THE POST OFFICE WHETHER THIS SEAT IS REACHABLE. Do not infer it + # from a local artifact. + # + # This bell used to report 🔔 iff `wake-listener-.lock` named a + # live pid — one MECHANISM, not the property. That was right while the + # FIFO waiter was the only channel and became wrong the moment 3.3.0 + # added `cc`: this very seat is reachable over its Claude Code socket, + # has no waiter lock at all, and rendered 🔕 while the post office said + # push/reachable. A pane-routed seat was wrong the same way before that. + # + # Asking the post office means this segment knows nothing about althing's + # internals — no lock paths, no channel names — so adding a fourth channel + # cannot make it stale. The old form also used `kill -0`, which proves a + # pid exists and not which process it is; see the identity-vs-liveness note + # in docs/runbooks/althing-deploy.md. + # + # THREE states, because an outage is not an empty inbox: + # 📵 the post office did not answer (timeout, down, wrong address) + # 🔔 reachable — a poke will arrive + # 🔕 declared but not reachable, or pull-only + if [ -z "$st" ]; then + mon="📵" + elif [ "$(printf '%s' "$st" | jq -r '.reachable // false' 2>/dev/null)" = "true" ]; then + mon="🔔" + else + mon="🔕" fi fi fi