Skip to content

campaign: build-lane tooling for the first beta (N-20..N-25, N-27) - #61

Merged
krassx merged 10 commits into
mainfrom
campaign/build-variants
Oct 9, 2026
Merged

krassx merged 10 commits into
mainfrom
campaign/build-variants

Conversation

@krassx

@krassx krassx commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Beta campaign BUILD lane tooling (PREP-build). Evidence and commands: campaign-prep-build.md in the campaign directory.

  • scripts/campaign/gen-rn-app.sh (N-21, N-22, N-23): one bare app per RN minor 0.81-0.87 from the npm-packed tarball, integrated by the package README; README gaps (DEVIATION R-n) and product-bug workarounds (WORKAROUND W-n) are logged by name and can be switched off (--readme-only, --no-workarounds). --engine jsc, --pm npm|yarn|pnpm, --smoke <dir> for the N-01 module; consumer tsc (API-48/49) with the template TypeScript and TS 6.
  • scripts/campaign/gen-expo-app.sh + examples/expo/App.js (N-20): Expo SDK 54-57 apps, config plugin, deep-link scenario, markers.
  • scripts/campaign/check-16kb.sh (N-24), build-app.sh, launch-check.sh, emulators.sh (API 24/30/36 AVDs + sweep), pack.sh.
  • examples/bare/scripts/run-ios.sh (N-27): IOS_DELIVERY=spm, IOS_TARGET=simulator, IOS_APP_DIR, IOS_LAUNCH.
  • .github/workflows/campaign-windows-hermes.yml (N-25, TEMPORARY, delete after the campaign). It fails by design of the finding: Hermes release on Windows stops at createBundleReleaseJsAndAssets (index.android.bundle.hbc missing; hermesc-preserve-js.sh is a shell script) — BLK-07 / Task 13.7.

Results (beta5 tarball, cc78c64): 14 Hermes apps (0.81-0.86, Expo 54-57, 0.87 via npm/Yarn/pnpm, README-only control) build Android Debug/Release and iOS sim Debug + device Debug/Release, and launch on the WOD_LX1 (Debug+Release) and the simulator (Debug); rn086 Release launches on the XS; SPM on the simulator passes; rn081 launches on API 24/30/36 emulators. Product findings for the campaign: native-versions.json missing from the tarball (pod install and Gradle fail for npm consumers), consumer tsc fails on RN 0.87, README gaps (static serialize, Gradle plugin, iOS bundle phase, pnpm allowBuilds), yarn pack drops the Expo plugin build. JSC is blocked by third-party issues.

🤖 Generated with Claude Code

@krassx
krassx force-pushed the campaign/build-variants branch from ff93993 to 52ec88f Compare October 7, 2026 03:26

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Deep review — campaign BUILD-lane tooling (N-20..N-25, N-27)

Reviewed 52ec88f against the generators' callers, run-ios.sh tests, the existing symbol-stub protocol, and .gitignore. This is BUILD-lane scaffolding only (no SDK runtime change), but the generators as landed cannot produce an app, and yarn test on CI will fail.

Findings

