Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 166 additions & 0 deletions .github/workflows/engine-version-watch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
name: Engine Version Watch

# Every 3 days: detect newer engine releases and have Claude file one
# researched upgrade issue per engine (deduped against open issues, so a
# version is only reported once).

on:
schedule:
- cron: '23 8 */3 * *'
workflow_dispatch:
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Comment thread
coderabbitai[bot] marked this conversation as resolved.
permissions:
contents: read

concurrency:
group: engine-version-watch
cancel-in-progress: false

jobs:
detect:
runs-on: k8s-runner-cpu
timeout-minutes: 10
permissions:
contents: read
issues: write
outputs:
pending: ${{ steps.dedup.outputs.pending }}
has_pending: ${{ steps.dedup.outputs.has_pending }}
steps:
- name: Checkout
uses: actions/checkout@v7
Comment thread
coderabbitai[bot] marked this conversation as resolved.
with:
persist-credentials: false

- name: Install gh CLI
run: |
if ! command -v gh &>/dev/null; then
mkdir -p "$HOME/.local/bin"
GH_VERSION="2.74.0"
GH_SHA256="e55c9d49dc49c0b0fef0a9acd3510482fd9e27ff52ae80f8a6e838cd25b4cd89"
curl -fsSL --connect-timeout 10 --max-time 120 -o /tmp/gh.tgz \
"https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_amd64.tar.gz"
echo "${GH_SHA256} /tmp/gh.tgz" | sha256sum --check --quiet
tar xzf /tmp/gh.tgz --strip-components=2 -C "$HOME/.local/bin" "gh_${GH_VERSION}_linux_amd64/bin/gh"
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
fi
Comment on lines +35 to +46

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file=".github/workflows/engine-version-watch.yml"

echo "== outline =="
ast-grep outline "$file" --view expanded || true

echo
echo "== lines 1-170 =="
nl -ba "$file" | sed -n '1,170p'

Repository: lightseekorg/smg

Length of output: 285


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file=".github/workflows/engine-version-watch.yml"

echo "== lines 1-170 =="
sed -n '1,170p' "$file" | cat -n

echo
echo "== gh occurrences =="
rg -n '\bgh\b|GH_TOKEN|PATH|Install gh CLI|command -v gh' "$file"

Repository: lightseekorg/smg

Length of output: 9753


Force the pinned gh binary
if ! command -v gh lets any preinstalled gh bypass the version/SHA pin, so the gh calls in both jobs can run against an untrusted binary. Install the verified tarball unconditionally, or check the existing binary’s version and provenance before skipping.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/engine-version-watch.yml around lines 35 - 46, Update the
“Install gh CLI” step to always install and expose the verified gh release,
removing the command -v gh bypass so both jobs use the pinned GH_VERSION binary
validated by GH_SHA256.


- name: Check versions
id: check
env:
GH_TOKEN: ${{ github.token }}
run: |
bash scripts/check_engine_versions.sh | tee versions.jsonl

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fail the version check when the detector fails

When any upstream lookup in scripts/check_engine_versions.sh fails (for example a curl timeout, NVIDIA index format change, or gh token issue), the script exits non-zero but this pipeline returns tee's status. GitHub documents an unspecified Linux/macOS run shell as bash -e {0}, while only shell: bash adds -o pipefail (docs), so the scheduled watch can continue with updates=[] or a partial JSONL file instead of alerting maintainers. Add shell: bash/set -o pipefail or avoid piping the detector before relying on its result.

Useful? React with 👍 / 👎.

jq -cs '[.[] | select(.update)]' versions.jsonl > updates.json
echo "updates=$(cat updates.json)" >> "$GITHUB_OUTPUT"

- name: Drop engines that already have an open issue
id: dedup
env:
GH_TOKEN: ${{ github.token }}
run: |
gh label create engine-watch --repo "$GITHUB_REPOSITORY" \
--description "Automated engine release tracking" --color 0e8a16 --force
gh label create enhancement --repo "$GITHUB_REPOSITORY" \
--description "New feature or request" --color a2eeef --force
# Exact substring match on fetched titles: GitHub's in:title search
# normalizes dots/hyphens, so "sglang 0.5.16" can match unrelated
# issues (or miss).
titles=$(gh issue list --repo "$GITHUB_REPOSITORY" --state open \
--label engine-watch --limit 200 --json title --jq '[.[].title]')
pending='[]'
while IFS= read -r row; do
engine=$(jq -r .engine <<<"$row")
latest=$(jq -r .latest <<<"$row")
existing=$(jq --arg t "$engine $latest" '[.[] | select(contains($t))] | length' <<<"$titles")
Comment on lines +72 to +78

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the workflow around the cited lines
FILE=".github/workflows/engine-version-watch.yml"
wc -l "$FILE"
sed -n '1,160p' "$FILE"

# Locate all uses of `gh issue list` and related dedup logic
rg -n "gh issue list|engine-watch|pending='\\[\\]'" .github/workflows -S

Repository: lightseekorg/smg

Length of output: 7832


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the gh CLI docs from the installed help text if available
gh issue list --help | sed -n '1,220p'

Repository: lightseekorg/smg

