Skip to content

Gate iOS 27 in CI: xcode-27 legs for the screenshot and fidelity suites - #5879

Merged
shai-almog merged 11 commits into
masterfrom
ios27-ci-gate
Sep 22, 2026
Merged

shai-almog merged 11 commits into
masterfrom
ios27-ci-gate

Conversation

@shai-almog

Copy link
Copy Markdown
Collaborator

Adds an iOS 27 target as its own gate, running on every pull request, with its own baselines.

What lands

  • build-ios-metal-27 — the helloworld iOS screenshot suite on the xcode-27 image, scored against scripts/ios/screenshots-metal-27/. A copy, not a move: build-ios-metal keeps gating macos-15/Xcode 26, which is the toolchain CN1_XCODE_MAJOR pins and what applications are built with today. The existing job is untouched to the byte, so its check name and port-status artifact keep working.
  • fidelity-ios-metal-27 — the fidelity suite against the ios-27-metal goldens, driven by a single CN1SS_FIDELITY_GOLDEN_SET so the theme the app ships and the goldens it is scored against cannot disagree.
  • helloworld now asks the port which generation it carries. It does not use the shipped default theme — it installs the modern theme itself, and both device-side sites named generation 26 outright. Hardcoded, the 27 leg would render the iOS 26 theme and score it against iOS 27 baselines, a difference in every glass tile with nothing saying why.
  • 24 seeded ios-27-metal-frames. These are CN1 self-goldens (run-ios-fidelity-tests.sh: "self-goldens (CN1 vs committed CN1)"), seeded with FIDELITY_UPDATE_GOLDENS=1, not native captures. Reviewed rather than trusted: names and sizes identical to the iOS 26 set, none blank, the ten SwitchMorph frames byte-identical to iOS 26 (Switch uses no glass recipe and iOS 27 did not change it), and TabsMorph moved in dark (~6.5) and barely in light (~0.11) — exactly where the theme changed. Re-validated against a clean rebuild: 4 group(s) OK.
  • scripts/check-duplicated-ci-legs.py holds each copy to its original. 320 and 78 duplicated lines drift, and both legs of a pair stay green while diverging because each passes on its own terms. Each pair declares the differences that are meant to exist; anything else fails. Verified to fail, and exit non-zero, on drift introduced from either side of either pair.

Two bugs this exposed

cn1_select_xcode died on the Xcode 27 image with exit 134 and no output. It probes every /Applications/Xcode*.app and means to skip any that cannot report a version — [ -n "$version" ] || continue says so — but under set -e the assignment carries the failing status and kills the caller first, while the crash text goes to /dev/null. That image holds the real Xcode plus three symlinks to it, and one invocation aborts. Latent on macos-15 only because nothing there crashes; it would have taken out both new legs, which pin CN1_XCODE_MAJOR=27 and call this first.

Generation invalidation was not invalidating enough. With only the generated *-ios-source directory removed, a rebuild after changing a core constant returned in 36 seconds and the emitted C still carried the previous value. The whole module target goes now, plus the sources archive. The stamp's remaining blind spot — a core edit at the same generation — is written down rather than left to be rediscovered.

Geometry: a stricter gate, not a looser one

ProcessScreenshots set empty=true when either side had no widget silhouette, so "invisible in both renders" and "rendered natively but not by us" were the same value. The second is a regression and was being folded into the first. It now records native_empty/cn1_empty separately, and FidelityGate exempts a pair only when both are true.

That check immediately caught a real defect in the iOS 27 constants from #5876 that a 97% fidelity score could not see — see below.

What is deliberately not green

fidelity-ios-metal-27 is continue-on-error, for one reason with one exit. Its baseline cannot be recorded: in dark, GlassPanelGrey and GlassPanelRed render with no silhouette at all. Over a flat mid-grey backdrop the material arithmetic gives 128 × 0.378 + 79.8 = 128.18, the renderer emits integers, so the panel lands on 128 — the backdrop exactly. The native capture is not flat there, averaging 128.7 across 101 distinct values where ours has 17.

An offset putting the arithmetic at 128.68 against the native's 128.7 was tried, at a cost of 0.026/255 of global fit error. On device it changed nothing — 128.68 still quantises to 128 — and the only other reachable value overshoots the native by 0.3 rather than undershooting by 0.7. Reverted to the fit's optimum, with the measurement recorded so it is not retried blind.

Closing it needs the material model to carry sub-level detail, not a different constant. The one-sided-empty refusal is not being softened to get a green tick, because that same check is what caught the bad constant.

The row still runs on every pull request, uploads artifacts and reports scores; it just does not fail the build.

Runner notes

