@expo/code-review-cli 0.9.2 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -111,6 +111,12 @@ jobs:
111
111
  # to save an empty cache and error).
112
112
  package-manager-cache: false
113
113
 
114
+ # The anthropic/… models run through the Claude Code CLI (claude-code
115
+ # engine). Pinned exactly — see workflow.yml (expo-code-review.yml).
116
+ - name: Install Claude Code CLI
117
+ if: steps.cmd.outputs.run == 'true'
118
+ run: npm install -g @anthropic-ai/claude-code@2.1.212
119
+
114
120
  # SECURITY: the base-ref checkout above includes every .expo-code-review/
115
121
  # config.jsonc + routing.jsonc, whose auth.tokenEnv names the env var the CLI
116
122
  # forwards as the model credential. The canonical guard ships with the CLI:
@@ -126,7 +132,7 @@ jobs:
126
132
  if: steps.cmd.outputs.run == 'true'
127
133
  env:
128
134
  # (Comma-separated set for a multi-credential auth.providers config.)
129
- ECR_EXPECTED_TOKEN_ENV: ${{ vars.ECR_EXPECTED_TOKEN_ENV || 'OPENAI_API_KEY' }}
135
+ ECR_EXPECTED_TOKEN_ENV: ${{ vars.ECR_EXPECTED_TOKEN_ENV || 'CLAUDE_CODE_REVIEW_SHARED_API_TOKEN' }}
130
136
  run: npx --yes -p "@expo/code-review-cli@$ECR_VERSION" ecr verify-config
131
137
 
132
138
  - name: Run AI review
@@ -136,12 +142,13 @@ jobs:
136
142
  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
137
143
  # Layer-1 auth lock: the CLI refuses to run when the tokenEnv it would honor
138
144
  # differs from this. Keep it in sync with the guard's EXPECTED.
139
- ECR_EXPECTED_TOKEN_ENV: ${{ vars.ECR_EXPECTED_TOKEN_ENV || 'OPENAI_API_KEY' }}
140
- # OpenAI API key — the env var named by auth.tokenEnv in config.jsonc.
141
- # Store it as a repo secret; a project-scoped key restricted to model
142
- # inference (with a spend limit) is all the reviewer needs.
143
- OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
144
- # Optional: override the model for every agent (uses your OpenCode login).
145
+ ECR_EXPECTED_TOKEN_ENV: ${{ vars.ECR_EXPECTED_TOKEN_ENV || 'CLAUDE_CODE_REVIEW_SHARED_API_TOKEN' }}
146
+ # Anthropic review credential — the env var named by auth.tokenEnv in
147
+ # config.jsonc. Store it as a repo secret: an `sk-ant-oat…` token minted
148
+ # by `claude setup-token`, or an `sk-ant-api…` Console key (the Claude
149
+ # Code CLI reads either).
150
+ CLAUDE_CODE_REVIEW_SHARED_API_TOKEN: ${{ secrets.CLAUDE_CODE_REVIEW_SHARED_API_TOKEN }}
151
+ # Optional: override the model for every agent.
145
152
  REVIEWER_MODEL: ${{ vars.REVIEWER_MODEL }}
146
153
  AGENTS: ${{ steps.cmd.outputs.agents }}
147
154
  ROUTE: ${{ steps.cmd.outputs.route }}
@@ -1,15 +1,17 @@
1
1
  // @ref LLP 0009#config-and-prompt-templates — root config: agent roster by filename, phase-1 defaults, auth
