Task 13.4: add the Expo config plugin - #39
Conversation
The plugin copies the bare app's source-map hook and Archive post-action, and writes bugsee.properties without turning NDK upload on for a placeholder token. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Stale comment
Deep code review (f1bde1f)
Reviewed Task 13.4 against the Expo SDK 57 templates (
expo-template-bare-minimumGradle + the Bundle React Native code and images phase), the bare example’s 13.1/13.2 hooks,packages/react-native/android/build.gradle, and the packagefileslist. Unit tests cover the string helpers; they do not exercise the plugin from an npm layout or a real prebuild. I did not runexpo prebuildor Jest here (node_moduleswas not installed in this environment).The Gradle edits match Expo 57’s Groovy templates (
apply plugin: "com.facebook.react",buildscriptthenallprojects,pluginManagementwithout repositories). The Expo bundle-phase regex matches the decoded SDK 57 invocation. Placeholder-token handling matches the 13.3 ruling. Those parts look right.The blocker is that
withBugseecannot resolve native versions once this package is installed from npm rather than as a workspace symlink.Findings
- P1 —
loadNativeVersionswalk-up only works in this monorepo; the published tarball has nonative-versions.json(see inline).- P2 — Expo rewrite hardcodes
${SRCROOT}/../node_modules/@bugsee/react-native/scripts/bugsee-xcode.sh(see inline).- P2 —
nativeCrashReporting: falsedoes not keepbugsee-android-ndkout of the APK (see inline).Overall risk: High
Merge recommendation
Request changes. Do not merge until the plugin can run from a realistic
node_modules/@bugsee/react-nativetree (copy or bakenative-versions.json). The path and NDK-opt-out issues should be fixed in the same pass or explicitly documented as known limits.Most important issues to fix
- Ship versions with the plugin (package file, or bake
android.sdk/android.gradlePluginintoplugin/buildat compile time). Add a test that loads versions from a fake published layout, not from the repo root.- Resolve
bugsee-xcode.shwithNODE_BINARY+require.resolve('@bugsee/react-native/package.json'), same as Expo resolvesreact-native-xcode.sh.- Make
nativeCrashReporting: falseactually drop the NDK artifact (or stop claiming it opts out of detection/size).Also missing, not filed separately: no CI job runs
examples/expoprebuild --clean, andandroid//ios/are gitignored, so a template-shape change will not fail the gate. Design §13 still calls prebuild-then-build the proof this plugin survives regeneration.Residual, out of this task’s listed Android surface: Expo
app/build.gradledoes not get the bare app’shermesc-preserve-js.shwrap, so Expo Android JS debug ids are still unwired. Fine for 13.4 if 13.5 is meant to catch it; it will fail Android Expo symbolication until someone adds it.Positive observations
- Maven Central is injected into
pluginManagement(including the no-repositoriesExpo 57 shape), and the Gradle plugin isapply falseon the root then applied on the app module — same constraint as the bare example.- Expo’s
ENTRY_FILE/CLI_PATH/BUNDLE_COMMAND=export:embedare preserved; the phase is not replaced with the bare script.plugin.ndk.enabledis omitted for the CI placeholder UUID;plugin.appTokenis never written.- Scheme post-action copies the bare script and binds
EnvironmentBuildableto the scheme’s own.apptarget.- Gradle version strings are allowlisted before interpolation.
Sent by Cursor Automation: Bugsee code review
A published install has no repo-root native-versions.json to walk to, the Expo bundle phase assumed a sibling node_modules, and nativeCrashReporting: false still left the wrapper NDK AAR on the APK. Co-authored-by: Cursor <cursoragent@cursor.com>
A later prebuild with the option omitted or true kept the exclude a false run had written, so the NDK artifact stayed off the app. Co-authored-by: Cursor <cursoragent@cursor.com>
Keep 13.3 and 13.4 checked. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Stale comment
Deep code review (23420e2)
Re-reviewed Task 13.4 at 23420e2 (prior f1bde1f plus bake, NDK-exclude, and merge of main). Checked the plugin against Expo SDK 54/56/57
expo-template-bare-minimum(Groovy Gradle + the Bundle React Native code and images phase),react-native-xcode.sh'sCOMPOSE_SOURCEMAP_PATH/ hermesc step afterexport:embed,packages/react-native/android/build.gradle, the packagefileslist, and the three prior threads. Unit tests andexamples/expoprebuild were not run here (node_modulesis not installed).All three findings from f1bde1f are fully_addressed:
loadNativeVersionsreadsplugin/build/native-versions.baked.json; the published-layout test loads7.3.0/4.0.7from a tree that has onlyplugin/build.- The Expo rewrite resolves
bugsee-xcode.shwith$NODE_BINARY+require.resolve('@bugsee/react-native/package.json'). The SDK 54–57 invocation matchesEXPO_XCODE_INVOCATION.nativeCrashReporting: falsewritesconfigurations.configureEach { exclude group: 'com.bugsee', module: 'bugsee-android-ndk' }and a later on/omitted run removes that block. Gradle configuration-level exclude applies to the wrapper's transitiveapiand to a leftover directimplementationline.Findings
- P2 — Archive dSYM post-action still only searches sibling / this-repo
node_modulesforbugsee-cli(see inline). Hoisted Expo monorepos miss it andexit 1.Overall risk: Medium
Merge recommendation
Request changes. The plugin can now run from a published
plugin/buildtree, and the Gradle/Xcode string edits match Expo 57. Do not treat Archive dSYM upload as done for any app whosenode_modulesis notios/../node_modules— the same class of miss you just fixed on the bundle phase.Most important issues to fix
- After the script finds
NODE_BINARY, resolve@bugsee/cliwithrequire.resolve(same as the Expo bundle rewrite) and invoke that path. Drop thepackages/react-native/node_moduleswalk; that only exists in this workspace.Residual, not re-filed: no CI job runs
examples/expoprebuild --clean. Expoapp/build.gradlestill does not gethermesc-preserve-js.sh, so Android JS debug ids stay unwired until 13.5. Separately, a published tarball still has nonative-versions.json:BugseeReactNative.podspecreads../../native-versions.jsonandandroid/build.gradlewalks for it, so the first npm/EASpod install/ Gradle configure after a successful plugin prebuild will fail. That is pre-existing packaging, not a regression in this head; it is the next break on the path this PR is meant to open.Positive observations
- Bake + the fake published-layout test close the f1bde1f P1 for the plugin itself.
- Expo 54/56/57 bundle-phase text is the same
NODE_BINARY+require.resolve('react-native/...')invocation the regex rewrites;ENTRY_FILE/CLI_PATH/export:embedstay.react-native-xcode.shstill runs hermesc andCOMPOSE_SOURCEMAP_PATHafterexport:embedwhen the CLI does not pass--bytecode, socompose-then-inject.jsis still on the compose path.- Stale NDK exclude is removed on a later on/omitted prebuild (
3a49e4b).plugin.ndk.enabledstays off for the CI placeholder;plugin.appTokenis never written.Sent by Cursor Automation: Bugsee code review
The Archive post-action only searched three node_modules directories, so a hoisted Expo app never found the CLI and the dSYM upload failed. Co-authored-by: Cursor <cursoragent@cursor.com>
@bugsee/cli does not export its bin subpath, and an Xcode post-action does not run from the app directory. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Stale comment
Deep code review (16f9cd6)
Re-reviewed Task 13.4 at 16f9cd6 (prior 23420e2 plus package-graph CLI resolve, then app-root
paths). Checked the plugin against Expo SDK 57expo-template-bare-minimum(Groovysettings.gradle/ root and appbuild.gradle, single shared.xcscheme), RN 0.86react-native-xcode.sh(hermesc +COMPOSE_SOURCEMAP_PATHafterexport:embed),@bugsee/cli@0.7.11exports/bin, the wrapperapiNDK line, and the four prior threads. Confirmednode --printputs the extra argument atprocess.argv[1]. Empirically ranrequire.resolve('@bugsee/cli/package.json', { paths: [appRoot] })against hoisted, monorepo-hoist-to-root, pnpm-nested, and YarnnmHoistingLimits: workspacestrees. Plugin unit tests andexamples/expoprebuild were not run here (node_modulesis not installed).All four prior threads are fully_addressed:
- Baked
plugin/build/native-versions.baked.json; published-layout test loads7.3.0/4.0.7from a tree that has onlyplugin/build.- Expo bundle rewrite resolves
bugsee-xcode.shvia$NODE_BINARY+require.resolve('@bugsee/react-native/package.json'). SDK 57's invocation still matchesEXPO_XCODE_INVOCATION.nativeCrashReporting: falsewrites the configuration exclude and a later on/omitted run removes it.- Default Yarn/npm hoist from
apps/mobilenow walks up from${PROJECT_DIR}/..and finds@bugsee/cliat the repo root. That was the 23420e2 scenario.Findings
- P1 — Archive post-action still cannot resolve transitive
@bugsee/cli(see inline).paths: [APP_ROOT]only walks upnode_modulesdirectories; it never enters@bugsee/react-native/node_modules. pnpm and this repo's YarnnmHoistingLimits: workspaceslayout both miss it andexit 1.Overall risk: Medium
Merge recommendation
Request changes. The plugin can run from a published
plugin/buildtree, and the Gradle / Expo 57 Xcode string edits match the template. Do not treat Archive dSYM upload as done for any install that does not hoist@bugsee/clito a directory on the walk up from the app root — includingexamples/expoin this workspace.Most important issues to fix
- After
NODE_BINARYis known, resolve@bugsee/react-native/package.jsonfrom the app root, then resolve@bugsee/cli(and the optional native package) withpaths: [dirname(wrapper)]. That is how Node finds a package's own dependencies, and it is the same starting point the Expo bundle rewrite already uses. Keepprocess.argv[1]for the post-action cwd. Replace the string-only test with one that actuallyrequire.resolves from a nested tree (CLI only under@bugsee/react-native/node_modules) and from a hoisted tree.Residual, not re-filed: no CI job runs
examples/expoprebuild --clean. Expoapp/build.gradlestill does not gethermesc-preserve-js.sh, so Android JS debug ids stay unwired until 13.5. A published tarball still has nonative-versions.jsonforBugseeReactNative.podspec/android/build.gradle; that is pre-existing packaging, not a regression in this head.Positive observations
node --print "…" "$APP_ROOT"really does put the app root atprocess.argv[1]on Node 22; the extra-arg approach is correct.@bugsee/cli@0.7.11exports./package.jsonand uses an objectbin, so reading.bin['bugsee-cli']is the right workaround for the unexported bin subpath.- Expo 57
pluginManagementhas norepositoriesand balanced{ paths: […] }strings insideproviders.exec;ensureMavenCentralstill closes the block correctly and injects Maven Central.- Root
plugins { id … apply false }lands afterbuildscriptand beforeallprojects/apply plugin: "expo-root-project", which is valid Gradle and matches the bare app.react-native-xcode.shon 0.86 still runs hermesc andCOMPOSE_SOURCEMAP_PATHafterexport:embedwhen Hermes is on, socompose-then-inject.jsis still on the iOS compose path.Sent by Cursor Automation: Bugsee code review
Yarn and pnpm nest the CLI under @bugsee/react-native, so an app-root require.resolve misses it and the Archive post-action exits 1. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Stale comment
Deep code review (c92ce65)
Re-reviewed Task 13.4 at c92ce65 (wrapper-directory CLI resolve). Checked the plugin against Expo SDK 57
expo-template-bare-minimum(Groovysettings.gradle/ root and appbuild.gradle, backtick$NODE_BINARYbundle invocation, emptyArchiveAction), RN wrapperapiNDK line, GradleConfiguration.excludecontract, and the five prior threads. Ran the compiled transforms in Node: Expo 57pluginManagementstill gets a balancedrepositoriesblock; the SDK 57 bundle-phase text matchesEXPO_XCODE_INVOCATION(one/bin/bash);ensureAppAppliesPlugin(on → off)keeps theimplementationline. Plugin unit tests andexamples/expoprebuild were not run here (node_modulesis not installed).All five prior threads are fully_addressed:
- Baked
plugin/build/native-versions.baked.json; published-layout test loads7.3.0/4.0.7from a tree that has onlyplugin/build.- Expo bundle rewrite resolves
bugsee-xcode.shvia$NODE_BINARY+require.resolve('@bugsee/react-native/package.json'). SDK 57's invocation still matchesEXPO_XCODE_INVOCATION.- First-run
nativeCrashReporting: falsewrites the configuration exclude (wrapperapiis transitive, so that path is covered). Off→on still drops a stale exclude.- Archive post-action resolves
@bugsee/react-nativefrom${PROJECT_DIR}/.., then@bugsee/clifrom that wrapper directory, then the Darwin package from the CLI directory.resolves a nested @bugsee/cli from the wrapper and a hoisted one from the app rootactuallyrequire.resolves both trees.Findings
- P2 —
nativeCrashReporting: falseon a later prebuild does not remove theimplementationline a default-on run wrote (see inline). Configuration-level exclude does not apply to that direct dependency, so the NDK AAR stays on the APK.Overall risk: Medium
Merge recommendation
Request changes. The plugin can run from a published
plugin/buildtree, Expo 57 Gradle/Xcode string edits match the template, and Archive CLI resolve now covers nested Yarn/pnpm layouts. Do not treatnativeCrashReporting: falseas done for any app that already ran a default-on prebuild — that is the same incremental path3a49e4bfixed in the other direction.Most important issues to fix
- When
ndkVersionis null, stripimplementation "com.bugsee:bugsee-android-ndk:…"(the line this plugin inserts) before writing the exclude. Add the inverse ofremoves a previous NDK exclude when native crash reporting is on: start from a file that already has that implementation line.Residual, not re-filed: no CI job runs
examples/expoprebuild --clean. Expoapp/build.gradlestill does not gethermesc-preserve-js.sh, so Android JS debug ids stay unwired until 13.5. A published tarball still has nonative-versions.jsonforBugseeReactNative.podspec/android/build.gradle; that is pre-existing packaging, not a regression in this head.Positive observations
- Nested
@bugsee/cliis resolved from the wrapper directory; the new test failspaths: [appRoot]on that tree and passes the script source.- Expo 57
pluginManagementhas norepositoriesand balanced{ paths: […] }strings insideproviders.exec;ensureMavenCentralstill closes the block correctly and injects Maven Central.- SDK 57's bundle-phase invocation is still the
NODE_BINARY+require.resolve('react-native/…')form the regex rewrites;ENTRY_FILE/CLI_PATH/export:embedstay; a secondbugsee-xcode.shis not appended.plugin.ndk.enabledstays off for the CI placeholder;plugin.appTokenis never written.- Root
plugins { id … apply false }still lands afterbuildscriptand beforeallprojects/apply plugin: "expo-root-project".Sent by Cursor Automation: Bugsee code review
A configuration exclude only removes the wrapper's transitive api, so an implementation line left by an earlier prebuild still put the NDK AAR on the APK. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Stale comment
Deep code review (872ab71)
Reviewed Task 13.4 against the surrounding 13.1/13.3 bare-app hooks, design §11, and the Expo SDK 57
expo-template-bare-minimumGradle/Xcode files. Ran the compiled plugin helpers on those templates (notyarn test/ not a fullexpo prebuildin this environment).Prior threads on this PR (baked native pins, Expo
require.resolveforbugsee-xcode.sh, nested@bugsee/cliresolve, NDK exclude ↔ directimplementationround-trip) are addressed on this head.Findings
- P1 — Expo Android never gets the 13.1/13.3
app/build.gradlecontract. The plugin appliescom.bugsee.android.gradleand the NDK artifact, then stops. It does not setdebugSymbolLevel 'SYMBOL_TABLE'(13.3: AGP defaults toNONE, native upload skips) and does not installhermesc-preserve-js.sh+ thecreateBundle*JsAndAssetsinject (13.1). iOS inject/dSYM are present; Android JS debug IDs and NDK symbol upload are not.packages/react-native/plugin/src/index.ts:66-69- P2 —
insertDsymPostActionemits a second<PostActions>sibling when Archive already has one, instead of appending anExecutionAction. Stock Expo schemes are empty, so the example prebuild does not catch this.packages/react-native/plugin/src/scheme.ts:50-52Overall risk: High
Expo iOS prebuild can look correct while Android release symbolication (JS and native) is silently a no-op.
Merge recommendation: Do not merge until the Android
app/build.gradlehooks from 13.1/13.3 are applied (and tested) by this plugin.Most important to fix
debugSymbolLevel+ Hermes preserve/inject on the Expo app module, resolved viarequire.resolve(not../../node_modules), with an Expo 57 template fixture.- Merge into an existing Archive
PostActionsrather than inserting a sibling block.Notes, not blocking
- No CI job runs
examples/expoprebuild --clean(design §13). Unit tests cover string rewrites; they would not have caught finding 1.uploadSymbols: falsedoes not strip an already-inserted post-action on incremental prebuild (same class as the NDK leftover that 872ab71 fixed). Secondary to the missing Android hooks.What looks solid
native-versions.baked.jsonis what a published install can actually read.- Expo 57
pluginManagementhas norepositories {};ensureMavenCentralinserts portal + Google + Maven Central, which is the right replacement for the implicit portal.plugins { id 'com.bugsee.android.gradle' … apply false }lands afterbuildscriptand beforeallprojects/apply pluginon the Expo 57 rootbuild.gradle(valid Gradle).- Expo bundle-phase regex matches the SDK 57 invocation and keeps
export:embed/ENTRY_FILE/CLI_PATH.- Nested vs hoisted
@bugsee/cliresolve is actually executed in the unit test, not only asserted as source text.Sent by Cursor Automation: Bugsee code review
The config plugin was applying the Gradle plugin without SYMBOL_TABLE or the Hermes preserve and finish hooks, and a second Archive PostActions sibling is not a valid scheme. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Stale comment
Deep code review (a71ec6e)
Reviewed Task 13.4 against the 13.1/13.3 bare-app hooks, design §11, and the Expo SDK 57
expo-template-bare-minimumGradle/Xcode files. Ran the compiled plugin helpers on those templates (notyarn test/ not a fullexpo prebuild;node_modulesis not installed here).All eight prior threads are fully_addressed: baked native pins, Expo
bugsee-xcode.shresolve, NDK exclude + leftoverimplementationstrip, nested@bugsee/cliresolve, AndroidSYMBOL_TABLE/ Hermes finish hook, and ArchivePostActionsmerge.Findings
- P2 — Replacing Expo 57's
hermesCommandwithhermesc-preserve-js.shdrops therequire.resolve('hermes-compiler', { paths: [react-native] })lookup the template used. The wrapper only checks$PWD/node_modules/hermes-compiler/…. A nested/pnpm/Yarn-workspace install failscreateBundleReleaseJsAndAssets(see inline).- P2 —
uploadSymbols: falseon a later prebuild does not remove the Archive post-action a default-on run wrote (see inline).Overall risk: Medium
The iOS hooks and the Gradle plugin/NDK/symbol-table edits look correct on a stock SDK 57 tree. Android JS debug IDs still depend on a hermesc lookup that Expo already solved and this commit undoes.
Merge recommendation
Request changes. Do not treat Android JS symbolication as done for pnpm or Yarn-workspace Expo apps —
assembleReleasedies increateBundle*JsAndAssetswithbugsee: hermesc binary not foundinstead of compiling with the binary Expo's template would have found.Most important issues to fix
- Resolve
hermescthe way the Expo 57 template does (require.resolve('hermes-compiler/package.json', { paths: [require.resolve('react-native/package.json')] })+hermesc/%OS-BIN%/hermesc), not via$PWD/node_modules/hermes-compiler. Teachfind_hermescthat, or bakeBUGSEE_REAL_HERMESCfrom the same expression. Add the inverse of the nested-CLI test: a tree wherenode_modules/hermes-compileris missing and the package lives underreact-native.- When
uploadSymbols === false, strip an ExecutionAction whosescriptTextcontainsxcode post-action(and drop an empty leftoverPostActions). Start from a scheme this plugin already edited.Residual, not re-filed: no CI job runs
examples/expoprebuild --clean. A published tarball still has nonative-versions.jsonfor the podspec /android/build.gradlewalk; that is pre-existing packaging.Positive observations
- Expo 57
pluginManagementhas norepositoriesand balanced{ paths: […] }strings insideproviders.exec;ensureMavenCentralstill closes the block and injects Maven Central.plugins { id 'com.bugsee.android.gradle' … apply false }lands afterbuildscriptand beforeallprojects/apply plugin: "expo-root-project".- SDK 57's bundle-phase invocation still matches
EXPO_XCODE_INVOCATION;ENTRY_FILE/CLI_PATH/export:embedstay; a secondbugsee-xcode.shis not appended.debugSymbolLevel 'SYMBOL_TABLE'is written on both build types; a hand-writtenndkblock is left alone;nativeCrashReporting: falseremoves only the marked block.- Archive already-has-
PostActionsnow gets one container holding both actions.- Nested
@bugsee/cliresolve is actually executed in the unit test, not only asserted as source text.plugin.ndk.enabledstays off for the CI placeholder;plugin.appTokenis never written.Sent by Cursor Automation: Bugsee code review
Expo resolves hermes-compiler from the react-native package, which a sibling node_modules walk misses. uploadSymbols false also has to remove an Archive post-action left by an earlier prebuild. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Stale comment
Deep code review (e9ca1d0)
Reviewed Task 13.4 against the 13.1/13.3 bare-app hooks, design §11, Expo SDK 54 and 57
expo-template-bare-minimumGradle files, andreact-native@0.81.4/0.83.1package manifests. Ranfind_hermescagainst a 0.81-shaped tree (notyarn test/ not a fullexpo prebuild;node_modulesis not installed here).All ten prior threads are fully_addressed: baked native pins, Expo
bugsee-xcode.shresolve, NDK exclude + leftoverimplementationstrip, nested@bugsee/cliresolve, AndroidSYMBOL_TABLE/ Hermes finish hook, ArchivePostActionsmerge, nestedhermes-compilerlookup, anduploadSymbols: falseleftover-action strip.Findings
- P1 —
find_hermescstill cannot see RN 0.81 / Expo SDK 54's shippedsdks/hermescbinary after the plugin overwrites that workinghermesCommand(see inline).Overall risk: High
SDK 57 prebuild and the nested-compiler test can look correct while an SDK 54 Android release dies in
createBundle*JsAndAssets.Merge recommendation
Request changes. Do not treat Android JS symbolication as done for the declared 0.81 floor —
assembleReleaseprintsbugsee: hermesc binary not foundon the layout Expo 54's template already solved.Most important issues to fix
- Resolve
react-native/sdks/hermesc/%OS-BIN%/hermescfromrequire.resolve('react-native/package.json')after the hermes-compiler lookup. Add a 0.81 fixture (shippedsdks/hermesc, nohermes-compilerpackage) that runs the wrapper.Residual, not re-filed: no CI job runs
examples/expoprebuild --clean. A published tarball still has nonative-versions.jsonfor the podspec /android/build.gradlewalk; that is pre-existing packaging.@expo/config-pluginsis pinned~57.0.9while the wrapper floor is SDK 54.Positive observations
- Nested
hermes-compilerunderreact-nativeis actually executed in the unit test, not only asserted as source text.uploadSymbols: falsenow removes the Bugsee ArchiveExecutionActionand drops an empty leftoverPostActions; a sibling action stays.- Expo 57
pluginManagementhas norepositoriesand balanced{ paths: […] }strings insideproviders.exec;ensureMavenCentralstill closes the block and injects Maven Central.- SDK 54 and 57 bundle-phase invocations still match
EXPO_XCODE_INVOCATION;ENTRY_FILE/CLI_PATH/export:embedstay.- Nested vs hoisted
@bugsee/cliresolve is actuallyrequire.resolved in the unit test.plugin.ndk.enabledstays off for the CI placeholder;plugin.appTokenis never written.Sent by Cursor Automation: Bugsee code review
Expo SDK 54 has no hermes-compiler package. After that resolve misses, the wrapper uses sdks/hermesc beside react-native, while newer SDKs still prefer hermes-compiler. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Stale comment
Deep code review (ec79c1f)
Reviewed Task 13.4 at ec79c1f against the 13.1/13.3 bare-app hooks, design §11, Expo SDK 54 and 57
expo-template-bare-minimumGradle/Xcode files, and RN 0.81.4 / 0.86.3BundleHermesCTask+detectOSAwareHermesCommand. Ranfind_hermescagainst a 0.81-shaped tree and a nested-compiler+shipped tree (notyarn test/ not a fullexpo prebuild;node_modulesis not installed here).All eleven prior threads are fully_addressed. The e9ca1d0 P1 is closed by this commit: after
hermes-compilermisses, the wrapper usessdks/hermesc/%OS-BIN%/hermescbesiderequire.resolve('react-native/package.json'). Reproduced: 0.81 tree with executablesdks/hermesc/linux64-bin/hermescand nohermes-compiler→ exit 0, recorded path is the shipped binary. A tree with both layouts still prefershermes-compiler. The new unit test actually runs the script.Checked the surrounding contract this plugin now reapplies:
- Expo 54
hermesCommandis thesdks/hermescGroovy line this wrapper replaces; Expo 57 is thehermes-compilerline. Both are single-line assignmentsrewriteHermesCommandmatches.- RN 0.81/0.86
detectOSAwareHermesCommandaccepts a non-blankhermesCommandas-is (no%OS-BIN%required), so the.shpath is not rejected.BundleHermesCTask.getHermescCommanduses-out ${bundle}.hbcthen the JS bundle as a separate argument, so the wrapper’s skip--outscan still finds the input under/generated/assets/.- SDK 54 root
build.gradlestill hasbuildscriptthenallprojects/apply plugin;plugins { … apply false }lands afterbuildscript.- SDK 54
settings.gradlepluginManagementstill has norepositoriesand balanced{ paths: […] }strings;ensureMavenCentralstill closes the block.- SDK 54 bundle-phase invocation still matches
EXPO_XCODE_INVOCATION;ENTRY_FILE/CLI_PATH/export:embedstay.Findings
No new P0–P3.
Overall risk: Low
Merge recommendation
Safe once CI is green on this head. Plugin correctness for the declared 0.81 / SDK 54 floor is no longer blocked. At review time
rn compat (0.83)had already failed in 22s; that job runscheck-rn-compat.shand does not readplugin/. The JS unit/mutation job was still running.Most important issues to fix
None on the plugin path. Do not treat 13.5 (a release build whose JS stack symbolicates) as done — design §13 still calls that the only proof of the whole chain.
Residual, not re-filed: no CI job runs
examples/expoprebuild --clean. A published tarball still has nonative-versions.jsonfor the podspec /android/build.gradlewalk; that is pre-existing packaging.@expo/config-pluginsis pinned~57.0.9whileexpo@54uses~54.0.0.Positive observations
- The 0.81 shipped-binary path and the nested-compiler preference are both executed, not only asserted as source text.
uploadSymbols: falsestill removes the Bugsee ArchiveExecutionActionand drops an empty leftoverPostActions; a sibling action stays.- Nested vs hoisted
@bugsee/cliresolve is still actuallyrequire.resolved in the unit test.plugin.ndk.enabledstays off for the CI placeholder;plugin.appTokenis never written.- Expo 54/57 Gradle string edits still match the templates;
debugSymbolLevel 'SYMBOL_TABLE'is written on both build types and a hand-writtenndkblock is left alone.Sent by Cursor Automation: Bugsee code review
grep -q closes the pipe at the first match, so grep -v dies with SIGPIPE and a real assignment is reported as a miss. Read the filtered file to completion instead. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Deep code review (11e090b)
Re-reviewed Task 13.4 at 11e090b against the 13.1/13.3 bare-app hooks, design §11, Expo SDK 54 and 57 expo-template-bare-minimum Gradle/Xcode templates, and the eleven prior findings.
Prior threads
All eleven remain fully addressed. Plugin sources, baked pins, NDK exclude/implementation round-trip, Archive PostActions insert/remove, nested @bugsee/cli resolve, and find_hermesc (hermes-compiler first, then RN 0.81 sdks/hermesc) are unchanged from ec79c1f.
SDK 54 and 57 iOS bundle phases still match EXPO_XCODE_INVOCATION (same `$NODE_BINARY` --print … react-native-xcode.sh line). Root android/build.gradle is still buildscript then allprojects, so the plugins { id 'com.bugsee.android.gradle' … apply false } insert after buildscript is valid Gradle. SDK 54 hermesCommand is still the single-line sdks/hermesc/%OS-BIN%/hermesc path that ec79c1f taught the wrapper to find.
New commit
11e090b stops assigns_handle from using grep -q on the comment-filter pipe. Under set -o pipefail, grep -q exits at the first match and closes the pipe; grep -v then dies with SIGPIPE, so a real __internalInstanceHandle assignment near the start of a large file is reported as a miss. Reproduced locally on an 80k-line file with the assignment on line 1: old pipeline exit 141, grep -E … >/dev/null exit 0. A comparison (===) still exits 1. rn compat (0.81) already passed on this head.
New findings
None (no P0–P3).
Residual (not re-filed)
- No CI job runs
examples/expoprebuild --clean. - The published tarball still has no repo-root
native-versions.jsonfor the podspec / wrapperandroid/build.gradlewalk (pre-existing packaging; the plugin itself reads the baked copy). @expo/config-pluginsis pinned~57.0.9while the wrapper floor is SDK 54. Nested install is the likely layout; not reproduced as a prebuild break.
Verdict
- Overall risk: Low
- Merge recommendation: Safe once CI is green
- Most important issues to fix: None on this head
- Positives: The Expo regex still targets only the
react-native-xcode.shinvocation soENTRY_FILE/CLI_PATH/export:embedstay. Incremental prebuild undoes NDK exclude, leftoverimplementation, and the Archive post-action. The pipefail guard is covered by a unit test that actually runs the extracted function underpipefail.
Sent by Cursor Automation: Bugsee code review


Summary
@bugsee/react-native/app.plugin.js. Prebuild inserts the Hermes source-map hook and the Archive dSYM post-action, applies the Bugsee Gradle plugin from Maven Central, and writes rootandroid/bugsee.propertieswith an unprefixedapp_token.plugin.ndk.enabled=trueis written only for a non-empty, non-placeholder token.nativeCrashReportingstill addsbugsee-android-ndkby default.examples/expoprebuild --cleancompleted, including CocoaPods.Test plan
CI=1 yarn expo prebuild --cleaninexamples/expo(exit 0)app_tokenandplugin.ndk.enabled; the CI placeholder does not write the NDK flag;plugin.appTokenis absentMade with Cursor