@expo/code-review-cli 0.11.1 → 0.12.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/code-review-cli",
3
- "version": "0.11.1",
3
+ "version": "0.12.0",
4
4
  "description": "Generic, config-driven AI code reviewer engine. Repos supply their agents via .expo-code-review/.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -11,11 +11,13 @@
11
11
  "bin": {
12
12
  "ecr": "build/cli.js",
13
13
  "expo-code-review": "build/cli.js",
14
- "code-review-cli": "build/cli.js"
14
+ "code-review-cli": "build/cli.js",
15
+ "review-research-mcp": "build/research-mcp/cli.js"
15
16
  },
16
17
  "files": [
17
18
  "build",
18
- "templates"
19
+ "templates",
20
+ "research/sources.json"
19
21
  ],
20
22
  "engines": {
21
23
  "node": ">=20"
@@ -23,6 +25,9 @@
23
25
  "publishConfig": {
24
26
  "access": "public"
25
27
  },
28
+ "overrides": {
29
+ "@hono/node-server": "2.0.10"
30
+ },
26
31
  "scripts": {
27
32
  "build": "tsc -p tsconfig.build.json",
28
33
  "clean": "rimraf build",
@@ -33,11 +38,17 @@
33
38
  "llp:check": "./ref-check",
34
39
  "dev": "bun run src/cli.ts",
35
40
  "test:unit": "bun test",
41
+ "research:update": "bun run src/research-mcp/cli.ts update",
42
+ "research:evaluate:corpora": "bun run build && node scripts/research/evaluate-corpora.mjs",
43
+ "research:evaluate:expo": "bun run build && node scripts/research/evaluate-expo-prs.mjs",
36
44
  "release": "bash scripts/release.sh",
37
45
  "prepublishOnly": "rimraf build && tsc -p tsconfig.build.json"
38
46
  },
39
47
  "dependencies": {
48
+ "@modelcontextprotocol/sdk": "1.30.0",
40
49
  "@opencode-ai/sdk": "1.18.4",
50
+ "cheerio": "1.1.2",
51
+ "minisearch": "7.2.0",
41
52
  "opencode-ai": "1.18.4",
42
53
  "zod": "^4.4.3"
43
54
  },
@@ -0,0 +1,283 @@
1
+ {
2
+ "output": "data/docs-index.json",
3
+ "crawl": {
4
+ "maxPagesPerProvider": 250,
5
+ "maxDepth": 4,
6
+ "delayMs": 200,
7
+ "timeoutMs": 15000,
8
+ "maxResponseBytes": 5000000
9
+ },
10
+ "sources": [
11
+ {
12
+ "provider": "apple",
13
+ "sourceKind": "official-api",
14
+ "maxPages": 170,
15
+ "seedUrls": [
16
+ "https://developer.apple.com/documentation/swift",
17
+ "https://developer.apple.com/documentation/swiftui",
18
+ "https://developer.apple.com/documentation/uikit",
19
+ "https://developer.apple.com/documentation/foundation",
20
+ "https://developer.apple.com/documentation/avfoundation",
21
+ "https://developer.apple.com/documentation/coregraphics",
22
+ "https://developer.apple.com/documentation/photos",
23
+ "https://developer.apple.com/documentation/usernotifications",
24
+ "https://developer.apple.com/documentation/webkit",
25
+ "https://developer.apple.com/documentation/storekit",
26
+ "https://developer.apple.com/documentation/activitykit",
27
+ "https://developer.apple.com/documentation/widgetkit",
28
+ "https://developer.apple.com/documentation/appintents",
29
+ "https://developer.apple.com/documentation/network",
30
+ "https://developer.apple.com/documentation/photos/phasset",
31
+ "https://developer.apple.com/documentation/photos/phasset/location",
32
+ "https://developer.apple.com/documentation/network/nwpathmonitor",
33
+ "https://developer.apple.com/documentation/network/nwpathmonitor/pathupdatehandler",
34
+ "https://developer.apple.com/documentation/appintents/liveactivityintent",
35
+ "https://developer.apple.com/documentation/activitykit/activity",
36
+ "https://developer.apple.com/documentation/activitykit/activity/id",
37
+ "https://developer.apple.com/documentation/activitykit/activity/activities",
38
+ "https://developer.apple.com/documentation/activitykit/activity/activitystate",
39
+ "https://developer.apple.com/documentation/activitykit/activity/pushtokenupdates-swift.property",
40
+ "https://developer.apple.com/documentation/avfaudio/avaudiosession",
41
+ "https://developer.apple.com/documentation/avfaudio/avaudiosession/setactive(_:options:)",
42
+ "https://developer.apple.com/documentation/avfaudio/avaudiosession/setactiveoptions/notifyothersondeactivation",
43
+ "https://developer.apple.com/documentation/swiftui/view/widgeturl(_:)",
44
+ "https://developer.apple.com/design/human-interface-guidelines/"
45
+ ]
46
+ },
47
+ {
48
+ "provider": "apple-releases",
49
+ "sourceKind": "release-notes",
50
+ "maxPages": 40,
51
+ "maxDepth": 2,
52
+ "seedUrls": [
53
+ "https://developer.apple.com/documentation/xcode-release-notes",
54
+ "https://developer.apple.com/documentation/ios-ipados-release-notes"
55
+ ]
56
+ },
57
+ {
58
+ "provider": "swift-evolution",
59
+ "sourceKind": "official-guide",
60
+ "maxPages": 35,
61
+ "maxDepth": 1,
62
+ "seedUrls": [
63
+ "https://www.swift.org/swift-evolution/",
64
+ "https://github.com/swiftlang/swift-evolution/blob/main/proposals/0302-concurrent-value-and-concurrent-closures.md",
65
+ "https://github.com/swiftlang/swift-evolution/blob/main/proposals/0304-structured-concurrency.md",
66
+ "https://github.com/swiftlang/swift-evolution/blob/main/proposals/0306-actors.md",
67
+ "https://github.com/swiftlang/swift-evolution/blob/main/proposals/0316-global-actors.md",
68
+ "https://github.com/swiftlang/swift-evolution/blob/main/proposals/0338-clarify-execution-non-actor-async.md",
69
+ "https://github.com/swiftlang/swift-evolution/blob/main/proposals/0420-inheritance-of-actor-isolation.md",
70
+ "https://github.com/swiftlang/swift-evolution/blob/main/proposals/0430-transferring-parameters-and-results.md"
71
+ ]
72
+ },
73
+ {
74
+ "provider": "android",
75
+ "sourceKind": "official-api",
76
+ "maxPages": 150,
77
+ "seedUrls": [
78
+ "https://developer.android.com/develop",
79
+ "https://developer.android.com/reference",
80
+ "https://developer.android.com/develop/ui/views/text-and-emoji/fonts-in-xml",
81
+ "https://developer.android.com/reference/androidx/biometric/BiometricPrompt.PromptInfo.Builder",
82
+ "https://developer.android.com/reference/android/media/AudioFocusRequest",
83
+ "https://developer.android.com/reference/android/media/AudioManager",
84
+ "https://developer.android.com/reference/android/net/ConnectivityManager",
85
+ "https://developer.android.com/reference/android/net/ConnectivityManager.NetworkCallback",
86
+ "https://developer.android.com/reference/android/content/Intent",
87
+ "https://developer.android.com/reference/android/app/NotificationManager",
88
+ "https://developer.android.com/reference/android/os/Build.VERSION_CODES",
89
+ "https://developer.android.com/reference/androidx/core/os/BuildCompat",
90
+ "https://developer.android.com/reference/androidx/work/Constraints.Builder",
91
+ "https://developer.android.com/reference/androidx/work/NetworkType",
92
+ "https://developer.android.com/develop/ui/compose/graphics/images/loading",
93
+ "https://developer.android.com/develop/ui/compose/graphics/images/customize",
94
+ "https://developer.android.com/reference/kotlin/androidx/compose/foundation/Image.composable",
95
+ "https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderClient",
96
+ "https://developers.google.com/android/reference/com/google/android/gms/location/LocationCallback"
97
+ ]
98
+ },
99
+ {
100
+ "provider": "android-releases",
101
+ "sourceKind": "release-notes",
102
+ "maxPages": 50,
103
+ "maxDepth": 2,
104
+ "seedUrls": [
105
+ "https://developer.android.com/about/versions/16",
106
+ "https://developer.android.com/about/versions/16/features",
107
+ "https://developer.android.com/about/versions/16/behavior-changes-all",
108
+ "https://developer.android.com/about/versions/16/behavior-changes-16",
109
+ "https://developer.android.com/about/versions/15/behavior-changes-all",
110
+ "https://developer.android.com/about/versions/15/behavior-changes-15",
111
+ "https://developer.android.com/about/versions/14/behavior-changes-all",
112
+ "https://developer.android.com/about/versions/14/behavior-changes-14"
113
+ ]
114
+ },
115
+ {
116
+ "provider": "media3",
117
+ "sourceKind": "official-guide",
118
+ "maxPages": 40,
119
+ "maxDepth": 2,
120
+ "seedUrls": [
121
+ "https://developer.android.com/media/media3",
122
+ "https://developer.android.com/media/media3/session/background-playback",
123
+ "https://developer.android.com/jetpack/androidx/releases/media3",
124
+ "https://developer.android.com/reference/androidx/media3/common/Player",
125
+ "https://developer.android.com/reference/androidx/media3/session/MediaSessionService"
126
+ ]
127
+ },
128
+ {
129
+ "provider": "glide",
130
+ "sourceKind": "official-guide",
131
+ "maxPages": 30,
132
+ "maxDepth": 2,
133
+ "seedUrls": [
134
+ "https://bumptech.github.io/glide/doc/caching.html",
135
+ "https://bumptech.github.io/glide/doc/configuration.html",
136
+ "https://bumptech.github.io/glide/javadocs/450/com/bumptech/glide/load/engine/cache/DiskCache.html",
137
+ "https://bumptech.github.io/glide/javadocs/450/com/bumptech/glide/load/engine/cache/InternalCacheDiskCacheFactory.html"
138
+ ]
139
+ },
140
+ {
141
+ "provider": "okhttp",
142
+ "sourceKind": "official-guide",
143
+ "maxPages": 30,
144
+ "maxDepth": 2,
145
+ "seedUrls": [
146
+ "https://lysine.dev/okhttp/",
147
+ "https://lysine.dev/okhttp/recipes/",
148
+ "https://lysine.dev/okhttp/features/caching/",
149
+ "https://lysine.dev/okhttp/features/calls/",
150
+ "https://lysine.dev/okhttp/features/connections/",
151
+ "https://lysine.dev/okhttp/features/https/",
152
+ "https://lysine.dev/okhttp/features/interceptors/",
153
+ "https://lysine.dev/okhttp/changelogs/changelog/",
154
+ "https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-ok-http-client/"
155
+ ]
156
+ },
157
+ {
158
+ "provider": "kotlin-coroutines",
159
+ "sourceKind": "official-guide",
160
+ "maxPages": 40,
161
+ "maxDepth": 1,
162
+ "seedUrls": [
163
+ "https://kotlinlang.org/docs/coroutines-guide.html",
164
+ "https://kotlinlang.org/docs/coroutines-basics.html",
165
+ "https://kotlinlang.org/docs/cancellation-and-timeouts.html",
166
+ "https://kotlinlang.org/docs/exception-handling.html",
167
+ "https://kotlinlang.org/docs/shared-mutable-state-and-concurrency.html",
168
+ "https://kotlinlang.org/docs/flow.html",
169
+ "https://kotlinlang.org/api/kotlinx.coroutines/"
170
+ ]
171
+ },
172
+ {
173
+ "provider": "gradle",
174
+ "sourceKind": "official-guide",
175
+ "maxPages": 40,
176
+ "maxDepth": 1,
177
+ "seedUrls": [
178
+ "https://docs.gradle.org/current/userguide/tooling_api.html",
179
+ "https://docs.gradle.org/current/userguide/composite_builds.html",
180
+ "https://docs.gradle.org/current/userguide/public_apis.html",
181
+ "https://docs.gradle.org/current/userguide/upgrading_version_9.html",
182
+ "https://docs.gradle.org/current/release-notes.html"
183
+ ]
184
+ },
185
+ {
186
+ "provider": "agp",
187
+ "sourceKind": "release-notes",
188
+ "maxPages": 40,
189
+ "maxDepth": 1,
190
+ "seedUrls": [
191
+ "https://developer.android.com/build/releases/about-agp",
192
+ "https://developer.android.com/build/releases/gradle-plugin-roadmap",
193
+ "https://developer.android.com/build/releases/agp-9-0-0-release-notes",
194
+ "https://developer.android.com/reference/tools/gradle-api"
195
+ ]
196
+ },
197
+ {
198
+ "provider": "jetbrains-issues",
199
+ "sourceKind": "issue-tracker",
200
+ "maxPages": 1,
201
+ "maxDepth": 0,
202
+ "seedUrls": [
203
+ "https://youtrack.jetbrains.com/issue/IDEA-329756/Importing-symlinked-Gradle-included-build-fails"
204
+ ]
205
+ },
206
+ {
207
+ "provider": "expo",
208
+ "sourceKind": "official-api",
209
+ "maxPages": 100,
210
+ "maxDepth": 3,
211
+ "seedUrls": [
212
+ "https://docs.expo.dev/versions/latest/",
213
+ "https://docs.expo.dev/versions/latest/sdk/expo/",
214
+ "https://docs.expo.dev/versions/latest/sdk/camera/",
215
+ "https://docs.expo.dev/versions/latest/sdk/notifications/",
216
+ "https://docs.expo.dev/router/introduction/",
217
+ "https://docs.expo.dev/modules/overview/",
218
+ "https://docs.expo.dev/guides/new-architecture/"
219
+ ]
220
+ },
221
+ {
222
+ "provider": "react-native",
223
+ "sourceKind": "official-api",
224
+ "maxPages": 80,
225
+ "maxDepth": 3,
226
+ "seedUrls": [
227
+ "https://reactnative.dev/docs/getting-started",
228
+ "https://reactnative.dev/docs/components-and-apis",
229
+ "https://reactnative.dev/docs/flatlist",
230
+ "https://reactnative.dev/docs/view",
231
+ "https://reactnative.dev/docs/platform",
232
+ "https://reactnative.dev/architecture/landing-page"
233
+ ]
234
+ },
235
+ {
236
+ "provider": "react-native-reanimated",
237
+ "sourceKind": "official-guide",
238
+ "maxPages": 60,
239
+ "maxDepth": 3,
240
+ "seedUrls": [
241
+ "https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/",
242
+ "https://docs.swmansion.com/react-native-reanimated/docs/guides/testing/",
243
+ "https://docs.swmansion.com/react-native-reanimated/docs/guides/compatibility/",
244
+ "https://docs.swmansion.com/react-native-reanimated/docs/category/core/",
245
+ "https://docs.swmansion.com/react-native-reanimated/docs/category/advanced-apis/"
246
+ ]
247
+ },
248
+ {
249
+ "provider": "react-native-gesture-handler",
250
+ "sourceKind": "official-guide",
251
+ "maxPages": 60,
252
+ "maxDepth": 3,
253
+ "seedUrls": [
254
+ "https://docs.swmansion.com/react-native-gesture-handler/docs/fundamentals/getting-started/",
255
+ "https://docs.swmansion.com/react-native-gesture-handler/docs/gestures/pan-gesture/",
256
+ "https://docs.swmansion.com/react-native-gesture-handler/docs/gestures/gesture-detector/"
257
+ ]
258
+ },
259
+ {
260
+ "provider": "react-native-screens",
261
+ "sourceKind": "official-guide",
262
+ "maxPages": 50,
263
+ "maxDepth": 3,
264
+ "seedUrls": [
265
+ "https://docs.swmansion.com/react-native-screens/",
266
+ "https://github.com/software-mansion/react-native-screens/blob/main/README.md"
267
+ ]
268
+ },
269
+ {
270
+ "provider": "react-native-worklets",
271
+ "sourceKind": "official-guide",
272
+ "maxPages": 60,
273
+ "maxDepth": 3,
274
+ "seedUrls": [
275
+ "https://docs.swmansion.com/react-native-worklets/docs/fundamentals/getting-started/",
276
+ "https://docs.swmansion.com/react-native-worklets/docs/guides/testing/",
277
+ "https://docs.swmansion.com/react-native-worklets/docs/category/fundamentals/",
278
+ "https://docs.swmansion.com/react-native-worklets/docs/fundamentals/sharing-memory/",
279
+ "https://docs.swmansion.com/react-native-worklets/docs/guides/feature-flags/"
280
+ ]
281
+ }
282
+ ]
283
+ }
@@ -24,6 +24,22 @@
24
24
  // *.min.js, *.map, __snapshots__/*.snap, @generated markers).
25
25
  "noise": { "additionalIgnores": [] },
26
26
 
27
+ // Optional trusted host-side platform research (ROOT-ONLY; off by default).
28
+ // ECR starts its bundled review-research-mcp in read-only `serve` mode against
29
+ // the absolute index path. It derives short API identifiers
30
+ // from native diffs, queries the MCP before model startup, and injects only
31
+ // bounded, fenced evidence. The reviewer remains on Claude `--safe-mode` and
32
+ // never receives an MCP tool. Expo-provider searches send only the derived,
33
+ // bounded API query to Expo's public documentation search and fall back locally.
34
+ // Never point this at the separately networked `update` command.
35
+ // "research": {
36
+ // "enabled": true,
37
+ // "indexPath": "/opt/expo-review/docs-index.json",
38
+ // "maxQueries": 8,
39
+ // "resultsPerQuery": 2,
40
+ // "timeoutMs": 15000
41
+ // },
42
+
27
43
  // Large diffs are split into focused chunks by changed-line count, plus a
28
44
  // cross-cutting pass for multi-file issues. Diffs under maxChangedLines are one
29
45
  // full-context pass. Defaults shown; raise/lower per your model + PR sizes.