diff --git a/.claude/scripts/arm-loop.sh b/.claude/scripts/arm-loop.sh index db2ef89..2206221 100755 --- a/.claude/scripts/arm-loop.sh +++ b/.claude/scripts/arm-loop.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# @orchestrator-managed arm-loop v6 +# @orchestrator-managed arm-loop v7 # arm-loop.sh — installs the cron-less PR-loop as systemd (user) units # (issue #102). Templated + re-stamped by `/orchestrator:setup`/`sync`; do # not hand-edit the copy scaffold.sh wrote into this repo if you want future @@ -218,6 +218,25 @@ sed -e "s#__WORKDIR__#$repo_root#g" \ echo "arm-loop.sh: wrote $pr_loop_dst" echo "arm-loop.sh: wrote $claude_rc_dst" +# Guard against template/script skew (issue #130): if either sed block above +# is missing a substitution for a placeholder the template still contains +# (e.g. a new __FOO__ added to the .service template without a matching -e +# here), the installed unit silently keeps the literal token and systemd +# fails it at the NEXT boot with an opaque status=127 -- long after this +# script has exited 0. Fail loudly, right here, instead. +for dst in "$pr_loop_dst" "$claude_rc_dst"; do + # Scan only directive (non-comment) lines: the template header comments carry + # the literal doc token __PLACEHOLDER__, which is not a sed target and must + # not false-positive. A REAL leftover lives in a directive line. `|| true` + # keeps the no-leftover healthy path from aborting under `set -euo pipefail` + # (grep exits 1 on no match). Fail loudly on genuine skew (issue #130). + leftover="$(grep -v '^[[:space:]]*#' "$dst" | grep -o '__[A-Z_]*__' | sort -u | tr '\n' ' ' || true)" + if [ -n "$leftover" ]; then + echo "arm-loop.sh: unsubstituted placeholder(s) leaked into $dst: ${leftover}-- the sed block that generated this file is missing a substitution (issue #130); fix arm-loop.sh before re-running." >&2 + exit 1 + fi +done + systemctl --user daemon-reload # pr-loop: enable --now on purpose (NOT restart) — never kill a daemon that # may have a driver in flight; a re-arm only rewrites its unit file, and the