fix(statusline): ask the post office if this seat is reachable, not a lock file

The bell reported 🔔 iff wake-listener-<handle>.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.
This commit is contained in:
vh
2026-09-02 09:14:06 -07:00
parent 1935e48456
commit 5e0c23b0b5
+32 -10
View File
@@ -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 | jq -r '.unread // 0' 2>/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)
unread=$(printf '%s' "$st" | jq -r '.unread // 0' 2>/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-<handle>.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-<handle>.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