diff --git a/.claude/skills/review-issue/SKILL.md b/.claude/skills/review-issue/SKILL.md index dc3ee110a..384aa137c 100644 --- a/.claude/skills/review-issue/SKILL.md +++ b/.claude/skills/review-issue/SKILL.md @@ -31,7 +31,7 @@ merge, not a courtesy. - Maintainer-authored PRs are exempt. A `trusted-contributor` label exempts a contributor up front. Reopening the PR or removing the `missing-issue-link` label applies a sticky `bypass-issue-check`. -- Sibling bots have usually already run on the issue: `martian-triage-issue` (investigates + +- Sibling bots have usually already run on the issue: `marvin-triage-issue` (investigates + recommends), `marvin-dedupe-issues` / `auto-close-duplicates` (dupes), `auto-close-needs-mre` (missing MRE). Read their comments before re-deriving anything. diff --git a/.github/actions/run-claude/action.yml b/.github/actions/run-claude/action.yml index fff6788a6..66f4bb286 100644 --- a/.github/actions/run-claude/action.yml +++ b/.github/actions/run-claude/action.yml @@ -40,7 +40,7 @@ inputs: model: description: "Model to use for Claude" required: false - default: "claude-opus-4-6" + default: "claude-opus-4-8" allowed-bots: description: "Allowed bot usernames, or '*' for all bots" diff --git a/.github/actions/run-pytest/action.yml b/.github/actions/run-pytest/action.yml index b7e5509e5..e7ee2b8ec 100644 --- a/.github/actions/run-pytest/action.yml +++ b/.github/actions/run-pytest/action.yml @@ -19,7 +19,7 @@ runs: MAX_PROCS="2" EXTRA_FLAGS="" elif [ "${{ inputs.test-type }}" == "client_process" ]; then - MARKER="client_process" + MARKER="client_process or subprocess_heavy" TIMEOUT="5" MAX_PROCS="0" EXTRA_FLAGS="-x" @@ -29,14 +29,20 @@ runs: MAX_PROCS="0" EXTRA_FLAGS="-x" else - MARKER="not integration and not client_process and not conformance" + MARKER="not integration and not client_process and not subprocess_heavy and not conformance" TIMEOUT="5" MAX_PROCS="4" EXTRA_FLAGS="" fi + # Windows previously ran serially: parallel workers crashed intermittently + # when many tests spawned stdio subprocesses (#2715, reverted in #2726). + # Most of those tests now run in-memory, but tests that spawn a fresh + # interpreter importing all of FastMCP still crash xdist workers on the + # 2-core Windows runners. They carry the subprocess_heavy marker and run + # in the serial client_process step instead. PARALLEL_FLAGS="" - if [ "$MAX_PROCS" != "0" ] && [ "${{ runner.os }}" != "Windows" ]; then + if [ "$MAX_PROCS" != "0" ]; then PARALLEL_FLAGS="--numprocesses auto --maxprocesses $MAX_PROCS --dist worksteal" fi diff --git a/.github/scripts/triage-label.sh b/.github/scripts/triage-label.sh new file mode 100755 index 000000000..c6bdda85c --- /dev/null +++ b/.github/scripts/triage-label.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash +# Locked-down label helper for the Marvin triage workflow. +# +# Marvin runs on untrusted issue/PR bodies from non-write users, so it must +# NOT be handed raw `gh api` (that would expose every endpoint the app token +# can reach). This helper is the ONLY GitHub write it is allowed to perform: +# it adds or removes repository labels on the one issue/PR being triaged. +# +# The target repo and number come from the environment set by the workflow — +# never from the model — and the operation is fixed to the additive labels +# endpoint (POST/DELETE /repos/{repo}/issues/{n}/labels), which works for both +# issues and PRs and cannot clobber labels applied by other workflows. +set -euo pipefail + +repo="${TRIAGE_REPO:?TRIAGE_REPO not set}" +number="${TRIAGE_NUMBER:?TRIAGE_NUMBER not set}" + +if [[ ! "$number" =~ ^[0-9]+$ ]]; then + echo "TRIAGE_NUMBER must be numeric, got: $number" >&2 + exit 1 +fi + +op="${1:-}" +shift || true +case "$op" in + add) method=POST ;; + remove) method=DELETE ;; + *) + echo "usage: triage-label.sh