@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.
- package/README.md +83 -60
- package/build/commands/ci.js +137 -26
- package/build/commands/init.js +18 -13
- package/build/core/adjudicate.js +1 -0
- package/build/core/auth.js +4 -1
- package/build/core/claude-code.js +315 -43
- package/build/core/coordinator.js +2 -1
- package/build/core/exec.js +10 -0
- package/build/core/opencode.js +8 -9
- package/build/core/render.js +10 -3
- package/build/core/review-cache.js +108 -0
- package/build/core/review.js +81 -13
- package/build/core/router.js +2 -1
- package/build/core/schema.js +78 -23
- package/build/core/stack-confirm.js +2 -1
- package/build/core/verify.js +1 -0
- package/build/reporters/github.js +3 -3
- package/package.json +1 -1
- package/templates/agents/security.md +3 -3
- package/templates/atlantis.yml +11 -5
- package/templates/command.yml +14 -7
- package/templates/config.jsonc +31 -39
- package/templates/coordinator.md +2 -2
- package/templates/shared.md +18 -3
- package/templates/workflow.yml +15 -7
package/templates/command.yml
CHANGED
|
@@ -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 || '
|
|
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 || '
|
|
140
|
-
#
|
|
141
|
-
# Store it as a repo secret
|
|
142
|
-
#
|
|
143
|
-
|
|
144
|
-
|
|
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 }}
|
package/templates/config.jsonc
CHANGED
|
@@ -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.
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
|
|
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:
|
|
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:
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
//
|
|
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
|
-
//
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
//
|
|
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
|
-
//
|
|
72
|
-
//
|
|
73
|
-
//
|
|
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
|
-
// "
|
|
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,
|
|
81
|
-
//
|
|
82
|
-
//
|
|
83
|
-
//
|
|
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": "
|
|
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
|
-
"
|
|
90
|
-
|
|
91
|
-
|
|
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
|
package/templates/coordinator.md
CHANGED
|
@@ -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
|
|
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:
|
|
8
|
+
model: anthropic/claude-opus-5
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
# Coordinator — consolidation & decision
|
package/templates/shared.md
CHANGED
|
@@ -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
|
|
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.
|
package/templates/workflow.yml
CHANGED
|
@@ -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 || '
|
|
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 || '
|
|
105
|
-
#
|
|
106
|
-
# Store it as a repo secret
|
|
107
|
-
#
|
|
108
|
-
|
|
109
|
-
|
|
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 +
|