Compare commits

...
4 changed files with 31 additions and 24 deletions

No files matched your search

+3 -3
View File
@@ -1,9 +1,9 @@
---
description: Security and secrets. Injection, credential or secret leakage, unsafe shell/child-process use, missing validation at trust boundaries.
alwaysRun: true
# Security is the highest-stakes agent, so it runs on the pro tier — via the
# openai-api alias (metered API key), because the subscription excludes pro models.
model: openai-api/gpt-5.5-pro
# Security is the highest-stakes agent, so it runs on the Opus tier (included in
# the Max/Team subscription the claude-code engine authenticates with).
model: anthropic/claude-opus-5
---
# Security & secrets
+13 -10
View File
@@ -1,8 +1,8 @@
{
// Default model for every agent. Override per-agent via frontmatter in the
// agent's markdown, or at runtime with the REVIEWER_MODEL env var
// (e.g. REVIEWER_MODEL=openai/gpt-5.4-mini).
"model": "openai/gpt-5.5",
// (e.g. REVIEWER_MODEL=anthropic/claude-haiku-4-5).
"model": "anthropic/claude-sonnet-5",
// Agents: every markdown file in agents/ is one reviewer (id = filename).
// Add or remove files to change the roster — no list needed here.
@@ -24,6 +24,10 @@
// cross-cutting pass for multi-file issues. Diffs under maxChangedLines are one
// full-context pass. Defaults shown; raise/lower per your model + PR sizes.
// "chunk": { "maxChangedLines": 1000, "maxFiles": 20, "concurrency": 4 },
// An explicit concurrency always wins over the auth-aware default, which caps
// subscription runs at 3 and makes big reviews crawl. The subscription absorbs
// the parallelism fine, so run the passes wide.
"chunk": { "concurrency": 100 },
// A maintainer comment containing this marker skips the CI review.
"breakGlass": { "marker": "/skip-review" },
@@ -31,16 +35,15 @@
// HTML marker used to find + update the single PR comment. Keep it stable.
"commentTag": "expo-ai-code-reviewer",
// Mixed credentials: the ChatGPT/Codex subscription serves the default models
// (zero marginal cost); the usage-based API key serves only the pro-tier models
// the subscription excludes (security runs on openai-api/gpt-5.5-pro). The oauth
// tokenEnv holds the REFRESH token from an `opencode auth login` ChatGPT sign-in;
// "openai-api" is an alias (upstream openai) synthesized in the OpenCode config.
// ECR_EXPECTED_TOKEN_ENV (repo variable) must equal this comma-separated set.
// Anthropic models always run through the Claude Code CLI (`claude -p`) — the
// engine is inferred per agent from its model, so this entry only supplies the
// credential. In CI the tokenEnv holds a token minted by `claude setup-token`
// (an `sk-ant-oat…` subscription token; an `sk-ant-api…` Console key works too);
// locally an active `claude` login is enough — the entry could even be omitted.
// ECR_EXPECTED_TOKEN_ENV (repo variable) must equal this tokenEnv.
"auth": {
"providers": {
"openai": { "mode": "oauth", "tokenEnv": "CODEX_OAUTH_ACCESS_TOKEN" },
"openai-api": { "mode": "api-key", "tokenEnv": "OPENAI_API_KEY", "upstream": "openai" }
"anthropic": { "tokenEnv": "CLAUDE_CODE_OAUTH_TOKEN" }
}
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
---
# The coordinator only consolidates text (no repo tools), so a fast, cheap model
# fits and keeps this serial step from adding latency. Override as you like.
model: openai/gpt-5.4-mini
model: anthropic/claude-haiku-4-5
---
# Coordinator — consolidation & decision
+14 -10
View File
@@ -52,6 +52,13 @@ jobs:
- name: Install dependencies
run: bun install --frozen-lockfile
# The claude-code auth mode runs reviews through the Claude Code CLI on a
# Max/Team subscription (see .expo-code-review/config.jsonc). Pinned exactly,
# like `opencode-ai` in package.json — an unpinned CLI would silently drift
# on every CI run; bump it deliberately.
- name: Install Claude Code CLI
run: bun install -g @anthropic-ai/[email protected]
# SECURITY: the TRUSTED BASE checkout above includes .expo-code-review/
# config.jsonc, whose auth.tokenEnv names the env var the CLI forwards as the
# model credential. `ecr verify-config` is the canonical guard (ships with the
@@ -61,7 +68,7 @@ jobs:
# source, so the guard runs from that same base source — same engine as `ci`.
- name: Guard config tokenEnv
env:
ECR_EXPECTED_TOKEN_ENV: ${{ vars.ECR_EXPECTED_TOKEN_ENV || 'CODEX_OAUTH_ACCESS_TOKEN,OPENAI_API_KEY' }}
ECR_EXPECTED_TOKEN_ENV: ${{ vars.ECR_EXPECTED_TOKEN_ENV || 'CLAUDE_CODE_OAUTH_TOKEN' }}
run: bun run src/cli.ts verify-config
- name: Run AI review
@@ -76,13 +83,10 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Layer-1 auth lock: `ecr ci` re-checks the honored tokenEnv at runtime,
# catching what the guard step above can't. Keep in sync with the guard.
ECR_EXPECTED_TOKEN_ENV: ${{ vars.ECR_EXPECTED_TOKEN_ENV || 'CODEX_OAUTH_ACCESS_TOKEN,OPENAI_API_KEY' }}
# Mixed credentials (see config.jsonc auth.providers): the ChatGPT/Codex
# subscription ACCESS token serves the default models; the usage-based
# API key (project-scoped, inference-only, budget-capped) serves the
# pro-tier security pass. ECR_EXPECTED_TOKEN_ENV (repo variable) locks
# the comma-separated set of BOTH names.
CODEX_OAUTH_ACCESS_TOKEN: ${{ secrets.CODEX_OAUTH_ACCESS_TOKEN }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
# Optional: override the model for every agent (uses your OpenCode login).
ECR_EXPECTED_TOKEN_ENV: ${{ vars.ECR_EXPECTED_TOKEN_ENV || 'CLAUDE_CODE_OAUTH_TOKEN' }}
# Claude Max/Team subscription token minted by `claude setup-token`
# (~1 year lifetime). The claude-code engine forwards it to the Claude
# Code CLI as the only credential (any ANTHROPIC_* key is stripped).
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# Optional: override the model for every agent.
REVIEWER_MODEL: ${{ vars.REVIEWER_MODEL }}