Symptom
After the v5 sync landed in a consumer repo (reDeploy PR #136) and the machine rebooted, pr-loop-<slug>.service crash-loops:
env[3970]: /usr/bin/env: 'bash': No such file or directory
systemd[411]: pr-loop-redeploy.service: Main process exited, code=exited, status=127/n/a
The previously running daemon (started under the pre-v5 unit) masked this until the reboot forced a cold start.
Root cause
Version skew between two managed files as shipped:
.claude/systemd/pr-loop.service (@orchestrator-managed pr-loop-service v1) contains Environment=PATH=__PATH__ (line 22) and its header advertises a "baked runtime PATH".
.claude/scripts/arm-loop.sh (@orchestrator-managed arm-loop v5) substitutes only __WORKDIR__, __REPO_SLUG__, __GATES_ENV__ for that template (the __PATH__ sed expression is missing — compare the claude-rc sed right below it, which does bake __CLAUDE_DIR__).
The literal __PATH__ survives into ~/.config/systemd/user/pr-loop-<slug>.service, so the service PATH is the string __PATH__ and /usr/bin/env bash finds nothing. Older installed units (armed pre-v5, no Environment=PATH= line) keep working, which hides the regression until a consumer re-arms and reboots.
Fix
In arm-loop.sh's pr-loop sed block, bake the arming terminal's PATH (same rationale as the existing claude_bin resolution comment — the unit runs under systemd's minimal environment and needs nvm-provisioned node/claude and gh):
sed -e "s#__WORKDIR__#$repo_root#g" \
-e "s#__REPO_SLUG__#$repo_slug#g" \
-e "s#__GATES_ENV__#$gates_env#g" \
-e "s#__PATH__#$PATH#g" \
"$pr_loop_src" > "$pr_loop_dst"
(If $PATH may contain #, pick another sed delimiter or pre-escape.) Also worth a guard after both seds: grep -q '__[A-Z_]*__' "$dst" && fail "unsubstituted placeholder" so any future template/script skew fails loudly at arm time instead of silently at the next reboot.
Observed in consumer repo robercano/reDeploy on 2026-07-16 (WSL reboot at 11:00; unit crash-looped every 15s until systemd gave up).
🤖 Generated with Claude Code
Symptom
After the v5 sync landed in a consumer repo (reDeploy PR #136) and the machine rebooted,
pr-loop-<slug>.servicecrash-loops:The previously running daemon (started under the pre-v5 unit) masked this until the reboot forced a cold start.
Root cause
Version skew between two managed files as shipped:
.claude/systemd/pr-loop.service(@orchestrator-managed pr-loop-service v1) containsEnvironment=PATH=__PATH__(line 22) and its header advertises a "baked runtime PATH"..claude/scripts/arm-loop.sh(@orchestrator-managed arm-loop v5) substitutes only__WORKDIR__,__REPO_SLUG__,__GATES_ENV__for that template (the__PATH__sed expression is missing — compare the claude-rc sed right below it, which does bake__CLAUDE_DIR__).The literal
__PATH__survives into~/.config/systemd/user/pr-loop-<slug>.service, so the service PATH is the string__PATH__and/usr/bin/env bashfinds nothing. Older installed units (armed pre-v5, noEnvironment=PATH=line) keep working, which hides the regression until a consumer re-arms and reboots.Fix
In arm-loop.sh's pr-loop sed block, bake the arming terminal's PATH (same rationale as the existing
claude_binresolution comment — the unit runs under systemd's minimal environment and needs nvm-provisioned node/claude and gh):(If
$PATHmay contain#, pick another sed delimiter or pre-escape.) Also worth a guard after both seds:grep -q '__[A-Z_]*__' "$dst" && fail "unsubstituted placeholder"so any future template/script skew fails loudly at arm time instead of silently at the next reboot.Observed in consumer repo robercano/reDeploy on 2026-07-16 (WSL reboot at 11:00; unit crash-looped every 15s until systemd gave up).
🤖 Generated with Claude Code