Length of output: 2785


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Probe whether gh issue list defaults imply pagination limits or whether --limit is only a display cap
python3 - <<'PY'
print("noop")
PY

Repository: lightseekorg/smg

Length of output: 159


Fetch all open engine-watch issues for deduping. --limit 200 only checks the first 200 matches, so an older open issue can be skipped and a duplicate created once the label grows past that cap.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/engine-version-watch.yml around lines 72 - 78, Update the
issue query in the engine-version watch workflow to fetch all open engine-watch
issues rather than limiting results to 200, so deduplication checks the complete
issue set. Preserve the existing title JSON and jq filtering used by the pending
loop.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Important: jq contains does substring matching, which causes false dedup when a final release's version string is a prefix of an existing RC issue's version.

Concrete scenario: an open issue is titled [engine-watch] tensorrt-llm 1.3.0rc18 available (pinned: 1.2.0). When the stable 1.3.0 ships, the search term becomes "tensorrt-llm 1.3.0", and contains("tensorrt-llm 1.3.0") returns true against the RC title because "1.3.0rc18" contains "1.3.0" as a substring. The stable release notification is silently dropped.

Same class of bug for minor-version prefixes: "sglang 0.5.1" would match an open "sglang 0.5.16" issue.

Fix: construct and match the full expected title prefix instead of a bare substring:

Suggested change
existing=$(jq --arg t "$engine $latest" '[.[] | select(contains($t))] | length' <<<"$titles")
expected="[engine-watch] $engine $latest available"
existing=$(jq --arg t "$expected" '[.[] | select(startswith($t))] | length' <<<"$titles")

if [ "$existing" = "0" ]; then
pending=$(jq -c --argjson r "$row" '. + [$r]' <<<"$pending")
else
echo "Skipping $engine $latest: open issue exists"
fi
done < <(jq -c '.[]' updates.json)
echo "pending=$pending" >> "$GITHUB_OUTPUT"
echo "has_pending=$(jq 'length > 0' <<<"$pending")" >> "$GITHUB_OUTPUT"

Comment on lines +57 to +84

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does GitHub's issue search "in:title" with a quoted phrase containing dots or hyphens reliably match only the exact literal substring?

💡 Result:

No, GitHub's issue search does not reliably match quoted phrases containing dots or hyphens as exact literal substrings [1]. While GitHub issue search supports double quotes for multi-word phrases [2][3], the underlying search mechanism typically processes queries by normalizing text, which often involves treating punctuation marks like dots and hyphens as noise or delimiters [1]. Consequently, a search for a phrase such as "item-name" or "version.1" frequently results in the search engine treating those characters as separators rather than literal parts of the string, causing the search to return matches for the individual words (e.g., "item" and "name") rather than the specific, combined string [4][1]. This limitation is a known point of frustration for users searching for identifiers, function names, or version strings that rely on these characters [1]. It is distinct from GitHub's separate Code Search functionality, which does support more advanced exact matching and special character handling [5][6]. For issue search, no native syntax currently guarantees that these special characters will be treated as part of an immutable, literal substring [1].

Citations:


🌐 Web query:

GitHub issue search quoted phrase punctuation dots hyphens exact match docs

💡 Result:

When searching for issues and pull requests on GitHub, the search engine does not support exact string matching for punctuation, including dots and hyphens [1][2]. While you can use quotation marks to group multi-word terms (e.g., "in progress") to ensure those specific words appear in the result [1][2], GitHub's standard search behavior treats punctuation marks as delimiters or ignores them entirely [3][4]. Consequently, a search for a phrase containing punctuation will typically return results that match the words themselves, regardless of the punctuation [3][4]. For searching source code on GitHub, the experience differs due to GitHub's specialized Code Search engine [5]. GitHub Code Search supports exact string matching by surrounding the string in quotes [5]. It also allows for more advanced pattern matching using regular expressions enclosed in forward slashes (e.g., /my-exact-string/) [5][6]. Unlike the standard issue/pull request search, this code-specific engine is designed to handle non-alphanumeric characters more effectively [5]. In summary: - For issues and pull requests: Use quotes to group words, but be aware that punctuation like hyphens and dots will not be treated as part of an exact string match [1][2][3]. - For code: Use quotes for exact string matching or regular expressions (between slashes) to include specific punctuation marks in your search criteria [5][6].

Citations:


Avoid relying on quoted title search for dedup
gh issue list --search "\"$engine $latest\" in:title" is brittle for versions and names containing punctuation like . or -. GitHub issue search treats those characters loosely, so this can miss an existing issue or match the wrong one. Use a structured marker or metadata check instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/engine-version-watch.yml around lines 46 - 68, Replace the
quoted title search in the dedup loop with a structured marker or metadata-based
check that uniquely identifies the engine and latest version, avoiding GitHub
search parsing of punctuation in names and versions. Update the `existing`
calculation while preserving the current behavior of excluding rows with an open
matching `engine-watch` issue.

research-and-file:
needs: detect
if: needs.detect.outputs.has_pending == 'true'
runs-on: k8s-runner-cpu
timeout-minutes: 30
permissions:
contents: read
issues: write
id-token: write
steps:
- name: Checkout
uses: actions/checkout@v7
with:
persist-credentials: false

