fix(review): unbreak /review slash command poisoned by \!\` sequence#234
Merged
Conversation
PR #217 added a code-comment explaining the `||` vs `if \!` workaround, but the comment itself contained `` `if \!` ``. Claude Code's slash-command preprocessor scans the file for `` \!` `` (exec-command prefix) regardless of markdown code fences, extracts the text up to the next backtick as a shell command, and runs it. The extracted command was `` — the Bash tool escapes `, which bash fails to parse (`—: command not found`), and the preprocessor delivered an empty prompt body to Claude. Every `/review <N>` invocation since the merge of PR #217 produced a 5-line session with no assistant turn and no review posted — PRs #225–#233 all received zero reviews from the bot. Rephrase the comment in both `review/SKILL.md` and `running-in-ci/SKILL.md` to avoid the `` \!` `` sequence entirely. The guidance is unchanged; the text no longer trips the slash-command preprocessor. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
tend-agent
pushed a commit
that referenced
this pull request
Apr 11, 2026
…ents PR #226 rewrote the CI-polling code block in `running-in-ci/SKILL.md` and `review/SKILL.md` to include the comment `# Use \`||\` rather than \`if \!\` — the Bash tool escapes \`\!\` as \`\\!\``, re-introducing the exact \\!\` sequence that PR #234 fixed on 2026-04-10. Claude Code's slash-command preprocessor treats \\!\` as "execute the next backticked string as a shell command", consumes text through the next backtick, and runs ` — the Bash tool escapes ` as bash. The em-dash is not a command, so bash reports: Error: Shell command failed for pattern "\!\` — the Bash tool escapes \`": /bin/bash: line 1: —: command not found When the preprocessor fails, the prompt body is not delivered. Every /review invocation produces the same 5-line trace with no assistant turn — the model never sees the review instructions. Evidence from the past hour on max-sixty/worktrunk: - Run 24287041911 — tend-review on PR #2077 (fix/issue-2075), 16:49Z. Session artifact is 5 lines, ends with the stderr above. No review posted. - Run 24287289871 — tend-review on PR #2077, 17:03Z. Same 5-line trace, same stderr, no review posted. Both target the same PR because the bot pushed a commit that retriggered pull_request_target; the PR currently has zero bot reviews despite two review-workflow runs. Earlier review runs in the hour (24281048388 at 11:00Z, 24280957116 at 10:54Z) succeeded, which dates the regression to the 76debaf merge that shipped PR #226. Fix: rephrase both comments to avoid any \\!\` sequence, matching the approach used in PR #234. The guidance content is preserved verbatim in spirit; only the backticks around `if \!` and `\!` are dropped. After the fix, `grep -rn '\!\`' plugins/` returns no matches. Gate assessment: - Evidence level: Critical (clearly wrong outcome — 100% of reviews on the affected PR are empty; also regresses a fix that was already shipped as PR #234) - Classification: Structural — the slash-command preprocessor runs deterministically and will fail on every \\!\` sequence regardless of the model's approach - Occurrences this run: 2 on the same PR (same mechanism as #234) - Change type: Targeted fix (3 lines per file, 2 files) - Both gates pass
3 tasks
tend-agent
pushed a commit
that referenced
this pull request
Apr 11, 2026
…ression PR #226 (`fix(ci-runner): filter CI polling by run URL, not workflow name`) reintroduced the exact poisoned-text regression that PR #234 fixed. Its diff on plugins/tend-ci-runner/skills/review/SKILL.md and plugins/tend-ci-runner/skills/running-in-ci/SKILL.md reverted the CI-polling comment from the PR #234 wording back to the pre-#234 wording containing `` `if \!` ``, which the slash-command preprocessor scans and exec's as bash. Since #226 merged at 2026-04-11 15:01:22 UTC, every `/review` invocation has failed identically with the 5-line trace: queue/dequeue, command-caveat, command-name, local-command-stderr, then nothing. Three tend-review runs in this hour's window (PRs #240, #241, #242) all produced that exact trace and posted zero reviews. Rephrase the CI-polling comment in both files to avoid any `\!` adjacent to a backtick. The guidance is unchanged. Matches the wording that PR #234 already merged successfully — this is a straight restoration of that fix. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4 tasks
tend-agent
pushed a commit
that referenced
this pull request
Apr 11, 2026
…ents PR #226 rewrote the CI-polling code block in `running-in-ci/SKILL.md` and `review/SKILL.md` to include the comment `# Use \`||\` rather than \`if \!\` — the Bash tool escapes \`\!\` as \`\\!\``, re-introducing the exact \\!\` sequence that PR #234 fixed on 2026-04-10. Claude Code's slash-command preprocessor treats \\!\` as "execute the next backticked string as a shell command", consumes text through the next backtick, and runs ` — the Bash tool escapes ` as bash. The em-dash is not a command, so bash reports: Error: Shell command failed for pattern "\!\` — the Bash tool escapes \`": /bin/bash: line 1: —: command not found When the preprocessor fails, the prompt body is not delivered. Every /review invocation produces the same 5-line trace with no assistant turn — the model never sees the review instructions. Evidence from the past hour on max-sixty/worktrunk: - Run 24287041911 — tend-review on PR #2077 (fix/issue-2075), 16:49Z. Session artifact is 5 lines, ends with the stderr above. No review posted. - Run 24287289871 — tend-review on PR #2077, 17:03Z. Same 5-line trace, same stderr, no review posted. Both target the same PR because the bot pushed a commit that retriggered pull_request_target; the PR currently has zero bot reviews despite two review-workflow runs. Earlier review runs in the hour (24281048388 at 11:00Z, 24280957116 at 10:54Z) succeeded, which dates the regression to the 76debaf merge that shipped PR #226. Fix: rephrase both comments to avoid any \\!\` sequence, matching the approach used in PR #234. The guidance content is preserved verbatim in spirit; only the backticks around `if \!` and `\!` are dropped. After the fix, `grep -rn '\!\`' plugins/` returns no matches. Gate assessment: - Evidence level: Critical (clearly wrong outcome — 100% of reviews on the affected PR are empty; also regresses a fix that was already shipped as PR #234) - Classification: Structural — the slash-command preprocessor runs deterministically and will fail on every \\!\` sequence regardless of the model's approach - Occurrences this run: 2 on the same PR (same mechanism as #234) - Change type: Targeted fix (3 lines per file, 2 files) - Both gates pass
tend-agent
pushed a commit
that referenced
this pull request
Apr 11, 2026
…v vars
tend-triage run 24286871206 (2026-04-11 16:40Z) on max-sixty/worktrunk
issue #2076 posted a comment with two visible rendering failures that
both originate in a single `cat > /tmp/comment.md << 'EOF'` heredoc:
1. The literal string "${GITHUB_REPOSITORY}" appears in three markdown
links (e.g.
https://github.com/${GITHUB_REPOSITORY}/blob/.../reference/config.md#L136-L141).
The single-quoted heredoc disabled variable expansion, so the env
var never interpolated.
2. The greeting "Thanks for the suggestion\!" renders as "Thanks for the
suggestion\\!" — the Bash tool pre-escapes every `\!` to `\\!` before
bash sees the heredoc, which makes the quoting mode irrelevant (both
`<< 'EOF'` and `<<EOF` produce `\\!`).
The bot never verified the posted output, declared the task complete,
and the broken comment is still live on worktrunk#2076 as of this
commit (comment id 4229779789).
The prior `\!`-escape-in-comment-heredoc occurrence was recorded as
below-threshold in run 24281303125 (2026-04-11 11:55Z), where the
review bot wrote `if \!is_builtin` inside an inline-suggestion heredoc,
noticed the escaped `\\!` via a post-write verify, and recovered by
rewriting the comment via python3. That tracking entry's explicit
follow-up condition was "If this surface produces a second occurrence,
promote to a one-paragraph addition in running-in-ci/SKILL.md under
the existing \!-escape paragraph." Run 24286871206 is that second
occurrence, and it's worse: the bot did not recover, and the broken
artifact is public.
Extending the GitHub URLs paragraph in running-in-ci is the narrow
targeted fix the prior finding pointed to. The new prose explicitly
tells the bot to:
- Scan for literal `${GITHUB_REPOSITORY}` in the rendered comment, and
rewrite heredocs as unquoted `<<EOF` or use the Write tool instead.
- Use the Write tool for any comment body containing an exclamation
mark, because the Bash tool rewrites `\!` to `\\!` regardless of the
heredoc quoting mode.
The new paragraph is carefully written to contain no `` \!` `` sequence
so it can't trip the slash-command preprocessor (the same footgun
PR #234 and the sibling PR #243 in this hour's cycle both address).
Verified with `grep -rn '\!\`' plugins/` returning zero matches.
This branch also carries PR #243's comment-rewrite on line 147 as a
dependency so that `/review` can actually run on this PR without
hitting the preprocessor error. If PR #243 merges first, the merge
of this branch is a no-op on those lines.
Gate assessment:
- Evidence level: High — structural, 2 occurrences in the same surface
(heredoc-write comment body), second occurrence produced a live
public broken artifact.
- Classification: Structural — the Bash tool's `\!`-escape is
deterministic; single-quoted heredocs are standard bash semantics.
The bot has no decision point that would produce different behavior.
- Change type: Targeted fix (two-sentence addition to an existing
paragraph).
- Both gates pass.
tend-agent
pushed a commit
that referenced
this pull request
Apr 11, 2026
The Claude Code slash-command preprocessor treats a backtick-enclosed token beginning with an exclamation mark as shell command substitution. Any plugin skill file loaded by /review (or another slash command) that contains this sequence crashes the session before the assistant turn runs. The pattern has regressed twice already: PR #217 introduced it, PR #234 removed it, PR #226 reintroduced it, PR #243 removed it again. Each regression broke 100% of tend-review runs until the next fix merged. Add a local pre-commit hook that rejects the pattern at commit time. The check constructs its search string as chr(33)+chr(96) so the hook file itself is safe from the pattern it is searching for. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3 tasks
max-sixty
added a commit
that referenced
this pull request
Apr 19, 2026
The Bash tool no longer rewrites exclamation marks to backslash-bang in
heredocs. Verified: both `<<EOF` and `<< 'EOF'` now pass `!` through
unchanged. Drop the guidance to use Write + `--body-file` for comment
bodies containing `!`, and drop "unescaped bangs" from the bot-comment
corruption signals.
The `${GITHUB_REPOSITORY}` heredoc-quoting guidance stays (that's bash
semantics, not a Claude Code bug), as does the bang-backtick pre-commit
guard (separate slash-command preprocessor issue, #234/#243/#244).
Co-Authored-By: Claude <noreply@anthropic.com>
max-sixty
added a commit
that referenced
this pull request
Apr 19, 2026
The Bash tool no longer rewrites exclamation marks to backslash-bang in
heredocs. Verified locally — both `<<EOF` and `<< 'EOF'` now pass `!`
through unchanged.
Changes:
- `running-in-ci`: drop the paragraph telling agents to use the Write
tool + `--body-file` for comment bodies containing `!`. Heredocs with
`gh ... --body` work fine again.
- `review-reviewers`: drop "unescaped bangs" from the bot-comment
corruption signals — no longer a thing to watch for.
Kept intentionally:
- The `${GITHUB_REPOSITORY}` heredoc-quoting warning (bash semantics
around single-quoted heredocs, not a Claude Code bug).
- The `.pre-commit-config.yaml` bang-backtick guard — that's a separate
slash-command preprocessor issue (#234/#243/#244), not the heredoc bug.
> _This was written by Claude Code on behalf of @max-sixty_
Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Apr 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Every
/tend-ci-runner:reviewinvocation has been silently broken since PR #217 merged at 2026-04-10 20:07 UTC. PRs #225–#233 all received zero reviews from the bot — the review runs reportsuccessbut the session artifacts show no assistant turn at all. This PR removes the poison and restores reviews.Root cause
PR #217 (
fix(ci-runner): replace if-not polling loop with || to avoid bash escaping) added an explanatory comment inside the CI-polling code block:Claude Code's slash-command preprocessor scans the loaded file for
\!`(a prefix that means "execute the next backticked string as a shell command") regardless of markdown code fences. It found\!`inside`if \!`, consumed text through the next backtick, and ran— the Bash tool escapes `as bash. The em-dash is not a command, so bash reported:When the preprocessor fails, the prompt body is not delivered. Every
/review <N>session in this window produced the same 5-line trace — two internalqueue-operationmessages, the command caveat, the command invocation, the stderr — and then nothing. The model was never given instructions to follow.Evidence
All tend-review sessions in the past hour's window ran this preprocessor and failed identically:
review-runs-timeout-detectiontend-mention-dedup-review-eventshourly/review-24261599977hourly/review-24261599977raise-job-timeoutsmention-verify-paginatetend-claude-md-workflow-update-noteraise-job-timeoutsmention-review-inline-reply-promptraise-job-timeoutstend-mention-dedup-review-eventsSample JSONL from run 24262987799 (PR #229):
{"type":"queue-operation"} {"type":"queue-operation"} {"type":"user","content":"<local-command-caveat>..."} {"type":"user","content":"<command-name>/review</command-name>\n<command-args>229</command-args>"} {"type":"user","content":"<local-command-stderr>Error: Shell command failed for pattern \"\!` — the Bash tool escapes `\": [stderr]\n/bin/bash: line 1: —: command not found</local-command-stderr>"}No assistant turn. No Skill loads. No tool calls. No review.
Confirmation via the target PRs:
gh pr view <N> --json reviewsreturns[]for every one of PRs #225–#233. PR #224, reviewed before #217 landed, has the bot's APPROVED review.The same preprocessor error is also visible in the
tend-mentionrun 24261917519 when it loadedrunning-in-civia the Skill tool — there the error appeared as a tool_result and the model continued working, because skill-load failures are non-fatal. Only the top-level slash-command invocation is lethal.Gate assessment
Fix
Rephrase the comments in
plugins/tend-ci-runner/skills/review/SKILL.md:294andplugins/tend-ci-runner/skills/running-in-ci/SKILL.md:142to avoid any\!`sequence. The guidance content is unchanged: "Use||rather thanif-based negation; the Bash tool escapes the exclamation mark to a literal backslash-exclamation." No\!now appears adjacent to a backtick anywhere inplugins/.grep '\!\' plugins/` after the fix returns zero matches.Test plan
grep -r '\!\' plugins/` returns no matchestend-mentionandtend-notificationsskill loads ofrunning-in-cino longer showShell command failed for patternin tool_results🤖 Generated with Claude Code