From 302b062680c8fbd9743d4e083154ac5fc314955a Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Mon, 20 Jul 2026 16:03:08 -0500 Subject: feat(pager): document the Signal pager and add the receive timer The pager worked but was undocumented and drifting stale: signal-cli warned the account had gone 47 days without a receive, and no runbook existed to hand a future session or a non-Claude runtime. I added the runbook under docs/design/ and a roam-sync-shaped receive timer that drains the queue every 15 minutes, keeping the account warm and surfacing reply messages. I also generalized agent-page: it now sends directly from any machine holding the pager account and relays to velox only when it doesn't. ratio is linked as a device of the account, so a page lands even when velox is down. The receive script no-ops cleanly where the account isn't registered, since the units stow onto every machine via the shared common package. --- scripts/tests/signal-receive.bats | 66 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 scripts/tests/signal-receive.bats (limited to 'scripts/tests/signal-receive.bats') diff --git a/scripts/tests/signal-receive.bats b/scripts/tests/signal-receive.bats new file mode 100644 index 0000000..8fe4d67 --- /dev/null +++ b/scripts/tests/signal-receive.bats @@ -0,0 +1,66 @@ +#!/usr/bin/env bats +# signal-receive.sh — drains the Signal pager account's inbound queue to keep it +# warm (the roam-sync-shaped fix for receive-staleness) and to surface Craig's +# replies. Run on velox by the signal-receive systemd timer. These tests stub +# signal-cli on PATH to verify command construction without a network or the +# real account. + +setup() { + REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../.." && pwd)" + RECV="$REPO_ROOT/scripts/signal-receive.sh" + STUBS="$(mktemp -d)" + LOG="$STUBS/calls.log" + # HAS_ACCOUNT (default 1) controls the listAccounts answer so the local-account + # guard can be exercised: "1" lists both test accounts as present, "0" lists + # none (so the guard no-ops). + cat > "$STUBS/signal-cli" <> "$LOG" +exit 0 +EOF + chmod +x "$STUBS/signal-cli" +} + +teardown() { + rm -rf "$STUBS" +} + +@test "defaults to the pager account, a 10s timeout, and read receipts" { + PATH="$STUBS:$PATH" run bash "$RECV" + [ "$status" -eq 0 ] + grep -q -- "-a +15045173983 receive --timeout 10 --send-read-receipts" "$LOG" +} + +@test "honors an explicit account and timeout" { + PATH="$STUBS:$PATH" run bash "$RECV" +19995550000 25 + [ "$status" -eq 0 ] + grep -q -- "-a +19995550000 receive --timeout 25" "$LOG" +} + +@test "no-ops (exit 0) when the account is not registered on this machine" { + # Guards the runbook claim that the timer no-ops on a common-package machine + # that stows the units but holds no pager account. + HAS_ACCOUNT=0 PATH="$STUBS:$PATH" run bash "$RECV" + [ "$status" -eq 0 ] + [[ "$output" == *"not registered"* ]] + # The receive must not have run. + ! grep -q "receive" "$LOG" +} + +@test "no-ops (exit 0) when signal-cli is not on PATH" { + # Empty stub dir with no signal-cli; echo/exit/command are bash builtins, so + # the script still runs and hits its signal-cli-absent branch, which no-ops. + rm -f "$STUBS/signal-cli" + # Invoke bash by absolute path so `run` finds it regardless of the empty + # PATH the script itself sees. + PATH="$STUBS" run "$(command -v bash)" "$RECV" + [ "$status" -eq 0 ] + [[ "$output" == *"signal-cli"* ]] +} -- cgit v1.2.3