- name: Export API key from pod env
run: |
if [ -z "${ANTHROPIC_API_KEY:-}" ]; then
echo "::error::ANTHROPIC_API_KEY is not present in the runner pod environment"
exit 1
fi
echo "::add-mask::${ANTHROPIC_API_KEY}"
echo "ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}" >> "$GITHUB_ENV"
Comment thread
coderabbitai[bot] marked this conversation as resolved.

- name: Install gh CLI
run: |
if ! command -v gh &>/dev/null; then
mkdir -p "$HOME/.local/bin"
GH_VERSION="2.74.0"
GH_SHA256="e55c9d49dc49c0b0fef0a9acd3510482fd9e27ff52ae80f8a6e838cd25b4cd89"
curl -fsSL --connect-timeout 10 --max-time 120 -o /tmp/gh.tgz \
"https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_amd64.tar.gz"
echo "${GH_SHA256} /tmp/gh.tgz" | sha256sum --check --quiet
tar xzf /tmp/gh.tgz --strip-components=2 -C "$HOME/.local/bin" "gh_${GH_VERSION}_linux_amd64/bin/gh"
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
fi
Comment on lines +109 to +120

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated gh CLI install block across both jobs.

Lines 109-120 are byte-identical to lines 35-46 in the detect job. Extracting this into a local composite action would centralize the pinned GH_VERSION/GH_SHA256 pair so future bumps only need one edit.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/engine-version-watch.yml around lines 109 - 120, Extract
the duplicated “Install gh CLI” step from both the detect and engine-version
jobs into a local composite action. Move the pinned GH_VERSION and GH_SHA256
values and installation logic into that action, then replace both inline blocks
with action invocations so future version updates require a single edit.


- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ env.ANTHROPIC_API_KEY }}
prompt: |
REPO: ${{ github.repository }}
PENDING ENGINE UPDATES (JSON): ${{ needs.detect.outputs.pending }}

For EACH entry, research the upgrade and create ONE GitHub issue.

Research per engine:
1. Locate every pin of the current version in this repo
(scripts/ci_install_<engine>.sh, .github/workflows/release-*-docker.yml,
grpc_servicer/pyproject.toml, docker/engine.Dockerfile).
2. Check whether nearby workaround comments are tied to the pinned
version (e.g. dependency band pins, forced reinstalls) and
whether the new release's dependency metadata makes them
obsolete — for PyPI packages fetch
https://pypi.org/pypi/<pkg>/<version>/json and inspect
requires_dist. For tensorrt-llm use https://pypi.nvidia.com.
For tokenspeed, `current`/`latest` are commit SHAs — summarize
`gh api repos/lightseekorg/tokenspeed/compare/<current>...<latest>`
(commit subjects only) and note that the torch pin in
ci_install_tokenspeed.sh must be re-checked against upstream.
3. Verify the release image/wheel actually exists (Docker Hub tag,
NGC wheel listing) before recommending it.

Then create the issue:
gh issue create --repo ${{ github.repository }} \
--label engine-watch --label enhancement \
--title "[engine-watch] <engine> <latest> available (pinned: <current>)" \
--body <researched body>
Comment on lines +143 to +154

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep the Claude prompt declarative.

The embedded gh api/gh issue create shell syntax and <researched body> placeholder can be interpreted as executable shell rather than instructions. Describe the required API lookup and issue fields in natural language.

Proposed fix
-               `gh api repos/lightseekorg/tokenspeed/compare/<current>...<latest>`
-               (commit subjects only) and note that the torch pin in
+               compare the current and latest commits through the GitHub API,
+               summarize commit subjects only, and note that the torch pin in
                ci_install_tokenspeed.sh must be re-checked against upstream.
@@
-            Then create the issue:
-              gh issue create --repo ${{ github.repository }} \
-                --label engine-watch --label enhancement \
-                --title "[engine-watch] <engine> <latest> available (pinned: <current>)" \
-                --body <researched body>
+            Then create an issue in the repository with the `engine-watch`
+            and `enhancement` labels. Its title must be:
+            `[engine-watch] <engine> <latest> available (pinned: <current>)`.

Based on learnings, prompt: fields intended for an LLM should use natural-language instructions rather than shell-specific constructs.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
For tokenspeed, `current`/`latest` are commit SHAs — summarize
`gh api repos/lightseekorg/tokenspeed/compare/<current>...<latest>`
(commit subjects only) and note that the torch pin in
ci_install_tokenspeed.sh must be re-checked against upstream.
3. Verify the release image/wheel actually exists (Docker Hub tag,
NGC wheel listing) before recommending it.
Then create the issue:
gh issue create --repo ${{ github.repository }} \
--label engine-watch --label enhancement \
--title "[engine-watch] <engine> <latest> available (pinned: <current>)" \
--body <researched body>
For tokenspeed, `current`/`latest` are commit SHAs — summarize
compare the current and latest commits through the GitHub API,
summarize commit subjects only, and note that the torch pin in
ci_install_tokenspeed.sh must be re-checked against upstream.
3. Verify the release image/wheel actually exists (Docker Hub tag,
NGC wheel listing) before recommending it.
Then create an issue in the repository with the `engine-watch`
and `enhancement` labels. Its title must be:
`[engine-watch] <engine> <latest> available (pinned: <current>)`.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/engine-version-watch.yml around lines 143 - 154, Update
the prompt text in the workflow so it declaratively instructs the agent to
research the tokenspeed commit comparison, re-check the torch pin, verify the
release artifact, and create an issue in the current repository with the
engine-watch and enhancement labels, specified title, and researched body.
Remove embedded gh command syntax, shell continuations, and the <researched
body> placeholder while preserving the required lookup and issue fields as
natural-language requirements.

