#!/bin/bash # brief-nightly.sh - render the cross-repo briefing to a file, atomically. # # This is the ONLY writer in the briefing path, and it exists so that board.sh # does not become one. board.sh is read-only by construction - it writes to no # repo, no STATE.md and no mailbox - and a `--brief --out FILE` flag would have # ended that for the sake of one redirect. # # Why not just `board.sh --brief > file` from launchd: # # 1. A plain redirect TRUNCATES the target before the renderer has produced # a byte. An unattended job that fails, or is read mid-run, then leaves # the operator an empty or half-written briefing - and the briefing is # read exactly when nobody is watching it being made. Rendering to a temp # file in the same directory and rename()-ing it into place means a reader # sees either the old briefing or the new one, never a partial one. # 2. An EMPTY render is treated as a FAILED render and never replaces a good # briefing. Board prints nothing at all when its scan roots do not exist, # which is exactly what a mistyped path or a moved home directory looks # like - silent truncation to zero would destroy yesterday's briefing on # a bad launchd environment. A repo tree where nobody owes anything is a # different case entirely: that renders a valid, non-empty briefing saying # so, and is written normally. # # Zero model calls, by construction: it runs two shell scripts. That is the # whole point - a nightly job on subscription auth draws from the same quota # pool as interactive work, and every turn it would spend is a turn the # operator does not get. Measured floor for one headless turn on # claude-opus-5[1m]: ~0.25 USD-equivalent, which --max-budget-usd cannot # prevent (it aborts AFTER turn one, never before it). # # ASCII only, bash 3.2 safe. set -u SELFDIR="$(cd "$(dirname "$0")" && pwd)" BOARD="$SELFDIR/board.sh" OUT="${CLAUDE_BRIEF_FILE:-$HOME/.claude/briefing.md}" case "${1:-}" in -h|--help) grep '^#' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;; esac OUTDIR="$(dirname "$OUT")" mkdir -p "$OUTDIR" 2>/dev/null || { echo "brief-nightly: cannot create $OUTDIR" >&2; exit 1; } # Same directory as the target: rename() is only atomic within one filesystem. TMP="$OUT.tmp.$$" trap '/bin/rm -f "$TMP" 2>/dev/null' EXIT bash "$BOARD" --brief "$@" > "$TMP" 2>/dev/null rc=$? if [ "$rc" -ne 0 ]; then echo "brief-nightly: board.sh --brief exited $rc, keeping previous briefing" >&2 exit 1 fi if [ ! -s "$TMP" ]; then echo "brief-nightly: empty render, keeping previous briefing" >&2 exit 1 fi mv -f "$TMP" "$OUT" || { echo "brief-nightly: could not install $OUT" >&2; exit 1; } exit 0