Repository navigation
Task 8.1: upload with severity and labels, and showReportDialog - #18
Conversation
…through R8 Co-authored-by: Cursor <cursoragent@cursor.com>
…rom render
Banner: Bugsee Android SDK 7.3.0 [beb390dc0].
One handled payload (nonce 6877ef246252):
{"name":"TypeError","reason":"E2E handled 6877ef246252","frames":[{"data":{"member":"bugseeE2EThrowSite"},"debug_id":"8a1c2f4e-0d3b-5e6f-9a7b-6877ef246252"}],"cause":{"name":"RangeError","reason":"inner 6877ef246252"},"signature":"8362dd3b5785297d7d387925b94ce0ea5e857cfc","platform_os":"android","debug_ids":{"http://localhost:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=com.bareexample&modulesOnly=false&runModule=true&excludeSource=true&sourcePaths=url-server":"8a1c2f4e-0d3b-5e6f-9a7b-6877ef246252"}}
Gated release R1–R3 bundles (nonce 824ac61adb58): exactly one crash,
com.bugsee.reactnative.ReactNativeWebException, reason JSON with
"E2E fatal 824ac61adb58". No JavascriptException Bugsee bundle observed
(R2 prediction unmet; assertion left intact for controller ruling).
Thread: exception handled sent tid→comm BugseeRN-except (TASK_COMM_LEN
truncation of BugseeRN-exceptions).
Co-authored-by: Cursor <cursoragent@cursor.com>
Controller ruling: R13's second Bugsee crash is not retained on Android SDK 7.3.0. Logcat still shows FATAL EXCEPTION / JavascriptException and the process dies; Bugsee keeps exactly one crash named ReactNativeWebException. Gated R2/R3 updated; debug case 10 stays it.failing. awaitBundles(1) for the release beforeAll. Release verify (WOD_LX1): R1–R3 PASS; one bundle 894ba5df-af93-4d4b-9678-5d06ec218db4.bundle.zip. Co-authored-by: Cursor <cursoragent@cursor.com>
ExceptionStage registers _bugseeDebugIds synchronously before mounting BugseeE2EThrower, so the map exists for the first render throw. Root polls for a crash with the boundary reason instead of requiring two bundles. Release R1 asserts exactly one ours. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…cannot be lost Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
beta3 0d9c9d0a-9 stores the unhandled report and does not claim override_report.plcrash on the next launch. The one-crash asserts stay it.failing so an empty recovery list cannot pass as the desired outcome. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Stale comment
Deep review (c437703, Task 8.1)
Reviewed against the Phase 8 plan, the existing
upload(summary, description)call sites, both native SDKs (Android 7.3.0 AAR + iOS 7.0.0-beta3 headers), and the report-handler path this API feeds. No P0–P3 with a credible failure scenario.What I checked
- JS contract. Two-arg
uploadstill compiles and crossesseverity=0/labels=null. Explicit0,6,2.5, non-numbers, non-string labels, and a fifth argument are rejected before the bridge; error text does not echo the rejected value. Labels are copied.showReportDialog()crossesnull, null, 0, null.- Severity mapping. JS
IssueSeverity.Criticalis4. Android usesIssueSeverity.fromIntValueafter a 1..5 guard (the one-argfromIntValuewould otherwise snap unknowns toVeryLow;values()[4]isBlocker). iOS upload resolves0throughBugseeOptionReportingDefaultBugPriorityor High (3); requested 1..5 wins. Tests pin value-not-ordinal and reject a boolean-boxed launch option.- Android 7.3.0.
showReportDialog()is literally four nulls into the same internal method.createBugReportAndUpload/createAndPrepareBugReportskipsetSeverity/setLabelswhen those arguments are null, so omitted fields keep the SDK default. Labels are materialized withtoArrayList()on the native-modules thread before the UI hop, so theReadableArrayis not used after the method returns. Void methods catchRuntimeExceptionso an SDK throw cannot kill the host.- iOS 7.0.0-beta3. Dialog summary/description are
nonnull, so nil becomes@""as specified. Labels are_Nullable. The no-arg selector is used only when every argument is absent; otherwise0severity is left for the SDK’sif (level)skip. Upload cannot use the two-arg selector once labels exist, which is why0is resolved natively. Both run insideBGSRNRunOnMain. Existing two-arg scenario calls are unchanged.- Compatibility. TurboModule spec grows
uploadby two required parameters and addsshowReportDialog.ios-spec-coveragederives selectors from the spec (upload:description:severity:labels:,showReportDialog:description:severity:labels:). RN compat 0.81–0.87 is green on this SHA.I did not run the workspace Jest locally (no
node_modulesin this agent). CI on this SHA: android, ios cocoapods/spm, ios unit (BugseeRNSupport), ios e2e simulator, and rn compat 0.81–0.87 all passed.lint, typecheck, unit, mutationwas still running at review time.Device proof that severity/labels land in retained bundles is Task 8.3a, which this PR correctly leaves out.
Overall risk: Low
Merge recommendation
Safe to merge into
feat/phase-7-5bfor this slice. Task 8.2a is based on this branch; nothing here needs to wait on 8.3a.Most important issues to fix
None for this PR.
Positives
The ordinal trap is treated as load-bearing (Android test literally asserts
values()[4]is Blocker while wire4is Critical). TheincludeVideofifth-argument guard fails 6.x call sites loudly instead of dropping the flag. Native marshalling is unit-tested without RN (ReportArgsTest,BGSRNReportArgsTests), and the facade tests pin copy-on-labels and secret-free error messages.Sent by Cursor Automation: Bugsee code review
Mutation was surviving the boundary at severity 5 and any rewrite of the TypeError and RangeError text, which pulled the score under the break threshold. Co-authored-by: Cursor <cursoragent@cursor.com>
The deadline is a third caller into that barrier. On a slow CI runner it fires while the two threads are parked and steals a signal, so the test never finishes. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Stale comment
Deep review (53a2e97, Task 8.1)
Re-review of the two test follow-ups on top of c437703, against the Phase 8 plan, JS callers of two-arg
upload, Android 7.3.0 (createAndPrepareBugReport/createBugReportAndUpload), and iOS 7.0.0-beta3 (showReportControllerWithSummary:description:severity:labels:).One P1. The rest of the slice still matches the plan.
Finding
P1 — iOS
showReportDialogturns omitted summary/description into@"", which the SDK treats as a provided field. The no-arg selector exists because nil and empty are not the same; that distinction is then discarded on every partial call. Details on the conversion lines.What I checked (no additional findings)
- JS contract. Two-arg
uploadstill crossesseverity=0/labels=null. Explicit0,6,2.5, non-numbers, non-string labels,nulllabels, and a fifth argument are rejected before the bridge; error text does not echo the rejected value. Labels are copied.showReportDialog()crossesnull, null, 0, null.showReportDialog('s')correctly crosses description asnull— the loss happens natively on iOS only.- Severity mapping. JS
IssueSeverity.Criticalis4. Android usesIssueSeverity.fromIntValueafter a 1..5 guard (one-argfromIntValuesnaps unknowns toVeryLow;values()[4]isBlocker). iOS upload resolves0throughBugseeOptionReportingDefaultBugPriorityor High (3); requested 1..5 wins. Boolean-boxed launch options are rejected (CFBooleanGetTypeID).- Android 7.3.0.
showReportDialog()is four nulls intoshowBugReportingDialog. Coordinator skipssetSeverity/setLabelson null;setSummary/setDescriptionalways run (including null), which is the same as the SDK's own no-arg path. Labels aretoArrayList()on the native-modules thread before the UI hop. Void methods catchRuntimeException.- iOS 7.0.0-beta3 (disassembled). No-arg
showReportDialogcallsshowReportControllerand never seeds fields. The with-summary completion doescbzthensetSummary:/setReportDescription:/setSeverity:/clearLabels+addLabels:. Pointercbzis a nil check (@""is non-nil). Integercbzis why severity0is skipped, as specified. Upload still resolves0because the four-arg selector cannot carry labels otherwise. Both hop withBGSRNRunOnMain(async off main).- Tests in this SHA.
db302b5pins severity bounds and exact error strings.53a2e97drops the settle-once race's deadline so it cannot steal a barrier signal on a slow runner — productionBGSRNSettleOnceis unchanged.- Compatibility. Spec grows
uploadby two required parameters and addsshowReportDialog. Existing two-arg JS call sites still compile. I did not run workspace Jest (nonode_moduleshere). CI on this SHA at review time: android, ios cocoapods, ios unit, ios e2e simulator, rn compat 0.81–0.87 passed; ios spm andlint, typecheck, unit, mutationwere still pending.Device proof that severity/labels land in retained bundles remains Task 8.3a.
Overall risk: Medium
Merge recommendation
Do not merge until the iOS dialog nil→
@""conversion is fixed (or proven equivalent to omit in the dialog UI). The upload path and the JS facade are otherwise ready; Task 8.2a can stay based on this branch after the dialog fix.Most important issues to fix
- Pass omitted iOS dialog summary/description as
nil, not@"", so the SDKcbzskip matches Android's null and the JS "absent → null" contract.Positives
The ordinal trap is still load-bearing (Android test asserts
values()[4]is Blocker while wire4is Critical). TheincludeVideofifth-argument guard fails 6.x call sites loudly. Native marshalling is unit-tested without RN. The settle-once test change is the right fix for a third caller into a two-party barrier.Sent by Cursor Automation: Bugsee code review
A shared go semaphore let the faster caller enter the next window and consume the other caller's release, so that caller never arrived and CI timed out. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Stale comment
Deep review (924a3bf, Task 8.1)
Re-review of HEAD 924a3bf (per-window settle-once test fix on top of 53a2e97 / c437703), against the Phase 8 plan, JS callers of two-arg
upload, Android 7.3.0 (showBugReportingDialog/createAndPrepareBugReport), and the iOS 7.0.0-beta3 dialog contract already recorded in this repo (if (summ),if (level),if (labels)).The prior P1 is not addressed.
924a3bfonly changesBGSRNSettleOnceTests; productionshowReportDialogstill converts omitted iOS text to@"".Finding
P1 — iOS
showReportDialogturns omitted summary/description into@"", which the SDK treats as a provided field. The no-arg selector exists because nil and empty are not the same; that distinction is then discarded on every partial call. Details on the conversion lines. Independently re-checked on this SHA: JS still crosses omitted text asnull(optionalReportText); Android still forwards thatnull; the iOS handler snapshot still keeps an emptyNSStringas a present string.What I checked (no additional findings)
- JS contract. Two-arg
uploadstill crossesseverity=0/labels=null. Explicit0,6,2.5, non-numbers, non-string labels,nulllabels, and a fifth argument are rejected before the bridge; error text does not echo the rejected value. Labels are copied.showReportDialog()crossesnull, null, 0, null.showReportDialog('s')correctly crosses description asnull— the loss happens natively on iOS only.- Severity mapping. JS
IssueSeverity.Criticalis4. Android usesIssueSeverity.fromIntValueafter a 1..5 guard (one-argfromIntValuesnaps unknowns toVeryLow;values()[4]isBlocker). iOS upload resolves0throughBugseeOptionReportingDefaultBugPriorityor High (3); requested 1..5 wins. Boolean-boxed launch options are rejected (CFBooleanGetTypeID). The High fallback matches the 7.x Android options manifest default forbug-priority.- Android 7.3.0.
showReportDialog()is four nulls intoshowBugReportingDialog. Labels aretoArrayList()on the native-modules thread before the UI hop. Void methods catchRuntimeException.- iOS dialog vs upload. Upload still resolves
0because the four-arg selector cannot carry labels otherwise. Dialog leaves0for the SDKif (level)skip, as specified. Both hop withBGSRNRunOnMain(async off main).- 924a3bf. Production
BGSRNSettleOnceis unchanged. The test now uses one release semaphore per window so a fast caller cannot consume the other caller's go signal. That is the right fix for the CI timeout; it does not affect this slice's production API.- Compatibility. Spec grows
uploadby two required parameters and addsshowReportDialog. Existing two-arg JS call sites still compile. I did not run workspace Jest or native unit tests in this agent.Device proof that severity/labels land in retained bundles remains Task 8.3a. That task's dialog case passes every field, so it would not catch this omit bug.
Overall risk: Medium
Merge recommendation
Do not merge until the iOS dialog nil→
@""conversion is fixed (or proven equivalent to omit in the dialog UI and inonBeforeReportCreated). The upload path, the JS facade, and the settle-once test fix are otherwise ready; Task 8.2a can stay based on this branch after the dialog fix.Most important issues to fix
- Pass omitted iOS dialog summary/description as
nil, not@"", so the SDKif (summ)skip matches Android's null and the JS "absent → null" contract.Positives
The ordinal trap is still load-bearing (Android test asserts
values()[4]is Blocker while wire4is Critical). TheincludeVideofifth-argument guard fails 6.x call sites loudly. Native marshalling is unit-tested without RN. The settle-once test change is the right fix for a shared release stealing a two-party barrier.Sent by Cursor Automation: Bugsee code review
beta3 writes summary and description only when the pointer is non-nil, so substituting @"" pre-filled an empty string whenever another argument was set. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Stale comment
Deep review (a88a7e0, Task 8.1)
Re-review of HEAD a88a7e0 against the Phase 8 plan, two-arg
uploadcallers, Android 7.3.0 (showBugReportingDialog/createAndPrepareBugReport), and the iOS 7.0.0-beta3 dialog contract (if (summ),if (level),if (labels)).The prior P1 is fully addressed.
a88a7e0passes omitted iOS dialog summary/description through asnil; the no-arg selector is unchanged. Rechecked on this SHA: JS still crosses omitted text asnull(optionalReportText); Android still forwards thatnull; the with-arguments iOS path no longer substitutes@"".No new P0–P3 with a credible failure scenario.
What I checked
- JS contract. Two-arg
uploadstill crossesseverity=0/labels=null. Explicit0,6,2.5, non-numbers, non-string labels,nulllabels, and a fifth argument are rejected before the bridge; error text does not echo the rejected value. Labels are copied.showReportDialog()crossesnull, null, 0, null.showReportDialog('s')crosses description asnull— and native iOS now leaves thatnil.- Prior P1.
showReportDialogWithSummary:is called withsummary/descriptionas-is. beta3 only writes those fields when the pointer is non-nil (cbz/if (summ)), sonilis omit.@""remains only when JS actually sent an empty string. Severity0and nil labels are unchanged.- Severity mapping. JS
IssueSeverity.Criticalis4. Android usesIssueSeverity.fromIntValueafter a 1..5 guard (one-argfromIntValuesnaps unknowns toVeryLow;values()[4]isBlocker). iOS upload resolves0throughBugseeOptionReportingDefaultBugPriorityor High (3); requested 1..5 wins. Boolean-boxed launch options are rejected (CFBooleanGetTypeID). The High fallback matches the 7.x Android options manifest default forbug-priority.- Android 7.3.0.
showReportDialog()is four nulls intoshowBugReportingDialog. Labels aretoArrayList()on the native-modules thread before the UI hop. Void methods catchRuntimeException.- iOS dialog vs upload. Upload still resolves
0because the four-arg selector cannot carry labels otherwise. Dialog leaves0for the SDKif (level)skip. Both hop withBGSRNRunOnMain(async off main).- Settle-once tests. Production
BGSRNSettleOnceis unchanged. Per-window release semaphores keep the two-party barrier from stealing a signal on a slow runner.- Compatibility. Spec grows
uploadby two required parameters and addsshowReportDialog. Existing two-arg JS call sites still compile. I did not run workspace Jest or native unit tests in this agent. CI on this SHA at review time: android, ios spm, and rn compat 0.81–0.87 passed; ios cocoapods, ios unit, ios e2e simulator, andlint, typecheck, unit, mutationwere still pending.Device proof that severity/labels land in retained bundles remains Task 8.3a.
Overall risk: Low
Merge recommendation
Safe to merge into
feat/phase-7-5b. The dialog omit bug is fixed; the upload path, the JS facade, and the settle-once test fixes were already ready. Task 8.2a can stay based on this branch.Most important issues to fix
None for this PR.
Positives
The ordinal trap is still load-bearing (Android test asserts
values()[4]is Blocker while wire4is Critical). TheincludeVideofifth-argument guard fails 6.x call sites loudly. Native marshalling is unit-tested without RN.a88a7e0matches the SDK’s pointer check instead of the plan’s?: @"", which is the right correction.Sent by Cursor Automation: Bugsee code review
Keep the split exception executors and the beta3 recovery comment from main, and keep omitted dialog fields as nil on this branch. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Deep review (58dddec, Task 8.1)
Re-review of HEAD 58dddec (Merge main into feat/phase-8-1, parents a88a7e0 + 57af056) against the Phase 8 plan, two-arg upload callers, Android 7.3.0 (showBugReportingDialog / createAndPrepareBugReport), and the iOS 7.0.0-beta3 dialog contract (if (summ), if (level), if (labels)).
The prior P1 remains fully addressed. Omitted iOS dialog summary/description still pass through as nil; the no-arg selector is unchanged. The merge kept main’s split ExceptionExecutors (handled vs unhandled queues) and the beta3 override_report.plcrash recovery comment, and did not revive the @"" substitution.
No new P0–P3 with a credible failure scenario.
What I checked
- Merge resolution.
BugseeModule.javastill posts handled reports ontoExceptionExecutors.HANDLEDand unhandled ontoUNHANDLED(the #17 split), then the 8.1upload/showReportDialogmapping. iOSlogUnhandledExceptionstill carries main’s beta3 recovery note;showReportDialogWithSummary:still takessummary/descriptionas-is (BugseeModule.mm647–650). Support/SPM and CocoaPods import branches both pull inBGSRNReportArgs.h. - Prior P1. beta3 only writes dialog fields when the pointer is non-nil (
cbz/if (summ)), sonilis omit.@""remains only when JS actually sent an empty string. Rechecked: JSoptionalReportTextstill crosses omitted text asnull; Android still forwards thatnull; iOS no longer substitutes@"". - JS contract. Two-arg
uploadstill crossesseverity=0/labels=null. Explicit0,6,2.5, non-numbers, non-string labels,nulllabels, and a fifth argument are rejected before the bridge; error text does not echo the rejected value. Labels are copied.showReportDialog()crossesnull, null, 0, null.showReportDialog('s')crosses description asnull, and native iOS leaves thatnil. - Severity mapping. JS
IssueSeverity.Criticalis4. Android usesIssueSeverity.fromIntValueafter a 1..5 guard (one-argfromIntValuesnaps unknowns toVeryLow;values()[4]isBlocker). iOS upload resolves0throughBugseeOptionReportingDefaultBugPriorityor High (3); requested 1..5 wins. Boolean-boxed launch options are rejected (CFBooleanGetTypeID). The High fallback matches the 7.x Android options manifest default forbug-priority. - Android 7.3.0.
showReportDialog()is four nulls intoshowBugReportingDialog. Labels aretoArrayList()on the native-modules thread before the UI hop. Void methods catchRuntimeException. Existing two-arg exampleuploadcall sites still typecheck. - iOS dialog vs upload. Upload still resolves
0because the four-arg selector cannot carry labels otherwise. Dialog leaves0for the SDKif (level)skip. Both hop withBGSRNRunOnMain(inline on main, async off main). - Settle-once tests. Production
BGSRNSettleOnceis unchanged. Per-window release semaphores keep the two-party barrier from stealing a signal on a slow runner. - Compatibility. Spec grows
uploadby two required parameters and addsshowReportDialog. Existing two-arg JS call sites still compile. I did not run workspace Jest or native unit tests in this agent. CI on this merge SHA was still in progress at review time;a88a7e0was green.
Device proof that severity/labels land in retained bundles remains Task 8.3a.
Overall risk: Low
Merge recommendation
Safe to merge into main. The dialog omit bug stays fixed; the upload path, the JS facade, and the settle-once test fixes were already ready; this merge only folds Phase 7’s executor split and recovery comment without touching that contract.
Most important issues to fix
None for this PR.
Positives
The ordinal trap is still load-bearing (Android test asserts values()[4] is Blocker while wire 4 is Critical). The includeVideo fifth-argument guard fails 6.x call sites loudly. Native marshalling is unit-tested without RN. The merge kept the right side of both conflicts: split exception threads from main, nil dialog fields from this branch.
Sent by Cursor Automation: Bugsee code review


Summary
uploadtakes summary, description, severity, and labels. Severity0means the SDK default. A fifth argument is refused before the native call.showReportDialogcalls the no-argument SDK method only when every argument is absent. Otherwise it uses the with-summary form.IssueSeverity.fromIntValue. iOS resolves upload severity0from the launch option, or to High.Test plan
ReportArgsTest6,BGSRNReportArgsTests6 on simulator6FA9B3E8, compat 0.81.6, both example buildsBGSRNUploadSeverityMade with Cursor