Source: Learnings

Body sections: current pin locations (file:line), what the new
release changes for us (workarounds now obsolete / new pins
required, with evidence), an upgrade checklist mirroring the
files above, and which e2e legs validate the bump. Keep it
factual and short; no speculation beyond the metadata checked.

Do NOT open pull requests. Do NOT edit repository files.
One issue per engine, nothing else.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
claude_args: |
--model claude-opus-4-6
--max-turns 40
--allowedTools "Read,Glob,Grep,Bash,WebFetch,WebSearch,TaskCreate,TaskUpdate,TaskGet"
env:
GH_TOKEN: ${{ github.token }}
Comment on lines +161 to +166

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the workflow around the referenced lines
sed -n '130,190p' .github/workflows/engine-version-watch.yml

# Find references to claude-code-action and any related docs/config in the repo
rg -n "claude-code-action|allowedTools|ANTHROPIC_API_KEY|GH_TOKEN|Bash,WebFetch|Do not edit|engine-version-watch" .github/workflows . -g '!**/node_modules/**' -g '!**/dist/**' -g '!**/build/**'

Repository: lightseekorg/smg

Length of output: 8132


🌐 Web query:

claude-code-action@v1 allowedTools Bash WebFetch WebSearch command-scoped shell permissions GH_TOKEN ANTHROPIC_API_KEY documentation

💡 Result:

In the claude-code-action@v1 GitHub Action, WebSearch and WebFetch are disabled by default for security reasons [1][2][3]. To enable them, you must explicitly include them in the allowed_tools configuration [2][4]. The action logic is designed so that if these tools appear in your provided allowed_tools list, they are removed from the internal disallowed list, effectively overriding the default restriction [5][2][4]. Configuration Example: To allow these tools, update your workflow YAML: - uses: anthropics/claude-code-action@v1 with: allowed_tools: "WebSearch,WebFetch,Bash" anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} Regarding permissions and security: 1. Environment Variables: Never hardcode your ANTHROPIC_API_KEY or tokens in workflow files [6]. Always use repository secrets and reference them via ${{ secrets.SECRET_NAME }} [6][7]. 2. Shell Permissions: Bash tool permissions can be restricted using command-pattern matching [8]. You can limit access to specific commands by specifying them in the allowed_tools string (e.g., allowed_tools: "Bash(git:*),Bash(npm run *)") [8][9]. 3. GitHub Tokens: If using allowed_non_write_users to bypass standard write permission requirements, it is strongly recommended to use a scoped github_token (e.g., ${{ secrets.GITHUB_TOKEN }}) rather than a personal access token, and to restrict allowed_tools to the minimum necessary for the workflow [6]. 4. Global Settings: Tools denied at any level (e.g., through managed settings or explicit deny rules) cannot be overridden by allowed_tools [10]. Documentation on specific tool behavior and security best practices can be found in the official Claude Code documentation [8][7] and the repository's security guide [6].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the workflow file with line numbers around the referenced section
nl -ba .github/workflows/engine-version-watch.yml | sed -n '145,180p'

# Locate any job-level env/permissions near this workflow
rg -n -C 3 "permissions:|ANTHROPIC_API_KEY|GH_TOKEN|allowedTools|claude_args" .github/workflows/engine-version-watch.yml

Repository: lightseekorg/smg

Length of output: 194


Restrict Claude’s shell access. Bash is still enabled alongside GH_TOKEN and ANTHROPIC_API_KEY, so a prompt-injected response can still drive arbitrary shell commands with repo write access. Use command-pattern Bash allowlists for only the GitHub CLI operations this job needs, or move issue creation into a deterministic workflow step.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/engine-version-watch.yml around lines 161 - 166, Restrict
shell access in the Claude invocation’s claude_args by removing unrestricted
Bash and allowing only the specific gh command patterns required for this job,
or move issue creation to a deterministic workflow step. Preserve the existing
GitHub and Anthropic credentials while ensuring prompt-injected responses cannot
execute arbitrary repository commands.

161 changes: 161 additions & 0 deletions .github/workflows/nightly-triage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
name: Nightly Triage

# Daily: collect recent nightly benchmark/eval failures and have Claude
# triage them — classify each (regression vs infra/upstream flake vs
# config), rerun clear one-off flakes once, and keep one rolling issue per
# workflow so failures stop landing in a void. Runs after the ~7h bfcl/tau2
# windows finish.

on:
schedule:
- cron: '30 15 * * *'
workflow_dispatch:
Comment thread
coderabbitai[bot] marked this conversation as resolved.

permissions:
contents: read