P0 — scripts/campaign/lib/*.js is missing, and .gitignore would hide it

  • Location: scripts/campaign/gen-rn-app.sh:152 (also gen-expo-app.sh)
  • Problem: Both generators node six helpers (use-jsc.js, readme-android.js, deviation-gradle-plugin.js, deviation-ios-bundle-phase.js, metro-port.js, workaround-fmt.js). None are in the tree. Root .gitignore has lib/, which matches any directory named lib/ — git check-ignore reports scripts/campaign/lib/metro-port.js as ignored.
  • Impact: gen-rn-app.sh dies on the first unconditional helper (README Android source-map edits). JSC, Gradle-plugin deviations, Metro port, and the fmt workaround never run. --readme-only still fails. Adding the files later with a normal git add is silently dropped.
  • Scenario: scripts/campaign/pack.sh then gen-rn-app.sh 0.81 (the documented N-21 path).
  • Fix: Add the helpers (or inline the edits). Negate them in .gitignore (!scripts/campaign/lib/) or put them under a name git will track (scripts/campaign/helpers/).

P1 — run-ios-configuration.test.ts still asserts the old APP= path

  • Location: examples/bare/scripts/run-ios.sh:71
  • Problem: APP is now $APP_DIR/$BUILD_DIR/Build/Products/${CONFIGURATION}-${SDK}/${SCHEME}.app. scripts/__tests__/run-ios-configuration.test.ts still requires APP="ios/build/Build/Products/${CONFIGURATION}-iphoneos/BareExample.app".
  • Impact: The js job (yarn test in .github/workflows/ci.yml) fails on this PR. The embed-check-follows-configuration contract is no longer pinned.
  • Scenario: Any CI run of this branch.
  • Fix: Update the test to the new interpolation and still require that the embed CLI receives the same $APP xcodebuild writes (including ios/build-spm and iphonesimulator).

P1 — Metro PORT is last-flag-wins; N-22 × N-23 collide

  • Location: scripts/campaign/gen-rn-app.sh:72-78
  • Problem: Each flag replaces PORT instead of composing it. yarn forces 8400+N, pnpm 8500+N, --readme-only 8600+N, so earlier JSC/readme offsets are discarded. Directory names stay unique (rn081-jscyarn vs rn081-yarn); ports do not.
  • Impact: Two variants of the same minor share Metro. launch-check.sh starts bundlers on the same port, and its cleanup lsof | kill on that port takes down the other lane. The script's own comment says unique ports exist so "another lane's Metro is never used".
  • Scenario: gen-rn-app.sh 0.81 --pm yarn and gen-rn-app.sh 0.81 --engine jsc --pm yarn (or --readme-only --pm yarn) launched together, then launch-check.sh debug on both.
  • Fix: Encode every variant bit into the port (or hash DIR into a free port) and write campaign.port from that. Do not overwrite.

P1 — Windows upload stub does not speak the symbol API; the check can false-pass

  • Location: .github/workflows/campaign-windows-hermes.yml:56-62
  • Problem: The in-repo stub (packages/react-native/scripts/__tests__/fixtures/symbol-stub-server.js) answers POST /apps/<token>/symbols with {code:0,endpoint:"http://127.0.0.1:<port>/put/N"} and then accepts the PUT of the map zip. This job's stub returns {ok:true,url:".../upload"} for every request. @bugsee/cli debug-files upload will not PUT the map. The later step only requires grep -v /ping stub.log to be non-empty, so the handshake POST (or the /ping probe if the filter is wrong) greens the job.
  • Impact: N-25 / HOOK-13 can record "source map reached the stub" without a map landing. A failed Windows Hermes path can also look like an upload success.
  • Scenario: assembleRelease gets far enough to spawn bugsee-cli (or even just the /ping + a failed POST). The artifact step still uploads.
  • Fix: Run symbol-stub-server.js --port 8777 --log ... and assert a PUT whose zip entry has the same debug_id as the composed map (the unit tests already do this).

P2 — launch-check.sh lock is an absolute External2TB path with no timeout

  • Location: scripts/campaign/launch-check.sh:31
  • Problem: LOCK=/Volumes/External2TB/Projects/Bugsee/cross/bugsee-react-native/.device-lock. until mkdir "$LOCK" uses mkdir without -p and never times out. If the volume is unmounted, every wait fails and the script loops every 30s forever. run-ios.sh comments talk about a repo-relative .device-lock; this path does not share it.
  • Impact: After a reboot (or on any other checkout) launch-check hangs instead of failing, and it will not serialize with a caller holding the repo lock.
  • Scenario: External2TB not mounted; or another lane using $REPO/.device-lock while this script uses the volume path.
  • Fix: Resolve the lock from the repo root (or CAMPAIGN_LOCK). Fail if the parent is missing. Keep the blocking acquire, but do not spin on ENOENT.

Residual (not filed)

  • Gradle on windows-latest invokes hermesc-preserve-js.sh as react.hermesCommand. That is the N-25 experiment; the job is on pull_request without continue-on-error, so a disprove will red this PR and any later packages/react-native/scripts/** change.
  • gen-expo-app.sh lses the feedback tarball up front under set -euo pipefail, so a missing feedback pack aborts even without --with-feedback. pack.sh writes both, so the documented path is fine.

Overall risk: High

Merge recommendation: Request changes

The N-20/N-21 generators cannot finish, and the js unit job will fail on the run-ios.sh path rewrite. Fix those and the Metro port / Windows stub before treating the BUILD lane as usable.

Most important to fix

  1. Land the campaign helpers (and stop .gitignore from eating scripts/campaign/lib/).
  2. Update run-ios-configuration.test.ts for the new APP=.
  3. Make Metro ports unique across combined --engine / --pm / --readme-only.
  4. Use the real symbol stub and assert a PUT of the map.

What looks solid

Placeholder tokens and https://127.0.0.1:9 everywhere a campaign app launches. Device allowlist + refused-prefix guard in run-ios.sh. pack.sh fails if plugin/build/index.js is missing from the npm tarball (W-2). SPM path backs up ios/ and restores on EXIT. Consumer tsc pins removed 6.x APIs with @ts-expect-error. The Windows workflow is clearly marked temporary.

Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

Comment thread scripts/campaign/gen-rn-app.sh
Comment thread scripts/campaign/gen-rn-app.sh
Comment thread examples/bare/scripts/run-ios.sh
Comment thread .github/workflows/campaign-windows-hermes.yml Outdated
Comment thread scripts/campaign/launch-check.sh Outdated

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Deep review of c0ad13a (campaign BUILD-lane tooling: N-20..N-25, N-27).

This is campaign harness code, not the wrapper. The intended matrix (generate from the packed tarball, build five targets, launch-check, Windows Hermes, SPM run-ios.sh) cannot actually run as committed: the generators depend on helper modules that are not in the tree, launch-check hangs off-machine, and N-25/N-27 can record a false pass.

Overall risk: High
Merge recommendation: Request changes

Must fix

  1. P0 — scripts/campaign/lib/*.js are missing, and root .gitignore lib/ would ignore them even if added. gen-rn-app.sh / gen-expo-app.sh die on the first helper (readme-android.js, metro-port.js, …). N-20..N-23 cannot generate an app from this PR.
  2. P1 — launch-check.sh takes a lock at /Volumes/External2TB/Projects/Bugsee/cross/bugsee-react-native/.device-lock with mkdir (no -p) in an infinite loop. Any machine without that volume hangs forever.
  3. P1 — IOS_LAUNCH=1 treats Bugsee iOS SDK as success. The native banner prints before Status.Launched; a hang at Launching (keychain -34018, placeholder against a live host) is recorded PASS. launch-check.sh correctly requires status=2 only.
  4. P1 — campaign-windows-hermes.yml never installs an Android SDK/NDK, then enables NDK upload via a non-placeholder token. windows-latest cannot assembleRelease as written, so N-25 does not measure Hermes-on-Windows.

Also fix

  1. P2 — build-app.sh skips cli-assert-framework-embedded.ts on simulator targets; run-ios.sh always asserts. An all / sim-only cell can PASS without Bugsee.framework.
  2. P2 — check-16kb.sh documents APK|AAB but on an AAB skips zipalign, extracts no .so, and prints PASS.

Positive: placeholder token + https://127.0.0.1:9 in campaign configs; BugseeLaunchOptions.serialize still runs endpointFor so iOS gets /v2; Windows upload uses a stub rather than api.bugsee.com; run-ios.sh simulator path correctly uses --console-pty (the e2e learned --console never delivers RN stdout).

Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

Comment thread scripts/campaign/gen-rn-app.sh
Comment thread scripts/campaign/launch-check.sh Outdated
Comment thread examples/bare/scripts/run-ios.sh Outdated
Comment thread .github/workflows/campaign-windows-hermes.yml
Comment thread scripts/campaign/build-app.sh
Comment thread scripts/campaign/check-16kb.sh

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Deep review of 7f0b102 (campaign BUILD-lane tooling: N-20..N-25, N-27).

This is harness code, not the wrapper. The generators, run-ios.sh switches, 16 KB check, launch-check, and the temporary Windows Hermes job were re-checked against the README Android snippet, the podspec/android/build.gradle native-versions walk, symbol-stub-server.js, write-credentials.mjs, e2e/device.ts allowlist, and cli-assert-framework-embedded.ts.

All prior P0–P2s are fully addressed. No remaining P0–P3.

Prior findings (now closed)

  • P0 scripts/campaign/lib/*.js is committed; .gitignore has !scripts/campaign/lib/ (git ls-files lists seven helpers; git check-ignore is clean).
  • P1 Metro ports compose per variant bit (8100+minor, +100 jsc, +200 yarn, +400 pnpm, +800 readme).
  • P1 run-ios-configuration.test.ts pins the new $APP / $SDK / $BUILD_DIR shape. CI lint, typecheck, unit is green on this SHA.
  • P1 Windows upload uses symbol-stub-server.js and requires a PUT whose zip entry debug_id matches the composed map. Run 37577419349 fails closed: no .hbc, then “no composed-map debug id” — that is the N-25 result, not a handshake false pass.
  • P1 IOS_LAUNCH accepts only BUGSEE_E2E status=2; the SDK banner is printed, never a pass. Generated RN apps get ios-log-mirror.js.
  • P1 CAMPAIGN_DEVICE_LOCK plus fail-fast if the lock parent is missing (launch-check and emulators sweep).
  • P1 Synthetic token’s plugin.ndk.enabled is stripped; the stub lives in the Gradle step; the job uses Gradle’s exit code. windows-latest did reach :app:createBundleReleaseJsAndAssets.
  • P2 build-app.sh ios-sim-* now runs cli-assert-framework-embedded.ts after a successful xcodebuild (7f0b102).
  • P2 check-16kb.sh takes an APK only; zero 64-bit .so examined is FAIL.

Residual (not defects)

  • The temporary campaign-windows-hermes.yml job is expected red until hermesc-preserve-js.sh produces .hbc on Windows, or the workflow is deleted after the campaign. It no longer greens without a map PUT.
  • The android CI job’s testDebugUnitTest failure on this SHA is the bridge unit suite, not this diff.

Overall risk: Low

Merge recommendation: Approve

Most important to fix

Nothing remaining for merge. Optional: continue-on-error (or drop pull_request) on the temporary Windows job if a red N-25 check is noisy in the merge box.

What looks solid

Placeholder token + https://127.0.0.1:9 in campaign configs; BugseeLaunchOptions.serialize still runs endpointFor so iOS gets /v2. Device allowlist + refused-prefix guard in run-ios.sh. pack.sh fails if plugin/build/index.js is missing from the npm tarball. SPM path backs up ios/ and restores on EXIT. Consumer tsc pins removed 6.x APIs with @ts-expect-error. W-1 copies native-versions.json to node_modules/ where both the podspec (../../ from the scoped package) and the Android walk-up find it.

Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Deep review — campaign BUILD-lane tooling at 7f0b102

Prior findings (missing lib/, colliding Metro ports, run-ios test path, Windows stub protocol, lock hang, IOS_LAUNCH_EXPECT banner, sim embed skip, AAB false-PASS) are fixed in e0197e6 / 7f0b102. This pass is against the generators, run-ios.sh, launch-check.sh, and the Windows job as they stand now — not the diff in isolation.

This is still BUILD-lane scaffolding (no SDK runtime change). The remaining issues are campaign-matrix false FAILs / false PASSes, not a production-app regression.

Findings

P1 — Documented XS launch path cannot pass a Debug campaign app
launch-check.sh is android / ios-sim only; the header tells operators to drive the iPhone XS with run-ios.sh (IOS_APP_DIR, IOS_LAUNCH=1). That path never starts Metro, and generated apps bake a unique RCT_METRO_PORT (not 8081). Default IOS_CONFIGURATION is Debug. Status=2 never appears.

P2 — Expo N-20 on device has no NSLog mirror
ios-log-mirror.js leaves Expo's AppDelegate alone. devicectl ... --console does not stream os_log, which is where RN 0.87 console.log goes. Release Expo on the XS also false-FAILs.

P2 — --no-workarounds / --readme-only do not mean what the header says
W-3 (fmt C++17) always runs. R-4 (allowBuilds for pnpm) always runs. Those cells cannot reproduce the bugs they exist to log.

P2 — emulators.sh sweep never fails, and early launch-check exits skip the TSV
|| true plus grep PASS|FAIL hides Metro/install crashes that never write launch-results.tsv.

P2 — gen-expo-app.sh exits 0 if the config plugin did not apply
The two grep -q … && log checks are the N-20 assertion and do not fail the generator.

Overall risk: Medium

Merge recommendation: Request changes

Fix the XS Debug launch path (start Metro on campaign.port, or refuse Debug without it) before treating N-27 device cells as green. The P2s are campaign-integrity issues: a sweep or --no-workarounds cell can look like a pass while hiding the finding.

Most important to fix

  1. run-ios.sh IOS_LAUNCH=1 + Debug + unique Metro port
  2. Gate W-3 on --no-workarounds (and R-4 on --readme-only)
  3. Make emulators.sh sweep fail when a launch-check fails, and always write a TSV row

What looks solid

Helpers are tracked (!scripts/campaign/lib/). Ports compose per variant bit. check-16kb.sh refuses AABs and fails when zero 64-bit .sos are examined. ios-sim-* now runs the embed assertion. Windows uses the real symbol stub, drops plugin.ndk.enabled, and fails on Gradle's exit code. IOS_LAUNCH_EXPECT is BUGSEE_E2E status=2 only.

Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

Comment thread examples/bare/scripts/run-ios.sh Outdated
Comment thread scripts/campaign/lib/ios-log-mirror.js
Comment thread scripts/campaign/gen-rn-app.sh Outdated
Comment thread scripts/campaign/emulators.sh Outdated
Comment thread scripts/campaign/gen-expo-app.sh Outdated

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Deep review — campaign BUILD-lane tooling at 6ebb951

Reviewed against the generators, run-ios.sh, launch-check.sh, Expo's setPackageInBuildGradle, e2e/scenario.ts metroArgs / DeviceConsole, and the RN 0.81 / Expo 54–57 AppDelegate templates — not the diff in isolation.

6ebb951 is a real fix, not a drive-by. Expo prebuild rewrites applicationId "…" to applicationId 'com.bugsee.campaign.expo…' (@expo/config-plugins setPackageInBuildGradle). The old double-quote-only parse returned empty, so N-20 Android launch-check exited before a TSV row. ios-sim Debug now passes -RCT_jsLocation localhost:<campaign.port>, which is the same lever warm-simulator-metal.sh and e2e/scenario.ts already use, because RCT_METRO_PORT on React-Core does not reach a prebuilt core (0.84+). That was the missing piece for simulator Debug.

The documented XS path is still run-ios.sh (IOS_APP_DIR, IOS_LAUNCH=1). That path still does not start Metro and still does not pass RCT_jsLocation. This is BUILD-lane scaffolding (no SDK runtime change); remaining issues are campaign-matrix false FAILs / false PASSes.

Closed this pass: the prior P2 that Expo's AppDelegate is skipped by ios-log-mirror.js. Expo SDK 54–57 AppDelegate has import React and the same multiline didFinishLaunchingWithOptions … = nil / ) -> Bool { the inject regex requires, so campaignMirrorMarkers() is applied. The file header comment is stale; N-20 device --console can see markers on Release.

CI on this SHA: lint, typecheck, unit green. Windows Hermes job red as expected (no .hbc). Did not run Jest locally (node_modules absent). Did confirm the applicationId regex against Expo's single-quoted rewrite and the log-mirror regex against Expo 54/57 and RN 0.81 AppDelegate shapes.

Findings

P1 — IOS_LAUNCH=1 never starts Metro and never sets RCT_jsLocation
Documented XS / N-27 path. Default IOS_CONFIGURATION is Debug. 0.84+ therefore loads 8081 (another lane's Metro, or nothing). A physical iPhone also cannot use localhost.

P2 — --no-workarounds / --readme-only still do not mean what the header says
W-3 (fmt C++17) always runs. R-4 (allowBuilds for pnpm) always runs.

P2 — emulators.sh sweep never fails; early launch-check exits skip the TSV
|| true plus grep PASS|FAIL hides Metro/install crashes that never append launch-results.tsv.

P2 — gen-expo-app.sh exits 0 if the config plugin did not apply
The two grep -q … && log checks are the N-20 assertion and are not fatal.

Overall risk: Medium

Merge recommendation: Request changes

Fix the XS Debug launch path (Metro on campaign.port + RCT_jsLocation, Mac IP and devicectl -- on device) before treating N-27 device cells as green. The P2s are campaign-integrity issues: a sweep or --no-workarounds cell can look like a pass while hiding the finding.

Most important to fix

  1. run-ios.sh IOS_LAUNCH=1 + Debug: start Metro, pass -RCT_jsLocation (device: LAN host, -- before args)
  2. Gate W-3 on --no-workarounds (and R-4 on --readme-only)
  3. Make emulators.sh sweep fail when a launch-check fails, and always write a TSV row

What looks solid

6ebb951 matches the e2e Metro contract on ios-sim. Expo applicationId quotes now parse. Helpers are tracked (!scripts/campaign/lib/). Ports compose per variant bit. check-16kb.sh refuses AABs and fails when zero 64-bit .sos are examined. ios-sim-* runs the embed assertion. Windows uses the real symbol stub, drops plugin.ndk.enabled, and fails on Gradle's exit code. IOS_LAUNCH_EXPECT is BUGSEE_E2E status=2 only. Placeholder token + https://127.0.0.1:9 in campaign configs.

Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

Comment thread examples/bare/scripts/run-ios.sh Outdated
Comment thread scripts/campaign/gen-rn-app.sh Outdated
Comment thread scripts/campaign/emulators.sh Outdated
Comment thread scripts/campaign/gen-expo-app.sh Outdated
@krassx

krassx commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

android release (windows-latest) is red on purpose: it is a product finding (BLK-07 / Task 13.7), not runner setup.

Root cause: the bare example sets react.hermesCommand to @bugsee/react-native/scripts/hermesc-preserve-js.sh, as the package README says. On Windows React Native's Gradle plugin runs that command through windowsAwareCommandLine, i.e. cmd /c <...>\\scripts\\hermesc-preserve-js.sh -emit-binary -out ...hbc ... (BundleHermesCTask.kt:173, detectOSAwareHermesCommand keeps a user-set command). cmd cannot execute a bash script: nothing compiles, the step exits 0, and RN then fails moving the bytecode:

> Task :app:createBundleReleaseJsAndAssets FAILED
> kotlin.io.NoSuchFileException: D:\a\...\examples\bare\android\app\build\generated\assets\react\release\index.android.bundle.hbc: The source file doesn't exist.

Runs 37566757670, 37567458498, 37584777337, 37587420367 (same failure each time; the SDK, NDK and JS bundling all work, the build reaches the Hermes step). So a Hermes release build of any app integrated per the README (bare or Expo, whose plugin writes the same hermesCommand) cannot be built on a Windows host. The fix is product work (a Windows-runnable preserve wrapper, e.g. a .cmd/node entry point selected per OS), tracked as Task 13.7; this job will turn green when that lands and then proves the composed map, the debug id in the bytecode and the upload to the stub.

🤖 Generated with Claude Code

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Deep review — campaign BUILD-lane tooling at 155bfcb

Reviewed against the generators, run-ios.sh, launch-check.sh, emulators.sh sweep, e2e/scenario.ts (nonce + log attachment), and the campaign App templates — not the diff in isolation.

155bfcb closes the previous round. IOS_LAUNCH=1 Debug now starts Metro on campaign.port (else E2E_METRO_PORT / 8081), passes -RCT_jsLocation host:port (localhost on sim, E2E_METRO_HOST or en0 on device, -- before devicectl args), and uses the 180 s budget. W-3 is behind --no-workarounds; R-4 (allowBuilds) is behind --readme-only. Plugin greps in gen-expo-app.sh are fatal. launch-check writes a FAIL TSV row on every exit after the lock; emulators.sh sweep exits 1 when any cell failed. Author verified rn086 Debug on the simulator through run-ios.sh (status=2).

This is still BUILD-lane scaffolding (no SDK runtime change). One campaign-integrity hole remains on the Android launch path the sweep actually uses.

CI on this SHA: lint, typecheck, unit green. Windows Hermes job red as expected (preserve wrapper is a shell script). Did not run Jest locally (node_modules absent).

Findings

P2 — Android launch-check can false-PASS on stale logcat and false-FAIL if logcat attaches late
The wait is grep BUGSEE_E2E status=2 in $OUT. The app logs that line once, on a status transition (template/App.tsx / examples/expo/App.js). The e2e harness uses a per-run nonce for exactly this class of stale/missed marker. This script does not.

Overall risk: Low

Merge recommendation: Request changes

Fix the Android log attachment before treating emulators.sh sweep cells as green. The rest of round 2 is solid.

Most important to fix

  1. launch-check.sh Android: succeed-or-exit on logcat -c, wait until logcat is attached (iOS already sleep 2s), and accept status=2 only after a fresh BUGSEE_E2E launching from this run (or a nonce).

What looks solid

155bfcb matches the e2e Metro contract on the XS/run-ios.sh Debug path (start bundler, RCT_jsLocation, devicectl --). Helpers are tracked. Ports compose per variant bit. check-16kb.sh refuses AABs and fails when zero 64-bit .sos are examined. Windows uses the real symbol stub and Gradle's exit code. IOS_LAUNCH_EXPECT is BUGSEE_E2E status=2 only. Placeholder token + https://127.0.0.1:9 in campaign configs.

Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

Comment thread scripts/campaign/launch-check.sh

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Deep review — campaign BUILD-lane tooling at 647a021

Reviewed against the generators, run-ios.sh, launch-check.sh (including the new pid-gated wait), emulators.sh sweep, e2e/device.ts logcat/devicectl contracts, and the Windows Hermes job — not the diff in isolation.

647a021 closes the previous round. Android launch-check now fails on logcat -c, kills and waits the previous dump, sleeps 2 s before monkey (same attach delay as iOS), and treats status=2 as a pass only after this run's BUGSEE_E2E launching on line from the same process (-v time (pid) / compact [pid:). The Windows job is continue-on-error with the BLK-07 / Task 13.7 root cause written on the job; run 37589901572 is job-red at createBundleReleaseJsAndAssets and workflow-green, which is the intended merge-box behavior until fix/windows-hermes-release removes the line.

All prior P0–P2 threads are fully_addressed. This is still BUILD-lane scaffolding (no SDK runtime change). No remaining correctness holes on the sweep / XS / N-25 paths that would record a false PASS or hide a failed cell.

I replayed launched_this_run against -v time and compact [pid:tid] fixtures (including hex tids and a subsystem bracket): a lone stale status=2 FAILs; a same-pid launching→status=2 PASSes; a different-pid status=2 FAILs.

CI: ci on 155bfcb SUCCESS (37587420787). ci on this SHA (37589902003) was still queued at review. Did not run Jest locally (node_modules absent).

Findings

None remaining (P0–P2).

Residual, not a merge blocker: the awk still keys off the first launching line in $OUT. A stale launching+status=2 pair left in the logcat buffer after a lying logcat -c would still PASS. That is the old race after the dump has been waited on and -c has been checked; not filing.

Overall risk: Low

Merge recommendation: Approve

Most important to fix

Nothing remaining for merge.

What looks solid

IOS_LAUNCH=1 Debug starts Metro and passes -RCT_jsLocation (localhost / E2E_METRO_HOST or en0, -- for devicectl). W-3 / R-4 are behind the flags that exist to reproduce them. Plugin greps in gen-expo-app.sh are fatal. Sweep records a FAIL row on every exit and itself exits 1. Helpers are tracked; ports compose per variant bit; check-16kb.sh refuses AABs and fails when zero 64-bit .sos are examined. Windows uses the real symbol stub and Gradle's exit code. Placeholder token + https://127.0.0.1:9 in campaign configs.

Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Deep review — campaign BUILD-lane tooling at d9ed0cb

Reviewed against the generators, run-ios.sh, launch-check.sh, the Expo plugin’s rewriteHermesCommand, bugsee-sourcemaps.gradle’s Windows cmd rewrite, the preserve wrapper, and the temporary Windows workflow — not the diff in isolation.

d9ed0cb merges the Task 13.7 / BLK-07 product fix into this campaign branch: hermesc-preserve-js.js plus .cmd/.sh launchers, a per-OS hermesCommand, the leftover-.sh guard, and a relative launcher when cmd would cut the absolute path. readme-android.js now refuses a split README line and requires both launchers. All prior campaign P0–P2 threads remain fully_addressed.

This is still BUILD-lane scaffolding plus the Windows Hermes product path. One merge-integrity hole is new: the job that was allowed to stay red for BLK-07 still has that exception after the fix is in the tree.

Did not run Jest (node_modules absent). CI on this SHA was still in progress at review (ci 37924486047, campaign windows hermes 37924485585). Last green ci on this branch was 37589902003 at 647a021.

Findings

P2 — android-release still continue-on-error after the product fix landed
The comment on that job says the fix/windows-hermes-release branch removes the flag so the job gates merge. That fix is now commit d9ed0cb on this PR. expo-android-release and android-release-spaced-path already fail the workflow; this first job is the only one that runs the Windows wrapper tests and the leftover-.sh guard.

Overall risk: Medium

Merge recommendation: Request changes

Drop continue-on-error on android-release (and the stale “KNOWN FAILURE” comment) so N-25 actually gates the product path this PR now ships. Campaign generators / launch-check / run-ios.sh look solid.

Most important to fix

  1. Remove continue-on-error: true from .github/workflows/campaign-windows-hermes.yml android-release.

What looks solid

Prior campaign holes stay closed: helpers tracked, Metro ports compose per variant bit, IOS_LAUNCH Debug starts Metro and passes -RCT_jsLocation, W-3/R-4 are behind the flags that exist to reproduce them, launch-check writes a FAIL row on every exit and keys status=2 to this run’s pid, check-16kb.sh refuses AABs. The preserve wrapper fails closed when hermesc writes no bytecode; the Gradle hook relativizes a Windows launcher that cmd would cut, and the README snippet the generator copies is one whole per-OS line.

Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

Comment thread .github/workflows/campaign-windows-hermes.yml Outdated

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Deep review — campaign BUILD-lane tooling at 037230a

Reviewed against the generators, run-ios.sh, launch-check.sh, emulators.sh sweep, the Expo plugin’s rewriteHermesCommand, bugsee-sourcemaps.gradle’s Windows cmd rewrite, the preserve wrapper, and the temporary Windows workflow — not the diff in isolation.

037230a closes the previous round. continue-on-error is gone from android-release; the comment now describes the job as the blocking N-25 / BLK-07 proof. Windows Hermes run 37924485585 on d9ed0cb (the product fix) is SUCCESS on all three jobs: android-release, expo-android-release, and android-release-spaced-path. 037230a is that flag/comment only.

All prior campaign P0–P2 threads are fully_addressed. This is still BUILD-lane scaffolding plus the Windows Hermes product path. Two campaign-integrity holes remain.

Did not run Jest (node_modules absent). ci on d9ed0cb (37924486047) was still in progress at review.

Findings

P2 — build-app.sh iOS embed check has no Node ≥22.18 gate
After the sim-embed fix, build-app.sh runs cli-assert-framework-embedded.ts with no version check. run-ios.sh already exits 2 when Node is older, because type-stripping of a .ts entry point only works from 22.18 and older Node throws ERR_UNKNOWN_FILE_EXTENSION with exit 1 — the same code as “framework missing”.

P2 — emulators.sh boot can hold .device-lock forever
adb wait-for-device and the sys.boot_completed loop have no timeout. Sweep takes the shared campaign lock before boot. A wedged AVD (corrupt image, emulator crash after create) never releases the lock; launch-check / other sweeps sleep 30s forever. Ctrl-C does run the EXIT trap; an unattended sweep does not.

Overall risk: Medium

Merge recommendation: Request changes

The Windows product path and the continue-on-error hole are done. Gate the embed check the same way run-ios.sh does, and bound emulator boot so a dead AVD cannot pin the device lock.

Most important to fix

  1. Copy run-ios.sh’s Node ≥22.18 gate before both iOS assert calls in build-app.sh; treat exit 2 as tooling, not an embed miss.
  2. Bound emulators.sh boot (e.g. 5–10 min); on timeout kill the emulator, drop the lock, fail that AVD.

What looks solid

037230a makes N-25 blocking. Helpers are tracked; Metro ports compose per variant bit; IOS_LAUNCH Debug starts Metro and passes -RCT_jsLocation; W-3/R-4 are behind the flags that exist to reproduce them; launch-check writes a FAIL row on every exit and keys status=2 to this run’s pid; check-16kb.sh refuses AABs. The preserve wrapper fails closed when hermesc writes no bytecode; the leftover-.sh guard and cmd-safe relative rewrite are the Windows customer path, and that path is green on windows-latest including a path with spaces and parentheses.

Residual, not filed: run-ios.sh still proceeds if Metro /status never says running (false FAIL after 180s, not a false PASS). The leftover-.sh guard’s suggested fix is the README bugseeDir form; Expo prebuild writes HERMES_COMMAND_EXPR instead, and --no-clean only migrates the exact legacy plugin .sh line — bare README upgrades have bugseeDir and paste correctly.

Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

Comment thread scripts/campaign/build-app.sh
Comment thread scripts/campaign/emulators.sh

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Deep review — campaign BUILD-lane tooling at 18732ae

Reviewed against the generators, run-ios.sh, launch-check.sh, emulators.sh sweep, the Expo plugin’s rewriteHermesCommand, bugsee-sourcemaps.gradle’s Windows cmd rewrite, the preserve wrapper, and the temporary Windows workflow — not the diff in isolation.

18732ae closes the previous round. Both remaining campaign P2s are fixed:

  1. Node ≥22.18 gate. build-app.sh embed_check now runs the same node -e version check as run-ios.sh before cli-assert-framework-embedded.ts. An older Node’s ERR_UNKNOWN_FILE_EXTENSION (exit 1, the same code as a missing framework) is recorded as TOOLING with the gate’s message, never as an embed FAIL. Both ios-sim-* and ios-device-* go through this helper; overall still exits 1.
  2. Bounded emulator boot. emulators.sh boot dropped unbounded adb wait-for-device. The sys.boot_completed wait uses BOOT_TIMEOUT (default 600 s). On timeout the emulator is killed, boot exits 3, and sweep records that AVD as FAIL, rmdirs .device-lock, and continues with the next AVD.

All prior campaign P0–P2 threads are fully_addressed. This is still BUILD-lane scaffolding plus the Windows Hermes product path. No remaining correctness holes that would record a false PASS, hide a failed cell, or pin the shared device lock.

Did not run Jest (node_modules absent). This environment’s Node is 22.14.0 — the case the new gate is for. ci and Windows Hermes last completed on d9ed0cb (37924486047 SUCCESS, 37924485585 all three jobs SUCCESS). 18732ae only touches build-app.sh / emulators.sh, so the Windows workflow correctly does not re-run.

Findings

None remaining (P0–P3).

Overall risk: Low

Merge recommendation: Approve

Most important to fix

Nothing remaining for merge.

What looks solid

18732ae matches run-ios.sh on the embed-check Node floor and no longer lets a dead AVD hold .device-lock. Helpers are tracked; Metro ports compose per variant bit; IOS_LAUNCH Debug starts Metro and passes -RCT_jsLocation; W-3/R-4 are behind the flags that exist to reproduce them; launch-check writes a FAIL row on every exit and keys status=2 to this run’s pid; check-16kb.sh refuses AABs. The preserve wrapper fails closed when hermesc writes no bytecode; the leftover-.sh guard and cmd-safe relative rewrite are the Windows customer path, and that path is green on windows-latest including a path with spaces and parentheses. N-25 is blocking (continue-on-error is gone).

Residual, not filed: run-ios.sh still proceeds if Metro /status never says running (false FAIL after 180 s, not a false PASS). If an emulator process never appears on ADB, timeout emu kill is a no-op and that qemu may linger — the campaign lock is still released.

Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

krassx added 10 commits October 9, 2026 18:18
Generator for one bare app per React Native minor integrated from the
packed tarball by the package README (deviations and workarounds logged),
Expo SDK 54-57 apps from examples/expo, JSC and package-manager variants
with a consumer type-check, the 16 KB alignment check, a temporary
windows-latest Hermes release workflow, run-ios.sh delivery/target/app
switches (SPM), launch checks and the emulator sweep AVDs.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
- un-ignore scripts/campaign/lib (the root .gitignore's lib/)
- Metro ports compose per variant flag, no collisions
- run-ios.sh IOS_LAUNCH passes only on BUGSEE_E2E status=2
- launch-check/emulators: CAMPAIGN_DEVICE_LOCK, fail fast on a missing lock dir
- check-16kb: APK only; zero 64-bit libraries examined is a FAIL
- windows workflow: the repo's symbol stub, PUT with the composed map's
  debug id asserted, no NDK upload, Gradle's exit code decides
- ios-log-mirror: BUGSEE_E2E markers reach NSLog in generated apps

🤖 Generated with [Claude Code](https://claude.com/claude-code)
…ts simulator Debug at the app's Metro with RCT_jsLocation

🤖 Generated with [Claude Code](https://claude.com/claude-code)
- run-ios.sh IOS_LAUNCH Debug: the app's own Metro (started if needed),
  -RCT_jsLocation host:port (devicectl after --), 180 s budget
- gen-rn-app: W-3 only with workarounds, R-4 only without --readme-only
- gen-expo-app: a prebuild without the plugin's Gradle/bundle-phase edits fails
- launch-check writes a FAIL row on every early exit; emulators.sh sweep
  exits non-zero when any launch failed

🤖 Generated with [Claude Code](https://claude.com/claude-code)
…b continue-on-error (BLK-07)

- launch-check: logcat -c checked, previous dump waited for, 2 s attach,
  PASS needs status=2 after this launch's own 'launching' line from the
  same pid
- campaign-windows-hermes: continue-on-error with the BLK-07 / Task 13.7
  root cause; the job still runs red; the fix branch
  fix/windows-hermes-release removes the line

🤖 Generated with [Claude Code](https://claude.com/claude-code)
)

* Android: Hermes release builds on Windows hosts (Task 13.7, BLK-07)

React Native runs react.hermesCommand through `cmd /c` on Windows
(BundleHermesCTask getHermescCommand -> windowsAwareCommandLine), and a
user-set command is kept as is (detectOSAwareHermesCommand). cmd cannot run
hermesc-preserve-js.sh: it exited 0, wrote no bytecode, and the task failed
later with NoSuchFileException on index.android.bundle.hbc.

- The wrapper's work moves to scripts/hermesc-preserve-js.js (Node). Two
  launchers start it: hermesc-preserve-js.sh (macOS, Linux; existing builds
  keep working) and hermesc-preserve-js.cmd (Windows, CRLF via
  .gitattributes). hermesc is found as before, with win64-bin/hermesc.exe
  on Windows.
- The wrapper exits non-zero whenever no bytecode came out: hermesc exited
  0 with no or an empty -out (a stale file is removed first), was killed,
  could not start, or no -out was given.
- hermesCommand picks the launcher when Gradle configures:
  System.getProperty("os.name").startsWith("Windows") ? .cmd : .sh, so one
  build.gradle serves a repo shared across macOS, Linux and Windows. README,
  bare example and the Expo plugin write it.
- Expo plugin: the exact line an earlier prebuild wrote (the .sh on every
  OS) is moved to the per-OS one; a user's own hermesCommand that names
  hermesc-preserve-js stays. Corpus cases for both.
- bugsee-sourcemaps.gradle: on Windows a Hermes bundle task whose
  hermesCommand names a .sh fails before hermesc, with the line to use.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* campaign: Windows Hermes release job covers Expo and the .sh guard

The windows-latest workflow now also runs the wrapper tests on Windows
(the .cmd through cmd /c with the repository's hermesc.exe), checks that a
.sh hermesCommand fails the bundle task with the fix before hermesc, and
builds the Expo example after an `expo prebuild` on the runner: composed
map debug id, the same id in the APK bytecode, and the upload to the stub.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* Preserve wrapper: tests for every helper; drop a redundant setter check

Scoped mutation run (stryker.plugin.json, --mutate on hermesc-preserve-js.js
and the hermesCommand rewrite in gradle.ts): 93.86 -> 98.25, the wrapper at
100. The setter-call check before the legacy match could not change the
outcome (a setter's value carries its closing bracket), so it goes. The
command-line entry runs only in a child process and is excluded from
mutation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* Preserve wrapper tests: absolute paths and real paths that hold on Windows

The windows-latest run showed three test-only failures: a rootless path
gains a drive letter when resolved, and the runner's temp directory comes
back in 8.3 short form from realpathSync. The launcher tests (the .cmd
through cmd /c with hermesc.exe) passed there.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* README: hermesCommand on one line; the campaign extractor checks it whole

Cursor review (PR 65): scripts/campaign/lib/readme-android.js copies the
README's hermesCommand with a one-line match, so the two-line per-OS
value was cut after `new File(new File(bugseeDir, "scripts"),` and every
generated bare app would fail to configure. The README keeps the value on
one line, the shape the Expo plugin writes, and the extractor now refuses
a value whose brackets do not close on its line or that does not name both
launchers. Test: the real README goes through the extractor whole, and a
split value is refused.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* Preserve wrapper tests: resolveFrom compares native real paths (Windows 8.3)

Cursor review (PR 65): the resolveFrom test still used realpathSync, which
keeps the runner's 8.3 temp path, while require.resolve returns the long
form; it failed on windows-latest before the release build ran.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* campaign: the Windows guard step exits 0 once the expected failure is seen

pwsh ended the step with Gradle's last exit code, the very failure the step
expects; run 37593316440 printed 'guard: failed with the fix, before
hermesc' and still went red.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* campaign: Windows bare release from a path with spaces and parentheses

Same release build, debug-id and stub-upload checks as the bare job, from
a checkout under 'my projects (x86)/bugsee rn': React Native runs
hermesCommand through cmd /c, whose quote handling changes when the
command path holds spaces or ( ).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* campaign: the spaced-path job builds from a short root

Under the workspace, 'my projects (x86)/bugsee rn' pushed the New
Architecture codegen objects past Windows' 260-character limit, and CMake
failed before any JavaScript step. That is React Native's path-length
limit, not the spaces; the job now copies the checkout to 'C:/s (x86)/b rn'.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* Android: Windows hermesCommand survives a project path with spaces and ( )

The new windows-latest job from 'C:/s (x86)/b rn' (run 37601601358) failed
in createBundleReleaseJsAndAssets with "'C:\s' is not recognized": React
Native runs hermesCommand through cmd /c, and cmd strips the quotes around
a command path that holds spaces together with ( ) & ^ @ < > |, then runs
it cut at the first space. React Native passes its own paths relative to
the project root and runs hermesc from there; on Windows the hook now does
the same for hermesCommand when its absolute path would be cut (another
drive, or a relative path that would be cut too, keeps it as written).
README says so. The spaced-path job also splits its artifact, since
upload-artifact needs one root.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* Android: the Windows relative hermesCommand may hold @

Run 37602820088 still ran the absolute launcher: the relative form,
node_modules\@bugsee\..., was rejected for its @. That character only
matters inside cmd's quote rule; an unquoted relative path is cut only by
a space or an operator (& < > ^ |), which is now the whole check.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* Android: Windows hermesCommand rewrite also covers ( ) without a space

Cursor review (PR 65): c34ceba dropped ( ) from the check, so an absolute
launcher path like C:\Users\John(US)\... (no space, so Java does not quote
it) was kept, and cmd groups at the bracket. Two checks now: an absolute
path holding a space or ( ) & < > @ ^ | is given relative to the project
root, and that relative path is used unless it holds a space or
( ) & < > ^ | (@ is fine unquoted). The helper is kept on the project, and
the real-Gradle hook test runs it on eight paths: the campaign's spaced
path with @, John(US), plain, an operator, another tree, and an already
relative path. README names both shapes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
…is fixed

The job was allowed to fail while the Windows hermesCommand defect was open.
#65 fixed it, so drop continue-on-error and describe the job as the blocking
N-25 proof it now is.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
…boot wait

build-app.sh ran the .ts embed check without the Node version gate run-ios.sh
has, so an older Node's ERR_UNKNOWN_FILE_EXTENSION (exit 1) was recorded as an
embed FAIL. It now checks first and records TOOLING instead.

emulators.sh waited for boot without a limit while a sweep held the shared
device lock. The wait is bounded (BOOT_TIMEOUT, default 600 s); on timeout the
emulator is killed, the sweep records the AVD as FAIL, releases the lock and
moves on.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@krassx
krassx force-pushed the campaign/build-variants branch from 18732ae to c460da8 Compare October 9, 2026 13:19

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deep review — campaign BUILD-lane tooling at c460da8

Re-reviewed #61 at c460da8 (prior 18732ae). Base is main @ d957f55. The campaign scripts are unchanged vs the last approve; this synchronize rebases them with the Windows Hermes product fix (BLK-07 / Task 13.7), which is how that work reaches main.

Looked at the generators (gen-rn-app.sh / gen-expo-app.sh + scripts/campaign/lib/*), build-app.sh / embed_check, emulators.sh boot|sweep, launch-check.sh (including the launching-then-status=2 awk), run-ios.sh, the Windows Hermes workflow, and the customer-facing wrapper path (hermesc-preserve-js.js + .cmd/.sh, plugin HERMES_COMMAND_EXPR, bugsee-sourcemaps.gradle cmd-safe rewrite and .sh-on-Windows guard). Also checked Expo SDK 54/57 Podfile templates: react_native_post_install( is multi-line, so metro-port.js / workaround-fmt.js still match.

All 24 prior threads remain fully_addressed (helpers committed; composed Metro ports; embed path + Node ≥22.18 as TOOLING; stub PUT + debug_id; lock parent fail-fast; launch-check FAIL rows; plugin-apply greps fail the generator; status=2 only after this launch’s launching line; Windows job required; boot wait bounded).

No remaining P0–P3.

Did not run Jest (node_modules absent). Node in this environment is 22.14.0 (the gated embed-check case). CI on c460da8 was still in flight at review time — the three Windows Hermes jobs are now required proofs, so they need to go green before merge.

Overall risk: Low

Merge recommendation

Approve. Merge once CI is green, especially android release (windows-latest) / Expo / spaced-path.

Most important issues to fix

None.

Positive observations

  • Old Node is TOOLING (rc 99), not an embed FAIL, matching run-ios.sh.
  • A wedged AVD no longer holds .device-lock forever: BOOT_TIMEOUT (600s), sweep records FAIL, unlocks, continues.
  • One build.gradle serves macOS/Linux/Windows (hermesCommand picks .cmd vs .sh at configure time); leftover .sh on Windows fails in doFirst with the README line, not a later missing .hbc.
  • readme-android.js copies the README hermesCommand as one per-OS line and refuses a split value.
Open in Web View Automation 

Sent by Cursor Automation: Bugsee code review

@krassx
krassx merged commit 990e999 into main Oct 9, 2026
50 checks passed
@krassx
krassx deleted the campaign/build-variants branch October 9, 2026 14:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant