fix(inbox): replace the broadcast watermark with a per-repo seen set

The single high-water mark assumed broadcast filenames within one
second were written in sort order; a later broadcast with a lexically
smaller uniq part sorted below an already-advanced watermark and was
silently never delivered to repos that had read the first (review §2).
_broadcast/seen/<repo> now records one delivered filename per line and
delivery is membership-based, removing the ordering assumption. Four
regression checks added first (the ordering check failed against the
watermark), selftest 48/48.

Upgrade note: a legacy single-line watermark file is read as a one-entry
seen set, so pre-existing broadcasts older than the watermark may be
re-delivered once.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HBbjgS5A55RVavoyjJC4FX
This commit is contained in:
Kjell Tore Guttormsen 2026-07-24 01:41:14 +02:00
commit b9bec85a80
2 changed files with 30 additions and 17 deletions

View file

@ -7,7 +7,7 @@
# pending and are re-injected on every SessionStart (startup, /clear, resume)
# until marked handled with coord-done (so /clear never loses them, and this is
# safe to re-run manually mid-session). Broadcasts are delivered once per repo
# via a filename watermark. Prints nothing (exit 0) when nothing is pending.
# via a per-repo seen set. Prints nothing (exit 0) when nothing is pending.
# ASCII only, bash 3.2 safe.
#
# Usage: coord-inbox.sh [--repo <name>]
@ -58,32 +58,29 @@ ${body}
done
fi
# --- Broadcasts: delivered once per repo via a filename watermark ---
# --- Broadcasts: delivered once per repo via a per-repo seen set ---
# _broadcast/seen/<repo> holds one delivered broadcast filename per line.
# Order-independent: replaces the old single high-water mark, which silently
# dropped a same-second broadcast whose name sorted below one already seen.
BC_INBOX="$COORD/_broadcast/inbox"
SEEN_DIR="$COORD/_broadcast/seen"
SEEN_FILE="$SEEN_DIR/$REPO"
if [ -d "$BC_INBOX" ]; then
watermark=""
[ -f "$SEEN_FILE" ] && watermark="$(cat "$SEEN_FILE" 2>/dev/null)"
newest="$watermark"
for f in "$BC_INBOX"/*.md; do
[ -e "$f" ] || continue
fname="$(basename "$f")"
# fixed-width ASCII ts prefix + LC_ALL=C -> lexical compare is chronological
if [ -z "$watermark" ] || [[ "$fname" > "$watermark" ]]; then
# Same untrusted-data escaping as the directed inbox above.
body="$(sed 's/^/> /' "$f" 2>/dev/null)"
OUT="${OUT}
if [ -f "$SEEN_FILE" ] && grep -Fxq "$fname" "$SEEN_FILE" 2>/dev/null; then
continue
fi
# Same untrusted-data escaping as the directed inbox above.
body="$(sed 's/^/> /' "$f" 2>/dev/null)"
OUT="${OUT}
--- broadcast: ${fname} ---
${body}
"
COUNT=$((COUNT + 1))
[[ "$fname" > "$newest" ]] && newest="$fname"
fi
COUNT=$((COUNT + 1))
mkdir -p "$SEEN_DIR" 2>/dev/null && printf '%s\n' "$fname" >> "$SEEN_FILE" 2>/dev/null
done
if [ -n "$newest" ] && [ "$newest" != "$watermark" ]; then
mkdir -p "$SEEN_DIR" 2>/dev/null && printf '%s\n' "$newest" > "$SEEN_FILE" 2>/dev/null
fi
fi
[ "$COUNT" -eq 0 ] && exit 0