concurrency:
group: nightly-triage
cancel-in-progress: false

env:
WATCHED_WORKFLOWS: nightly-bfcl.yml nightly-tau2.yml nightly-benchmark.yml nightly-docker.yml nightly-engine-docker.yml nightly-mlx-bench.yml

jobs:
collect:
runs-on: k8s-runner-cpu
timeout-minutes: 10
permissions:
actions: read
outputs:
failures: ${{ steps.gather.outputs.failures }}
has_failures: ${{ steps.gather.outputs.has_failures }}
steps:
- name: Install gh CLI
run: |
if ! command -v gh &>/dev/null; then
mkdir -p "$HOME/.local/bin"
GH_VERSION="2.74.0"
GH_SHA256="e55c9d49dc49c0b0fef0a9acd3510482fd9e27ff52ae80f8a6e838cd25b4cd89"
curl -fsSL --connect-timeout 10 --max-time 120 -o /tmp/gh.tgz \
"https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_amd64.tar.gz"
echo "${GH_SHA256} /tmp/gh.tgz" | sha256sum --check --quiet
tar xzf /tmp/gh.tgz --strip-components=2 -C "$HOME/.local/bin" "gh_${GH_VERSION}_linux_amd64/bin/gh"
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
fi
Comment on lines +34 to +45

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Duplicated gh CLI install block.

The checksum-verified gh install (lines 34-45) is repeated verbatim in triage (94-105). Consider extracting to a local composite action to keep the pinned version/SHA256 in one place.

Also applies to: 94-105

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/nightly-triage.yml around lines 34 - 45, Extract the
duplicated checksum-verified gh CLI installation blocks from the workflow’s
install step and the triage step into a local composite action. Invoke that
action from both locations, keeping the pinned GH_VERSION and GH_SHA256
definitions centralized while preserving the existing PATH setup and
installation behavior.


- name: Gather failed nightly runs
id: gather
env:
GH_TOKEN: ${{ github.token }}
run: |
# 48h lookback: a run still in progress at collection time (e.g.
# nightly-benchmark allows 24h) is picked up the next day; Claude
# dedups already-triaged run ids against the rolling issue.
since=$(date -u -d '48 hours ago' +%Y-%m-%dT%H:%M:%SZ)
failures='[]'
for wf in $WATCHED_WORKFLOWS; do
rows=$(gh run list --repo "$GITHUB_REPOSITORY" --workflow "$wf" \
--created ">=$since" --limit 10 \
--json databaseId,conclusion,status,url,attempt,workflowName \
--jq '[.[] | select(.status == "completed" and (.conclusion | IN("success", "cancelled", "skipped") | not))
| {workflow: .workflowName, run_id: .databaseId, attempt: .attempt, conclusion: .conclusion, url: .url}]')
failures=$(jq -c --argjson r "$rows" '. + $r' <<<"$failures")
Comment thread
coderabbitai[bot] marked this conversation as resolved.
done
echo "failures=$failures" >> "$GITHUB_OUTPUT"
echo "has_failures=$(jq 'length > 0' <<<"$failures")" >> "$GITHUB_OUTPUT"
jq . <<<"$failures"

triage:
needs: collect
if: needs.collect.outputs.has_failures == 'true'
runs-on: k8s-runner-cpu
timeout-minutes: 45
permissions:
contents: read
actions: write
issues: write
id-token: write
steps:
- name: Checkout
uses: actions/checkout@v7
with:
persist-credentials: false

- name: Export API key from pod env
run: |
if [ -z "${ANTHROPIC_API_KEY:-}" ]; then
echo "::error::ANTHROPIC_API_KEY is not present in the runner pod environment"
exit 1
fi
echo "::add-mask::${ANTHROPIC_API_KEY}"
echo "ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}" >> "$GITHUB_ENV"

- name: Install gh CLI
run: |
if ! command -v gh &>/dev/null; then
mkdir -p "$HOME/.local/bin"
GH_VERSION="2.74.0"
GH_SHA256="e55c9d49dc49c0b0fef0a9acd3510482fd9e27ff52ae80f8a6e838cd25b4cd89"
curl -fsSL --connect-timeout 10 --max-time 120 -o /tmp/gh.tgz \
"https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_amd64.tar.gz"
echo "${GH_SHA256} /tmp/gh.tgz" | sha256sum --check --quiet
tar xzf /tmp/gh.tgz --strip-components=2 -C "$HOME/.local/bin" "gh_${GH_VERSION}_linux_amd64/bin/gh"
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
fi

- name: Ensure label
env:
GH_TOKEN: ${{ github.token }}
run: |
gh label create nightly-triage --repo "$GITHUB_REPOSITORY" \
--description "Automated nightly failure triage" --color d93f0b --force

- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ env.ANTHROPIC_API_KEY }}
prompt: |
REPO: ${{ github.repository }}
FAILED NIGHTLY RUNS (last 48h, JSON): ${{ needs.collect.outputs.failures }}

Triage every run listed. For each:
1. Find the rolling issue first:
gh issue list --repo ${{ github.repository }} --state open
--label nightly-triage --json number,title
and pick the exact title "[nightly-triage] <workflow name>".
If that issue already mentions this run_id in its body or
comments, the run was triaged on a previous day — skip it.
Comment on lines +126 to +127

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Track rerun attempts instead of only run IDs