xcode-27 is a public preview image (actions/runner-images#14404). A dispatch probe on this branch confirmed: the label resolves, the image is macOS 27.0 / Xcode 27.0 (27A266a) with the iOS 27.0 simulator runtime, and an iPhone 16 boots there through boot-ios-simulator.sh despite not being pre-installed — which the ios-27-metal goldens depend on. It waited ~24 minutes behind this repo's own macOS backlog, not on image capacity. actionlint ships a static label list that lags GitHub's, so xcode-27 is declared in .github/actionlint.yaml the same way windows-11-arm already is.

The probe workflow is temporary and removed once its re-run confirms the cn1_select_xcode fix.

Not covered

The xcode-27 legs have never run end to end — only the probe has. This PR is the first time they execute.

🤖 Generated with Claude Code

shai-almog and others added 8 commits September 21, 2026 13:12
Three things have to be true before an iOS 27 gate is worth writing, and none
of them can be assumed: that the xcode-27 label resolves for this repository at
all (it is a public preview image), which Xcode and iOS runtime it carries, and
whether an iPhone 16 can be CREATED there -- the image pre-creates iPhone 17 /
17e / 18 Pro / 18 Pro Max / Air and no iPhone 16, and the ios-27-metal goldens
were captured on an iPhone 16.

Dispatch-only and deleted once answered. Finding out by watching a 60-minute
screenshot job fail is the alternative.

actionlint ships a static label list that lags GitHub's, so xcode-27 is declared
in .github/actionlint.yaml the same way windows-11-arm already is -- rather than
muting the rule, so a genuine typo in a runs-on is still caught.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…issing widget

FidelityGate refused to write the ios-27-metal baseline at all because two tiles
reported no geometry: GlassPanelGrey_normal_dark and GlassPanelRed_normal_dark.
Neither is a defect. iOS 27's dark glass over a flat mid-grey backdrop
transforms to within a shade of that same grey -- 128 * 0.378 + 79.8 is 128 --
so the panel has no edge to find, and the NATIVE capture agrees: #818181 panel
over #808080 backdrop. The same holds for red on red.

geometryMetrics already reported this honestly as empty=true with no numbers.
The gate could not tell that from geometry being withheld, and its contract --
"a compared pair cannot evade its geometry contract by returning no metrics" --
is right to be strict, so everything stopped.

What was actually missing is WHICH SIDE is blank. empty=true was set when either
box came back zero, so "the widget is invisible in both renders" and "the widget
rendered natively and not in ours" were the same value. The second is a
regression, and it was being folded into the first.

geometryMetrics now records native_empty and cn1_empty, and the gate exempts a
pair from the geometry contract only when BOTH are true. Verified over three
cases: both blank updates the baseline; native present with ours blank still
fails; and a report carrying empty alone, with no side flags, still fails -- an
older report must not acquire an exemption it never measured.

Net effect is a stricter gate, not a looser one: the one-sided case used to
arrive as "no geometry" and is now named.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…he generation

A COPY, not a move. build-ios-metal keeps gating macos-15 / Xcode 26, which is
the toolchain CN1_XCODE_MAJOR actually pins and what applications are built with
today; the new leg runs the identical suite on the Xcode 27 / iOS 27 image with
its own baseline directory. The existing job is untouched to the byte -- this
commit is a pure insertion -- so its check name, its port-status artifact and
anything keyed on either keep working.

helloworld does not use the shipped default theme: it installs the modern theme
itself, and DualAppearanceBaseTest.pickModernThemeResource named generation 26
outright. Hardcoded, the 27 leg would render the iOS 26 theme and score it
against iOS 27 baselines -- a difference in every glass tile with nothing saying
why. Both device-side sites now ask the port which generation the build carries
(IOSImplementation.getProperty, which answers with the resource that is actually
present and falls back to 26 when a bundle lacks the other). The dev-guide
screenshot test under src/test is deliberately left alone: it renders on JavaSE
for the developer guide and is generation-neutral.

The 27 leg deliberately does NOT upload a port status. There is one iOS port and
the published report is keyed on `ios-metal`; a second upload under that id would
publish whichever leg finished last -- the same clobber the PR-comment marker
already had to be split to avoid.

scripts/check-ios-metal-legs-match.py holds the two jobs to being the same job.
320 duplicated lines drift, and both legs would stay green while diverging
because each passes on its own terms and nothing compares them. It normalises
away the differences that are meant to exist and requires the rest to match,
so a real difference has to be declared in the script with a reason. Verified to
fail on drift introduced from either side, and to exit non-zero when it does.

The xcode-27 image is a public preview (actions/runner-images#14404) and its
capacity is still being balanced.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…th pairs

fidelity-ios-metal-27 scores the iOS 27 theme against the ios-27-metal goldens on
the Xcode 27 image. A copy rather than a move, for the same reason as the
screenshot leg: ios.themeGeneration defaults to 26, so the 26 row keeps gating
what applications actually get, and this row is what keeps the 27 theme honest.

One variable drives it. CN1SS_FIDELITY_GOLDEN_SET reaches the capture script, the
app build (which turns it into ios.themeGeneration=27) and the comparison, so the
theme the app ships and the goldens it is scored against cannot disagree -- which
they silently did throughout the tuning of gen27.css, and the symptom was two runs
whose scores matched to the last decimal.

The drift guard is now pair-driven and covers both copies rather than one, and is
renamed accordingly. Each pair declares the differences that are meant to exist --
runner, toolchain pin, golden set, baseline and artifact names -- and anything
left over is drift. Verified to fail, and to exit non-zero, on drift introduced
into the fidelity pair as well as the screenshot pair.

This row cannot pass until the ios-27-metal frame goldens are seeded and its
baseline recorded; both are deliberate local acts and neither has landed yet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ctually are

Removing the generated *-ios-source directory does not invalidate enough.
Measured: with only that removed, a rebuild after changing a CORE constant
returned in 36 SECONDS and the emitted C still carried the previous value --
the core jar on the classpath had the new one, the generated C did not. The
whole module target goes now, along with the sources archive build-ios-app.sh
writes beside it.

The stamp's limit is written down rather than left to be discovered: it keys on
the generation, so it does not fire for a core edit at the same generation.
Maven does not treat a changed dependency as invalidating generated sources, so
iterating on core and the fidelity app together still needs a manual clean.

Also documents what cost a wrong plan earlier in this work: `<set>-frames` holds
CN1 renders, not platform captures -- run-ios-fidelity-tests.sh calls them
"self-goldens (CN1 vs committed CN1)" and seeds them from a single
FIDELITY_UPDATE_GOLDENS=1 flag. The neighbouring `-anim` directory IS native and
does need record-ios-native-anim.sh with a tap-driven tabs recording, so reading
one as the other leads to preparing an xcodegen + XCUITest capture for something
a flag produces. The note also records what reviewing a seed looks like, since
whatever CN1 rendered becomes the reference.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…elity row non-gating

THE FRAMES. ios-27-metal-frames had nothing in it, so every animation frame
failed as a missing golden. These are CN1 self-goldens -- run-ios-fidelity-tests
.sh compares CN1 against committed CN1 to catch a stuck frame, non-monotonic
travel or a broken overshoot -- so they are seeded, not captured, and reviewed
rather than trusted. Seeded from an app built with Xcode 27.0 against the iOS 27
theme, then checked: 24 names and sizes identical to the iOS 26 set, none blank,
the ten SwitchMorph frames byte-identical to iOS 26 (Switch uses no glass recipe
and iOS 27 did not change it), and TabsMorph moved in dark (~6.5) and barely in
light (~0.11) -- exactly where the theme changed, since the pill recipe's light
variant measured unchanged. Re-validated against a clean rebuild: 4 groups OK.

THE OFFSET STAYS AT THE FIT'S 79.8. 80.3 was tried, on the argument that it puts
the mid-grey arithmetic at 128.68 against the native's 128.7 for 0.026/255 of
fit error. On device it changed nothing: the renderer emits integers and 128.68
lands on 128, the backdrop exactly. The only other reachable value is 129, which
overshoots the native by 0.3 rather than undershooting by 0.7, and choosing it
would be picking a constant for what the quantiser does with it. Reverted, with
the measurement recorded so it is not retried blind.

THE 27 FIDELITY ROW IS NON-GATING, for one reason with one exit. Its baseline
cannot be recorded: GlassPanelGrey and GlassPanelRed in dark render with no
silhouette where the native has a faint one, so ProcessScreenshots reports
cn1_empty and FidelityGate refuses a one-sided empty. That refusal is correct and
is NOT being softened to get a green tick -- the same check caught a real defect
in these very constants, which a 97% fidelity score could not see. The row runs
on every pull request, uploads artifacts and reports scores; it just does not
fail the build until the material model can carry sub-level detail.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ing on it

cn1_select_xcode probes every /Applications/Xcode*.app with `xcodebuild -version`
and means to skip any that cannot answer -- the `[ -n "$version" ] || continue`
right below says so. Under `set -e`, which every CI step here runs with, it never
got that far: the assignment itself carries the failing status and kills the
caller first, and since the crash text goes to /dev/null the job dies with no
output whatsoever.

Measured on the GitHub xcode-27 image, where /Applications holds the real Xcode
plus three symlinks to it: selection aborted with exit 134 (SIGABRT) and printed
nothing. Reduced to the shell semantics on their own, the old form exits 134
without reaching the emptiness check; with `|| true` it reaches it with an empty
version and the candidate is skipped, which is what was intended all along.

Latent on macos-15 only because nothing there crashes. It would have taken out
both new iOS 27 legs, which pin CN1_XCODE_MAJOR=27 and call this first.

The probe now also reports each candidate out loud, so which one misbehaves is on
the record rather than inferred from an exit code.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@shai-almog

shai-almog commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 12 screenshots: 12 matched.
✅ JavaSE simulator integration screenshots matched stored baselines.

@github-actions

github-actions Bot commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

Developer Guide build artifacts are available for download from this workflow run:

Developer Guide quality checks:

  • AsciiDoc linter: No issues found (report)
  • Vale: No alerts found (report)
  • Paragraph capitalization: No paragraph capitalization issues (report)
  • LanguageTool: No grammar matches (report)
  • Image references: No unused images detected (report)

@shai-almog

shai-almog commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 166 screenshots: 166 matched.
Native Windows port (x64 / Intel-AMD): full hellocodenameone screenshot suite rendered offscreen with Direct2D/DirectWrite, plus the real benchmarks (base64 native/CN1/SIMD, image createMask/applyMask/modifyAlpha/PNG/JPEG, SSE2 SIMD kernels). Compared against the in-repo baseline in scripts/windows/screenshots.

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 63ms / native 5ms = 12.6x speedup
SIMD float-mul (64K x300) java 63ms / native 6ms = 10.5x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
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 199.000 ms
Base64 CN1 decode 131.000 ms
Base64 SIMD encode 100.000 ms
Base64 encode ratio (SIMD/CN1) 0.503x (49.7% faster)
Base64 SIMD decode 99.000 ms
Base64 decode ratio (SIMD/CN1) 0.756x (24.4% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 10.000 ms
Image createMask (SIMD on) 32.000 ms
Image createMask ratio (SIMD on/off) 3.200x (220.0% slower)
Image applyMask (SIMD off) 60.000 ms
Image applyMask (SIMD on) 91.000 ms
Image applyMask ratio (SIMD on/off) 1.517x (51.7% slower)
Image modifyAlpha (SIMD off) 75.000 ms
Image modifyAlpha (SIMD on) 75.000 ms
Image modifyAlpha ratio (SIMD on/off) 1.000x (0.0% slower)
Image modifyAlpha removeColor (SIMD off) 59.000 ms
Image modifyAlpha removeColor (SIMD on) 55.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.932x (6.8% faster)

@shai-almog

shai-almog commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 166 screenshots: 166 matched.
Native Windows port, REAL shipping pipeline: the hellocodenameone screenshot suite rendered by a binary CROSS-COMPILED on Linux (clang-cl + xwin, WebView2 linked) and RUN on a Windows x64 runner. Compared against the in-repo baseline in scripts/windows/screenshots.

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 30ms / native 2ms = 15.0x speedup
SIMD float-mul (64K x300) java 29ms / native 2ms = 14.5x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
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 107.000 ms
Base64 CN1 decode 66.000 ms
Base64 SIMD encode 47.000 ms
Base64 encode ratio (SIMD/CN1) 0.439x (56.1% faster)
Base64 SIMD decode 51.000 ms
Base64 decode ratio (SIMD/CN1) 0.773x (22.7% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 5.000 ms
Image createMask (SIMD on) 22.000 ms
Image createMask ratio (SIMD on/off) 4.400x (340.0% slower)
Image applyMask (SIMD off) 19.000 ms
Image applyMask (SIMD on) 41.000 ms
Image applyMask ratio (SIMD on/off) 2.158x (115.8% slower)
Image modifyAlpha (SIMD off) 33.000 ms
Image modifyAlpha (SIMD on) 11.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.333x (66.7% faster)
Image modifyAlpha removeColor (SIMD off) 43.000 ms
Image modifyAlpha removeColor (SIMD on) 26.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.605x (39.5% faster)

@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 21, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-21T11:55:45.530212Z 4c92f9f Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@shai-almog

shai-almog commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 151 screenshots: 151 matched.

Native Android coverage

  • 📊 Line coverage: 9.26% (9212/99491 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 9.00% (47300/525310), branch 3.58% (1781/49799), complexity 3.53% (1872/53060), method 5.44% (1518/27892), class 10.92% (408/3737)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6367 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.ClassReader – 0.00% (0/1524 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1187 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.MethodWriter – 0.00% (0/922 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/736 lines covered)
      • com.google.common.cache.com.google.common.cache.LocalCache$Segment – 0.00% (0/726 lines covered)
      • okio.okio.Buffer – 0.00% (0/687 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/625 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.Frame – 0.00% (0/570 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 9.26% (9212/99491 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 9.00% (47300/525310), branch 3.58% (1781/49799), complexity 3.53% (1872/53060), method 5.44% (1518/27892), class 10.92% (408/3737)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6367 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.ClassReader – 0.00% (0/1524 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1187 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.MethodWriter – 0.00% (0/922 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/736 lines covered)
      • com.google.common.cache.com.google.common.cache.LocalCache$Segment – 0.00% (0/726 lines covered)
      • okio.okio.Buffer – 0.00% (0/687 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/625 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.Frame – 0.00% (0/570 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend scalar fallback (no native SIMD)
SIMD int-add (64K x300) java 37ms / native 69ms = 0.5x speedup
SIMD float-mul (64K x300) java 52ms / native 50ms = 1.0x 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 39.000 ms
Base64 CN1 decode 46.000 ms
Base64 native encode 271.000 ms
Base64 encode ratio (CN1/native) 0.144x (85.6% faster)
Base64 native decode 205.000 ms
Base64 decode ratio (CN1/native) 0.224x (77.6% faster)
Image encode benchmark status skipped (SIMD unsupported)

@github-actions

github-actions Bot commented Sep 21, 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)
    • build-hint-catalog: 0 findings (no issues)
    • build-hint-tools: 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.

@github-actions

Copy link
Copy Markdown
Contributor

Cloudflare Preview

@shai-almog

shai-almog commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 166 screenshots: 166 matched.
Native Linux port (x64), GTK3/Cairo/Pango, ParparVM bytecode-to-C (no JVM): the hellocodenameone screenshot suite rendered by a native ELF built + run on the GitHub x64 runner. Baseline: scripts/linux/screenshots.

@shai-almog

shai-almog commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 166 screenshots: 166 matched.
Native Linux port (arm64), GTK3/Cairo/Pango, ParparVM bytecode-to-C (no JVM): the hellocodenameone screenshot suite rendered by a native ELF built + run on the GitHub arm64 runner. Baseline: scripts/linux/screenshots-arm.

@shai-almog

shai-almog commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 166 screenshots: 166 matched.
Native Windows port (arm64 / Apple Silicon - Arm): full hellocodenameone screenshot suite rendered offscreen with Direct2D/DirectWrite, plus the real benchmarks (base64 native/CN1/SIMD, image createMask/applyMask/modifyAlpha/PNG/JPEG, NEON SIMD kernels). Compared against the in-repo baseline in scripts/windows/screenshots.

Benchmark Results

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 55ms / native 3ms = 18.3x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
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 246.000 ms
Base64 CN1 decode 128.000 ms
Base64 SIMD encode 66.000 ms
Base64 encode ratio (SIMD/CN1) 0.268x (73.2% faster)
Base64 SIMD decode 63.000 ms
Base64 decode ratio (SIMD/CN1) 0.492x (50.8% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 8.000 ms
Image createMask (SIMD on) 3.000 ms
Image createMask ratio (SIMD on/off) 0.375x (62.5% faster)
Image applyMask (SIMD off) 25.000 ms
Image applyMask (SIMD on) 18.000 ms
Image applyMask ratio (SIMD on/off) 0.720x (28.0% faster)
Image modifyAlpha (SIMD off) 19.000 ms
Image modifyAlpha (SIMD on) 12.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.632x (36.8% faster)
Image modifyAlpha removeColor (SIMD off) 38.000 ms
Image modifyAlpha removeColor (SIMD on) 13.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.342x (65.8% faster)

…probe

The probe answered what it was for, on the real image:

  Xcode_27_Release_Candidate.app -> prints "Xcode 27.0", exit 134
  Xcode_27.0.0.app / Xcode_27.0.app / Xcode.app -> 27.0, exit 0

Two traps in one line, not one. The crashing app is FIRST in glob order, so
without `|| true` the failing status propagates out of the assignment and
`set -e` kills selection on candidate one -- before any working Xcode is tried,
and with no output at all, because the crash text went to /dev/null. That much
the previous commit fixed.

But it also prints a perfectly good version BEFORE aborting, so testing the
string alone accepts an Xcode whose xcodebuild dies. On this image that was
survivable only because all four report 27.0 and the tie-break keeps the last
one, which is luck: had the crashing app sorted last, it would have been chosen
and every build on it would have failed somewhere less obvious. Candidates are
now judged on their exit status too.

A/B against a fake /Applications holding a crasher that sorts first and prints a
version, plus a working Xcode: master exits 134 and selects nothing; this selects
the working one and exits 0.

The probe workflow goes, as its header said it would.

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

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4c92f9fbe2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/scripts-ios.yml
Comment thread scripts/common/java/FidelityGate.java
Comment thread .github/workflows/scripts-ios.yml
Comment thread .github/workflows/scripts-fidelity.yml
Comment thread .github/workflows/scripts-fidelity.yml Outdated
Comment thread .github/workflows/scripts-fidelity.yml Outdated
All six are real; two are holes in fixes from earlier in this same branch.

P1 -- the 27 screenshot job pointed at a directory that does not exist.
run-ios-ui-tests.sh exits 3 when SCREENSHOT_REF_DIR is not a directory, so every
run would have died before the suite started. The directory now exists with a
README, and its screenshot STEP is marked as a seeding run: these images can only
come from a run on the 27 image, because capturing them on a maintainer's machine
records that machine's toolchain rather than the gate's. The README carries the
steps that turn it into a gate.

P1 -- continue-on-error was on the JOB. That converts every failure into a green
tick, so a broken Xcode selection, build, boot or capture would have reported
success while producing none of the scores the comment promises. Both 27 legs now
tolerate exactly one step, and everything before it still fails the job.

P2 -- FidelityGate let a one-sided empty through on a NEW pair. The parse loop
added it to neither collection, and the validation below only iterates pairs that
already have baseline geometry, so a widget missing from our render passed with
exit 0 -- the exact case the native_empty/cn1_empty split was added to catch, and
it did not catch it on the pairs most likely to hit it. It now fails at parse
time, naming which side is blank. Re-tested over four cases: missing from our
render and missing from the native both fail (the first was exit 0 before), both
blank still passes, and a report predating the flags is unchanged.

P2 -- the two fidelity jobs shared a PR comment and a preview path.
run-ios-fidelity-tests.sh exported a fixed marker and subdirectory for every iOS
run, so whichever generation finished last hid the other's scores and could
replace its images. Marker, preview path and title now derive from the golden
set, with ios-26-metal keeping its historical values so existing comments and
links are not orphaned. The screenshot suite already hit this and had to split
its markers; this is the same failure one workflow over.

P2 -- the screenshot workflow's path filters named only screenshots-metal, so a
PR changing an iOS 27 baseline would skip the job that validates it.

P2 -- the fidelity PR trigger was CSS-only, which is right for the 26 row and
wrong for the 27 one: it is the only check on a generation nothing else
exercises. THIS pull request proved it -- it edits the workflow, GlassRecipe, the
gate and the frame goldens, and neither fidelity row ran.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@shai-almog

shai-almog commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

Native fidelity (Android, Material 3)

54 pairs compared -- median 95.6%, worst 91.3% (FlatButton_pressed_dark), 25th pct 94.9%, mean 95.7%.

Distribution -- >=99%: 2 | 95-99%: 37 | 90-95%: 15 | <90%: 0

Component State Appearance Material Fidelity SSIM mean delta vs base Geometry
FlatButton pressed dark normal 91.3% 0.899 3.10 0.0 ok
Tabs normal light normal 92.3% 0.914 3.05 0.0 ok
Button pressed dark normal 92.6% 0.949 4.32 0.0 ok
FlatButton normal dark normal 93.2% 0.938 2.69 0.0 ok
Button disabled dark normal 93.3% 0.928 2.20 0.0 ok
Button pressed light normal 93.3% 0.952 3.68 0.0 ok
FlatButton normal light normal 93.7% 0.941 2.29 0.0 ok
FlatButton pressed light normal 93.8% 0.942 2.56 0.0 ok
FloatingActionButton pressed light normal 94.4% 0.927 2.82 0.0 OFF (h 0.88)
RadioButton normal dark normal 94.5% 0.963 2.19 0.0 ok
RadioButton normal light normal 94.7% 0.964 1.85 0.0 ok
CheckBox selected dark normal 94.7% 0.950 2.60 0.0 ok
RadioButton selected dark normal 94.8% 0.963 2.42 0.0 ok
CheckBox normal dark normal 94.9% 0.952 2.69 0.0 ok
Button normal dark normal 94.9% 0.949 3.16 0.0 ok
CheckBox normal light normal 95.0% 0.953 2.30 0.0 ok
Toolbar normal dark normal 95.1% 0.906 1.60 0.0 ok
RaisedButton pressed dark normal 95.2% 0.950 2.39 0.0 ok
CheckBox disabled dark normal 95.2% 0.954 1.47 0.0 ok
CheckBox disabled light normal 95.2% 0.956 1.34 0.0 ok
Tabs normal dark normal 95.2% 0.913 3.65 0.0 ok
RadioButton disabled dark normal 95.3% 0.963 1.18 0.0 ok
RadioButton selected light normal 95.3% 0.964 1.84 0.0 ok
CheckBox selected light normal 95.4% 0.952 2.06 0.0 ok
Switch selected light normal 95.4% 0.966 1.59 0.0 ok
Switch selected dark normal 95.5% 0.966 1.86 0.0 ok
RadioButton disabled light normal 95.5% 0.966 1.08 0.0 ok
Switch disabled dark normal 95.6% 0.961 0.85 0.0 ok
Dialog normal light normal 95.7% 0.930 2.30 0.0 ok
RaisedButton pressed light normal 95.8% 0.958 2.16 0.0 ok
Button normal light normal 95.8% 0.953 2.46 0.0 ok
Dialog normal dark normal 95.8% 0.932 2.30 0.0 ok
Switch normal light normal 96.0% 0.961 1.45 0.0 ok
FloatingActionButton normal light normal 96.1% 0.937 1.14 0.0 ok
FloatingActionButton pressed dark normal 96.2% 0.951 2.45 0.0 ok
Switch normal dark normal 96.2% 0.962 1.39 0.0 ok
TextField disabled dark normal 96.2% 0.965 0.76 0.0 ok
RaisedButton normal dark normal 96.4% 0.952 1.78 0.0 ok
Switch disabled light normal 96.4% 0.970 0.61 0.0 ok
Button disabled light normal 96.8% 0.960 1.06 0.0 ok
ProgressBar normal dark normal 96.9% 0.967 2.03 0.0 OFF (h 1.50)
RaisedButton disabled dark normal 97.0% 0.955 0.89 0.0 ok
FloatingActionButton normal dark normal 97.1% 0.952 1.43 0.0 ok
ProgressBar normal light normal 97.3% 0.974 1.53 0.0 OFF (h 1.50)
RaisedButton disabled light normal 97.3% 0.961 0.79 0.0 ok
TextField disabled light normal 97.3% 0.965 0.79 0.0 ok
RaisedButton normal light normal 97.3% 0.961 1.40 0.0 ok
TextField normal dark normal 97.6% 0.958 1.83 0.0 ok
TextField normal light normal 97.6% 0.958 1.63 0.0 ok
Slider normal dark normal 98.4% 0.990 0.87 0.0 ok
Toolbar normal light normal 98.7% 0.974 1.28 0.0 ok
Slider normal light normal 99.0% 0.991 0.47 0.0 ok
Slider disabled dark normal 99.6% 0.993 0.22 0.0 ok
Slider disabled light normal 99.6% 0.993 0.18 0.0 ok
Geometry vs native (bbox offset / size ratio / center offset / corner radius) -- gated separately from the visual score
Component State Appearance bbox dx,dy (px) w ratio h ratio center off (px) radius native->cn1 (px)
FloatingActionButton pressed light +0,+0 0.929 0.881 4.0 -
FloatingActionButton normal light +0,+0 0.946 0.912 2.9 -
Button pressed dark +0,+0 0.947 0.975 2.6 -
Button disabled dark +0,+0 0.947 0.975 2.6 -
Button pressed light +0,+0 0.947 0.975 2.6 -
Button normal dark +0,+0 0.947 0.975 2.6 -
RaisedButton pressed dark +0,+0 0.945 0.975 2.6 -
RaisedButton pressed light +0,+0 0.945 0.975 2.6 -
Button normal light +0,+0 0.947 0.975 2.6 -
RaisedButton normal dark +0,+0 0.945 0.975 2.6 -
Button disabled light +0,+0 0.947 0.975 2.6 -
RaisedButton disabled dark +0,+0 0.945 0.975 2.6 -
RaisedButton disabled light +0,+0 0.945 0.975 2.6 -
RaisedButton normal light +0,+0 0.945 0.975 2.6 -
RadioButton normal dark +1,+1 1.029 1.000 2.2 -
RadioButton normal light +1,+1 1.029 1.000 2.2 -
RadioButton selected dark +1,+1 1.029 1.000 2.2 -
RadioButton disabled dark +1,+1 1.029 1.000 2.2 -
RadioButton selected light +1,+1 1.029 1.000 2.2 -
Switch selected light +0,+0 1.080 1.063 2.2 -
RadioButton disabled light +1,+1 1.029 1.000 2.2 -
CheckBox selected dark +1,+1 1.013 1.000 1.8 -
CheckBox normal dark +1,+1 1.013 1.000 1.8 -
CheckBox normal light +1,+1 1.013 1.000 1.8 -
CheckBox disabled dark +1,+1 1.013 1.000 1.8 -
CheckBox disabled light +1,+1 1.013 1.000 1.8 -
CheckBox selected light +1,+1 1.013 1.000 1.8 -
Switch selected dark +0,+0 1.060 1.031 1.6 -
Switch disabled dark +0,-1 1.060 1.031 1.6 -
Dialog normal light +0,+0 1.007 0.982 1.6 -
Dialog normal dark +0,+0 1.007 0.982 1.6 -
Switch normal light +0,-1 1.060 1.031 1.6 -
Switch normal dark +0,-1 1.060 1.031 1.6 -
Switch disabled light +0,-1 1.060 1.031 1.6 -
FloatingActionButton pressed dark +0,+0 0.963 0.963 1.4 -
FloatingActionButton normal dark +0,+0 0.963 0.963 1.4 -
Toolbar normal light -1,+1 1.000 1.000 1.4 -
FlatButton pressed dark +0,+0 0.977 0.975 1.1 -
FlatButton normal dark +0,+0 0.977 0.975 1.1 -
FlatButton normal light +0,+0 0.977 0.975 1.1 -
FlatButton pressed light +0,+0 0.977 0.975 1.1 -
TextField normal dark +0,+0 1.015 1.036 1.1 -
TextField normal light +0,+0 1.015 1.036 1.1 -
Toolbar normal dark +0,+0 1.000 1.032 1.0 -
ProgressBar normal dark +0,+0 1.000 1.500 1.0 -
ProgressBar normal light +0,+0 1.000 1.500 1.0 -
TextField disabled dark +0,+0 1.015 1.018 0.7 -
TextField disabled light +0,+0 1.015 1.018 0.7 -
Tabs normal light +0,+1 1.000 0.984 0.5 -
Slider normal dark +1,+0 0.996 1.000 0.5 -
Slider normal light +1,+0 0.996 1.000 0.5 -
Tabs normal dark +0,+0 1.000 1.000 0.0 -
Slider disabled dark +0,+0 1.000 1.000 0.0 -
Slider disabled light +0,+0 1.000 1.000 0.0 -

Side-by-side comparisons (worst first)

  • FlatButton_pressed_dark -- 91.25% fidelity (SSIM 0.8985) (no change)

    native FlatButton_pressed_dark cn1 FlatButton_pressed_dark
    Left: native widget. Right: Codename One render.

  • Tabs_normal_light -- 92.28% fidelity (SSIM 0.9140) (no change)

    native Tabs_normal_light cn1 Tabs_normal_light
    Left: native widget. Right: Codename One render.

  • Button_pressed_dark -- 92.61% fidelity (SSIM 0.9485) (no change)

    native Button_pressed_dark cn1 Button_pressed_dark
    Left: native widget. Right: Codename One render.

  • FlatButton_normal_dark -- 93.24% fidelity (SSIM 0.9381) (no change)

    native FlatButton_normal_dark cn1 FlatButton_normal_dark
    Left: native widget. Right: Codename One render.

  • Button_disabled_dark -- 93.26% fidelity (SSIM 0.9278) (no change)

    native Button_disabled_dark cn1 Button_disabled_dark
    Left: native widget. Right: Codename One render.

  • Button_pressed_light -- 93.34% fidelity (SSIM 0.9521) (no change)

    native Button_pressed_light cn1 Button_pressed_light
    Left: native widget. Right: Codename One render.

  • FlatButton_normal_light -- 93.72% fidelity (SSIM 0.9410) (no change)

    native FlatButton_normal_light cn1 FlatButton_normal_light
    Left: native widget. Right: Codename One render.

  • FlatButton_pressed_light -- 93.77% fidelity (SSIM 0.9424) (no change)

    native FlatButton_pressed_light cn1 FlatButton_pressed_light
    Left: native widget. Right: Codename One render.

  • FloatingActionButton_pressed_light -- 94.44% fidelity (SSIM 0.9273) (no change)

    native FloatingActionButton_pressed_light cn1 FloatingActionButton_pressed_light
    Left: native widget. Right: Codename One render.

  • RadioButton_normal_dark -- 94.46% fidelity (SSIM 0.9630) (no change)

    native RadioButton_normal_dark cn1 RadioButton_normal_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_normal_light -- 94.69% fidelity (SSIM 0.9643) (no change)

    native RadioButton_normal_light cn1 RadioButton_normal_light
    Left: native widget. Right: Codename One render.

  • CheckBox_selected_dark -- 94.71% fidelity (SSIM 0.9502) (no change)

    native CheckBox_selected_dark cn1 CheckBox_selected_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_selected_dark -- 94.79% fidelity (SSIM 0.9630) (no change)

    native RadioButton_selected_dark cn1 RadioButton_selected_dark
    Left: native widget. Right: Codename One render.

  • CheckBox_normal_dark -- 94.93% fidelity (SSIM 0.9516) (no change)

    native CheckBox_normal_dark cn1 CheckBox_normal_dark
    Left: native widget. Right: Codename One render.

  • Button_normal_dark -- 94.94% fidelity (SSIM 0.9491) (no change)

    native Button_normal_dark cn1 Button_normal_dark
    Left: native widget. Right: Codename One render.

  • CheckBox_normal_light -- 95.03% fidelity (SSIM 0.9531) (no change)

    native CheckBox_normal_light cn1 CheckBox_normal_light
    Left: native widget. Right: Codename One render.

  • Toolbar_normal_dark -- 95.07% fidelity (SSIM 0.9059) (no change)

    native Toolbar_normal_dark cn1 Toolbar_normal_dark
    Left: native widget. Right: Codename One render.

  • RaisedButton_pressed_dark -- 95.19% fidelity (SSIM 0.9501) (no change)

    native RaisedButton_pressed_dark cn1 RaisedButton_pressed_dark
    Left: native widget. Right: Codename One render.

  • CheckBox_disabled_dark -- 95.20% fidelity (SSIM 0.9538) (no change)

    native CheckBox_disabled_dark cn1 CheckBox_disabled_dark
    Left: native widget. Right: Codename One render.

  • CheckBox_disabled_light -- 95.21% fidelity (SSIM 0.9562) (no change)

    native CheckBox_disabled_light cn1 CheckBox_disabled_light
    Left: native widget. Right: Codename One render.

  • Tabs_normal_dark -- 95.23% fidelity (SSIM 0.9125) (no change)

    native Tabs_normal_dark cn1 Tabs_normal_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_disabled_dark -- 95.29% fidelity (SSIM 0.9630) (no change)

    native RadioButton_disabled_dark cn1 RadioButton_disabled_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_selected_light -- 95.33% fidelity (SSIM 0.9642) (no change)

    native RadioButton_selected_light cn1 RadioButton_selected_light
    Left: native widget. Right: Codename One render.

  • CheckBox_selected_light -- 95.37% fidelity (SSIM 0.9524) (no change)

    native CheckBox_selected_light cn1 CheckBox_selected_light
    Left: native widget. Right: Codename One render.

  • Switch_selected_light -- 95.37% fidelity (SSIM 0.9658) (no change)

    native Switch_selected_light cn1 Switch_selected_light
    Left: native widget. Right: Codename One render.

  • Switch_selected_dark -- 95.45% fidelity (SSIM 0.9656) (no change)

    native Switch_selected_dark cn1 Switch_selected_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_disabled_light -- 95.46% fidelity (SSIM 0.9657) (no change)

    native RadioButton_disabled_light cn1 RadioButton_disabled_light
    Left: native widget. Right: Codename One render.

  • Switch_disabled_dark -- 95.57% fidelity (SSIM 0.9613) (no change)

    native Switch_disabled_dark cn1 Switch_disabled_dark
    Left: native widget. Right: Codename One render.

  • Dialog_normal_light -- 95.65% fidelity (SSIM 0.9300) (no change)

    native Dialog_normal_light cn1 Dialog_normal_light
    Left: native widget. Right: Codename One render.

  • RaisedButton_pressed_light -- 95.78% fidelity (SSIM 0.9578) (no change)

    native RaisedButton_pressed_light cn1 RaisedButton_pressed_light
    Left: native widget. Right: Codename One render.

  • Button_normal_light -- 95.79% fidelity (SSIM 0.9528) (no change)

    native Button_normal_light cn1 Button_normal_light
    Left: native widget. Right: Codename One render.

  • Dialog_normal_dark -- 95.79% fidelity (SSIM 0.9322) (no change)

    native Dialog_normal_dark cn1 Dialog_normal_dark
    Left: native widget. Right: Codename One render.

  • Switch_normal_light -- 95.97% fidelity (SSIM 0.9612) (no change)

    native Switch_normal_light cn1 Switch_normal_light
    Left: native widget. Right: Codename One render.

  • FloatingActionButton_normal_light -- 96.09% fidelity (SSIM 0.9367) (no change)

    native FloatingActionButton_normal_light cn1 FloatingActionButton_normal_light
    Left: native widget. Right: Codename One render.

  • FloatingActionButton_pressed_dark -- 96.16% fidelity (SSIM 0.9513) (no change)

    native FloatingActionButton_pressed_dark cn1 FloatingActionButton_pressed_dark
    Left: native widget. Right: Codename One render.

  • Switch_normal_dark -- 96.17% fidelity (SSIM 0.9616) (no change)

    native Switch_normal_dark cn1 Switch_normal_dark
    Left: native widget. Right: Codename One render.

  • TextField_disabled_dark -- 96.21% fidelity (SSIM 0.9648) (no change)

    native TextField_disabled_dark cn1 TextField_disabled_dark
    Left: native widget. Right: Codename One render.

  • RaisedButton_normal_dark -- 96.41% fidelity (SSIM 0.9516) (no change)

    native RaisedButton_normal_dark cn1 RaisedButton_normal_dark
    Left: native widget. Right: Codename One render.

  • Switch_disabled_light -- 96.43% fidelity (SSIM 0.9698) (no change)

    native Switch_disabled_light cn1 Switch_disabled_light
    Left: native widget. Right: Codename One render.

  • Button_disabled_light -- 96.80% fidelity (SSIM 0.9596) (no change)

    native Button_disabled_light cn1 Button_disabled_light
    Left: native widget. Right: Codename One render.

  • ProgressBar_normal_dark -- 96.91% fidelity (SSIM 0.9669) (no change)

    native ProgressBar_normal_dark cn1 ProgressBar_normal_dark
    Left: native widget. Right: Codename One render.

  • RaisedButton_disabled_dark -- 97.02% fidelity (SSIM 0.9549) (no change)

    native RaisedButton_disabled_dark cn1 RaisedButton_disabled_dark
    Left: native widget. Right: Codename One render.

  • FloatingActionButton_normal_dark -- 97.07% fidelity (SSIM 0.9521) (no change)

    native FloatingActionButton_normal_dark cn1 FloatingActionButton_normal_dark
    Left: native widget. Right: Codename One render.

  • ProgressBar_normal_light -- 97.26% fidelity (SSIM 0.9739) (no change)

    native ProgressBar_normal_light cn1 ProgressBar_normal_light
    Left: native widget. Right: Codename One render.

  • RaisedButton_disabled_light -- 97.26% fidelity (SSIM 0.9611) (no change)

    native RaisedButton_disabled_light cn1 RaisedButton_disabled_light
    Left: native widget. Right: Codename One render.

  • TextField_disabled_light -- 97.29% fidelity (SSIM 0.9649) (no change)

    native TextField_disabled_light cn1 TextField_disabled_light
    Left: native widget. Right: Codename One render.

  • RaisedButton_normal_light -- 97.32% fidelity (SSIM 0.9613) (no change)

    native RaisedButton_normal_light cn1 RaisedButton_normal_light
    Left: native widget. Right: Codename One render.

  • TextField_normal_dark -- 97.61% fidelity (SSIM 0.9583) (no change)

    native TextField_normal_dark cn1 TextField_normal_dark
    Left: native widget. Right: Codename One render.

  • TextField_normal_light -- 97.62% fidelity (SSIM 0.9582) (no change)

    native TextField_normal_light cn1 TextField_normal_light
    Left: native widget. Right: Codename One render.

  • Slider_normal_dark -- 98.39% fidelity (SSIM 0.9900) (no change)

    native Slider_normal_dark cn1 Slider_normal_dark
    Left: native widget. Right: Codename One render.

  • Toolbar_normal_light -- 98.69% fidelity (SSIM 0.9739) (no change)

    native Toolbar_normal_light cn1 Toolbar_normal_light
    Left: native widget. Right: Codename One render.

  • Slider_normal_light -- 98.95% fidelity (SSIM 0.9908) (no change)

    native Slider_normal_light cn1 Slider_normal_light
    Left: native widget. Right: Codename One render.

  • Slider_disabled_dark -- 99.56% fidelity (SSIM 0.9927) (no change)

    native Slider_disabled_dark cn1 Slider_disabled_dark
    Left: native widget. Right: Codename One render.

  • Slider_disabled_light -- 99.59% fidelity (SSIM 0.9932) (no change)

    native Slider_disabled_light cn1 Slider_disabled_light
    Left: native widget. Right: Codename One render.

@shai-almog

shai-almog commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

Native fidelity (ios-27-metal)

68 pairs compared -- median 94.5%, worst 68.8% (Tabs_normal_dark), 25th pct 91.6%, mean 92.8%.

Distribution -- >=99%: 0 | 95-99%: 31 | 90-95%: 23 | <90%: 14

Component State Appearance Material Fidelity SSIM mean delta vs base Geometry
Tabs normal dark glass 68.8% 0.834 29.29 n/a ok
Toolbar normal dark glass 74.5% 0.930 7.16 n/a ok
Button normal dark glass 79.3% 0.938 7.66 n/a OFF (off 11px)
Button disabled dark glass 79.6% 0.942 7.41 n/a OFF (off 11px)
RaisedButton disabled dark glass 81.2% 0.954 6.32 n/a ok
Tabs normal light glass 81.8% 0.877 13.56 n/a ok
Button pressed dark glass 86.3% 0.948 5.27 n/a OFF (off 11px)
TextField normal light normal 86.6% 0.948 3.33 n/a ok
Toolbar normal light glass 86.9% 0.949 3.85 n/a ok
TabsGeom normal dark normal 87.7% 0.847 24.01 n/a ok
TabsGeom normal light normal 89.4% 0.867 21.23 n/a ok
Button normal light glass 89.5% 0.959 4.54 n/a OFF (off 11px)
Button pressed light glass 89.5% 0.959 4.33 n/a OFF (off 11px)
TextField disabled light normal 89.5% 0.953 2.50 n/a ok
Spinner normal dark normal 90.7% 0.880 3.47 n/a ok
FlatButton normal dark glass 90.9% 0.981 2.38 n/a ok
Button disabled light glass 91.6% 0.962 3.21 n/a OFF (off 11px)
Spinner normal light normal 91.6% 0.910 4.20 n/a ok
CheckBox normal light normal 91.7% 0.994 0.72 n/a ok
RadioButton normal light normal 91.7% 0.994 0.72 n/a ok
Slider disabled dark normal 92.1% 0.943 2.45 n/a ok
Switch selected light normal 92.1% 0.981 1.47 n/a ok
CheckBox disabled light normal 92.3% 0.995 0.52 n/a ok
RadioButton disabled light normal 92.3% 0.995 0.52 n/a ok
FlatButton pressed dark glass 92.4% 0.982 1.37 n/a ok
RaisedButton disabled light glass 92.4% 0.960 2.43 n/a ok
Slider normal dark normal 92.5% 0.944 2.63 n/a ok
FlatButton pressed light glass 93.3% 0.981 1.90 n/a ok
FlatButton normal light glass 93.9% 0.981 1.88 n/a ok
Slider disabled light normal 94.0% 0.963 1.75 n/a OFF (h 4.50)
RaisedButton pressed dark glass 94.1% 0.966 2.29 n/a ok
RaisedButton normal dark glass 94.1% 0.966 2.32 n/a ok
RadioButton selected light normal 94.3% 0.990 0.95 n/a ok
GlassPanelPhoto normal dark glass 94.5% 0.950 13.19 n/a ok
RaisedButton pressed light glass 94.5% 0.963 2.16 n/a ok
RaisedButton normal light glass 94.6% 0.963 2.17 n/a ok
GlassPanelPhoto normal light glass 94.7% 0.952 11.54 n/a ok
Slider normal light normal 95.1% 0.959 1.56 n/a ok
CheckBox disabled dark normal 95.4% 0.992 0.25 n/a ok
RadioButton disabled dark normal 95.4% 0.992 0.25 n/a ok
Switch normal light normal 95.5% 0.986 0.70 n/a ok
CheckBox selected light normal 95.8% 0.995 0.65 n/a ok
CheckBox normal dark normal 95.8% 0.992 0.39 n/a ok
RadioButton normal dark normal 95.8% 0.992 0.39 n/a ok
Switch selected dark normal 95.9% 0.985 1.02 n/a ok
TextField normal dark normal 96.0% 0.938 4.56 n/a ok
RadioButton selected dark normal 96.1% 0.989 0.67 n/a ok
TabOne normal light normal 96.2% 0.954 8.00 n/a ok
Switch disabled light normal 96.4% 0.990 0.53 n/a ok
TextField disabled dark normal 96.4% 0.940 3.42 n/a ok
TabOne normal dark normal 96.8% 0.953 4.61 n/a ok
Switch normal dark normal 96.8% 0.986 0.82 n/a ok
GlassIcon normal dark normal 97.0% 0.952 3.33 n/a OFF (w 0.07, h 0.36)
GlassText normal dark normal 97.1% 0.953 3.30 n/a OFF (off 7px, w 0.05, h 0.12)
GlassPanelGrey normal dark normal 97.3% 0.958 3.41 n/a -
ProgressBar normal dark normal 97.5% 0.997 0.60 n/a ok
ProgressBar normal light normal 97.6% 0.999 0.61 n/a ok
GlassPanelRed normal dark normal 97.8% 0.980 6.75 n/a -
GlassPanelGrad normal dark normal 97.8% 0.974 4.87 n/a OFF (off 106px, h 0.02)
CheckBox selected dark normal 97.9% 0.995 0.37 n/a ok
Dialog normal dark normal 97.9% 0.961 1.38 n/a ok
Dialog normal light normal 98.0% 0.963 1.42 n/a ok
Switch disabled dark normal 98.0% 0.987 0.41 n/a ok
GlassIcon normal light normal 98.2% 0.976 3.63 n/a ok
GlassText normal light normal 98.3% 0.978 3.60 n/a ok
GlassPanelGrad normal light normal 98.5% 0.989 5.48 n/a ok
GlassPanelGrey normal light normal 98.8% 0.989 3.57 n/a ok
GlassPanelRed normal light normal 98.9% 0.992 4.09 n/a ok
Geometry vs native (bbox offset / size ratio / center offset / corner radius) -- gated separately from the visual score
Component State Appearance bbox dx,dy (px) w ratio h ratio center off (px) radius native->cn1 (px)
GlassPanelGrad normal dark +13,+0 0.975 0.019 105.5 102.0 -> 0.0
Button normal dark +0,-6 1.094 1.067 10.9 90.5 -> 45.2
Button disabled dark +0,-6 1.094 1.067 10.9 92.0 -> 45.2
Button pressed dark +0,-6 1.094 1.080 10.8 79.4 -> 45.3
Button normal light +0,+0 1.094 1.000 10.5 45.7 -> 45.3
Button pressed light +0,+0 1.094 1.000 10.5 87.5 -> 45.4
Button disabled light +0,+0 1.094 1.000 10.5 49.1 -> 45.3
GlassText normal dark +502,+97 0.046 0.117 6.5 102.3 -> 19.5
GlassIcon normal dark +486,+71 0.074 0.361 5.7 102.3 -> 60.1
TabOne normal light +0,+0 0.993 0.948 4.6 80.9 -> 77.0
TabOne normal dark +1,+0 0.986 0.948 4.6 95.2 -> 76.4
Toolbar normal dark +6,-3 0.983 1.009 3.5 90.3 -> 55.5
Toolbar normal light +6,+7 0.984 0.926 3.2 70.9 -> 56.1
RaisedButton disabled dark +0,-6 1.009 1.079 2.7 89.6 -> 46.1
Switch selected light +0,+0 1.028 1.026 2.7 -
Slider disabled light +0,-29 1.000 4.500 2.5 -
Switch normal light +0,+0 1.023 1.013 2.1 -
Switch disabled light +0,+0 1.023 1.013 2.1 -
Switch normal dark +0,+0 1.023 1.013 2.1 -
Switch disabled dark +0,+0 1.023 1.013 2.1 -
Spinner normal light +11,-8 0.978 1.052 1.6 -
RaisedButton disabled light +0,+0 1.014 1.011 1.6 71.9 -> 96.6
FlatButton normal light +0,+0 0.980 1.011 1.6 86.2 -> 51.8
Switch selected dark +0,+0 1.017 1.013 1.6 -
Spinner normal dark +12,-8 0.977 1.052 1.5 -
CheckBox normal light +0,+0 0.977 0.977 1.4 -
RadioButton normal light +0,+0 0.977 0.977 1.4 -
RadioButton selected light +0,+0 0.977 0.977 1.4 -
CheckBox selected light +0,+0 0.977 0.977 1.4 -
CheckBox normal dark +0,+0 0.977 0.977 1.4 -
RadioButton normal dark +0,+0 0.977 0.977 1.4 -
RadioButton selected dark +0,+0 0.977 0.977 1.4 -
CheckBox selected dark +0,+0 0.977 0.977 1.4 -
Tabs normal dark +12,+0 0.968 1.012 1.1 92.9 -> 80.9
Tabs normal light +12,+0 0.968 1.012 1.1 85.9 -> 80.3
TabsGeom normal dark +12,+0 0.968 1.012 1.1 98.6 -> 80.0
TabsGeom normal light +11,+0 0.970 1.012 1.1 79.8 -> 80.6
FlatButton pressed light +1,+0 0.973 1.011 1.1 94.6 -> 65.6
RaisedButton pressed dark +0,+0 1.009 1.011 1.1 44.6 -> 44.3
RaisedButton normal dark +0,+0 1.009 1.011 1.1 44.5 -> 44.3
CheckBox disabled dark +1,+0 0.966 0.977 1.1 -
RadioButton disabled dark +1,+0 0.966 0.977 1.1 -
RaisedButton pressed light +0,+0 1.009 1.000 1.0 43.3 -> 44.3
RaisedButton normal light +0,+0 1.009 1.000 1.0 43.3 -> 44.1
TextField disabled light +0,+1 0.999 0.996 0.7 13.9 -> 38.8
FlatButton normal dark +4,+0 0.952 1.011 0.7 86.1 -> 95.7
FlatButton pressed dark +4,+0 0.952 1.011 0.7 94.7 -> 97.9
GlassPanelPhoto normal light +1,+1 0.997 0.995 0.7 35.1 -> 33.3
GlassPanelGrey normal light +1,+1 0.997 0.995 0.7 30.0 -> 26.1
Slider disabled dark +0,-1 1.000 1.015 0.5 -
CheckBox disabled light +1,+0 0.977 0.988 0.5 -
RadioButton disabled light +1,+0 0.977 0.988 0.5 -
Slider normal light +0,+1 1.000 0.964 0.5 -
ProgressBar normal dark +0,+0 1.000 0.900 0.5 -
ProgressBar normal light +0,+0 1.000 0.900 0.5 -
GlassIcon normal light +1,+0 0.998 1.005 0.5 91.7 -> 92.4
GlassText normal light +1,+0 0.998 1.005 0.5 91.7 -> 92.4
GlassPanelGrad normal light +1,+0 0.998 1.005 0.5 24.3 -> 26.1
GlassPanelRed normal light +1,+0 0.998 1.005 0.5 24.4 -> 26.3
TextField normal light +0,+0 1.000 1.000 0.0 13.4 -> 40.5
Slider normal dark +0,+0 1.000 1.000 0.0 -
GlassPanelPhoto normal dark +3,+1 0.994 0.991 0.0 67.3 -> 68.4
TextField normal dark +0,+0 1.000 1.000 0.0 6.4 -> 15.1
TextField disabled dark +0,+0 1.000 1.000 0.0 6.4 -> 15.9
Dialog normal dark +0,+0 1.000 1.000 0.0 -
Dialog normal light +0,+0 1.000 1.000 0.0 -

Side-by-side comparisons (worst first)

  • Tabs_normal_dark -- 68.75% fidelity (SSIM 0.8336) (no baseline)

    native Tabs_normal_dark cn1 Tabs_normal_dark
    Left: native widget. Right: Codename One render.

  • Toolbar_normal_dark -- 74.49% fidelity (SSIM 0.9295) (no baseline)

    native Toolbar_normal_dark cn1 Toolbar_normal_dark
    Left: native widget. Right: Codename One render.

  • Button_normal_dark -- 79.28% fidelity (SSIM 0.9380) (no baseline)

    native Button_normal_dark cn1 Button_normal_dark
    Left: native widget. Right: Codename One render.

  • Button_disabled_dark -- 79.63% fidelity (SSIM 0.9423) (no baseline)

    native Button_disabled_dark cn1 Button_disabled_dark
    Left: native widget. Right: Codename One render.

  • RaisedButton_disabled_dark -- 81.15% fidelity (SSIM 0.9544) (no baseline)

    native RaisedButton_disabled_dark cn1 RaisedButton_disabled_dark
    Left: native widget. Right: Codename One render.

  • Tabs_normal_light -- 81.80% fidelity (SSIM 0.8766) (no baseline)

    native Tabs_normal_light cn1 Tabs_normal_light
    Left: native widget. Right: Codename One render.

  • Button_pressed_dark -- 86.28% fidelity (SSIM 0.9483) (no baseline)

    native Button_pressed_dark cn1 Button_pressed_dark
    Left: native widget. Right: Codename One render.

  • TextField_normal_light -- 86.57% fidelity (SSIM 0.9483) (no baseline)

    native TextField_normal_light cn1 TextField_normal_light
    Left: native widget. Right: Codename One render.

  • Toolbar_normal_light -- 86.94% fidelity (SSIM 0.9488) (no baseline)

    native Toolbar_normal_light cn1 Toolbar_normal_light
    Left: native widget. Right: Codename One render.

  • TabsGeom_normal_dark -- 87.73% fidelity (SSIM 0.8469) (no baseline)

    native TabsGeom_normal_dark cn1 TabsGeom_normal_dark
    Left: native widget. Right: Codename One render.

  • TabsGeom_normal_light -- 89.37% fidelity (SSIM 0.8672) (no baseline)

    native TabsGeom_normal_light cn1 TabsGeom_normal_light
    Left: native widget. Right: Codename One render.

  • Button_normal_light -- 89.45% fidelity (SSIM 0.9588) (no baseline)

    native Button_normal_light cn1 Button_normal_light
    Left: native widget. Right: Codename One render.

  • Button_pressed_light -- 89.45% fidelity (SSIM 0.9588) (no baseline)

    native Button_pressed_light cn1 Button_pressed_light
    Left: native widget. Right: Codename One render.

  • TextField_disabled_light -- 89.54% fidelity (SSIM 0.9532) (no baseline)

    native TextField_disabled_light cn1 TextField_disabled_light
    Left: native widget. Right: Codename One render.

  • Spinner_normal_dark -- 90.72% fidelity (SSIM 0.8800) (no baseline)

    native Spinner_normal_dark cn1 Spinner_normal_dark
    Left: native widget. Right: Codename One render.

  • FlatButton_normal_dark -- 90.88% fidelity (SSIM 0.9805) (no baseline)

    native FlatButton_normal_dark cn1 FlatButton_normal_dark
    Left: native widget. Right: Codename One render.

  • Button_disabled_light -- 91.57% fidelity (SSIM 0.9621) (no baseline)

    native Button_disabled_light cn1 Button_disabled_light
    Left: native widget. Right: Codename One render.

  • Spinner_normal_light -- 91.58% fidelity (SSIM 0.9097) (no baseline)

    native Spinner_normal_light cn1 Spinner_normal_light
    Left: native widget. Right: Codename One render.

  • CheckBox_normal_light -- 91.66% fidelity (SSIM 0.9935) (no baseline)

    native CheckBox_normal_light cn1 CheckBox_normal_light
    Left: native widget. Right: Codename One render.

  • RadioButton_normal_light -- 91.66% fidelity (SSIM 0.9935) (no baseline)

    native RadioButton_normal_light cn1 RadioButton_normal_light
    Left: native widget. Right: Codename One render.

  • Slider_disabled_dark -- 92.13% fidelity (SSIM 0.9434) (no baseline)

    native Slider_disabled_dark cn1 Slider_disabled_dark
    Left: native widget. Right: Codename One render.

  • Switch_selected_light -- 92.13% fidelity (SSIM 0.9806) (no baseline)

    native Switch_selected_light cn1 Switch_selected_light
    Left: native widget. Right: Codename One render.

  • CheckBox_disabled_light -- 92.31% fidelity (SSIM 0.9948) (no baseline)

    native CheckBox_disabled_light cn1 CheckBox_disabled_light
    Left: native widget. Right: Codename One render.

  • RadioButton_disabled_light -- 92.31% fidelity (SSIM 0.9948) (no baseline)

    native RadioButton_disabled_light cn1 RadioButton_disabled_light
    Left: native widget. Right: Codename One render.

  • FlatButton_pressed_dark -- 92.38% fidelity (SSIM 0.9821) (no baseline)

    native FlatButton_pressed_dark cn1 FlatButton_pressed_dark
    Left: native widget. Right: Codename One render.

  • RaisedButton_disabled_light -- 92.40% fidelity (SSIM 0.9596) (no baseline)

    native RaisedButton_disabled_light cn1 RaisedButton_disabled_light
    Left: native widget. Right: Codename One render.

  • Slider_normal_dark -- 92.52% fidelity (SSIM 0.9441) (no baseline)

    native Slider_normal_dark cn1 Slider_normal_dark
    Left: native widget. Right: Codename One render.

  • FlatButton_pressed_light -- 93.29% fidelity (SSIM 0.9811) (no baseline)

    native FlatButton_pressed_light cn1 FlatButton_pressed_light
    Left: native widget. Right: Codename One render.

  • FlatButton_normal_light -- 93.91% fidelity (SSIM 0.9811) (no baseline)

    native FlatButton_normal_light cn1 FlatButton_normal_light
    Left: native widget. Right: Codename One render.

  • Slider_disabled_light -- 93.96% fidelity (SSIM 0.9625) (no baseline)

    native Slider_disabled_light cn1 Slider_disabled_light
    Left: native widget. Right: Codename One render.

  • RaisedButton_pressed_dark -- 94.08% fidelity (SSIM 0.9659) (no baseline)

    native RaisedButton_pressed_dark cn1 RaisedButton_pressed_dark
    Left: native widget. Right: Codename One render.

  • RaisedButton_normal_dark -- 94.13% fidelity (SSIM 0.9660) (no baseline)

    native RaisedButton_normal_dark cn1 RaisedButton_normal_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_selected_light -- 94.26% fidelity (SSIM 0.9903) (no baseline)

    native RadioButton_selected_light cn1 RadioButton_selected_light
    Left: native widget. Right: Codename One render.

  • GlassPanelPhoto_normal_dark -- 94.49% fidelity (SSIM 0.9495) (no baseline)

    native GlassPanelPhoto_normal_dark cn1 GlassPanelPhoto_normal_dark
    Left: native widget. Right: Codename One render.

  • RaisedButton_pressed_light -- 94.53% fidelity (SSIM 0.9633) (no baseline)

    native RaisedButton_pressed_light cn1 RaisedButton_pressed_light
    Left: native widget. Right: Codename One render.

  • RaisedButton_normal_light -- 94.64% fidelity (SSIM 0.9632) (no baseline)

    native RaisedButton_normal_light cn1 RaisedButton_normal_light
    Left: native widget. Right: Codename One render.

  • GlassPanelPhoto_normal_light -- 94.72% fidelity (SSIM 0.9520) (no baseline)

    native GlassPanelPhoto_normal_light cn1 GlassPanelPhoto_normal_light
    Left: native widget. Right: Codename One render.

  • Slider_normal_light -- 95.09% fidelity (SSIM 0.9588) (no baseline)

    native Slider_normal_light cn1 Slider_normal_light
    Left: native widget. Right: Codename One render.

  • CheckBox_disabled_dark -- 95.41% fidelity (SSIM 0.9924) (no baseline)

    native CheckBox_disabled_dark cn1 CheckBox_disabled_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_disabled_dark -- 95.41% fidelity (SSIM 0.9924) (no baseline)

    native RadioButton_disabled_dark cn1 RadioButton_disabled_dark
    Left: native widget. Right: Codename One render.

  • Switch_normal_light -- 95.51% fidelity (SSIM 0.9863) (no baseline)

    native Switch_normal_light cn1 Switch_normal_light
    Left: native widget. Right: Codename One render.

  • CheckBox_selected_light -- 95.80% fidelity (SSIM 0.9951) (no baseline)

    native CheckBox_selected_light cn1 CheckBox_selected_light
    Left: native widget. Right: Codename One render.

  • CheckBox_normal_dark -- 95.84% fidelity (SSIM 0.9922) (no baseline)

    native CheckBox_normal_dark cn1 CheckBox_normal_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_normal_dark -- 95.84% fidelity (SSIM 0.9922) (no baseline)

    native RadioButton_normal_dark cn1 RadioButton_normal_dark
    Left: native widget. Right: Codename One render.

  • Switch_selected_dark -- 95.90% fidelity (SSIM 0.9850) (no baseline)

    native Switch_selected_dark cn1 Switch_selected_dark
    Left: native widget. Right: Codename One render.

  • TextField_normal_dark -- 96.02% fidelity (SSIM 0.9375) (no baseline)

    native TextField_normal_dark cn1 TextField_normal_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_selected_dark -- 96.13% fidelity (SSIM 0.9894) (no baseline)

    native RadioButton_selected_dark cn1 RadioButton_selected_dark
    Left: native widget. Right: Codename One render.

  • TabOne_normal_light -- 96.16% fidelity (SSIM 0.9537) (no baseline)

    native TabOne_normal_light cn1 TabOne_normal_light
    Left: native widget. Right: Codename One render.

  • Switch_disabled_light -- 96.35% fidelity (SSIM 0.9896) (no baseline)

    native Switch_disabled_light cn1 Switch_disabled_light
    Left: native widget. Right: Codename One render.

  • TextField_disabled_dark -- 96.38% fidelity (SSIM 0.9402) (no baseline)

    native TextField_disabled_dark cn1 TextField_disabled_dark
    Left: native widget. Right: Codename One render.

  • TabOne_normal_dark -- 96.76% fidelity (SSIM 0.9529) (no baseline)

    native TabOne_normal_dark cn1 TabOne_normal_dark
    Left: native widget. Right: Codename One render.

  • Switch_normal_dark -- 96.80% fidelity (SSIM 0.9855) (no baseline)

    native Switch_normal_dark cn1 Switch_normal_dark
    Left: native widget. Right: Codename One render.

  • GlassIcon_normal_dark -- 97.03% fidelity (SSIM 0.9521) (no baseline)

    native GlassIcon_normal_dark cn1 GlassIcon_normal_dark
    Left: native widget. Right: Codename One render.

  • GlassText_normal_dark -- 97.06% fidelity (SSIM 0.9528) (no baseline)

    native GlassText_normal_dark cn1 GlassText_normal_dark
    Left: native widget. Right: Codename One render.

  • GlassPanelGrey_normal_dark -- 97.28% fidelity (SSIM 0.9578) (no baseline)

    native GlassPanelGrey_normal_dark cn1 GlassPanelGrey_normal_dark
    Left: native widget. Right: Codename One render.

  • ProgressBar_normal_dark -- 97.47% fidelity (SSIM 0.9973) (no baseline)

    native ProgressBar_normal_dark cn1 ProgressBar_normal_dark
    Left: native widget. Right: Codename One render.

  • ProgressBar_normal_light -- 97.60% fidelity (SSIM 0.9989) (no baseline)

    native ProgressBar_normal_light cn1 ProgressBar_normal_light
    Left: native widget. Right: Codename One render.

  • GlassPanelRed_normal_dark -- 97.75% fidelity (SSIM 0.9800) (no baseline)

    native GlassPanelRed_normal_dark cn1 GlassPanelRed_normal_dark
    Left: native widget. Right: Codename One render.

  • GlassPanelGrad_normal_dark -- 97.84% fidelity (SSIM 0.9742) (no baseline)

    native GlassPanelGrad_normal_dark cn1 GlassPanelGrad_normal_dark
    Left: native widget. Right: Codename One render.

  • CheckBox_selected_dark -- 97.85% fidelity (SSIM 0.9945) (no baseline)

    native CheckBox_selected_dark cn1 CheckBox_selected_dark
    Left: native widget. Right: Codename One render.

  • Dialog_normal_dark -- 97.86% fidelity (SSIM 0.9614) (no baseline)

    native Dialog_normal_dark cn1 Dialog_normal_dark
    Left: native widget. Right: Codename One render.

  • Dialog_normal_light -- 97.95% fidelity (SSIM 0.9634) (no baseline)

    native Dialog_normal_light cn1 Dialog_normal_light
    Left: native widget. Right: Codename One render.

  • Switch_disabled_dark -- 98.01% fidelity (SSIM 0.9869) (no baseline)

    native Switch_disabled_dark cn1 Switch_disabled_dark
    Left: native widget. Right: Codename One render.

  • GlassIcon_normal_light -- 98.19% fidelity (SSIM 0.9759) (no baseline)

    native GlassIcon_normal_light cn1 GlassIcon_normal_light
    Left: native widget. Right: Codename One render.

  • GlassText_normal_light -- 98.28% fidelity (SSIM 0.9776) (no baseline)

    native GlassText_normal_light cn1 GlassText_normal_light
    Left: native widget. Right: Codename One render.

  • GlassPanelGrad_normal_light -- 98.51% fidelity (SSIM 0.9894) (no baseline)

    native GlassPanelGrad_normal_light cn1 GlassPanelGrad_normal_light
    Left: native widget. Right: Codename One render.

  • GlassPanelGrey_normal_light -- 98.81% fidelity (SSIM 0.9889) (no baseline)

    native GlassPanelGrey_normal_light cn1 GlassPanelGrey_normal_light
    Left: native widget. Right: Codename One render.

  • GlassPanelRed_normal_light -- 98.89% fidelity (SSIM 0.9923) (no baseline)

    native GlassPanelRed_normal_light cn1 GlassPanelRed_normal_light
    Left: native widget. Right: Codename One render.

@shai-almog

shai-almog commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

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

@shai-almog

shai-almog commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

Native fidelity (iOS Modern, Metal)

68 pairs compared -- median 95.0%, worst 83.5% (Tabs_normal_dark), 25th pct 92.5%, mean 94.6%.

Distribution -- >=99%: 3 | 95-99%: 31 | 90-95%: 29 | <90%: 5

Component State Appearance Material Fidelity SSIM mean delta vs base Geometry
Tabs normal dark glass 83.5% 0.884 11.66 0.0 ok
Tabs normal light glass 86.4% 0.896 8.01 0.0 ok
Toolbar normal light glass 87.6% 0.951 4.24 0.0 ok
Toolbar normal dark glass 87.7% 0.950 3.69 0.0 ok
Button pressed dark glass 89.9% 0.958 4.21 0.0 OFF (off 12px, w 1.10)
TextField normal light normal 90.0% 0.958 2.78 -0.4 ok
Spinner normal dark normal 90.8% 0.881 3.39 -0.7 ok
TextField disabled light normal 91.1% 0.962 2.24 -0.2 ok
Spinner normal light normal 91.6% 0.910 4.11 -0.2 ok
RaisedButton disabled light glass 91.8% 0.961 3.09 +0.2 ok
Button normal dark glass 91.8% 0.958 3.52 0.0 OFF (off 12px, w 1.10)
Slider disabled dark normal 92.1% 0.943 2.45 -0.3 ok
Switch selected light normal 92.1% 0.981 1.47 0.0 ok
CheckBox normal light normal 92.2% 0.994 0.68 0.0 ok
RadioButton normal light normal 92.2% 0.994 0.68 0.0 ok
FlatButton normal dark glass 92.2% 0.983 2.21 +4.3 ok
Button normal light glass 92.4% 0.961 3.65 0.0 OFF (off 12px, w 1.10)
Slider normal dark normal 92.5% 0.944 2.63 -0.2 ok
RaisedButton disabled dark glass 92.7% 0.965 2.72 +1.3 ok
CheckBox disabled light normal 92.7% 0.995 0.50 0.0 ok
RadioButton disabled light normal 92.7% 0.995 0.50 0.0 ok
Button pressed light glass 92.9% 0.962 3.29 0.0 OFF (off 12px, w 1.10)
FlatButton pressed dark glass 92.9% 0.985 1.26 +2.3 ok
TabsGeom normal dark normal 93.0% 0.892 8.76 0.0 ok
TabsGeom normal light normal 93.0% 0.886 7.10 0.0 ok
FlatButton pressed light glass 93.2% 0.982 1.90 +4.3 ok
Button disabled dark glass 93.5% 0.962 2.47 0.0 OFF (off 12px, w 1.10)
Slider disabled light normal 94.0% 0.963 1.75 -0.1 OFF (h 4.50)
FlatButton normal light glass 94.2% 0.983 1.79 +1.3 ok
Button disabled light glass 94.4% 0.964 2.36 0.0 OFF (off 12px, w 1.10)
RaisedButton pressed dark glass 94.6% 0.965 2.07 +1.5 ok
RaisedButton normal dark glass 94.6% 0.966 2.08 +1.7 ok
RaisedButton pressed light glass 94.8% 0.967 2.22 +2.0 ok
RadioButton selected light normal 94.8% 0.992 0.86 0.0 ok
RaisedButton normal light glass 95.0% 0.967 2.19 +2.4 ok
Slider normal light normal 95.1% 0.959 1.56 0.0 ok
Switch normal light normal 95.5% 0.986 0.70 0.0 ok
CheckBox disabled dark normal 95.8% 0.993 0.25 0.0 ok
RadioButton disabled dark normal 95.8% 0.993 0.25 0.0 ok
CheckBox selected light normal 95.8% 0.994 0.67 0.0 ok
Switch selected dark normal 95.9% 0.985 1.02 0.0 ok
Switch disabled light normal 96.4% 0.990 0.53 0.0 ok
CheckBox normal dark normal 96.5% 0.993 0.35 0.0 ok
RadioButton normal dark normal 96.5% 0.993 0.35 0.0 ok
GlassPanelPhoto normal light glass 96.7% 0.980 7.95 +0.6 ok
GlassPanelPhoto normal dark glass 96.8% 0.983 8.78 +0.6 ok
TabOne normal dark normal 96.8% 0.953 4.44 +0.7 ok
Switch normal dark normal 96.8% 0.986 0.82 0.0 ok
RadioButton selected dark normal 96.8% 0.991 0.57 0.0 ok
TextField normal dark normal 96.9% 0.949 3.30 -0.2 ok
TextField disabled dark normal 97.2% 0.953 2.37 -0.2 ok
ProgressBar normal dark normal 97.5% 0.997 0.60 +3.0 ok
TabOne normal light normal 97.5% 0.961 2.89 +1.9 ok
ProgressBar normal light normal 97.6% 0.999 0.61 +2.2 ok
CheckBox selected dark normal 97.8% 0.993 0.38 0.0 ok
Dialog normal dark normal 97.9% 0.961 1.38 +0.9 ok
Dialog normal light normal 98.0% 0.963 1.42 +0.9 ok
Switch disabled dark normal 98.0% 0.987 0.41 +2.5 ok
GlassIcon normal dark normal 98.6% 0.984 3.55 0.0 ok
GlassText normal dark normal 98.6% 0.984 3.52 0.0 ok
GlassIcon normal light normal 98.7% 0.986 3.54 0.0 ok
GlassText normal light normal 98.7% 0.986 3.58 0.0 ok
GlassPanelGrad normal light normal 98.9% 0.994 4.38 +0.7 ok
GlassPanelGrad normal dark normal 99.0% 0.993 3.84 +0.5 ok
GlassPanelGrey normal dark normal 99.0% 0.992 3.30 +0.6 ok
GlassPanelGrey normal light normal 99.1% 0.994 3.29 +0.7 ok
GlassPanelRed normal dark normal 99.1% 0.993 3.22 +0.5 ok
GlassPanelRed normal light normal 99.1% 0.994 3.49 +0.7 ok
Geometry vs native (bbox offset / size ratio / center offset / corner radius) -- gated separately from the visual score
Component State Appearance bbox dx,dy (px) w ratio h ratio center off (px) radius native->cn1 (px)
Button pressed dark +0,+0 1.104 1.000 11.5 45.4 -> 45.3
Button normal dark +0,+0 1.104 1.000 11.5 45.8 -> 45.2
Button normal light +0,+0 1.104 1.000 11.5 44.5 -> 45.3
Button pressed light +0,+0 1.104 1.000 11.5 48.1 -> 45.4
Button disabled dark +0,+0 1.104 1.000 11.5 45.1 -> 45.2
Button disabled light +0,+0 1.104 1.000 11.5 44.0 -> 45.3
TabOne normal dark -3,+0 1.007 0.948 4.9 80.3 -> 77.3
TabOne normal light -3,+0 1.007 0.948 4.9 79.1 -> 77.0
Toolbar normal light +4,+7 0.987 0.926 3.5 62.5 -> 56.1
Toolbar normal dark +4,+7 0.987 0.919 3.2 60.5 -> 55.5
Switch selected light +0,+0 1.028 1.026 2.7 -
RaisedButton disabled dark +0,+0 1.024 1.011 2.6 49.8 -> 46.1
Slider disabled light +0,-29 1.000 4.500 2.5 -
CheckBox disabled light +1,-3 1.000 1.023 2.2 -
RadioButton disabled light +1,-3 1.000 1.023 2.2 -
CheckBox disabled dark +1,-3 1.000 1.023 2.2 -
RadioButton disabled dark +1,-3 1.000 1.023 2.2 -
RaisedButton disabled light +0,+0 1.019 1.011 2.1 54.1 -> 96.6
RaisedButton pressed dark +0,+0 1.019 1.011 2.1 44.5 -> 44.3
RaisedButton normal dark +0,+0 1.019 1.011 2.1 44.4 -> 44.3
RaisedButton pressed light +0,+0 1.019 1.011 2.1 44.7 -> 44.3
RaisedButton normal light +0,+0 1.019 1.011 2.1 44.5 -> 44.1
Switch normal light +0,+0 1.023 1.013 2.1 -
Switch disabled light +0,+0 1.023 1.013 2.1 -
Switch normal dark +0,+0 1.023 1.013 2.1 -
Switch disabled dark +0,+0 1.023 1.013 2.1 -
CheckBox normal dark +0,-2 1.000 1.000 2.0 -
RadioButton normal dark +0,-2 1.000 1.000 2.0 -
RadioButton selected dark +0,-2 1.000 1.000 2.0 -
CheckBox selected dark +0,-2 1.000 1.000 2.0 -
Tabs normal dark +9,+0 0.973 1.012 1.8 79.7 -> 80.7
Tabs normal light +9,+0 0.973 1.012 1.8 79.2 -> 80.3
TabsGeom normal dark +9,+0 0.973 1.012 1.8 80.5 -> 80.9
TabsGeom normal light +9,+0 0.973 1.012 1.8 79.3 -> 80.6
FlatButton normal dark +4,+0 0.966 1.011 1.6 91.8 -> 95.7
FlatButton pressed dark +4,+0 0.966 1.011 1.6 95.3 -> 97.9
Switch selected dark +0,+0 1.017 1.013 1.6 -
CheckBox normal light +0,-2 1.000 1.011 1.5 -
RadioButton normal light +0,-2 1.000 1.011 1.5 -
RadioButton selected light +0,-2 1.000 1.011 1.5 -
CheckBox selected light +0,-2 1.000 1.011 1.5 -
Spinner normal light +11,-9 0.978 1.055 1.1 -
GlassIcon normal dark +0,+1 0.999 1.000 1.1 92.1 -> 91.5
GlassText normal dark +0,+1 0.999 1.000 1.1 92.1 -> 91.5
Spinner normal dark +12,-9 0.977 1.055 1.0 -
GlassPanelGrey normal dark +0,+1 1.000 1.000 1.0 26.4 -> 26.9
TextField disabled light +0,+1 0.999 0.996 0.7 13.9 -> 38.7
FlatButton normal light +0,+0 0.993 1.011 0.7 91.9 -> 51.8
Slider disabled dark +0,-1 1.000 1.015 0.5 -
FlatButton pressed light +1,+0 0.986 1.011 0.5 95.4 -> 65.6
Slider normal light +0,+1 1.000 0.964 0.5 -
GlassPanelPhoto normal light +0,+0 1.000 1.005 0.5 25.6 -> 31.4
GlassPanelPhoto normal dark +0,+0 1.000 1.005 0.5 23.0 -> 27.0
ProgressBar normal dark +0,+0 1.000 0.900 0.5 -
ProgressBar normal light +0,+0 1.000 0.900 0.5 -
GlassIcon normal light +0,+0 1.000 1.005 0.5 91.6 -> 92.3
GlassText normal light +0,+0 1.000 1.005 0.5 91.6 -> 92.3
GlassPanelGrad normal light +0,+0 1.000 1.005 0.5 22.3 -> 25.9
GlassPanelGrad normal dark +1,+1 0.998 0.995 0.5 25.7 -> 22.5
GlassPanelGrey normal light +0,+0 1.000 1.005 0.5 22.4 -> 26.0
GlassPanelRed normal dark +1,+1 0.998 0.995 0.5 26.6 -> 22.8
GlassPanelRed normal light +0,+0 1.000 1.005 0.5 22.1 -> 26.1
TextField normal light +0,+0 1.000 1.000 0.0 13.4 -> 40.5
Slider normal dark +0,+0 1.000 1.000 0.0 -
TextField normal dark +0,+0 1.000 1.000 0.0 6.4 -> 15.1
TextField disabled dark +0,+0 1.000 1.000 0.0 6.4 -> 15.9
Dialog normal dark +0,+0 1.000 1.000 0.0 -
Dialog normal light +0,+0 1.000 1.000 0.0 -

Side-by-side comparisons (worst first)

  • Tabs_normal_dark -- 83.45% fidelity (SSIM 0.8842) (no change)

    native Tabs_normal_dark cn1 Tabs_normal_dark
    Left: native widget. Right: Codename One render.

  • Tabs_normal_light -- 86.44% fidelity (SSIM 0.8961) (no change)

    native Tabs_normal_light cn1 Tabs_normal_light
    Left: native widget. Right: Codename One render.

  • Toolbar_normal_light -- 87.64% fidelity (SSIM 0.9511) (no change)

    native Toolbar_normal_light cn1 Toolbar_normal_light
    Left: native widget. Right: Codename One render.

  • Toolbar_normal_dark -- 87.70% fidelity (SSIM 0.9495) (no change)

    native Toolbar_normal_dark cn1 Toolbar_normal_dark
    Left: native widget. Right: Codename One render.

  • Button_pressed_dark -- 89.93% fidelity (SSIM 0.9576) (no change)

    native Button_pressed_dark cn1 Button_pressed_dark
    Left: native widget. Right: Codename One render.

  • TextField_normal_light -- 90.03% fidelity (SSIM 0.9576) (-0.37 vs baseline)

    native TextField_normal_light cn1 TextField_normal_light
    Left: native widget. Right: Codename One render.

  • Spinner_normal_dark -- 90.78% fidelity (SSIM 0.8814) (-0.69 vs baseline)

    native Spinner_normal_dark cn1 Spinner_normal_dark
    Left: native widget. Right: Codename One render.

  • TextField_disabled_light -- 91.13% fidelity (SSIM 0.9619) (-0.22 vs baseline)

    native TextField_disabled_light cn1 TextField_disabled_light
    Left: native widget. Right: Codename One render.

  • Spinner_normal_light -- 91.58% fidelity (SSIM 0.9099) (-0.21 vs baseline)

    native Spinner_normal_light cn1 Spinner_normal_light
    Left: native widget. Right: Codename One render.

  • RaisedButton_disabled_light -- 91.76% fidelity (SSIM 0.9613) (+0.15 vs baseline)

    native RaisedButton_disabled_light cn1 RaisedButton_disabled_light
    Left: native widget. Right: Codename One render.

  • Button_normal_dark -- 91.84% fidelity (SSIM 0.9583) (no change)

    native Button_normal_dark cn1 Button_normal_dark
    Left: native widget. Right: Codename One render.

  • Slider_disabled_dark -- 92.13% fidelity (SSIM 0.9434) (-0.31 vs baseline)

    native Slider_disabled_dark cn1 Slider_disabled_dark
    Left: native widget. Right: Codename One render.

  • Switch_selected_light -- 92.13% fidelity (SSIM 0.9806) (no change)

    native Switch_selected_light cn1 Switch_selected_light
    Left: native widget. Right: Codename One render.

  • CheckBox_normal_light -- 92.16% fidelity (SSIM 0.9938) (no change)

    native CheckBox_normal_light cn1 CheckBox_normal_light
    Left: native widget. Right: Codename One render.

  • RadioButton_normal_light -- 92.16% fidelity (SSIM 0.9938) (no change)

    native RadioButton_normal_light cn1 RadioButton_normal_light
    Left: native widget. Right: Codename One render.

  • FlatButton_normal_dark -- 92.21% fidelity (SSIM 0.9833) (+4.25 vs baseline)

    native FlatButton_normal_dark cn1 FlatButton_normal_dark
    Left: native widget. Right: Codename One render.

  • Button_normal_light -- 92.37% fidelity (SSIM 0.9609) (no change)

    native Button_normal_light cn1 Button_normal_light
    Left: native widget. Right: Codename One render.

  • Slider_normal_dark -- 92.52% fidelity (SSIM 0.9441) (-0.22 vs baseline)

    native Slider_normal_dark cn1 Slider_normal_dark
    Left: native widget. Right: Codename One render.

  • RaisedButton_disabled_dark -- 92.65% fidelity (SSIM 0.9653) (+1.25 vs baseline)

    native RaisedButton_disabled_dark cn1 RaisedButton_disabled_dark
    Left: native widget. Right: Codename One render.

  • CheckBox_disabled_light -- 92.71% fidelity (SSIM 0.9953) (no change)

    native CheckBox_disabled_light cn1 CheckBox_disabled_light
    Left: native widget. Right: Codename One render.

  • RadioButton_disabled_light -- 92.71% fidelity (SSIM 0.9953) (no change)

    native RadioButton_disabled_light cn1 RadioButton_disabled_light
    Left: native widget. Right: Codename One render.

  • Button_pressed_light -- 92.88% fidelity (SSIM 0.9617) (no change)

    native Button_pressed_light cn1 Button_pressed_light
    Left: native widget. Right: Codename One render.

  • FlatButton_pressed_dark -- 92.90% fidelity (SSIM 0.9849) (+2.31 vs baseline)

    native FlatButton_pressed_dark cn1 FlatButton_pressed_dark
    Left: native widget. Right: Codename One render.

  • TabsGeom_normal_dark -- 93.01% fidelity (SSIM 0.8920) (no change)

    native TabsGeom_normal_dark cn1 TabsGeom_normal_dark
    Left: native widget. Right: Codename One render.

  • TabsGeom_normal_light -- 93.02% fidelity (SSIM 0.8861) (no change)

    native TabsGeom_normal_light cn1 TabsGeom_normal_light
    Left: native widget. Right: Codename One render.

  • FlatButton_pressed_light -- 93.20% fidelity (SSIM 0.9819) (+4.33 vs baseline)

    native FlatButton_pressed_light cn1 FlatButton_pressed_light
    Left: native widget. Right: Codename One render.

  • Button_disabled_dark -- 93.52% fidelity (SSIM 0.9618) (no change)

    native Button_disabled_dark cn1 Button_disabled_dark
    Left: native widget. Right: Codename One render.

  • Slider_disabled_light -- 93.96% fidelity (SSIM 0.9625) (-0.05 vs baseline)

    native Slider_disabled_light cn1 Slider_disabled_light
    Left: native widget. Right: Codename One render.

  • FlatButton_normal_light -- 94.18% fidelity (SSIM 0.9825) (+1.32 vs baseline)

    native FlatButton_normal_light cn1 FlatButton_normal_light
    Left: native widget. Right: Codename One render.

  • Button_disabled_light -- 94.35% fidelity (SSIM 0.9636) (no change)

    native Button_disabled_light cn1 Button_disabled_light
    Left: native widget. Right: Codename One render.

  • RaisedButton_pressed_dark -- 94.56% fidelity (SSIM 0.9653) (+1.46 vs baseline)

    native RaisedButton_pressed_dark cn1 RaisedButton_pressed_dark
    Left: native widget. Right: Codename One render.

  • RaisedButton_normal_dark -- 94.57% fidelity (SSIM 0.9659) (+1.69 vs baseline)

    native RaisedButton_normal_dark cn1 RaisedButton_normal_dark
    Left: native widget. Right: Codename One render.

  • RaisedButton_pressed_light -- 94.80% fidelity (SSIM 0.9665) (+2.04 vs baseline)

    native RaisedButton_pressed_light cn1 RaisedButton_pressed_light
    Left: native widget. Right: Codename One render.

  • RadioButton_selected_light -- 94.84% fidelity (SSIM 0.9916) (no change)

    native RadioButton_selected_light cn1 RadioButton_selected_light
    Left: native widget. Right: Codename One render.

  • RaisedButton_normal_light -- 95.01% fidelity (SSIM 0.9673) (+2.40 vs baseline)

    native RaisedButton_normal_light cn1 RaisedButton_normal_light
    Left: native widget. Right: Codename One render.

  • Slider_normal_light -- 95.09% fidelity (SSIM 0.9588) (-0.04 vs baseline)

    native Slider_normal_light cn1 Slider_normal_light
    Left: native widget. Right: Codename One render.

  • Switch_normal_light -- 95.51% fidelity (SSIM 0.9863) (no change)

    native Switch_normal_light cn1 Switch_normal_light
    Left: native widget. Right: Codename One render.

  • CheckBox_disabled_dark -- 95.76% fidelity (SSIM 0.9928) (no change)

    native CheckBox_disabled_dark cn1 CheckBox_disabled_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_disabled_dark -- 95.76% fidelity (SSIM 0.9928) (no change)

    native RadioButton_disabled_dark cn1 RadioButton_disabled_dark
    Left: native widget. Right: Codename One render.

  • CheckBox_selected_light -- 95.80% fidelity (SSIM 0.9938) (no change)

    native CheckBox_selected_light cn1 CheckBox_selected_light
    Left: native widget. Right: Codename One render.

  • Switch_selected_dark -- 95.90% fidelity (SSIM 0.9850) (no change)

    native Switch_selected_dark cn1 Switch_selected_dark
    Left: native widget. Right: Codename One render.

  • Switch_disabled_light -- 96.35% fidelity (SSIM 0.9896) (+0.04 vs baseline)

    native Switch_disabled_light cn1 Switch_disabled_light
    Left: native widget. Right: Codename One render.

  • CheckBox_normal_dark -- 96.52% fidelity (SSIM 0.9927) (no change)

    native CheckBox_normal_dark cn1 CheckBox_normal_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_normal_dark -- 96.52% fidelity (SSIM 0.9927) (no change)

    native RadioButton_normal_dark cn1 RadioButton_normal_dark
    Left: native widget. Right: Codename One render.

  • GlassPanelPhoto_normal_light -- 96.72% fidelity (SSIM 0.9804) (+0.64 vs baseline)

    native GlassPanelPhoto_normal_light cn1 GlassPanelPhoto_normal_light
    Left: native widget. Right: Codename One render.

  • GlassPanelPhoto_normal_dark -- 96.76% fidelity (SSIM 0.9832) (+0.59 vs baseline)

    native GlassPanelPhoto_normal_dark cn1 GlassPanelPhoto_normal_dark
    Left: native widget. Right: Codename One render.

  • TabOne_normal_dark -- 96.77% fidelity (SSIM 0.9526) (+0.73 vs baseline)

    native TabOne_normal_dark cn1 TabOne_normal_dark
    Left: native widget. Right: Codename One render.

  • Switch_normal_dark -- 96.80% fidelity (SSIM 0.9855) (no change)

    native Switch_normal_dark cn1 Switch_normal_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_selected_dark -- 96.81% fidelity (SSIM 0.9908) (no change)

    native RadioButton_selected_dark cn1 RadioButton_selected_dark
    Left: native widget. Right: Codename One render.

  • TextField_normal_dark -- 96.88% fidelity (SSIM 0.9492) (-0.20 vs baseline)

    native TextField_normal_dark cn1 TextField_normal_dark
    Left: native widget. Right: Codename One render.

  • TextField_disabled_dark -- 97.19% fidelity (SSIM 0.9526) (-0.15 vs baseline)

    native TextField_disabled_dark cn1 TextField_disabled_dark
    Left: native widget. Right: Codename One render.

  • ProgressBar_normal_dark -- 97.47% fidelity (SSIM 0.9973) (+3.03 vs baseline)

    native ProgressBar_normal_dark cn1 ProgressBar_normal_dark
    Left: native widget. Right: Codename One render.

  • TabOne_normal_light -- 97.51% fidelity (SSIM 0.9608) (+1.89 vs baseline)

    native TabOne_normal_light cn1 TabOne_normal_light
    Left: native widget. Right: Codename One render.

  • ProgressBar_normal_light -- 97.60% fidelity (SSIM 0.9989) (+2.19 vs baseline)

    native ProgressBar_normal_light cn1 ProgressBar_normal_light
    Left: native widget. Right: Codename One render.

  • CheckBox_selected_dark -- 97.79% fidelity (SSIM 0.9932) (no change)

    native CheckBox_selected_dark cn1 CheckBox_selected_dark
    Left: native widget. Right: Codename One render.

  • Dialog_normal_dark -- 97.86% fidelity (SSIM 0.9614) (+0.89 vs baseline)

    native Dialog_normal_dark cn1 Dialog_normal_dark
    Left: native widget. Right: Codename One render.

  • Dialog_normal_light -- 97.95% fidelity (SSIM 0.9634) (+0.86 vs baseline)

    native Dialog_normal_light cn1 Dialog_normal_light
    Left: native widget. Right: Codename One render.

  • Switch_disabled_dark -- 98.01% fidelity (SSIM 0.9869) (+2.48 vs baseline)

    native Switch_disabled_dark cn1 Switch_disabled_dark
    Left: native widget. Right: Codename One render.

  • GlassIcon_normal_dark -- 98.59% fidelity (SSIM 0.9841) (no change)

    native GlassIcon_normal_dark cn1 GlassIcon_normal_dark
    Left: native widget. Right: Codename One render.

  • GlassText_normal_dark -- 98.59% fidelity (SSIM 0.9837) (no change)

    native GlassText_normal_dark cn1 GlassText_normal_dark
    Left: native widget. Right: Codename One render.

  • GlassIcon_normal_light -- 98.67% fidelity (SSIM 0.9860) (no change)

    native GlassIcon_normal_light cn1 GlassIcon_normal_light
    Left: native widget. Right: Codename One render.

  • GlassText_normal_light -- 98.69% fidelity (SSIM 0.9862) (no change)

    native GlassText_normal_light cn1 GlassText_normal_light
    Left: native widget. Right: Codename One render.

  • GlassPanelGrad_normal_light -- 98.91% fidelity (SSIM 0.9935) (+0.67 vs baseline)

    native GlassPanelGrad_normal_light cn1 GlassPanelGrad_normal_light
    Left: native widget. Right: Codename One render.

  • GlassPanelGrad_normal_dark -- 98.98% fidelity (SSIM 0.9928) (+0.55 vs baseline)

    native GlassPanelGrad_normal_dark cn1 GlassPanelGrad_normal_dark
    Left: native widget. Right: Codename One render.

  • GlassPanelGrey_normal_dark -- 98.99% fidelity (SSIM 0.9917) (+0.57 vs baseline)

    native GlassPanelGrey_normal_dark cn1 GlassPanelGrey_normal_dark
    Left: native widget. Right: Codename One render.

  • GlassPanelGrey_normal_light -- 99.05% fidelity (SSIM 0.9936) (+0.67 vs baseline)

    native GlassPanelGrey_normal_light cn1 GlassPanelGrey_normal_light
    Left: native widget. Right: Codename One render.

  • GlassPanelRed_normal_dark -- 99.09% fidelity (SSIM 0.9926) (+0.52 vs baseline)

    native GlassPanelRed_normal_dark cn1 GlassPanelRed_normal_dark
    Left: native widget. Right: Codename One render.

  • GlassPanelRed_normal_light -- 99.10% fidelity (SSIM 0.9939) (+0.67 vs baseline)

    native GlassPanelRed_normal_light cn1 GlassPanelRed_normal_light
    Left: native widget. Right: Codename One render.

@shai-almog

shai-almog commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

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

Benchmark Results

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

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 66ms / native 3ms = 22.0x speedup
SIMD float-mul (64K x300) java 74ms / native 3ms = 24.6x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 170.000 ms
Base64 CN1 decode 129.000 ms
Image encode benchmark iterations 100
Image createMask (SIMD off) 7.000 ms
Image createMask (SIMD on) 9.000 ms
Image createMask ratio (SIMD on/off) 1.286x (28.6% slower)
Image applyMask (SIMD off) 51.000 ms
Image applyMask (SIMD on) 43.000 ms
Image applyMask ratio (SIMD on/off) 0.843x (15.7% faster)
Image modifyAlpha (SIMD off) 32.000 ms
Image modifyAlpha (SIMD on) 29.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.906x (9.4% faster)
Image modifyAlpha removeColor (SIMD off) 38.000 ms
Image modifyAlpha removeColor (SIMD on) 29.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.763x (23.7% faster)

@shai-almog

shai-almog commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

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

@shai-almog

shai-almog commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

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

Benchmark Results

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

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 55ms / native 3ms = 18.3x speedup
SIMD float-mul (64K x300) java 60ms / native 2ms = 30.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 191.000 ms
Base64 CN1 decode 119.000 ms
Base64 native encode 661.000 ms
Base64 encode ratio (CN1/native) 0.289x (71.1% faster)
Base64 native decode 253.000 ms
Base64 decode ratio (CN1/native) 0.470x (53.0% faster)
Base64 SIMD encode 58.000 ms
Base64 encode ratio (SIMD/CN1) 0.304x (69.6% faster)
Base64 SIMD decode 55.000 ms
Base64 decode ratio (SIMD/CN1) 0.462x (53.8% faster)
Base64 encode ratio (SIMD/native) 0.088x (91.2% faster)
Base64 decode ratio (SIMD/native) 0.217x (78.3% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 7.000 ms
Image createMask (SIMD on) 4.000 ms
Image createMask ratio (SIMD on/off) 0.571x (42.9% faster)
Image applyMask (SIMD off) 48.000 ms
Image applyMask (SIMD on) 43.000 ms
Image applyMask ratio (SIMD on/off) 0.896x (10.4% faster)
Image modifyAlpha (SIMD off) 39.000 ms
Image modifyAlpha (SIMD on) 44.000 ms
Image modifyAlpha ratio (SIMD on/off) 1.128x (12.8% slower)
Image modifyAlpha removeColor (SIMD off) 39.000 ms
Image modifyAlpha removeColor (SIMD on) 34.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.872x (12.8% faster)

@shai-almog

shai-almog commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

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

Benchmark Results

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

Build and Run Timing

Metric Duration
Simulator Boot 58000 ms
Simulator Boot (Run) 2000 ms
App Install 41000 ms
App Launch 7000 ms
Test Execution 467000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 68ms / native 4ms = 17.0x speedup
SIMD float-mul (64K x300) java 105ms / native 4ms = 26.2x 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 313.000 ms
Base64 CN1 decode 139.000 ms
Base64 native encode 535.000 ms
Base64 encode ratio (CN1/native) 0.585x (41.5% faster)
Base64 native decode 672.000 ms
Base64 decode ratio (CN1/native) 0.207x (79.3% faster)
Base64 SIMD encode 57.000 ms
Base64 encode ratio (SIMD/CN1) 0.182x (81.8% faster)
Base64 SIMD decode 58.000 ms
Base64 decode ratio (SIMD/CN1) 0.417x (58.3% faster)
Base64 encode ratio (SIMD/native) 0.107x (89.3% faster)
Base64 decode ratio (SIMD/native) 0.086x (91.4% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 12.000 ms
Image createMask (SIMD on) 2.000 ms
Image createMask ratio (SIMD on/off) 0.167x (83.3% faster)
Image applyMask (SIMD off) 40.000 ms
Image applyMask (SIMD on) 60.000 ms
Image applyMask ratio (SIMD on/off) 1.500x (50.0% slower)
Image modifyAlpha (SIMD off) 48.000 ms
Image modifyAlpha (SIMD on) 40.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.833x (16.7% faster)
Image modifyAlpha removeColor (SIMD off) 148.000 ms
Image modifyAlpha removeColor (SIMD on) 187.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 1.264x (26.4% slower)

@shai-almog

shai-almog commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

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

…enshots

build-ios-metal-27 reported green on its first run and produced NOT ONE
screenshot. It failed the native warning census and exited before the suite
started; the tolerated screenshot step then turned that into a successful job.
A leg that produces nothing and says nothing is worse than a red one, and only
looking in the artifact showed it: zero PNGs.

The cause is the same shape as everything else in this branch -- a per-generation
thing wearing a per-platform identity. The census is a per-TOOLCHAIN ratchet, and
a new warning kind fails it by design. Xcode 27's clang does not emit the same
set as Xcode 26's, so inheriting CN1_WARNING_LEG=ios-sim-debug compared a 27
build against a 26 baseline and could never have passed.

The leg is declared in LEG_PORT_DIRS rather than accepted as free text -- the
tool refuses an unregistered leg, which is how this stayed honest -- and its
baseline is seeded from THIS job's own build log, 120 entries against the 26
leg's 128.

Verified both directions on that same log: against the new baseline the census
passes with "621 gating diagnostic(s), all baselined"; against the iOS 26
baseline it still fails, which is the symptom that stopped the job.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@shai-almog
shai-almog merged commit 5ba8d47 into master Sep 22, 2026
67 of 69 checks passed
@shai-almog
shai-almog deleted the ios27-ci-gate branch September 22, 2026 04:23
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