skills(running-in-ci): cover the joint case of $GITHUB_REPOSITORY + ! in a comment body - #381
Merged
Merged
Conversation
… `!` in a comment body
When a body contains both a `!` and a `${GITHUB_REPOSITORY}` reference, the existing guidance offers two recipes that each cover only one half: unquoted `<<EOF` interpolates the variable but the bash preprocessor still rewrites `!` to `\!`; the Write tool dodges the preprocessor but does not interpolate. The bot in worktrunk triage run 25295135366 picked single-quoted `<<'EOF'` and shipped a comment with both corruptions visible to a community reporter.
Add an explicit recipe for the joint case: write an `OWNER_REPO` placeholder via the Write tool, then substitute via `sed -i "s|OWNER_REPO|$GITHUB_REPOSITORY|g"` before `gh ... --body-file`.
The new sentence introduced four occurrences of backtick-bang-backtick, the very preprocessor poison the rule documents. The no-preprocessor-poison-in-skills pre-commit hook fails on it. Replace each occurrence with the prose phrase "an exclamation mark" so the rule's own page does not crash a slash-command session.
max-sixty
pushed a commit
that referenced
this pull request
May 15, 2026
…rule (#495) ## Summary Extend the existing `<<'EOF' ... EOF` backtick-escape rule to cover nested fenced code blocks. The current rule warns about escaping *inline code spans* (`` \`foo\` ``); the same single-quoted-heredoc mechanic also corrupts *nested fences* when the model defensively escapes the inner three-backtick fence (`` \`\`\`bash ``) to keep it from closing the outer fence. The fix is the standard markdown idiom: use a longer outer fence (four or five backticks) so the inner three-backtick fence renders intact without escaping. ## Evidence [PRQL/prql#5900](PRQL/prql#5900) (`tend ci-fix: transient classifier ignores repeat occurrences`, opened by prql-bot 2026-05-15T08:56:34Z). The body wraps a proposed skill addition in a `` ```markdown `` outer fence and contains an inner `` ```bash `` fence plus several inline code spans. The model escaped the inner fence and all inline backticks inside the inner section, producing visibly corrupted markdown — the rendered body shows `` \`\`\`bash ``, `` \`rustup-init\` ``, `` \`composer connect timeout\` ``, `` \`docker pull rate limit\` ``, `` \`gh issue search\` ``, and trailing `` \`\`\` `` (six distinct corrupted spans). Direct API spot-check: ```` $ gh api repos/PRQL/prql/issues/5900 --jq '.body' | grep -c '\\`' 6 ```` This is the first such occurrence in the PRQL evidence gist's tracked corruption-scan history (prior ticks all reported `backslash-backtick: clean`); the [evidence log](https://gist.github.com/tend-agent/5686b1fca82c08d385d9031a79be4a3e) for May 2026 records the scans. ## Classification - **Failure class**: structural. The trigger is deterministic — a body composed in a single-quoted heredoc that contains a nested fenced block + the model's defensive instinct to escape the inner fence. Replayed, this produces the same corruption every time. The existing rule already classifies the inline-code-span variant as authored (not preprocessor-injected); the nested-fence variant is the same shape with a different originating model habit. - **Evidence level**: structural / 1 occurrence — sufficient under [`review-gates.md`](https://github.com/max-sixty/tend/blob/main/plugins/tend-ci-runner/skills/review-reviewers/review-gates.md): *"Structural: no decision point — the same conditions produce the same failure every time... One clear occurrence is sufficient evidence for a targeted fix."* - **Change magnitude**: targeted fix — one sentence appended to an existing paragraph. Within the Gate-2 magnitude budget for structural-fix scope. ## Change `plugins/tend-ci-runner/skills/running-in-ci/SKILL.md`: extend the existing backtick-escape paragraph (already covering inline spans like `` \`foo\` ``) with a second sentence covering nested fenced blocks. Recommend a longer outer fence (four or five backticks outside, three inside) as the standard remedy. Adds a parenthetical noting that `--body-file` via the Write tool helps with delivery but not authoring — the model still has to author with bare backticks, since Write preserves data verbatim. ## Notes - #5900 itself is left as-is for now; its body is readable and stands as the in-evidence example for this fix. A clean re-author can follow once this skill update lands. - This change does not touch the inline-code-span rule (#423) or the bang-escape rules (#404, #427, #381, #432) — same paragraph, different shape, same delivery channel. Co-authored-by: tend-agent <270458913+tend-agent@users.noreply.github.com>
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.
Problem
tend-triagerun 25295135366 onmax-sixty/worktrunkshipped a public comment (issue #2564 comment 4367561809) with two simultaneous corruption signals:${GITHUB_REPOSITORY}that did not interpolate:[src/main.rs:1300](https://github.com/${GITHUB_REPOSITORY}/blob/main/src/main.rs#L1300). The link is broken — clicks 404.\!backslash-bang corruption ondebug_assert\!andbail\!(Rust syntax that should render asdebug_assert!/bail!).Session-log inspection confirmed the bot used
gh issue comment 2564 --body "$(cat <<'EOF' ... EOF)". The single-quoted heredoc form fails on both axes: the bash preprocessor's!→\!rewrite still fires (it operates at the string level before bash parses the heredoc), and${GITHUB_REPOSITORY}does not expand (single-quoted heredoc disables interpolation).Why the existing guidance didn't catch it
running-in-cialready has two relevant warnings:$GITHUB_REPOSITORYparagraph offers two ways to fix unexpanded variables: unquoted<<EOFor the Write tool.!paragraph mandates the Write tool when the body contains an exclamation mark.Neither paragraph addresses the joint case — when a body contains both a
!and a${GITHUB_REPOSITORY}reference. Unquoted<<EOFfixes the variable but not the!(preprocessor still mangles). Write-tool composition fixes the!but not the variable (Write does not interpolate). The bot picked single-quoted<<'EOF', which fails both.The
!rule says "use Write tool"; the URL rule offers Write tool as an alternative — but neither tells the bot how to embed$GITHUB_REPOSITORYin a Write-tool-composed file. So when both gotchas applied at once, neither rule's recipe was complete.Fix
One sentence added to the
$GITHUB_REPOSITORYparagraph: when the body contains a!(Write mandatory), write anOWNER_REPOplaceholder into the file and substitute viased -i "s|OWNER_REPO|$GITHUB_REPOSITORY|g" /tmp/body.mdbeforegh ... --body-file. Plus an explicit warning that single-quoted<<'EOF'with both a!and${GITHUB_REPOSITORY}in the body fails on both counts.The
sedrecipe is preprocessor-safe:$GITHUB_REPOSITORYisowner/repo(no!), and the sed command itself contains no!(uses|as delimiter because/appears in the value).Gate assessment
!and${GITHUB_REPOSITORY}will plausibly pick<<'EOF'again.\!-shipping incidents in the last month's evidence gist (issue #2309 comment, PR #2359 title, PR #2361 title, the<\!--HTML-comment case). The${GITHUB_REPOSITORY}non-expansion case is new this run. Both gates pass.Evidence
test_prune_skips_unmergedon Windows —Permission deniedreading.git/configfrom background subprocess worktrunk#2564 (comment)\!shipping incident write-up: tend PR #318