When Claude reruns a clear flake and that second attempt also fails, GitHub keeps it as another attempt of the same workflow run (the collector already carries attempt, and GitHub shows prior attempts under the same run in its rerun docs). The next collection will therefore see the same run_id with attempt == 2, but these instructions tell Claude to skip solely because that run_id was mentioned in the first day's comment, so failed reruns are never triaged or reported; dedup by (run_id, attempt) or add an explicit follow-up after reruns complete.

Useful? React with 👍 / 👎.

2. Fetch evidence:
`gh run view <run_id> --repo ${{ github.repository }} --log-failed | tail -300`
(fall back to `gh api .../jobs` for job names/conclusions if
logs are unavailable). Read the workflow file and the scripts
it calls when the failure points into them.
3. Classify with the log lines as evidence:
- infra/flake: runner lost, OOM-killed runner, network timeout,
registry/HF download failure, upstream API 5xx
- regression: assertion/score threshold failures (bfcl/tau2
score drops, benchmark deltas), build breaks in our code
- config/env: version conflicts, missing secrets, disk full
4. Rerun policy (conservative): if AND ONLY IF the failure is a
clear infra/flake and the run's attempt == 1, rerun it once:
`gh run rerun <run_id> --repo ${{ github.repository }} --failed`.
Never rerun regressions or second attempts.
5. Report per workflow in the rolling issue:
- If it exists, add a comment titled with today's date holding
the day's triage (classification, key log lines, action
taken, run links — always include the run_id). If the same
failure signature already appears in recent comments, say
so — recurring failures are the signal these issues exist
to surface.
- Else create it:
gh issue create --label nightly-triage
--title "[nightly-triage] <workflow name>"
--body <first day's triage>
Keep each day's entry short: verdict first, then evidence.
Do NOT edit repository files or open pull requests.
Comment on lines +117 to +155

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep the Claude prompt declarative.

Replace embedded gh commands and shell pipelines with natural-language instructions describing the evidence to retrieve, rerun policy, and issue updates. Based on learnings, LLM prompt: fields should use natural-language guidance rather than shell-specific constructs.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/nightly-triage.yml around lines 94 - 128, Replace the
shell-specific commands and pipelines in the prompt block with declarative
natural-language instructions for fetching failed-run evidence, applying the
conservative rerun policy, and finding or updating the rolling triage issue.
Preserve the repository/workflow context, classification criteria, attempt
restrictions, recurring-signature reporting, concise format, and prohibition on
file edits or pull requests.

Source: Learnings

claude_args: |
--model claude-opus-4-6
--max-turns 60
--allowedTools "Read,Glob,Grep,Bash,WebFetch,WebSearch,TaskCreate,TaskUpdate,TaskGet"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

curl -fsSL \
  https://raw.githubusercontent.com/anthropics/claude-code-action/v1/docs/configuration.md |
  grep -nE 'Bash\(|allowedTools'

Repository: lightseekorg/smg

Length of output: 871


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

# Show the relevant section of the workflow.
sed -n '120,190p' .github/workflows/nightly-triage.yml | cat -n

# Also show the job permissions block if present.
rg -n "permissions:|actions: write|issues: write|allowedTools|claude" .github/workflows/nightly-triage.yml

Repository: lightseekorg/smg

Length of output: 3483


Restrict Claude’s Bash access to the gh commands this job needs.

Bash is still unrestricted here while the job has actions: write and issues: write; drop WebFetch/WebSearch and allow only the specific gh commands used by the triage prompt.

Suggested restriction
-            --allowedTools "Read,Glob,Grep,Bash,WebFetch,WebSearch,TaskCreate,TaskUpdate,TaskGet"
+            --allowedTools "Read,Glob,Grep,Bash(gh run view:*),Bash(gh run rerun:*),Bash(gh issue list:*),Bash(gh issue create:*),Bash(gh issue comment:*),Bash(gh api:*),TaskCreate,TaskUpdate,TaskGet"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
--allowedTools "Read,Glob,Grep,Bash,WebFetch,WebSearch,TaskCreate,TaskUpdate,TaskGet"
--allowedTools "Read,Glob,Grep,Bash(gh run view:*),Bash(gh run rerun:*),Bash(gh issue list:*),Bash(gh issue create:*),Bash(gh issue comment:*),Bash(gh api:*),TaskCreate,TaskUpdate,TaskGet"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/nightly-triage.yml at line 161, Update the --allowedTools
configuration in the nightly triage workflow to remove WebFetch and WebSearch
and replace unrestricted Bash with allowlisted gh commands matching only those
invoked by the triage prompt. Preserve the other required tools and ensure no
general shell commands remain permitted.

Comment on lines +156 to +159

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Claude retains unrestricted Bash plus WebFetch/WebSearch while holding actions:write + issues:write.

Carried over from the prior review: this job can rerun workflows and write issues, yet --allowedTools still grants full Bash and web access rather than an allowlist of the specific gh run view/rerun/issue list/create/comment commands the prompt actually needs.

