Skip to content

fix(mention): paginate gh api calls in verify job#228

Merged
max-sixty merged 1 commit into
mainfrom
mention-verify-paginate
Apr 10, 2026
Merged

fix(mention): paginate gh api calls in verify job#228
max-sixty merged 1 commit into
mainfrom
mention-verify-paginate

Conversation

@max-sixty
Copy link
Copy Markdown
Owner

Without --paginate, gh api silently truncates at 30 results. On issues/PRs with many comments or reviews, the verify job could miss bot engagement and skip a valid mention.

Adds --paginate to all four gh api GET calls in the verify step. The jq expressions work unchanged on paginated output.

This was written by Claude Code on behalf of @max-sixty

Without --paginate, gh api silently truncates at 30 results. On issues/PRs with
many comments or reviews, this could miss bot engagement and skip a valid
mention.

Co-Authored-By: Claude <noreply@anthropic.com>
@max-sixty max-sixty merged commit 2fb6a91 into main Apr 10, 2026
3 checks passed
@max-sixty max-sixty deleted the mention-verify-paginate branch April 10, 2026 20:36
max-sixty pushed a commit that referenced this pull request Apr 10, 2026
#234)

## Summary

Every `/tend-ci-runner:review` invocation 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 report `success` but 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:

```markdown
# Use `||` rather than `if \!` — the Bash tool escapes `\!` as `\\!`, which
# prevents bash from recognizing the pipeline-negation reserved word...
```

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:

```
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 <N>` session in this window produced the same 5-line trace —
two internal `queue-operation` messages, 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:

| Run | PR | Branch | Session size | Review posted |
|---|---|---|---|---|
| 24261252532 | #224 | `review-runs-timeout-detection` | ~120 lines | ✅
APPROVED (ran **before** #217 merged at 20:07Z) |
| 24262024783 | #225 | `tend-mention-dedup-review-events` | 5 lines | ❌
|
| 24262028666 | #226 | `hourly/review-24261599977` | — | ❌ (checkout
failure — infra race, separate issue) |
| 24262305841 | #226 | `hourly/review-24261599977` | 5 lines | ❌ |
| 24262406137 | #227 | `raise-job-timeouts` | 5 lines | ❌ |
| 24262970448 | #228 | `mention-verify-paginate` | 5 lines | ❌ |
| 24262987799 | #229 | `tend-claude-md-workflow-update-note` | 5 lines |
❌ |
| 24263043865 | #230 | `raise-job-timeouts` | 5 lines | ❌ |
| 24263117206 | #231 | `mention-review-inline-reply-prompt` | 5 lines |
❌ |
| 24263177723 | #232 | `raise-job-timeouts` | 5 lines | ❌ |
| 24263220447 | #233 | `tend-mention-dedup-review-events` | 5 lines | ❌
|

Sample JSONL from run 24262987799 (PR #229):
```json
{"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 reviews` returns
`[]` 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-mention` run
24261917519 when it loaded `running-in-ci` via 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

- **Evidence level**: Critical (wrong outcome — reviews 100%
non-functional)
- **Classification**: Structural (deterministic; every invocation fails
the same way)
- **Occurrences this run**: 9 (plus 1 non-fatal skill-load collision in
tend-mention)
- **Historical evidence**: N/A — this regression was introduced by #217
earlier today and has no prior tracking entries
- **Change type**: Targeted fix (two-line comment rephrase in two files)
- **Both gates**: pass

## Fix

Rephrase the comments in
`plugins/tend-ci-runner/skills/review/SKILL.md:294` and
`plugins/tend-ci-runner/skills/running-in-ci/SKILL.md:142` to avoid any
`` \!` `` sequence. The guidance content is unchanged: "Use `||` rather
than `if`-based negation; the Bash tool escapes the exclamation mark to
a literal backslash-exclamation." No `\!` now appears adjacent to a
backtick anywhere in `plugins/`.

`grep '\!\`' plugins/` after the fix returns zero matches.

## Test plan

- [ ] A tend-review run on this PR completes with an assistant session
longer than 5 lines and posts an actual review (self-approval blocked,
but the bot must at least read the diff and comment)
- [ ] `grep -r '\!\`' plugins/` returns no matches
- [ ] `tend-mention` and `tend-notifications` skill loads of
`running-in-ci` no longer show `Shell command failed for pattern` in
tool_results

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: continuous-bot <269947486+continuous-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
tend-agent added a commit that referenced this pull request Apr 11, 2026
Syncs the checked-in workflow file with the in-repo generator. Pulls in
changes from #225 (pull_request_review_comment dedup), #233 (drop
bot-author filter), #228 (--paginate on gh api), and #235 (move
behavioral instructions from prompt to skill).

Generated with the local `generator/` source tree rather than
`uvx tend@latest init`, because PyPI 0.0.11 lags behind main for these
changes — running `uvx tend@latest init` against the current tree would
*add* `timeout-minutes: 60` back and drop the mention generator updates.
tend-agent pushed a commit that referenced this pull request Apr 13, 2026
When `generator/pyproject.toml` exists (i.e. on the tend repo itself),
Step 5 of the nightly skill now regenerates workflows via the in-tree
generator instead of `uvx tend@latest`. Adopter repos without `generator/`
fall through to the existing `uvx tend@latest` path unchanged.

Motivation: PR #264 (from run 24330194038) ran `uvx tend@latest init` with
PyPI's `tend` at 0.0.11 (released 2026-04-10). `main` has 10 generator
commits landed since — #223 (drop hardcoded job timeouts), #225 (dedup
review events), #227 (workflow_extra), #228 (paginate), #231 (inline-reply
guidance), #233 (drop bot-author filter on issue_comment), #235 (prompt →
skill), #254 (notifications freshness gate + bot-closed-PR drop), etc.
Regenerating against the stale wheel reverted each of these. Maintainer
flagged the PR as regressions; diagnosis confirmed the PyPI lag.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

1 participant