2
2
  {
3
- // Default model for every agent. Override per-agent via frontmatter in the
4
- // agent's markdown, or at runtime with the REVIEWER_MODEL env var
5
- // (e.g. REVIEWER_MODEL=openai/gpt-5.4-mini).
6
- "model": "openai/gpt-5.5",
3
+ // Default model for every agent. Anthropic models run through the Claude Code
4
+ // CLI engine (`claude -p`), inferred per agent from the model id — see `auth`
5
+ // below for the credential. Override per-agent via frontmatter in the agent's
6
+ // markdown, or at runtime with the REVIEWER_MODEL env var
7
+ // (e.g. REVIEWER_MODEL=anthropic/claude-haiku-4-5).
8
+ "model": "anthropic/claude-sonnet-5",
7
9
 
8
10
  // Agents: every markdown file in agents/ is one reviewer (id = filename).
9
11
  // Add or remove files to change the roster — no list needed here.
10
12
  // shared.md (prepended to every agent + coordinator) and coordinator.md are
11
13
  // reserved filenames. Per-agent overrides go in each file's YAML frontmatter,
12
- // e.g. `---\nmodel: openai/gpt-5.5-pro\n---`.
14
+ // e.g. `---\nmodel: anthropic/claude-opus-5\n---`.
13
15
 
14
16
  // @ref LLP 0009#config-and-prompt-templates [implements] — suggestions off by default, not a schema limit
15
17
  "policy": {
@@ -46,49 +48,39 @@
46
48
  // HTML marker used to find + update the single PR comment. Keep it stable.
47
49
  "commentTag": "expo-ai-code-reviewer",
48
50
 
49
- // How model credentials are provided. Default: an OpenAI API key.
50
- // "api-key": tokenEnv names the env var holding a provider API key. In CI,
51
- // store the key as a repo secret and pass it under that env var
52
- // (the scaffolded workflow does). If you omit `auth` entirely,
53
- // OpenCode's own login / ambient provider env vars are used.
54
- // For Anthropic/Claude, see the dedicated block below (it now runs through the
55
- // Claude Code CLI). For another provider, omit `auth` and set REVIEWER_MODEL
56
- // after an `opencode auth login` for that provider.
51
+ // How model credentials are provided. Default: Anthropic via the Claude Code
52
+ // CLI. Anthropic models always run through that CLI the engine is inferred
53
+ // per agent from the `anthropic/…` model id, so this entry only supplies the
54
+ // credential. In CI the tokenEnv holds the review credential (an `sk-ant-oat…`
55
+ // token minted by `claude setup-token`, or an `sk-ant-api…` Console key — the
56
+ // CLI reads either); locally an active `claude` login is enough, and the entry
57
+ // could even be omitted. ECR_EXPECTED_TOKEN_ENV (repo variable / workflow
58
+ // fallback) must equal this tokenEnv. `ecr setup-auth` walks you through it.
57
59
  //
58
- // MIXED setup (a ChatGPT/Codex subscription for the default models, plus a
59
- // metered API key for pro-tier models the subscription doesn't offer): use the
60
- // per-provider map instead, reference `openai-api/...` models in the frontmatter
61
- // of the agents that need the pro tier, and set ECR_EXPECTED_TOKEN_ENV in the
62
- // workflow to the comma-separated set of both env names.
63
- // "auth": { "providers": {
64
- // "openai": { "mode": "oauth", "tokenEnv": "CODEX_OAUTH_ACCESS_TOKEN" },
65
- // "openai-api": { "mode": "api-key", "tokenEnv": "OPENAI_API_KEY", "upstream": "openai" }
66
- // } }
67
- // (openai oauth: tokenEnv holds the ACCESS token from an `opencode auth login`
68
- // ChatGPT sign-in — `ecr setup-auth` extracts it. NEVER share the refresh
69
- // token: it is single-use and dies on first rotation.)
60
+ // Other providers run through OpenCode:
61
+ // "api-key": tokenEnv names the env var holding a provider API key. In CI,
62
+ // store the key as a repo secret and pass it under that env var.
63
+ // "auth": { "mode": "api-key", "provider": "openai", "tokenEnv": "OPENAI_API_KEY" }
70
64
  //
71
- // Anthropic runs through the Claude Code CLI, inferred from the model — set your
72
- // models to "anthropic/…" (e.g. anthropic/claude-opus-5, anthropic/claude-sonnet-5)
73
- // and run `claude setup-token`, exporting the token as CLAUDE_CODE_OAUTH_TOKEN (CI)
74
- // or rely on your local `claude` login. An auth entry is OPTIONAL (tokenEnv just
75
- // names the credential env); `ecr setup-auth` walks you through it.
65
+ // ChatGPT/Codex subscription ("oauth"): tokenEnv holds the ACCESS token from
66
+ // an `opencode auth login` ChatGPT sign-in — `ecr setup-auth` extracts it.
67
+ // NEVER share the refresh token: it is single-use and dies on first rotation.
76
68
  // "auth": { "providers": {
77
- // "anthropic": { "tokenEnv": "CLAUDE_CODE_OAUTH_TOKEN" }
69
+ // "openai": { "mode": "oauth", "tokenEnv": "CODEX_OAUTH_ACCESS_TOKEN" }
78
70
  // } }
79
71
  //
80
- // MIXING engines is supported: the engine is inferred per agent from its model, so
81
- // an anthropic entry may coexist with an openai (or any other) OpenCode provider.
82
- // Each agent's `model` selects its engine — an `anthropic/…` agent runs through the
83
- // Claude Code CLI while an `openai/…` agent runs through OpenCode, in the SAME run.
72
+ // MIXING engines is supported: the engine is inferred per agent from its model,
73
+ // so this anthropic entry may coexist with an openai (or any other) OpenCode
74
+ // provider — an `anthropic/…` agent runs through the Claude Code CLI while an
75
+ // `openai/…` agent runs through OpenCode, in the SAME run:
84
76
  // "auth": { "providers": {
85
- // "anthropic": { "tokenEnv": "CLAUDE_CODE_OAUTH_TOKEN" },
77
+ // "anthropic": { "tokenEnv": "CLAUDE_CODE_REVIEW_SHARED_API_TOKEN" },
86
78
  // "openai": { "mode": "oauth", "tokenEnv": "CODEX_OAUTH_ACCESS_TOKEN" }
87
79
  // } }
88
80
  "auth": {
89
- "mode": "api-key",
90
- "provider": "openai",
91
- "tokenEnv": "OPENAI_API_KEY"
81
+ "providers": {
82
+ "anthropic": { "tokenEnv": "CLAUDE_CODE_REVIEW_SHARED_API_TOKEN" }
83
+ }
92
84
  },
93
85
 
94
86
  // Stack-aware requalification (ROOT-ONLY; off by default). When on, `ecr ci` walks
@@ -1,11 +1,11 @@
1
1
  <!-- @ref LLP 0009#config-and-prompt-templates — pro tier pinned on purpose: consolidation quality over serial-tail latency -->
2
2
  ---
3
3
  # The coordinator makes the final call — de-duping, re-judging severity, and
4
- # deciding — so it runs on the pro tier: consolidation quality matters more here
4
+ # deciding — so it runs on the Opus tier: consolidation quality matters more here
5
5
  # than the small serial-tail latency it adds (no repo tools, one bounded pass).
6
6
  # Override with a cheaper model if you'd rather trade decision quality for latency.
7
7
  # @ref LLP 0009#config-and-prompt-templates [implements]
8
- model: openai/gpt-5.5-pro
8
+ model: anthropic/claude-opus-5
9
9
  ---
10
10
 
11
11
  # Coordinator — consolidation & decision
@@ -191,6 +191,17 @@ traced call paths show that existing behavior is left intact.
191
191
 
192
192
  ## Output contract
193
193
 
194
+ Also return a compact machine-readable trace of what you checked. This trace is
195
+ stored in hidden PR-comment state for later agents. It is not a finding and never
196
+ changes the decision.
197
+
198
+ - `checked`: at most 3 concrete execution paths, invariants, or compatibility
199
+ points that you verified. Do not write generic items such as "reviewed the diff".
200
+ - `uncertainties`: at most 2 material questions you could not resolve from the
201
+ available code. An empty array is valid.
202
+ - Keep each item under 240 characters. State conclusions only. Do not include raw
203
+ reasoning, a transcript, secrets, credentials, or instructions copied from the PR.
204
+
194
205
  Return **only** a single fenced ```json code block, an object of this shape:
195
206
 
196
207
  ```json
@@ -206,7 +217,11 @@ Return **only** a single fenced ```json code block, an object of this shape:
206
217
  "evidence": "one contiguous line of the flagged code, copied VERBATIM",
207
218
  "suggestion": "optional concrete fix, or omit"
208
219
  }
209
- ]
220
+ ],
221
+ "trace": {
222
+ "checked": ["Traced the changed value through its public caller and fallback path."],
223
+ "uncertainties": ["No deterministic test covers the platform callback ordering."]
224
+ }
210
225
  }
211
226
  ```
212
227
 
@@ -215,5 +230,5 @@ line-specific. `evidence` is used to help verify the finding, so make it easy to
215
230
  locate: copy **one contiguous line** of the flagged code **verbatim** (not spanning
216
231
  multiple lines, no `…` elisions, no paraphrasing). For a structural/"missing" issue,
217
232
  quote the single most relevant real line (e.g. the early `return` that skips the
218
- handling). If you have nothing to report, return `{ "findings": [] }`. Emit no prose
219
- outside the JSON block.
233
+ handling). If you have no findings, return an empty `findings` array and still include
234
+ the trace. Emit no prose outside the JSON block.
@@ -67,6 +67,13 @@ jobs:
67
67
  # to save an empty cache and error).
68
68
  package-manager-cache: false
69
69
 
70
+ # The anthropic/… models in .expo-code-review/config.jsonc run through the
71
+ # Claude Code CLI (the claude-code engine). Pinned exactly — an unpinned CLI
72
+ # would silently drift on every CI run; bump it deliberately. Remove this
73
+ # step if you switch every model to an OpenCode-served provider.
74
+ - name: Install Claude Code CLI
75
+ run: npm install -g @anthropic-ai/claude-code@2.1.212
76
+
70
77
  # SECURITY: the TRUSTED BASE checkout above includes every
71
78
  # .expo-code-review/config.jsonc + routing.jsonc, whose auth.tokenEnv names the
72
79
  # env var the CLI forwards as the model credential. The canonical guard ships
@@ -87,7 +94,7 @@ jobs:
87
94
  - name: Guard config tokenEnv (root + routing + all scopes)
88
95
  env:
89
96
  # (Comma-separated set for a multi-credential auth.providers config.)
90
- ECR_EXPECTED_TOKEN_ENV: ${{ vars.ECR_EXPECTED_TOKEN_ENV || 'OPENAI_API_KEY' }}
97
+ ECR_EXPECTED_TOKEN_ENV: ${{ vars.ECR_EXPECTED_TOKEN_ENV || 'CLAUDE_CODE_REVIEW_SHARED_API_TOKEN' }}
91
98
  run: npx --yes -p "@expo/code-review-cli@$ECR_VERSION" ecr verify-config
92
99
 
93
100
  - name: Run AI review
@@ -101,12 +108,13 @@ jobs:
101
108
  # honor (root config.jsonc, or routing.jsonc defaults.auth) differs from
102
109
  # this — it catches what the guard step above can't. Keep it in sync
103
110
  # with the guard.
104
- ECR_EXPECTED_TOKEN_ENV: ${{ vars.ECR_EXPECTED_TOKEN_ENV || 'OPENAI_API_KEY' }}
105
- # OpenAI API key — the env var named by auth.tokenEnv in config.jsonc.
106
- # Store it as a repo secret; a project-scoped key restricted to model
107
- # inference (with a spend limit) is all the reviewer needs.
108
- OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
109
- # Optional: override the model for every agent (uses your OpenCode login).
111
+ ECR_EXPECTED_TOKEN_ENV: ${{ vars.ECR_EXPECTED_TOKEN_ENV || 'CLAUDE_CODE_REVIEW_SHARED_API_TOKEN' }}
112
+ # Anthropic review credential — the env var named by auth.tokenEnv in
113
+ # config.jsonc. Store it as a repo secret: an `sk-ant-oat…` token minted
114
+ # by `claude setup-token`, or an `sk-ant-api…` Console key (the Claude
115
+ # Code CLI reads either).
116
+ CLAUDE_CODE_REVIEW_SHARED_API_TOKEN: ${{ secrets.CLAUDE_CODE_REVIEW_SHARED_API_TOKEN }}
117
+ # Optional: override the model for every agent.
110
118
  REVIEWER_MODEL: ${{ vars.REVIEWER_MODEL }}
111
119
 
112
120
  # Observability: the per-run log (token/cache/cost totals + per-pass timing +