Suggested restriction
-            --allowedTools "Read,Glob,Grep,Bash,WebFetch,WebSearch,TaskCreate,TaskUpdate,TaskGet"
+            --allowedTools "Read,Glob,Grep,Bash(gh run view:*),Bash(gh run rerun:*),Bash(gh issue list:*),Bash(gh issue create:*),Bash(gh issue comment:*),Bash(gh api:*),TaskCreate,TaskUpdate,TaskGet"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/nightly-triage.yml around lines 156 - 159, Restrict the
claude_args allowedTools configuration in the nightly triage job by removing
unrestricted Bash, WebFetch, and WebSearch, and grant only the narrowly required
GitHub CLI operations for viewing and rerunning runs plus listing, creating, and
commenting on issues. Preserve the existing model and turn-limit settings.

env:
GH_TOKEN: ${{ github.token }}
64 changes: 64 additions & 0 deletions scripts/check_engine_versions.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/bin/bash
# Compare pinned engine versions against the latest upstream releases.
#
# Emits one JSON object per line: {"engine","current","latest","update"}.
# Pins are read from the same files the upgrade PRs edit, so a bump lands
# here automatically. TokenSpeed is a source build pinned to a commit, so
# its "versions" are SHAs and any divergence from upstream main counts as
# an update.
#
# Requires: curl, jq; GH_TOKEN for the TokenSpeed upstream lookup.

set -euo pipefail
cd "$(dirname "$0")/.."

CURL=(curl -fsS --connect-timeout 10 --max-time 60)

require() { # name value
if [ -z "$2" ]; then
echo "ERROR: could not determine $1 (pin or upstream format changed?)" >&2
exit 1
fi
}
Comment on lines +17 to +22

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reject literal null values from upstream JSON.

jq -r emits null for a missing field, and this non-empty check accepts it. That can create a bogus TokenSpeed update/issue or corrupt a package update record instead of failing.

