Skip to content

Add "Get help" on local tooling failures + Crisp trigger events#5383

Merged
shai-almog merged 5 commits into
masterfrom
feature/tooling-get-help
Jul 15, 2026
Merged

Add "Get help" on local tooling failures + Crisp trigger events#5383
shai-almog merged 5 commits into
masterfrom
feature/tooling-get-help

Conversation

@shai-almog

Copy link
Copy Markdown
Collaborator

Why

Some signups never reach their first cloud build. Setup happens locally (install tooling → create project → build), so the server is blind to why people give up. This adds a user-initiated support path on local failures — nothing is telemetry, nothing is sent without an explicit click — and finally gives us visibility into where local setup breaks.

What

Get Help client (Maven plugin, com.codename1.maven.help, Java 1.7)

  • On any local failure (install / create_project / configure / local_run / build_submit) the tooling prints a "Get help" affordance. Running mvn cn1:get-help opens a dialog that pre-fills the signed-in account email (from Preferences /com/codename1/ui), auto-gathers the failure context, and — only on an explicit Send — POSTs to cloud.codenameone.com/api/v2/tooling/help.
  • Response contract {ticketId, token, chatUrl}, two paths:
    • Email presentWe've got it — #{ticketId}. We'll reply to you at {email}. (optional Chat-live → {chatUrl}#t={token}).
    • No email → open the browser to {chatUrl}#t={token}; the token-gated page fetches the report and drops the user into a live Crisp chat. Never a false "we'll reply" promise.
    • Forward-compatible: a missing token degrades to the bare chat URL.
  • errorDetail is the reproduction support reads: an env/command header (step, exact failing command, JAVA_HOME, java.home, proxy, versions) + the full stack trace, truncated client-side to 16 KB.
  • Never a dead end: offline / non-2xx degrades to self-serve guide + chat.
  • Capture is wired through the AbstractCN1Mojo.execute() choke point + helpStep()/helpAction() overrides, plus a direct hook in GenerateAppProjectMojo. BrowserOpener is injectable so tests never launch a browser.

Heads-up on the User-Agent: the endpoint's WAF 403s the default Java/<ver> agent. Since the target audience is people on JDK 8, that would have silently turned every send into the offline fallback. The client now sends User-Agent: CodenameOne-Tooling-Help/<version> (<component>). Only reproducible against the real server.

Crisp trigger events (docs/website/assets/js/cn1-crisp.js)

Fire the named session:events that launch the T1–T5 automated campaigns, inside loadCrisp() so they only run once chat consent is given. Once-per-view and once-per-session dedupe:

  • ConsoleDwell60, SigningScreenView, GettingStartedDwell, PricingEvaluator (dwell + upward exit-intent).
  • BuildError is fired by the external console app (not this repo); exposed here as window.cn1CrispEvents.buildError().

Testing

  • 30 JUnit4 tests in help/ (truncation caps, JSON + email-omission, token/deep-link parsing, both response paths, network-failure fallback, User-Agent, EOF/decline = nothing sent). Full suite: 47/47, no regressions on the touched mojos.
  • Verified end-to-end against live production: real JDK-8 cn1:run failure → affordance → cn1:get-help → no-email send returned a token and opened https://cloud.codenameone.com/tooling-help.html#t=<token>.
  • Crisp events verified in a mocked DOM (correct routes fire, non-target pages stay silent, dwell + exit-intent dedupe to one, payload shape matches the spec).

Follow-ups (not in this PR)

  • Activate campaigns T1–T5 in Crisp after deploy (manual step; suggested order T1 → T2/T3 → T4/T5).
  • Confirm the canonical help.codenameone.com article slugs in ToolingHelpClient.HELP_ARTICLES (safe defaults for now).
  • The desktop Settings and Certificate Wizard GUIs (CN1-UI apps in scripts/) aren't wired yet; the core here is UI-agnostic and reusable for them.

🤖 Generated with Claude Code

Some signups never reach their first cloud build because setup happens
locally and the server is blind to why people give up. This adds a
user-initiated support path: when a local step fails (install /
create_project / configure / local_run / build_submit), the tooling shows
a "Get help" affordance; running `mvn cn1:get-help` opens a dialog that
pre-fills the account email, gathers the failure context automatically,
and — only on an explicit Send — POSTs it to
`cloud.codenameone.com/api/v2/tooling/help`. Nothing is ever sent without
an explicit action.

Client (maven plugin, package com.codename1.maven.help, Java 1.7):
- ToolingHelpReport: context capture + client-side truncation (short<=64,
  medium<=512, errorDetail<=16KB), hand-rolled JSON, email omitted when
  unknown.
- ToolingHelpClient: POST + flat-JSON parse, step->help-article map, never
  throws (offline/non-2xx -> UNREACHABLE fallback). Sends a real
  User-Agent — the WAF 403s the default "Java/<ver>" agent, which would
  silently fail every send from a JDK 8 machine (this feature's audience).
- Response contract {ticketId, token, chatUrl}. Two paths:
  * email present  -> "We've got it — #{ticketId}. We'll reply to {email}."
  * no email       -> open the browser to {chatUrl}#t={token} (token-gated
    page drops the user into a live Crisp chat carrying the report); never
    a false "we'll reply" promise.
  Forward-compatible: missing token degrades to the bare chat URL.
- errorDetail is the reproduction support reads: env/command header
  (step, exact command, JAVA_HOME, java.home, proxy, versions) + full
  stack trace.
- Goal cn1:get-help (GetHelpMojo, requiresProject=false) replays the
  persisted failure; capture wired via the AbstractCN1Mojo.execute() choke
  point + helpStep()/helpAction() overrides, plus a direct hook in
  GenerateAppProjectMojo. BrowserOpener is injectable so tests never launch
  a browser.
- 30 JUnit4 tests (truncation, JSON, token/deep-link, both response paths,
  network-failure fallback, User-Agent, EOF/decline = no send).

Website (docs/website/assets/js/cn1-crisp.js): fire Crisp session:events for
the T1-T5 automated campaigns, inside loadCrisp() so they only run once chat
consent is given. Once-per-view + once-per-session dedupe. Events:
ConsoleDwell60, SigningScreenView, GettingStartedDwell, PricingEvaluator
(+ exit-intent), and a window.cn1CrispEvents hook for BuildError (which is
fired by the external console app, not this repo).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Cloudflare Preview

@shai-almog

shai-almog commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 145 screenshots: 145 matched.

Native Android coverage

  • 📊 Line coverage: 11.19% (11681/104413 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 9.96% (57600/578349), branch 5.09% (2691/52874), complexity 4.85% (2687/55436), method 7.29% (2081/28530), class 11.39% (461/4049)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • com.google.common.cache.com.google.common.cache.LocalCache$Segment – 0.00% (0/726 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 11.19% (11681/104413 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 9.96% (57600/578349), branch 5.09% (2691/52874), complexity 4.85% (2687/55436), method 7.29% (2081/28530), class 11.39% (461/4049)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • com.google.common.cache.com.google.common.cache.LocalCache$Segment – 0.00% (0/726 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend scalar fallback (no native SIMD)
SIMD int-add (64K x300) java 161ms / native 126ms = 1.2x speedup
SIMD float-mul (64K x300) java 120ms / native 89ms = 1.3x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 313.000 ms
Base64 CN1 decode 269.000 ms
Base64 native encode 947.000 ms
Base64 encode ratio (CN1/native) 0.331x (66.9% faster)
Base64 native decode 953.000 ms
Base64 decode ratio (CN1/native) 0.282x (71.8% faster)
Image encode benchmark status skipped (SIMD unsupported)

@shai-almog

shai-almog commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 168 screenshots: 168 matched.
✅ JavaScript-port screenshot tests passed.

The EOF signal used a String sentinel compared with `==`, which SpotBugs
flags (ES_COMPARING_STRINGS_WITH_EQ) and failed build-test (8). The
sentinel literal had also picked up a stray NUL byte. Replace it with a
plain null-for-EOF contract (empty string already means "user chose no
email"), removing both the reference comparison and the NUL.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

✅ Continuous Quality Report

Test & Coverage

Static Analysis

  • SpotBugs [Report archive]
    • ByteCodeTranslator: 0 findings (no issues)
    • android: 0 findings (no issues)
    • codenameone-maven-plugin: 0 findings (no issues)
    • core-unittests: 0 findings (no issues)
    • ios: 0 findings (no issues)
  • PMD: 0 findings (no issues) [Report archive]
  • Checkstyle: 0 findings (no issues) [Report archive]

Generated automatically by the PR CI workflow.

@shai-almog

shai-almog commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 138 screenshots: 138 matched.
✅ Native iOS screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 207 seconds

Build and Run Timing

Metric Duration
Simulator Boot 66000 ms
Simulator Boot (Run) 1000 ms
App Install 50000 ms
App Launch 2000 ms
Test Execution 585000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 104ms / native 4ms = 26.0x speedup
SIMD float-mul (64K x300) java 108ms / native 3ms = 36.0x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 405.000 ms
Base64 CN1 decode 218.000 ms
Base64 native encode 1217.000 ms
Base64 encode ratio (CN1/native) 0.333x (66.7% faster)
Base64 native decode 528.000 ms
Base64 decode ratio (CN1/native) 0.413x (58.7% faster)
Base64 SIMD encode 81.000 ms
Base64 encode ratio (SIMD/CN1) 0.200x (80.0% faster)
Base64 SIMD decode 110.000 ms
Base64 decode ratio (SIMD/CN1) 0.505x (49.5% faster)
Base64 encode ratio (SIMD/native) 0.067x (93.3% faster)
Base64 decode ratio (SIMD/native) 0.208x (79.2% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 11.000 ms
Image createMask (SIMD on) 4.000 ms
Image createMask ratio (SIMD on/off) 0.364x (63.6% faster)
Image applyMask (SIMD off) 110.000 ms
Image applyMask (SIMD on) 138.000 ms
Image applyMask ratio (SIMD on/off) 1.255x (25.5% slower)
Image modifyAlpha (SIMD off) 121.000 ms
Image modifyAlpha (SIMD on) 184.000 ms
Image modifyAlpha ratio (SIMD on/off) 1.521x (52.1% slower)
Image modifyAlpha removeColor (SIMD off) 156.000 ms
Image modifyAlpha removeColor (SIMD on) 198.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 1.269x (26.9% slower)

@shai-almog

shai-almog commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 144 screenshots: 144 matched.
✅ Native iOS Metal screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 306 seconds

Build and Run Timing

Metric Duration
Simulator Boot 58000 ms
Simulator Boot (Run) 1000 ms
App Install 10000 ms
App Launch 1000 ms
Test Execution 344000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 57ms / native 3ms = 19.0x speedup
SIMD float-mul (64K x300) java 56ms / native 3ms = 18.6x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 850.000 ms
Base64 CN1 decode 245.000 ms
Base64 native encode 1007.000 ms
Base64 encode ratio (CN1/native) 0.844x (15.6% faster)
Base64 native decode 1001.000 ms
Base64 decode ratio (CN1/native) 0.245x (75.5% faster)
Base64 SIMD encode 81.000 ms
Base64 encode ratio (SIMD/CN1) 0.095x (90.5% faster)
Base64 SIMD decode 44.000 ms
Base64 decode ratio (SIMD/CN1) 0.180x (82.0% faster)
Base64 encode ratio (SIMD/native) 0.080x (92.0% faster)
Base64 decode ratio (SIMD/native) 0.044x (95.6% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 7.000 ms
Image createMask (SIMD on) 1.000 ms
Image createMask ratio (SIMD on/off) 0.143x (85.7% faster)
Image applyMask (SIMD off) 52.000 ms
Image applyMask (SIMD on) 111.000 ms
Image applyMask ratio (SIMD on/off) 2.135x (113.5% slower)
Image modifyAlpha (SIMD off) 39.000 ms
Image modifyAlpha (SIMD on) 36.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.923x (7.7% faster)
Image modifyAlpha removeColor (SIMD off) 113.000 ms
Image modifyAlpha removeColor (SIMD on) 180.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 1.593x (59.3% slower)

@shai-almog

shai-almog commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 216 screenshots: 216 matched.
✅ Native Apple Watch (watchOS, Core Graphics) screenshot tests passed.

@shai-almog

shai-almog commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 139 screenshots: 139 matched.
✅ Native Apple TV (tvOS, Metal) screenshot tests passed.

@shai-almog

shai-almog commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 143 screenshots: 143 matched.
✅ Native Mac screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 171 seconds

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 52ms / native 3ms = 17.3x speedup
SIMD float-mul (64K x300) java 53ms / native 3ms = 17.6x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 169.000 ms
Base64 CN1 decode 118.000 ms
Base64 native encode 1032.000 ms
Base64 encode ratio (CN1/native) 0.164x (83.6% faster)
Base64 native decode 603.000 ms
Base64 decode ratio (CN1/native) 0.196x (80.4% faster)
Base64 SIMD encode 49.000 ms
Base64 encode ratio (SIMD/CN1) 0.290x (71.0% faster)
Base64 SIMD decode 45.000 ms
Base64 decode ratio (SIMD/CN1) 0.381x (61.9% faster)
Base64 encode ratio (SIMD/native) 0.047x (95.3% faster)
Base64 decode ratio (SIMD/native) 0.075x (92.5% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 7.000 ms
Image createMask (SIMD on) 1.000 ms
Image createMask ratio (SIMD on/off) 0.143x (85.7% faster)
Image applyMask (SIMD off) 52.000 ms
Image applyMask (SIMD on) 102.000 ms
Image applyMask ratio (SIMD on/off) 1.962x (96.2% slower)
Image modifyAlpha (SIMD off) 172.000 ms
Image modifyAlpha (SIMD on) 136.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.791x (20.9% faster)
Image modifyAlpha removeColor (SIMD off) 121.000 ms
Image modifyAlpha removeColor (SIMD on) 141.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 1.165x (16.5% slower)

@shai-almog shai-almog merged commit 923c551 into master Jul 15, 2026
26 checks passed
@shai-almog shai-almog deleted the feature/tooling-get-help branch July 15, 2026 03:44
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