Skip to content

fix(loop): fail arm-loop loudly on leftover __PLACEHOLDER__ after sed (#130)#167

Merged
robercano-ghbot merged 2 commits into
mainfrom
feat/issue-130-arm-loop-placeholder-guard
Jul 20, 2026
Merged

fix(loop): fail arm-loop loudly on leftover __PLACEHOLDER__ after sed (#130)#167
robercano-ghbot merged 2 commits into
mainfrom
feat/issue-130-arm-loop-placeholder-guard

Conversation

@robercano-ghbot

Copy link
Copy Markdown
Collaborator

Summary

Closes #130.

Adds a defensive post-sed guard to .claude/scripts/arm-loop.sh: after both sed blocks write the installed systemd unit files (pr-loop-<slug>.service, claude-rc-<slug>.service) and before systemctl --user daemon-reload, the script now scans each generated unit for any leftover __[A-Z_]*__ placeholder and, if found, fails loudly (stderr message naming the file and the exact leaked token, then exit 1).

Why (and what was already fixed)

The primary bug #130 reported — the missing __PATH__ substitution in the pr-loop sed block, which let the literal __PATH__ reach the installed unit and crash-loop it at boot with status=127 — was already resolved on main by commit f9dcfcb (issue #107), which bakes a composed $baked_path (node/claude dirs + system dirs). This PR implements the issue's explicitly-recommended follow-up hardening: turn any future template/script skew (a new __FOO__ added to a template without a matching -e here) into an immediate, obvious arm-time failure instead of a silent status=127 at the next reboot.

Implementation notes

  • Scans only non-comment (directive) lines (grep -v '^[[:space:]]*#'), because both templates carry the literal doc token __PLACEHOLDER__ in their header comments — that prose is never a sed target and must not false-positive. A real leftover always lives in a directive line.
  • pipefail-safe: grep -o exits 1 on no match; the || true inside the command substitution keeps the healthy (zero-leftover) path from aborting arm-loop.sh under set -euo pipefail, while a genuine leftover still triggers exit 1.
  • Managed-header bumped arm-loop v6 -> v7.

Validation

  • Gates green via GATES_FILE=.claude/self/gates.json: build, lint (bash -n on scripts), test (checks.sh test + smoke-fanout.sh).
  • Guard exercised against the real templates: (a) fully substituted -> no leftover / no __PLACEHOLDER__ false positive; (b) dropping a single substitution (__PATH__, __SPAWN_MODE__) -> the specific leftover is reported and would exit 1.

Reviews (consensus=all, per .claude/self/gates.json)

  • correctness (opus): APPROVE — verified pipefail-safe healthy path + still-fatal on genuine leftover; comment-line scoping non-lossy (all real tokens live on directive lines).
  • tests (sonnet): APPROVE — reproduced against the real templates, both the clean and dropped-substitution cases; gates re-run green.

🤖 Generated with Claude Code

robercano and others added 2 commits July 20, 2026 23:10
…#130)

Guard both installed unit files (pr-loop and claude-rc) right after the
sed blocks write them: grep each for any surviving __[A-Z_]*__ token and
exit 1 with the offending file/placeholder if one leaked through. Turns
future template/script skew into an immediate, diagnosable arm-time
failure instead of a silent status=127 at the next reboot.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…fail-safe (#130)

Two adversarial review findings on the arm-loop.sh leftover-placeholder
guard: (1) grep -o found nothing on a clean install and, under
set -euo pipefail, aborted the script before daemon-reload; (2) both
systemd templates carry the literal doc token __PLACEHOLDER__ in their
header comment, causing a false-positive exit 1 on every run. Scope
the scan to non-comment (directive) lines only and add `|| true` so a
no-match no longer aborts the healthy path.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

fix(loop): fail arm-loop loudly on leftover PLACEHOLDER after sed (#130) (not yet reviewed)

14 similar comments
@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

fix(loop): fail arm-loop loudly on leftover PLACEHOLDER after sed (#130) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

fix(loop): fail arm-loop loudly on leftover PLACEHOLDER after sed (#130) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

fix(loop): fail arm-loop loudly on leftover PLACEHOLDER after sed (#130) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

fix(loop): fail arm-loop loudly on leftover PLACEHOLDER after sed (#130) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

fix(loop): fail arm-loop loudly on leftover PLACEHOLDER after sed (#130) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

fix(loop): fail arm-loop loudly on leftover PLACEHOLDER after sed (#130) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

fix(loop): fail arm-loop loudly on leftover PLACEHOLDER after sed (#130) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

fix(loop): fail arm-loop loudly on leftover PLACEHOLDER after sed (#130) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

fix(loop): fail arm-loop loudly on leftover PLACEHOLDER after sed (#130) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

fix(loop): fail arm-loop loudly on leftover PLACEHOLDER after sed (#130) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

fix(loop): fail arm-loop loudly on leftover PLACEHOLDER after sed (#130) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

fix(loop): fail arm-loop loudly on leftover PLACEHOLDER after sed (#130) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

fix(loop): fail arm-loop loudly on leftover PLACEHOLDER after sed (#130) (not yet reviewed)

@robercano-ghbot

Copy link
Copy Markdown
Collaborator Author

fix(loop): fail arm-loop loudly on leftover PLACEHOLDER after sed (#130) (not yet reviewed)

@robercano-ghbot
robercano-ghbot merged commit 548f56e into main Jul 20, 2026
9 checks passed
@robercano-ghbot
robercano-ghbot deleted the feat/issue-130-arm-loop-placeholder-guard branch July 20, 2026 22:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

arm-loop v5: pr-loop.service template's __PATH__ placeholder is never substituted → unit fails at boot with status=127

2 participants