Proposed fix
 require() { # name value
-    if [ -z "$2" ]; then
+    if [ -z "$2" ] || [ "$2" = "null" ]; then
         echo "ERROR: could not determine $1 (pin or upstream format changed?)" >&2
         exit 1
     fi
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
require() { # name value
if [ -z "$2" ]; then
echo "ERROR: could not determine $1 (pin or upstream format changed?)" >&2
exit 1
fi
}
require() { # name value
if [ -z "$2" ] || [ "$2" = "null" ]; then
echo "ERROR: could not determine $1 (pin or upstream format changed?)" >&2
exit 1
fi
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/check_engine_versions.sh` around lines 17 - 22, Update the require()
validation to reject both empty values and the literal string "null" emitted by
jq -r for missing JSON fields. Preserve the existing error message and exit
behavior so invalid pin or upstream values fail before creating update or issue
records.


# Newest of two versions under PEP 440 pre-release ordering: rcN sorts
# before its final release (GNU sort -V treats '~' as lowest).
vmax() {
printf '%s\n%s\n' "$1" "$2" | sed 's/rc/~rc/' | sort -V | tail -1 | sed 's/~rc/rc/'
}
Comment on lines +24 to +28

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the referenced file and surrounding lines.
git ls-files scripts/check_engine_versions.sh
wc -l scripts/check_engine_versions.sh
cat -n scripts/check_engine_versions.sh | sed -n '1,120p'

# Probe whether the repo mentions the same version selection logic elsewhere.
rg -n "sort -V|rc/~rc|PEP 440|vmax\(\)" scripts . || true

# Run a small read-only Python probe comparing the current vmax logic on representative PEP 440-like inputs.
python3 - <<'PY'
from itertools import product
import subprocess, textwrap, os, tempfile, shlex, sys

def vmax(a, b):
    script = f"printf '%s\\n%s\\n' {shlex.quote(a)} {shlex.quote(b)} | sed 's/rc/~rc/' | sort -V | tail -1 | sed 's/~rc/rc/'"
    out = subprocess.check_output(["bash", "-lc", script], text=True).strip()
    return out

cases = [
    ("1.0a1", "1.0"),
    ("1.0b1", "1.0a1"),
    ("1.0rc1", "1.0b1"),
    ("1.0.dev1", "1.0a1"),
    ("1.0.post1", "1.0"),
    ("1!1.0", "2.0"),
    ("1.0", "1.0+local"),
    ("1.0rc1", "1.0"),
    ("1.0.post1", "1.0rc1"),
]

try:
    from packaging.version import Version
except Exception as e:
    print("packaging unavailable:", e)
    Version = None

for a,b in cases:
    got = vmax(a,b)
    py = None
    if Version is not None:
        py = a if Version(a) >= Version(b) else b
    print(f"{a:12} vs {b:12} -> vmax={got:12} python={py}")
PY

Repository: lightseekorg/smg

Length of output: 5063


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Focus on the exact file if it exists.
if [ -f scripts/check_engine_versions.sh ]; then
  cat -n scripts/check_engine_versions.sh | sed -n '1,120p'
fi

python3 - <<'PY'
try:
    from packaging.version import Version
except Exception as e:
    print("packaging unavailable:", e)
    raise SystemExit(0)

def vmax(a, b):
    import subprocess, shlex
    script = f"printf '%s\\n%s\\n' {shlex.quote(a)} {shlex.quote(b)} | sed 's/rc/~rc/' | sort -V | tail -1 | sed 's/~rc/rc/'"
    return subprocess.check_output(["bash", "-lc", script], text=True).strip()

cases = [
    ("1.0a1", "1.0"),
    ("1.0b1", "1.0a1"),
    ("1.0rc1", "1.0b1"),
    ("1.0.dev1", "1.0a1"),
    ("1.0.post1", "1.0"),
    ("1!1.0", "2.0"),
    ("1.0", "1.0+local"),
    ("1.0rc1", "1.0"),
    ("1.0.post1", "1.0rc1"),
]
for a,b in cases:
    got = vmax(a,b)
    py = a if Version(a) >= Version(b) else b
    print(f"{a:12} vs {b:12} -> vmax={got:12} python={py}")
PY

Repository: lightseekorg/smg

Length of output: 3372


Use a real PEP 440 comparator. vmax() only rewrites rc before sort -V, so it still misorders alpha/dev and epoch versions (1.0a1 vs 1.0, 1.0.dev1 vs 1.0a1, 1!1.0 vs 2.0). TensorRT-LLM uses the same logic, so upstream releases can be classified incorrectly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/check_engine_versions.sh` around lines 24 - 28, The vmax function
must compare versions using full PEP 440 ordering rather than the current
rc-only GNU sort transformation. Replace its comparison logic with a real PEP
440-compatible comparator that correctly orders dev, alpha, rc, final, and epoch
versions while returning the newer input.


emit() { # engine current latest
local update=false
if [ "$1" = "tokenspeed" ]; then
[ "$2" != "$3" ] && update=true
else
[ "$(vmax "$2" "$3")" != "$2" ] && update=true
fi
jq -cn --arg e "$1" --arg c "$2" --arg l "$3" --argjson u "$update" \
'{engine: $e, current: $c, latest: $l, update: $u}'
}

sglang_current=$(sed -n 's/.*"sglang\[all\]==\([^"]*\)".*/\1/p' scripts/ci_install_sglang.sh | head -1)
require "sglang pin" "$sglang_current"
sglang_latest=$("${CURL[@]}" https://pypi.org/pypi/sglang/json | jq -r .info.version)
require "sglang latest" "$sglang_latest"
emit sglang "$sglang_current" "$sglang_latest"

vllm_current=$(sed -n "s/.*default: 'vllm\/vllm-openai:v\([0-9.]*\)'.*/\1/p" .github/workflows/release-vllm-docker.yml | head -1)
require "vllm pin" "$vllm_current"
vllm_latest=$("${CURL[@]}" https://pypi.org/pypi/vllm/json | jq -r .info.version)
require "vllm latest" "$vllm_latest"
emit vllm "$vllm_current" "$vllm_latest"

trtllm_current=$(sed -n 's/^TRTLLM_VERSION="\(.*\)"$/\1/p' scripts/ci_install_trtllm.sh | head -1)
require "tensorrt-llm pin" "$trtllm_current"
trtllm_latest=$("${CURL[@]}" https://pypi.nvidia.com/tensorrt-llm/ \
| grep -o 'tensorrt_llm-[0-9][^-]*' | sed 's/tensorrt_llm-//;s/rc/~rc/' | sort -uV | tail -1 | sed 's/~rc/rc/')
require "tensorrt-llm latest" "$trtllm_latest"
emit tensorrt-llm "$trtllm_current" "$trtllm_latest"

tokenspeed_current=$(sed -n 's/.*TOKENSPEED_REF:-\([0-9a-f]*\)}.*/\1/p' scripts/ci_install_tokenspeed.sh | head -1)
require "tokenspeed pin" "$tokenspeed_current"
tokenspeed_latest=$(gh api repos/lightseekorg/tokenspeed/commits/main --jq .sha)
require "tokenspeed latest" "$tokenspeed_latest"
emit tokenspeed "$tokenspeed_current" "$tokenspeed_latest"
Comment on lines +45 to +64

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Nit: The sed -n extraction patterns for *_current values return empty strings silently if the source file format changes (sed exits 0 with no match, unlike grep). An empty current would make emit report update: true with current: "", causing Claude to file a confusing upgrade issue with no pin info.

Consider guarding each extraction, e.g.:

sglang_current=$(sed -n 's/.*"sglang\[all\]==\([^"]*\)".*/\1/p' scripts/ci_install_sglang.sh | head -1)
if [ -z "$sglang_current" ]; then
  echo "WARNING: failed to extract sglang pin" >&2
else
  sglang_latest=$(curl -fsS https://pypi.org/pypi/sglang/json | jq -r .info.version)
  emit sglang "$sglang_current" "$sglang_latest"
fi

This way a changed file format fails visibly in the Actions log rather than producing a bogus issue.

Separately: the TRT-LLM extraction uses grep -o in a pipeline (line 35), which unlike sed -n exits 1 on no match. Under pipefail that crashes the entire script before tokenspeed is checked — a single engine's scrape failure blocks all engines downstream.

Comment thread
coderabbitai[bot] marked this conversation as resolved.
Loading