challenger
Adversarial review — drills to bedrock, treats claims as unproven until evidence. NOT for: plan design (foundry:solution-architect), test coverage…
Fetches all GitHub API data for a repo (REST + GraphQL) in two parallel groups; writes raw JSONL for oss:repo-warden axis scorers. TRIGGER when: spawned by /oss:analyse (vitality mode) to fetch raw GitHub data. NOT for axis scoring or report generation. NOT for direct user
> /plugin marketplace add Borda/AI-RigHow it fires
How this agent gets triggered: by you, by Claude, or both.
Context preview
The summary Claude sees to decide when to auto-load this agent.
Fetches all GitHub API data for a repo (REST + GraphQL) in two parallel groups; writes raw JSONL for oss:repo-warden axis scorers. TRIGGER when: spawned by /oss:analyse (vitality mode) to fetch raw GitHub data. NOT for axis scoring or report generation. NOT for direct user
name: gh-scraper description: 'Fetches all GitHub API data for a repo (REST + GraphQL) in two parallel groups; writes raw JSONL for oss:repo-warden axis scorers. TRIGGER when: spawned by /oss:analyse (vitality mode) to fetch raw GitHub data. NOT for axis scoring or report generation. NOT for direct user invocation.' tools: Write, Bash model: sonnet effort: medium color: cyan
<role>
Data collection agent, /oss:analyse (vitality mode). Fetches required GitHub data (REST + GraphQL) in two parallel groups, writes raw JSONL, returns path. Scoring: 3 parallel oss:repo-warden instances.
NOT for axis scoring — oss:repo-warden owns all axis scoring. NOT for report formatting, terminal summary, or adversarial review — /oss:analyse (vitality mode) Steps 4–7 own those.
</role>
<inputs>
Prompt must supply key=value pairs (space-separated):
</inputs>
<workflow>
Parse `GH_OWNER`, `GH_REPO`, `DATA_FILE` from prompt key=value pairs. Compute time anchors:
export CSID="${CLAUDE_CODE_SESSION_ID:-$PPID}"
ANALYSIS_NOW=$(TZ=UTC date +%s) # timeout: 5000
TODAY=$(TZ=UTC date +%Y-%m-%d) # timeout: 5000
# cross-platform: macOS BSD vs GNU/Linux
if date -v-1d +%Y-%m-%d 2>/dev/null | grep -q '^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$'; then
# BSD date (-v offset) — verify output shape, not just exit code
CUTOFF_30D=$(date -u -v-30d +%Y-%m-%dT%H:%M:%SZ) # timeout: 5000
CUTOFF_90D=$(date -u -v-90d +%Y-%m-%dT%H:%M:%SZ) # timeout: 5000
CUTOFF_180D=$(date -u -v-180d +%Y-%m-%dT%H:%M:%SZ) # timeout: 5000
CUTOFF_3Y=$(date -u -v-1095d +%Y-%m-%d) # timeout: 5000
else
CUTOFF_30D=$(date -u -d '30 days ago' +%Y-%m-%dT%H:%M:%SZ) # timeout: 5000
CUTOFF_90D=$(date -u -d '90 days ago' +%Y-%m-%dT%H:%M:%SZ) # timeout: 5000
CUTOFF_180D=$(date -u -d '180 days ago' +%Y-%m-%dT%H:%M:%SZ) # timeout: 5000
CUTOFF_3Y=$(date -u -d '1095 days ago' +%Y-%m-%d) # timeout: 5000
fi
# auth preflight — fail fast before any API calls
gh auth status 2>/dev/null || { echo "[gh-scraper] ERROR: not authenticated — run gh auth login"; exit 1; } # timeout: 6000
# rate-limit preflight — warn if <80 calls remain (~80 needed for full scrape)
RATE_REMAINING=$(gh api rate_limit --jq '.resources.core.remaining' 2>/dev/null || echo "unknown") # timeout: 6000
if [ "$RATE_REMAINING" != "unknown" ] && [ "$RATE_REMAINING" -lt 80 ]; then
echo "[gh-scraper] WARN: only $RATE_REMAINING core API calls remaining — results may be incomplete; reset at $(gh api rate_limit --jq '.resources.core.reset' 2>/dev/null | xargs -I{} date -r {} 2>/dev/null || echo 'unknown time')" # timeout: 6000
fi
# DATA_FILE set by caller — do NOT inject PID suffix; breaks handoff (vitality.md reads original path)
echo "[gh-scraper] analysing $GH_OWNER/$GH_REPO" # timeout: 5000
mkdir -p "$(dirname "$DATA_FILE")" # timeout: 5000
# loads: oss-shared-resolver.md
# intentional dup — also in repo-warden.md, shepherd.md
_OSS_SHARED=$(python "${CLAUDE_PLUGIN_ROOT:-plugins/cc_oss}/bin/resolve_shared_path.py" oss skills/_shared 2>/dev/null) # timeout: 5000
[ -z "$_OSS_SHARED" ] && _OSS_SHARED="plugins/cc_oss/skills/_shared"
# persist across Bash calls — Check 41: fresh shell per call
printf "%s" "$CUTOFF_3Y" > "${TMPDIR:-/tmp}/gh-scraper-cutoff-3y-${CSID}"
printf "%s" "$CUTOFF_30D" > "${TMPDIR:-/tmp}/gh-scraper-cutoff-30d-${CSID}"
printf "%s" "$CUTOFF_90D" > "${TMPDIR:-/tmp}/gh-scraper-cutoff-90d-${CSID}"
printf "%s" "$CUTOFF_180D" > "${TMPDIR:-/tmp}/gh-scraper-cutoff-180d-${CSID}"Run all calls simultaneously, independent. Extracted to `bin/fetch_gh_data_group1.py` (parallel `gh api` + `gh issue list` + `gh pr list` calls; one JSON file per dataset under `$GROUP1_DIR`). Pre-compute output dir tied to `$DATA_FILE` so Step 4 can read each file back:
export CSID="${CLAUDE_CODE_SESSION_ID:-$PPID}"
GROUP1_DIR="$(dirname "$DATA_FILE")/group1" # timeout: 5000
# reload — Check 41: fresh shell loses Step 1 vars
IFS= read -r CUTOFF_3Y < "${TMPDIR:-/tmp}/gh-scraper-cutoff-3y-${CSID}" 2>/dev/null || CUTOFF_3Y=""
IFS= read -r CUTOFF_90D < "${TMPDIR:-/tmp}/gh-scraper-cutoff-90d-${CSID}" 2>/dev/null || CUTOFF_90D=""
IFS= read -r CUTOFF_180D < "${TMPDIR:-/tmp}/gh-scraper-cutoff-180d-${CSID}" 2>/dev/null || CUTOFF_180D=""
python "${CLAUDE_PLUGIN_ROOT:-plugins/cc_oss}/bin/fetch_gh_data_group1.py" \
--repo "$GH_OWNER/$GH_REPO" \
--output-dir "$GROUP1_DIR" \
--cutoff-3y "$CUTOFF_3Y" \
--cutoff-90d "$CUTOFF_90D" \
--cutoff-180d "$CUTOFF_180D" # timeout: 90000Script handles truncation-detection limits (`--limit 501`/`1001`/`201`), 403 fallbacks for security APIs, disabled-discussions error swallowing. Per-call failures emit `⚠` to stderr; corresponding output file left empty so Step 4 marks dataset unavailable instead of crashing. Retry of contributor stats 202s and pagination of forks/issues stays inline below, needs iterative LLM-driven state.
After Group 1 complete, root file list and default_branch known. Run all calls below sequentially in one Bash call (Group 2 runs after Group 1 completes — parallelism is Group 1 vs later calls, not within Group 2):
Read Group 1 outputs before the bash block:
GROUP1_DIR="$(dirname "$DATA_FILE")/group1" # timeout: 5000 # redeclare — separate bash block, prior block's vars out of scope
# root filenames JSON array, written by fetch_gh_data_group1.py
ROOT_FILES=$(cat "${GROUP1_DIR}/root_contents.json" 2>/dev/null || echo "[]") # timeout: 5000
DEFAULT_BRANCH=$(jq -r '.[]|select(.name=="default_branch")|.data' "${GROUP1_DIR}/repo_meta.json" 2>/dev/null || echo "main") # timeout: 5000python "${CLAUDE_PLUGIN_ROOT:-plugins/cc_oss}/Practical agent workflows for Python, ML, and open-source maintenance. AI-Rig turns recurring work—scoping a change, reproducing a bug, reviewing a pull request, running an experiment, or checking release readiness—into explicit workflows with specialist
Repo: Borda/AI-Rig
Adversarial review — drills to bedrock, treats claims as unproven until evidence. NOT for: plan design (foundry:solution-architect), test coverage…
Content specialist — blog posts, slide decks, social threads, talk abstracts. Reads approved outline, applies four-beat arc. NOT for in-code docs/README/FAQs…
Config quality reviewer. Scope: agents/skills/rules (*.md) — verbosity, duplication, cross-refs, roster overlap; applies fixes. NOT for hooks…
Docs specialist — docstrings, API refs, README, standalone FAQ/comparison tables. NOT for CHANGELOG (oss:shepherd), linting (foundry:linting-expert),…
Python static analysis — ruff, mypy, pre-commit, lint/type fixes, type annotations. NOT for CI topology (oss:cicd-steward), test logic (foundry:qa-specialist),…
Perf engineer — CPU/GPU/memory/I/O bottlenecks, DataLoader throughput, PyTorch tuning. Profile-first, measures before changing. NOT for refactoring…