Skip to content

Add shared Process API for desktop and backend - #6010

Merged
shai-almog merged 12 commits into
masterfrom
process-api-desktop
Oct 14, 2026
Merged

shai-almog merged 12 commits into
masterfrom
process-api-desktop

Conversation

@shai-almog

Copy link
Copy Markdown
Collaborator

Adds com.codename1.io.ProcessBuilder and Process for Windows, macOS, and Linux desktop applications and backend applications. The JavaSE-style API works without initializing Display or a server, with host-JDK and shared ParparVM adapters. Mobile/browser ports report unsupported and fail explicitly.

The API supports literal argument lists, working directories, environment changes, separate or merged stdout/stderr, binary stdin, exit status, interruptible timed waits, termination, and explicit cleanup. Native pipes use nonblocking/overlapped I/O, children are independently reaped, and backend virtual threads park between polls. The one-host regression exposed a scheduler bug: capture the nap-table entry's key before removing it, because the native map clears removed entries.

Documents platform behavior, resource ownership, and intentional JavaSE differences: native OS path strings, lazy environment snapshots, AutoCloseable cleanup, and no file redirection, inheritIO, pipelines, or ProcessHandle in this subset.

Fixes #5992.

Validation

  • Java 8 core reactor verify with ProcessBuilderTest,ButtonGroupTest: 11 tests passed, SpotBugs passed, zero Checkstyle findings.
  • JavaSE, macOS, Windows, Linux, and backend Maven artifacts packaged successfully. Verified native source packaging excludes the host-JDK adapter.
  • Real-child Java conformance passed on the JVM, the packaged JVM backend artifact, and translated macOS/Linux runtimes: arguments, Unicode, environment, cwd, binary duplex I/O, merged stderr, errors, timed waits, interrupts, termination, and repeated launches.
  • Optimized macOS/Linux one-host virtual-thread regression passed for both pending pipe reads and process waits, including cleanup.
  • OS-layer conformance passed on macOS/Linux and Windows under local Wine, including Unicode/space-containing executable paths, descriptor/handle counts, child reaping, and closed-stdin behavior. Windows code and translated bindings also compiled with MinGW; Windows execution coverage uses Wine.
  • Native signature verification passed for iOS, macOS, Windows, Linux, and backend. iOS simulator bindings compiled with no fork/exec/spawn imports.

All native execution was local. No native CI jobs, labels, or workflow changes were added.

@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 12, 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-10-12T18:35:29.883102Z 2fac0a4 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.

@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: d396e5faba

ℹ️ 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 CodenameOne/src/com/codename1/io/Process.java
@shai-almog

shai-almog commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 185 screenshots: 185 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 33ms / native 2ms = 16.5x speedup
SIMD float-mul (64K x300) java 33ms / native 3ms = 11.0x 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 36.000 ms
Base64 CN1 decode 45.000 ms
Base64 SIMD encode 56.000 ms
Base64 encode ratio (SIMD/CN1) 1.556x (55.6% slower)
Base64 SIMD decode 47.000 ms
Base64 decode ratio (SIMD/CN1) 1.044x (4.4% slower)
Image encode benchmark iterations 100
Image createMask (SIMD off) 4.000 ms
Image createMask (SIMD on) 1.000 ms
Image createMask ratio (SIMD on/off) 0.250x (75.0% faster)
Image applyMask (SIMD off) 12.000 ms
Image applyMask (SIMD on) 16.000 ms
Image applyMask ratio (SIMD on/off) 1.333x (33.3% slower)
Image modifyAlpha (SIMD off) 16.000 ms
Image modifyAlpha (SIMD on) 9.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.563x (43.8% faster)
Image modifyAlpha removeColor (SIMD off) 22.000 ms
Image modifyAlpha removeColor (SIMD on) 8.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.364x (63.6% faster)

@shai-almog

shai-almog commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 185 screenshots: 185 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 64ms / native 5ms = 12.8x speedup
SIMD float-mul (64K x300) java 63ms / native 5ms = 12.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 gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 73.000 ms
Base64 CN1 decode 90.000 ms
Base64 SIMD encode 104.000 ms
Base64 encode ratio (SIMD/CN1) 1.425x (42.5% slower)
Base64 SIMD decode 112.000 ms
Base64 decode ratio (SIMD/CN1) 1.244x (24.4% slower)
Image encode benchmark iterations 100
Image createMask (SIMD off) 7.000 ms
Image createMask (SIMD on) 5.000 ms
Image createMask ratio (SIMD on/off) 0.714x (28.6% faster)
Image applyMask (SIMD off) 18.000 ms
Image applyMask (SIMD on) 24.000 ms
Image applyMask ratio (SIMD on/off) 1.333x (33.3% slower)
Image modifyAlpha (SIMD off) 31.000 ms
Image modifyAlpha (SIMD on) 23.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.742x (25.8% faster)
Image modifyAlpha removeColor (SIMD off) 34.000 ms
Image modifyAlpha removeColor (SIMD on) 43.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 1.265x (26.5% slower)

ParparVM vs HotSpot (JDK 25): Windows x64

Runner CPU: AMD64 Family 25 Model 1 Stepping 1, AuthenticAMD (baseline windows-x64@amd64-family-25-model-1-authenticamd)

Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 15% (time) / 15% (RAM) away from its baseline in vm/selfhost/perf-baseline/ fails: above it is a regression, below it an improvement that has to be rebaselined (a row whose calibration runs were noisier carries a wider tolerance), and for RAM the change must also exceed 0.05x in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (WinHelloMain) 4 1.22x (base 1.22x, +0.3%) 0.76x (base 0.94x, -19.4%) ok
translator (self) 4 0.68x (base 0.60x, +12.1%) 0.56x (base 0.54x, +4.0%) ok
intArithmetic 4 1.17x (base 1.10x, +6.7%) 0.06x (base 0.06x, +5.0%) ok
longArithmetic 4 1.08x (base 1.08x, -0.1%) 0.05x (base 0.05x, +1.2%) ok
mathTranscendental 4 0.77x (base 0.79x, -2.2%) 0.06x (base 0.06x, +0.5%) ok
arraySequential 4 1.33x (base 1.36x, -2.1%) 0.39x (base 0.39x, +0.0%) ok
arrayRandom 4 0.90x (base 1.06x, -15.2%) 0.23x (base 0.23x, +0.1%) ok
objectAllocation 4 1.57x (base 1.56x, +0.6%) 0.28x (base 0.39x, -26.7%) ok
valueEscape 4 0.10x (base 0.10x, +0.2%) 0.05x (base 0.04x, +2.5%) ok
hashMapChurn 4 1.80x (base 1.80x, +0.2%) 0.09x (base 0.09x, -0.5%) ok
stringBuilding 4 1.23x (base 1.22x, +1.4%) 0.27x (base 0.32x, -17.1%) ok
recursion 4 1.38x (base 1.49x, -7.7%) 0.06x (base 0.06x, -0.7%) ok
quicksort 4 1.09x (base 1.13x, -3.4%) 0.12x (base 0.12x, -0.5%) ok

Result: no regression

@github-actions

github-actions Bot commented Oct 12, 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)
    • ✅ android-compat: 0 findings (no issues)
    • ✅ android-res-compiler: 0 findings (no issues)
    • ✅ backend: 0 findings (no issues)
    • ✅ backend-test: 0 findings (no issues)
    • ✅ build-engine: 0 findings (no issues)
    • ✅ build-hint-catalog: 0 findings (no issues)
    • ✅ build-hint-tools: 0 findings (no issues)
    • ✅ codenameone-gradle-plugin: 0 findings (no issues)
    • ✅ codenameone-maven-plugin: 0 findings (no issues)
    • ✅ core-unittests: 0 findings (no issues)
    • ✅ ios: 0 findings (no issues)
    • ✅ javac: 0 findings (no issues)
    • ✅ project-model: 0 findings (no issues)
  • ✅ PMD: 0 findings (no issues) [Report archive]
  • ✅ Checkstyle: 0 findings (no issues) [Report archive]

Generated automatically by the PR CI workflow.

@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@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: 2f3785fbf7

ℹ️ 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 vm/ByteCodeTranslator/src/cn1_process_vm.h Outdated
@github-actions

Copy link
Copy Markdown
Contributor

Cloudflare Preview

@shai-almog

shai-almog commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 170 screenshots: 170 matched.

Native Android coverage

  • 📊 Line coverage: 16.01% (26002/162390 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 14.37% (122147/850229), branch 9.91% (8466/85441), complexity 7.81% (6525/83503), method 11.59% (4648/40094), class 19.78% (960/4853)
    • 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)
      • 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)
      • com.codename1.androidcompat.rt.com.codename1.androidcompat.rt.TextXmlPullParser – 0.00% (0/623 lines covered)
      • com.codename1.androidcompat.androidx.constraintlayout.core.widgets.com.codename1.androidcompat.androidx.constraintlayout.core.widgets.Flow – 0.00% (0/576 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 16.01% (26002/162390 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 14.37% (122147/850229), branch 9.91% (8466/85441), complexity 7.81% (6525/83503), method 11.59% (4648/40094), class 19.78% (960/4853)
    • 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)
      • 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)
      • com.codename1.androidcompat.rt.com.codename1.androidcompat.rt.TextXmlPullParser – 0.00% (0/623 lines covered)
      • com.codename1.androidcompat.androidx.constraintlayout.core.widgets.com.codename1.androidcompat.androidx.constraintlayout.core.widgets.Flow – 0.00% (0/576 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend scalar fallback (no native SIMD)
SIMD int-add (64K x300) java 109ms / native 77ms = 1.4x speedup
SIMD float-mul (64K x300) java 94ms / native 62ms = 1.5x 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 72.000 ms
Base64 CN1 decode 67.000 ms
Base64 native encode 379.000 ms
Base64 encode ratio (CN1/native) 0.190x (81.0% faster)
Base64 native decode 240.000 ms
Base64 decode ratio (CN1/native) 0.279x (72.1% faster)
Image encode benchmark status skipped (SIMD unsupported)

@shai-almog

shai-almog commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator Author

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

@shai-almog

shai-almog commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 185 screenshots: 185 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.

ParparVM vs HotSpot (JDK 25): Linux x64

Runner CPU: INTEL(R) XEON(R) PLATINUM 8573C (baseline linux-x64@intel-xeon-platinum-8573c)

1 performance regression:

  • translator (self) on all 4 CPUs: time 0.61x against a 0.51x baseline (+21.7%, tolerance 20%)

Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 15% (time) / 15% (RAM) away from its baseline in vm/selfhost/perf-baseline/ fails: above it is a regression, below it an improvement that has to be rebaselined (a row whose calibration runs were noisier carries a wider tolerance), and for RAM the change must also exceed 0.05x in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (LinuxHelloMain) 4 0.92x (base 0.94x, -2.7%) 0.94x (base 0.88x, +7.2%) ok
translator (self) 4 0.61x (base 0.51x, +21.7%) 0.45x (base 0.52x, -12.3%) REGRESSION (time +21.7%)
intArithmetic 4 1.03x (base 1.03x, +0.1%) 0.06x (base 0.07x, -24.2%) ok
longArithmetic 4 0.97x (base 0.96x, +0.3%) 0.05x (base 0.05x, +1.3%) ok
mathTranscendental 4 1.04x (base 1.03x, +0.9%) 0.08x (base 0.06x, +32.0%) ok
arraySequential 4 2.38x (base 2.69x, -11.5%) 0.36x (base 0.35x, +0.3%) ok
arrayRandom 4 1.04x (base 1.05x, -0.8%) 0.23x (base 0.21x, +9.3%) ok
objectAllocation 4 1.23x (base 1.03x, +19.4%) 0.40x (base 0.51x, -22.3%) ok
valueEscape 4 0.13x (base 0.13x, -0.4%) 0.05x (base 0.04x, +2.7%) ok
hashMapChurn 4 0.81x (base 1.00x, -19.4%) 0.10x (base 0.10x, +6.2%) ok
stringBuilding 4 1.47x (base 1.53x, -4.4%) 0.22x (base 0.22x, +0.2%) ok
recursion 4 1.05x (base 1.05x, -0.7%) 0.06x (base 0.06x, -1.5%) ok
quicksort 4 1.06x (base 1.08x, -1.6%) 0.12x (base 0.11x, +10.7%) ok

A change that moves performance ON PURPOSE records the new baseline in vm/selfhost/perf-baseline/pr/6010.json, with the reason, from this job's perf-results.json. The rebaseline is then part of this pull request's diff:

python3 vm/selfhost/calibrate-perf-baseline.py --pr 6010 --reason "<why these benchmarks moved>" perf-results.json

Result: performance regression

@shai-almog

shai-almog commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 185 screenshots: 185 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.

ParparVM vs HotSpot (JDK 25): Linux arm64

Runner CPU: Neoverse-N2 (baseline linux-arm64@neoverse-n2)

Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 15% (time) / 15% (RAM) away from its baseline in vm/selfhost/perf-baseline/ fails: above it is a regression, below it an improvement that has to be rebaselined (a row whose calibration runs were noisier carries a wider tolerance), and for RAM the change must also exceed 0.05x in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (LinuxHelloMain) 4 1.05x (base 0.93x, +13.0%) 0.92x (base 0.87x, +6.2%) ok
translator (self) 4 0.75x (base 0.70x, +7.6%) 0.47x (base 0.45x, +5.2%) ok
intArithmetic 4 1.04x (base 1.04x, -0.0%) 0.03x (base 0.03x, -1.8%) ok
longArithmetic 4 0.79x (base 0.79x, -0.1%) 0.03x (base 0.03x, -1.2%) ok
mathTranscendental 4 1.10x (base 1.10x, -0.0%) 0.03x (base 0.03x, +1.3%) ok
arraySequential 4 0.38x (base 0.36x, +6.0%) 0.37x (base 0.37x, +0.3%) ok
arrayRandom 4 0.94x (base 0.94x, +0.3%) 0.20x (base 0.20x, -0.0%) ok
objectAllocation 4 1.86x (base 1.77x, +5.5%) 0.37x (base 0.38x, -1.9%) ok
valueEscape 4 0.51x (base 0.51x, -0.1%) 0.03x (base 0.03x, -1.0%) ok
hashMapChurn 4 0.80x (base 0.84x, -5.0%) 0.12x (base 0.12x, +0.1%) ok
stringBuilding 4 1.44x (base 1.36x, +6.0%) 0.26x (base 0.26x, +0.4%) ok
recursion 4 1.56x (base 1.43x, +8.5%) 0.03x (base 0.04x, -3.0%) ok
quicksort 4 1.00x (base 0.99x, +0.8%) 0.09x (base 0.09x, +0.6%) ok

Result: no regression

@shai-almog

shai-almog commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 185 screenshots: 185 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 53ms / native 3ms = 17.6x speedup
SIMD float-mul (64K x300) java 53ms / native 2ms = 26.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 60.000 ms
Base64 CN1 decode 73.000 ms
Base64 SIMD encode 74.000 ms
Base64 encode ratio (SIMD/CN1) 1.233x (23.3% slower)
Base64 SIMD decode 73.000 ms
Base64 decode ratio (SIMD/CN1) 1.000x (0.0% slower)
Image encode benchmark iterations 100
Image createMask (SIMD off) 6.000 ms
Image createMask (SIMD on) 1.000 ms
Image createMask ratio (SIMD on/off) 0.167x (83.3% faster)
Image applyMask (SIMD off) 19.000 ms
Image applyMask (SIMD on) 18.000 ms
Image applyMask ratio (SIMD on/off) 0.947x (5.3% faster)
Image modifyAlpha (SIMD off) 17.000 ms
Image modifyAlpha (SIMD on) 10.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.588x (41.2% faster)
Image modifyAlpha removeColor (SIMD off) 16.000 ms
Image modifyAlpha removeColor (SIMD on) 11.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.688x (31.3% faster)

ParparVM vs HotSpot (JDK 25): Windows arm64

Runner CPU: ARMv8 (64-bit) Family 8 Model D49 Revision 0, MICROSOFT CORPORATION (baseline windows-arm64@armv8-64-bit-family-8-model-d49-microsoft-corporation)

Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 15% (time) / 15% (RAM) away from its baseline in vm/selfhost/perf-baseline/ fails: above it is a regression, below it an improvement that has to be rebaselined (a row whose calibration runs were noisier carries a wider tolerance), and for RAM the change must also exceed 0.05x in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (WinHelloMain) 4 1.09x (base 1.11x, -1.2%) 1.13x (base 0.97x, +15.5%) ok
translator (self) 4 0.82x (base 0.84x, -2.0%) 0.51x (base 0.51x, +0.2%) ok
intArithmetic 4 1.04x (base 1.04x, -0.0%) 0.06x (base 0.06x, +1.6%) ok
longArithmetic 4 0.79x (base 0.80x, -0.3%) 0.06x (base 0.06x, +1.9%) ok
mathTranscendental 4 0.74x (base 0.72x, +3.0%) 0.06x (base 0.06x, +0.2%) ok
arraySequential 4 0.37x (base 0.46x, -18.0%) 0.39x (base 0.39x, -0.0%) ok
arrayRandom 4 0.93x (base 0.94x, -0.2%) 0.23x (base 0.23x, +0.0%) ok
objectAllocation 4 1.81x (base 2.81x, -35.4%) 0.34x (base 0.43x, -20.6%) ok
valueEscape 4 0.76x (base 0.76x, +0.0%) 0.05x (base 0.05x, +1.9%) ok
hashMapChurn 4 0.99x (base 0.98x, +0.0%) 0.12x (base 0.12x, +0.0%) ok
stringBuilding 4 1.53x (base 1.43x, +6.9%) 0.27x (base 0.27x, -0.5%) ok
recursion 4 1.46x (base 1.46x, -0.1%) 0.06x (base 0.07x, -0.4%) ok
quicksort 4 1.01x (base 1.00x, +1.1%) 0.12x (base 0.12x, -0.1%) ok

Result: no regression

@github-actions

github-actions Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

✅ ByteCodeTranslator Quality Report

Test & Coverage

  • ✅ Tests: 829 total, 0 failed, 57 skipped

Benchmark Results

  • Execution Time: 9677 ms

  • Hotspots (Top 20 sampled methods):

    • 7.63% com.codename1.tools.translator.BytecodeMethod.equals (109 samples)
    • 7.56% java.lang.System.identityHashCode (108 samples)
    • 6.93% java.util.ArrayList.indexOf (99 samples)
    • 6.72% java.lang.Object.hashCode (96 samples)
    • 4.34% com.codename1.tools.translator.IteratorEscape.ctorOnlyStoresParamsIntoThis (62 samples)
    • 3.85% com.codename1.tools.translator.IteratorEscape.mangle (55 samples)
    • 3.36% java.lang.StringBuilder.append (48 samples)
    • 2.24% com.codename1.tools.translator.ByteCodeClass.hasDeclaredMethod (32 samples)
    • 2.17% com.codename1.tools.translator.JavascriptReachability.enqueueResolved (31 samples)
    • 2.17% java.util.AbstractCollection.containsAll (31 samples)
    • 1.82% java.lang.String.equals (26 samples)
    • 1.82% com.codename1.tools.translator.BytecodeMethod.optimize (26 samples)
    • 1.75% com.codename1.tools.translator.Parser.cullMethods (25 samples)
    • 1.54% com.codename1.tools.translator.bytecodes.Invoke.findMethodUp (22 samples)
    • 1.40% java.util.HashMap.hash (20 samples)
    • 1.33% com.codename1.tools.translator.NativeSymbolIndex.<init> (19 samples)
    • 1.26% java.io.FileOutputStream.writeBytes (18 samples)
    • 1.19% com.codename1.tools.translator.BytecodeMethod.updateInlinableFieldDependencies (17 samples)
    • 0.98% com.codename1.tools.translator.bytecodes.Invoke.resolveDirectTarget (14 samples)
    • 0.98% com.codename1.tools.translator.DeadFieldElimination.run (14 samples)
  • ⚠️ Coverage report not generated.

Static Analysis

  • ✅ SpotBugs: no findings (report was not generated by the build).
  • ⚠️ PMD report not generated.
  • ⚠️ Checkstyle report not generated.

Generated automatically by the PR CI workflow.

@github-actions

github-actions Bot commented Oct 12, 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 Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator Author

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

@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@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: 26bd8cc408

ℹ️ 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 CodenameOne/src/com/codename1/io/ProcessBuilder.java
@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@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: d53d55000e

ℹ️ 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 vm/ByteCodeTranslator/src/cn1_process_vm.h
Comment thread vm/ByteCodeTranslator/src/cn1_process_vm.h
@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: 2fac0a411f

ℹ️ 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".

@shai-almog

shai-almog commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator Author

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

Benchmark Results

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

Build and Run Timing

Metric Duration
Simulator Boot 2000 ms
Simulator Boot (Run) 1000 ms
App Install 23000 ms
App Launch 12000 ms
Test Execution 502000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 153ms / native 5ms = 30.6x speedup
SIMD float-mul (64K x300) java 221ms / native 3ms = 73.6x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 148.000 ms
Base64 CN1 decode 136.000 ms
Base64 native encode 2343.000 ms
Base64 encode ratio (CN1/native) 0.063x (93.7% faster)
Base64 native decode 1274.000 ms
Base64 decode ratio (CN1/native) 0.107x (89.3% faster)
Base64 SIMD encode 105.000 ms
Base64 encode ratio (SIMD/CN1) 0.709x (29.1% faster)
Base64 SIMD decode 134.000 ms
Base64 decode ratio (SIMD/CN1) 0.985x (1.5% faster)
Base64 encode ratio (SIMD/native) 0.045x (95.5% faster)
Base64 decode ratio (SIMD/native) 0.105x (89.5% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 13.000 ms
Image createMask (SIMD on) 7.000 ms
Image createMask ratio (SIMD on/off) 0.538x (46.2% faster)
Image applyMask (SIMD off) 524.000 ms
Image applyMask (SIMD on) 123.000 ms
Image applyMask ratio (SIMD on/off) 0.235x (76.5% faster)
Image modifyAlpha (SIMD off) 114.000 ms
Image modifyAlpha (SIMD on) 95.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.833x (16.7% faster)
Image modifyAlpha removeColor (SIMD off) 305.000 ms
Image modifyAlpha removeColor (SIMD on) 88.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.289x (71.1% faster)

@shai-almog

shai-almog commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator Author

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

Benchmark Results

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

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 60ms / native 3ms = 20.0x speedup
SIMD float-mul (64K x300) java 65ms / native 3ms = 21.6x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 123.000 ms
Base64 CN1 decode 115.000 ms
Base64 native encode 1051.000 ms
Base64 encode ratio (CN1/native) 0.117x (88.3% faster)
Base64 native decode 381.000 ms
Base64 decode ratio (CN1/native) 0.302x (69.8% faster)
Base64 SIMD encode 76.000 ms
Base64 encode ratio (SIMD/CN1) 0.618x (38.2% faster)
Base64 SIMD decode 69.000 ms
Base64 decode ratio (SIMD/CN1) 0.600x (40.0% faster)
Base64 encode ratio (SIMD/native) 0.072x (92.8% faster)
Base64 decode ratio (SIMD/native) 0.181x (81.9% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 11.000 ms
Image createMask (SIMD on) 6.000 ms
Image createMask ratio (SIMD on/off) 0.545x (45.5% faster)
Image applyMask (SIMD off) 54.000 ms
Image applyMask (SIMD on) 75.000 ms
Image applyMask ratio (SIMD on/off) 1.389x (38.9% slower)
Image modifyAlpha (SIMD off) 60.000 ms
Image modifyAlpha (SIMD on) 45.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.750x (25.0% faster)
Image modifyAlpha removeColor (SIMD off) 42.000 ms
Image modifyAlpha removeColor (SIMD on) 66.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 1.571x (57.1% slower)

@shai-almog

shai-almog commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator Author

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

@shai-almog

shai-almog commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator Author

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

@shai-almog

shai-almog commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator Author

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

Benchmark Results

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

Build and Run Timing

Metric Duration
Simulator Boot 82000 ms
Simulator Boot (Run) 1000 ms
App Install 26000 ms
App Launch 3000 ms
Test Execution 661000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 108ms / native 3ms = 36.0x speedup
SIMD float-mul (64K x300) java 153ms / native 7ms = 21.8x 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 108.000 ms
Base64 CN1 decode 226.000 ms
Base64 native encode 2860.000 ms
Base64 encode ratio (CN1/native) 0.038x (96.2% faster)
Base64 native decode 1529.000 ms
Base64 decode ratio (CN1/native) 0.148x (85.2% faster)
Base64 SIMD encode 120.000 ms
Base64 encode ratio (SIMD/CN1) 1.111x (11.1% slower)
Base64 SIMD decode 87.000 ms
Base64 decode ratio (SIMD/CN1) 0.385x (61.5% faster)
Base64 encode ratio (SIMD/native) 0.042x (95.8% faster)
Base64 decode ratio (SIMD/native) 0.057x (94.3% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 14.000 ms
Image createMask (SIMD on) 9.000 ms
Image createMask ratio (SIMD on/off) 0.643x (35.7% faster)
Image applyMask (SIMD off) 645.000 ms
Image applyMask (SIMD on) 252.000 ms
Image applyMask ratio (SIMD on/off) 0.391x (60.9% faster)
Image modifyAlpha (SIMD off) 767.000 ms
Image modifyAlpha (SIMD on) 277.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.361x (63.9% faster)
Image modifyAlpha removeColor (SIMD off) 584.000 ms
Image modifyAlpha removeColor (SIMD on) 366.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.627x (37.3% faster)

@shai-almog

shai-almog commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator Author

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

Benchmark Results

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

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 61ms / native 3ms = 20.3x speedup
SIMD float-mul (64K x300) java 52ms / native 2ms = 26.0x 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 46.000 ms
Base64 CN1 decode 71.000 ms
Image encode benchmark iterations 100
Image createMask (SIMD off) 8.000 ms
Image createMask (SIMD on) 16.000 ms
Image createMask ratio (SIMD on/off) 2.000x (100.0% slower)
Image applyMask (SIMD off) 50.000 ms
Image applyMask (SIMD on) 80.000 ms
Image applyMask ratio (SIMD on/off) 1.600x (60.0% slower)
Image modifyAlpha (SIMD off) 72.000 ms
Image modifyAlpha (SIMD on) 69.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.958x (4.2% faster)
Image modifyAlpha removeColor (SIMD off) 77.000 ms
Image modifyAlpha removeColor (SIMD on) 68.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.883x (11.7% faster)

ParparVM vs HotSpot (JDK 25): macOS arm64

Runner CPU: Apple M1 (Virtual) (baseline macos-arm64)

Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 15% (time) / 15% (RAM) away from its baseline in vm/selfhost/perf-baseline/ fails: above it is a regression, below it an improvement that has to be rebaselined (a row whose calibration runs were noisier carries a wider tolerance), and for RAM the change must also exceed 0.05x in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (HelloCodenameOne) 3 0.88x (base 0.96x, -8.1%) 1.36x (base 1.34x, +1.6%) ok
translator (self) 3 0.70x (base 0.62x, +12.3%) 0.51x (base 0.57x, -9.6%) ok
intArithmetic 3 1.04x (base 1.03x, +0.4%) 0.12x (base 0.12x, +0.8%) ok
longArithmetic 3 1.05x (base 1.03x, +2.2%) 0.11x (base 0.07x, +60.8%) ok
mathTranscendental 3 1.01x (base 1.01x, +0.4%) 0.12x (base 0.12x, -0.5%) ok
arraySequential 3 0.44x (base 0.42x, +5.6%) 0.53x (base 0.53x, +0.2%) ok
arrayRandom 3 0.98x (base 0.99x, -0.7%) 0.33x (base 0.32x, +0.4%) ok
objectAllocation 3 1.00x (base 1.11x, -9.2%) 0.71x (base 0.81x, -13.0%) ok
valueEscape 3 0.51x (base 0.51x, +0.1%) 0.09x (base 0.09x, -0.5%) ok
hashMapChurn 3 0.95x (base 1.18x, -19.6%) 0.07x (base 0.07x, -3.0%) ok
stringBuilding 3 0.88x (base 0.84x, +4.2%) 0.46x (base 0.46x, -0.1%) ok
recursion 3 1.20x (base 1.24x, -2.9%) 0.12x (base 0.12x, +0.4%) ok
quicksort 3 1.01x (base 1.01x, +0.1%) 0.11x (base 0.11x, -1.2%) ok

Result: no regression

@shai-almog
shai-almog merged commit 53216e4 into master Oct 14, 2026
@shai-almog
shai-almog deleted the process-api-desktop branch October 14, 2026 00:50
shai-almog added a commit that referenced this pull request Oct 14, 2026
#6010 (merged) recorded the same translator memory improvement on that runner
from the same baseline (0.467x; ours 0.452x). Master's row stands.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
shai-almog added a commit that referenced this pull request Oct 14, 2026
…erlay after #6010

A driver's balance counts only fares that were paid for. An account in the
middle of a ride cannot be blocked, and a live connection opening while a
block or a role change commits reads the account again once registered.

#6010 rebaselined two of the rows this overlay moved, from the same values.
Windows arm64 translator RAM is left to its 0.513, which covers this change's
runs; Windows x64 hello RAM now chains from #6010's 0.828 to this change's
two runs, 1.154.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shai-almog added a commit that referenced this pull request Oct 16, 2026
…emplate (#5984)

* Wayline: a full-stack ride-hailing sample, its CI and an Initializr template

scripts/wayline is one Maven project in one language: a Codename One app
styled with CSS, and a Codename One Backend server. The role the server
gives an account decides what it opens on: a rider's map, a driver's
screen or an administrator's console, on a phone, on the desktop and
hosted by the server itself in a browser.

The server keeps its data in ORM entities behind repositories, with
transactional services and Flyway-style migrations, and runs on SQLite,
PostgreSQL, MySQL and MariaDB. It has sign-in through the built-in
authorization server, phone verification, driver applications, matching,
payments (simulated or Stripe), statistics and a live WebSocket channel.
The app reports usage to Codename One analytics after consent.

Tested like hellocodenameone: server tests on the JVM and as a native
binary, simulator end-to-end tests with screenshots on phone and desktop,
a headless-browser check of the hosted app, and a generated-project check
(.github/workflows/wayline.yml). The Initializr offers it as a template,
kept in step by scripts/sync-initializr-wayline.py, and the developer
guide gains a user's and an implementor's chapter.

Framework changes the sample needed or uncovered:

- cn1:backend-webapp and the Gradle backendWebApp task build the app for
  the browser and let the server host it.
- Shared-module contracts in an app reactor; ResponseStatusException;
  ConcurrencyFailureException for write conflicts and deadlocks, which
  MariaDB's snapshot isolation reports where other engines change no row.
- Build-time weaving no longer exposes private types in generated code.
- ParparVM: a receiver that escapes is no longer retired at frame exit.
- Vector maps: tile queue with stand-ins, label collision grid, halos,
  road hierarchy, kinetic pan, zoom about the cursor.
- JavaScript port: geolocation no longer blocks the EDT waiting for a
  position that never arrives; asynchronous XHR; coalesced accessibility
  refresh; released text layers.
- JavaSE test runner retires each test's threads and listeners, and a
  killed test process is reported as such.
- GridLayout preferred height counts implicit rows; GeneralPath grows
  geometrically; JavaSE mixed-font width uses advances.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: review fixes, and two builds this branch broke

Gradle: a project in Java and Kotlin failed in compileJava with two copies
of one generated mapper. Kotlin's pass compiles the Java it has not seen
yet only to resolve types, and that output was read as a dependency's, so a
@Mapped Java class was mapped by both passes. AnnotationProcessing now takes
the class directories that are the module's own and offers nothing out of
them.

wayline.yml: the simulator job runs in the pr-ci-container image and the
workflow could not pull it without packages: read.

Sample server:
- A refund is refused while a tip on the ride is still being charged, so a
  tip can no longer land on a ride that was refunded without it.
- A ride left completed with its payment pending is settled by a scheduled
  pass; settling is safe to repeat.
- The card limit is enforced where a card is saved, not only where a setup
  starts.
- Two registrations racing for one e-mail answer 409, not a server error.
- Changing an account's roles closes the live channel it has open.

Sample client: tokens are stored under a name made from the server's
address, and cleared when the address changes, so one server's tokens are
never sent to another.

Maps: a map removed while gliding is taken off the form that animates it,
and a failed tile is asked for again when its delay runs out, without
waiting for something else to repaint the map.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Reseed the Linux and Windows map baselines

The vector map engine draws differently on this branch, so the four map
screenshots are reseeded from this branch's CI captures.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Playground demo test: read a sample's bounds once the overlay has caught up

The JavaScript port on this branch brings the ARIA overlay up to date after
the screen goes quiet rather than on every change, so a bounds read 150ms
after a wheel event could still describe the list part way through the
scroll, and the click then selected a different sample.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Build an application with no Maven wrapper for iOS, and reseed two iOS 27 map baselines

build-ios-app.sh checked that MAVEN_HOME holds a Maven and then ran ./mvnw
regardless, so the Wayline iOS job failed with 'No such file or directory'.
It now uses the application's wrapper where there is one and that Maven
otherwise, as build-android-app.sh does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Initializr: offer the full-stack template from 7.0.277

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Lay a road name out by its letters' share of the drawn name, and reseed the macOS map baselines

A name that follows a bend is drawn a straight stretch at a time. The
stretches were laid out by each letter's width measured on its own, which
a font with kerning sets wider than the same letters drawn together, so
on iOS and Mac Catalyst a name read "Bro adway" where the road turned.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: second round of review fixes

- A charge that fails without the processor saying whether it took the
  money leaves the ride pending and is asked for again under the same key;
  only a refused card is a failed payment. The same for a tip, which stays
  on the ride and can be sent again with the same amount.
- A rider's two requests and two rides choosing one driver now take turns
  on the rider's and the driver's row, so neither ends in two rides.
- The limit on guesses at a phone code is applied by the statement that
  counts the guess.
- The driver role is not withdrawn from a driver who is on a ride.
- A reconnect timer left over from before the live channel was restarted
  no longer opens a second connection.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: give the generated template's theme compile a display, and two prose fixes

The template check built the generated app with no display, and the theme
compiler opens a window; it now takes a virtual display from xvfb-run on a
Linux machine without one, as server.sh does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Reseed the macOS map baselines for road names laid out by drawn width

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Say what laying a road name out by drawn width does and does not fix

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Initializr: let the generated-project build test take as long as a cold build does, and one prose fix

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: build the theme without a display, as the compiler now does

The CSS compiler no longer opens a window, so the virtual display the
template check, server.sh and the web job arranged for it goes, along with
the designer jar the simulator's pom passed along.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Rebaseline hello and translator RAM on Windows arm64 for the tightened retire proof

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: retryable refunds, retired addresses, admin races and five more review fixes

- A refund the server claimed and never recorded is asked for again; the
  processor's refund is keyed by the charge, so a repeat is one refund.
- A closed account's e-mail is retired (hash kept), since its rides stay
  filed under it and a re-registration would inherit them.
- Role changes and blocks hold both profiles and re-read the acting
  admin, so two admins cannot remove each other at once.
- A failed SMS send discards only its own code.
- Closing an account asks for the password again.
- /api/geo is rate limited.
- Recent destinations belong to the account that chose them.
- The location listener is removed when the last watcher leaves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: serialize account races, keep sign-in addresses private, and nine more review fixes

- Closing an account, removing a card, choosing the default card, keeping
  a first payment customer and sending a phone code hold the profile row,
  so each takes turns with a ride being asked for and with itself.
- A guess at a phone code is claimed against the hash that was read.
- A driver's status report holds the driver's row before reading it.
- A card tip counts toward the balance once its charge is recorded.
- A ride gives the rider's and the driver's usernames only to their
  owners and to an admin.
- The app ignores profile answers that arrive after the session changed.
- The staged web root is withheld only when the active profile, not any
  profile file, declares cn1.webapp.root.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline guide: say online minutes, as the prose gate asks

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ParparVM perf: rebaseline hello peak RAM on Linux arm64 and Windows x64 for this change

The tightened retire-early proof keeps more objects for the collector, so
hello's peak RAM rises on every platform, as it already had on Windows arm64.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: earnings are the driver's share, one cash-out at a time, and four more review fixes

The driving screen summed the fare, commission included, as earned. The
period totals counted a card tip whose charge never came back. Two cash-outs
at once could both be taken back. A date was accepted with a day its month
does not have. The map's retry timer ignored a tile that failed while a
longer wait was pending. The hosted-web job did not run for the JavaScript
port's Java sources.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* vm-tests: runtime-library tests on two JDKs, a wider limit; Wayline: one Stripe customer per account

The lock, file, stack-overflow, uncaught-exception and float-formatting tests
ran once per JDK although none depends on which javac compiled them; they now
run on the oldest and the newest. The job's limit goes from 120 to 150
minutes: passing runs were within a slow runner's variance of the old one.

Creating a Stripe customer now carries an idempotency key, so two first cards
started together do not leave a second customer behind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: a changed password ends the other sign-ins, and seven more review fixes

Changing a password removes the account's other grants, so a refresh token
on a lost device stops working; closing an account removes them all. Saving
or uploading to a driving application holds it against being handed in
meanwhile.

The map drops overzoomed pieces that left the view instead of drawing them
all, and bounds the labels it keeps. The JavaScript port's storage shim no
longer logs a prefix of what it stores.

The bytecode check takes only the sibling modules the application ships, not
test-scoped ones, and the stub goal deletes the stubs it no longer emits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Map: compare waiting pieces by serial, not by reference; rebaseline Windows x64 translator time

PMD forbids comparing references, and the piece waiting under a key is told
from one it replaced by a serial number instead.

The Windows x64 translator time is bimodal on its runner; its baseline is
taken from two runs and now sits between the groups.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Rebaseline Linux arm64 translator RAM

Two runs of the same code sit at 0.49 and 0.52 against 0.45, either side of
the 15% tolerance; the cause is the one already recorded for the hello rows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: five review fixes around privacy, payments and settings

A past ride no longer carries its driver's current position. Closing an
account deletes the rider's record at the payment processor, and neither a
card nor an account can be removed while a ride's charge is still being
asked about. A different account signing in on a device no longer sees or
saves the last account's home, work, contact and ride options, and a half of
the account's values that never arrived is fetched again rather than
overwritten. Two first saves of the settings take turns.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: unpaid fares stay out of payouts, no block mid-ride; perf overlay after #6010

A driver's balance counts only fares that were paid for. An account in the
middle of a ride cannot be blocked, and a live connection opening while a
block or a role change commits reads the account again once registered.

#6010 rebaselined two of the rows this overlay moved, from the same values.
Windows arm64 translator RAM is left to its 0.513, which covers this change's
runs; Windows x64 hello RAM now chains from #6010's 0.828 to this change's
two runs, 1.154.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: serialize password changes and approvals, refunds take tips back

- Accounts.changePassword holds the profile before checking the old
  password, so two changes made together cannot both pass it.
- Applications.approve holds the applicant's profile, as blocking does, so
  the rewrite of the sign-in row cannot undo a block that committed between.
- A card tip counts toward the balance only while its ride is paid: a
  refund returns it with the fare.
- The earnings screen's day/week/month totals count a fare only once paid,
  matching the balance; the trip still counts.
- LocationManager sets the request before bindListener(), which every port
  reads it from (priority on iOS/Android, accuracy in the browser).
- BackendWebApp.copy refuses a destination inside or around the staged app
  instead of copying it into itself or deleting its source.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: keep the previous SMS code good, stage/copy and watch-id fixes

- PhoneVerification keeps the code before a resend good until it would
  have expired: SMS order is not guaranteed and the first code can arrive
  last. At most two live codes; using either uses both up.
- BackendWebApp.stage refuses a bundle inside the output directory, which
  is emptied before the bundle is read.
- The Gradle backendPackage up-to-date check compares the whole staged web
  app (names, lengths, times), not only index.html.
- The browser geolocation shim answers -1 for "no watch" and clears a watch
  whose id is 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: accept vs block, code guess budget, payout and admin races; build freshness

- Accepting an offer holds the driver's profile and re-checks the account
  is enabled, so a block cannot land between the guard and the accept.
- The SMS code kept across a resend keeps its own remaining guesses.
- Saving payout details holds the profile: the first save has no row.
- Production admin bootstrap treats a concurrent instance's insert as done.
- backendWebApp is never up to date: its bundle is not a snapshot input.
- The bytecode compliance check counts checked sibling modules' classes
  when deciding whether its last result still holds.
- MapView wheel zoom keeps its sign; WheelEvent's doc stated the wrong
  wheel direction for a positive deltaY, which the ports negate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: reconcile pending refunds, and hold rows for first writes

- A refund Stripe answers pending (or requires_action) is recorded as
  REFUND_PENDING, not REFUNDED. Payments.settleRefunds asks the processor
  every minute until both the fare's and the tip's refunds succeed
  (REFUNDED) or either fails or is canceled (REFUND_FAILED, not retried).
  The tip's refund reference is kept in a new tip_refund_ref column.
  Receipts, the admin screens and the guides show both states; the
  simulated processor's 4000 0000 0000 7726 card refunds slowly.
- A customer created at the processor while the account was being
  closed is deleted again instead of being kept for a missing user.
- A driver's first state report and a driving application's submit hold
  the profile when there is no row of their own to hold yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: drop a CSS compiler cache committed by mistake

theme.css.checksums is the CSS CLI's incremental cache, left beside the
stylesheet by a compile run by hand; it does not belong in the sample and
made the Initializr template drift.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Perf overlay: the Intel Windows x64 runner's hello RAM and translator time

The first run of this branch on the Intel Family 6 Model 207 runner,
which the overlay had no rows for; the reason is recorded in the overlay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Perf overlay: bimodal Intel Windows hello RAM, arm64 stringBuilding time

A second run on the Intel Windows x64 runner measured hello RAM at 0.71
against the 1.11 the first had given: the row is now the median of all
ten rounds with the 0.35 memory tolerance Windows arm64 already uses.
Linux arm64 stringBuilding time follows the frame-retire change, as the
Intel Windows runner's does. Reasons are in the overlay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Open the test ComboBox popup on the EDT; bimodal AMD Windows hello RAM

ComboBoxPopupTestSupport clicked the combo from a thread of its own while
the @FormTest body pumped the EDT, so the popup was built and measured off
the dispatch thread. ComboBoxPopupWidthTest failed on that race in CI on
this branch and on desktop-compat-layer (80 against 64) and never alone.

The AMD Windows x64 runner's hello RAM is bimodal like the Intel one's:
0.81 against the 1.154 recorded from two higher runs. Baseline the middle
of the three run medians with the 0.35 tolerance the other runners carry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Perf overlay: macOS arm64 objectAllocation RAM

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Input validation: give every iOS step the budget of the XCUITest idle wait

The iOS tap step timed out 0.45s before XCUITest synthesized the tap: the
step is armed at READY, the driver was still launching, and its wait for
the app to idle then took 31.6s. The same wait already cost the browser
step its first focus tap, and keytype and browserkeytype have missed the
same way, so every iOS step gets the 90s the browser step had.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* JavaAPI: java.net.URLEncoder and URLDecoder with the JDK's semantics

Backend code is written against the JDK, and the compiled backend had no
URLEncoder/URLDecoder at all. Pure Java, so both runtimes answer the same
bytes; UrlCodecTest compares the JDK and ParparVM output directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ORM: persist private, package-private and protected entity fields

Every non-static, non-transient field is persistent now, whatever its
access (the JPA rule). The generated model is compiled against copies of
the declaring classes with those fields made public, and OrmEnhancer then
rewrites each GETFIELD/PUTFIELD in the generated classes into a call to a
static accessor woven into the declaring class -- mapped superclasses,
embeddables and dependency jars included. No reflection, so it works on
ParparVM. Java transient now opts a field out like @DbTransient; a
non-public final field without a mapping annotation is skipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ORM: backend defaults table and column names to snake_case

A table or column the entity does not name explicitly is now named the way
Spring Boot's CamelCaseToUnderscoresNamingStrategy names it on the backend
(RideEvent -> ride_event, fareCents -> fare_cents). The app keeps the field
name, because shipped SQLite files were created with it. Explicit
@Entity(table) and @Column(name) are used as written on both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Backend: inject @Repository interfaces as beans; Optional repository results

An injection point whose type is a @Repository interface that no bean provides
now receives the generated implementation, built once per interface from
Repositories.create over the injected transaction Session, as Spring Data makes
a repository a bean. It runs in the caller's @Transactional method and refuses
outside one, the same contract as the injected Session.

Repository methods may return Optional<T> for a single result (derived finds and
declared @Query selects), answering Optional.empty() when there is no row.

The snake-case naming test now ignores tables of entities other tests
registered in the process-wide registry, which made it order dependent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ParparVM: translate a record's implicit equals, hashCode and toString

javac writes each as an invokedynamic of java.lang.runtime.ObjectMethods,
which the translator refused, so any record without hand-written overrides
failed iOS (and every native) translation. The backend packager lowered them
beforehand; an application's records, such as DTOs shared with a server, had
nothing. The translator now replaces the call with a static helper doing
what ObjectMethods builds, with JDK float/double bit semantics.

RecordMethodsTest compares JDK and ParparVM output for a record with every
primitive kind, a String, an enum, a nested record, a list, null components,
NaN and -0.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Backend: records as JSON transfer objects

The backend codecs read a class's fields through public access or JavaBeans
accessors and built it with its no-arg constructor. A record has neither, so a
record DTO in a shared @RestClient contract went over the wire as {} and could
not be read at all. The codec now writes a record from its accessors and reads
it into one local per component, building it through the canonical
constructor; @JsonIgnore on a component passes its default.

The legacy cn1.restServer codec moves public fields only, so it now refuses a
record by name instead of transferring an empty object.

RecordDtoTest drives a record contract (enum, nested record, List of records,
List<String>, primitives, an ignored component) end to end: the client's
generated mappers and RestClient implementation, the server's generated
<Api>Server and controller, and a running backend.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Backend packager: a Java 17 dependency passes over JDK_8_HOME

A Java 8 backend module took JDK_8_HOME's javac for its native compile even
when a dependency -- a shared contract module at release 17, so its transfer
objects can be records -- was version 61 bytecode. JDK 8 cannot read that, so
the compiled backend failed with "class file has wrong version 61.0" while the
JVM build and tests passed. The legacy JDK 8 override now applies only when
every dependency class is Java 8 too; module descriptors and META-INF entries,
which Java 8 libraries commonly carry, do not count.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ORM repositories: Object[] rows from a declared JPQL @Query select

A declared JPQL select may now return Object[], List<Object[]> or
Optional<Object[]>, one array per row, as Spring Data returns a multi-column
projection: select a.x, count(a) ... group by a.x, or several sums at once.
Derived queries and native selects still refuse it -- a derived find
answers entities, and a native select answers one scalar column.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: repositories, private entity fields and a RideState enum

The backend's data access is now @Repository interfaces under
wayline.repository, injected into the services, with no Session or SQL
left in the sample: derived queries where the method name says it all,
JPQL @Query for the rest, and @Modifying @Query statements that answer
the number of rows they changed for every atomic claim (a ride move, an
offer, a tip or refund claim, a guess at a phone code). A ride move's
five shapes are five fixed statements, and the matcher's search is one
fixed query with the product and preference filters applied in Java.
Cross-entity cleanup is the AccountCleanup component over repositories.

Entities keep their fields private behind getters and setters and map
to snake_case columns; the migrations are renamed to match.

RideStates' string constants become the RideState enum in the shared
module, used by the backend, the client and the DTOs. Enum columns read
back from Object[] rows go through Rows.state, which never casts blind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: SMS and payment providers chosen by setting, no silent fallback

wayline.sms.provider picks Twilio, Vonage or MessageBird, each with its
own credentials; the console sender prints codes and is refused outside
a development profile. wayline.payments.provider picks stripe or
simulated. Unset, a development profile gets the console and simulated
cards, and any other profile the real provider. A provider whose
settings are missing logs a configuration error at start-up and on
every call, naming the missing settings, and fails each call with an
IOException, so phone verification answers 503 instead of a production
server quietly logging codes.

StripePayments is documented as an untested stub against live Stripe.
UrlText is gone; form bodies and paths use java.net.URLEncoder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: shared transfer objects are Java 17 records

The shared module compiles at Java 17, the app's level, and every *Dto
is now a record. The generated client mappers and the server's JSON codec
both build a record through its canonical constructor and read it through
its accessors, so the wire names are unchanged. Component docs moved to
@param tags on the record.

Call sites use the accessors and the canonical constructor. RideDto gains
a none() factory for the no-ride answer, and Drivers a describe(driver,
rides) overload for the admin statistics.

Also fixes RiderForm.request(), which never sent the pets preference.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: a driver going off line stays off line

Drivers.store() added the time since the last report before changing the
driver's row. Adding it is a @Modifying update, which flushes and then
clears the session, so the row it had just found was detached and the
off-line report was never written: a driver who had been on line moments
before stayed on line. The e2e DriverModeTest found it, failing on its
first step. The time is now counted first and added last, after the row
has been changed.

MatchingTest.aDriverWhoGoesOffLineIsOffLine fails without the fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline guide: include the sample's own sources, not copies

The developer guide quoted 23 classes from a second copy of the sample under
docs/demos, which had already drifted: UrlText, LoggingSmsSender, Session
repositories, RideStates and wl_ tables no longer exist in scripts/wayline.

- Delete the copies; the guide now includes 19 tagged regions of
  scripts/wayline itself. The two framework-only illustrations (a second
  database) move to standalone demo classes outside any wayline package.
- Rewrite the prose around the real code: injected @Repository interfaces,
  record DTOs, the RideState enum, snake_case tables, private entity fields,
  wayline.sms.provider (console/twilio/vonage/messagebird) and
  wayline.payments.provider (simulated/stripe) with configuration errors and
  no silent fallback.
- validate-guide-snippets.py accepts ../../scripts/wayline/ as an include
  root; the guide and website workflows trigger on scripts/wayline/**.
- sync-initializr-wayline.py strips the tag markers, so the Initializr
  template is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ORM: bulk statements leave the session alone, as JPA and Spring Data do

executeUpdate() on a JPQL or native query, and every @Modifying repository
method, cleared the session after the statement. An entity a service had read
before the statement was then detached, and a change made to it afterwards was
silently never written -- the Wayline driver going off line who stayed on line.

JPA's Query.executeUpdate does not clear the persistence context, and Spring
Data's @Modifying clears it only when asked. Now:

- executeUpdate (JPQL and native) flushes first and leaves the session as it
  is. Managed entities keep their pre-statement values; refresh() or clear()
  reads what the statement wrote. Flush writes only changed columns and a
  removed row fails with OptimisticLockException, so a stale managed entity
  cannot overwrite the bulk change or resurrect a deleted row.
- @Modifying gains clearAutomatically (default false), which the repository
  generator honours by clearing after the statement, and flushAutomatically
  (default false), accepted for source compatibility: the flush before a bulk
  statement always happens, as the AUTO flush mode does.

Wayline moves that re-read their entity afterwards (rides, applications,
documents, phone-code guesses) are marked clearAutomatically = true; the
hold/counter statements keep the default. Tests that re-read after a bulk
statement now clear first, and the generated-repository test covers both the
default (a change after the statement persists) and clearAutomatically.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Guide prose gates and Initializr template parity after the @Modifying change

Vale and LanguageTool flagged five uncontracted forms, an Oxford comma and
three British 'afterwards' in the ORM, backend-data and Wayline chapters, and
wayline-modules.zip still held the sample's sources from before
clearAutomatically was added to its repositories.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: card setups capped and swept, removed cards detached, refunds that overlap stay consistent

- Card setups: an account may have five open at once (429 past that,
  checked before the processor is asked and again with the account held),
  /api/payments/methods/setup is rate limited per user, and
  Payments.sweepSetups deletes finished setups and ones abandoned for two
  hours.
- Removing a card detaches it at the processor first, through the new
  PaymentProvider.detachCard (Stripe: POST /v1/payment_methods/{id}/detach;
  a card already detached or gone counts as detached).
- Refunds: a failed refund gives its claim back only while the payment is
  unrefunded, and a recorded refund writes the ride's status too, both on the
  ride's row first, so overlapping refunds leave the ride agreeing with its
  payment and a refunded fare never returns to the driver's balance.
- EarningsDto carries todayRides, counted with the day's earnings, for the
  driver screen's "Today, N trips".
- The app keeps a settings change marked unsent until the server takes it,
  retries it, and an account load sends it instead of overwriting it.
- Wayline guide: drop the second-database section (and its demo classes
  ArchiveDatabase and ArchivedRides).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: the admin's view of a driver shows what the driver earned

Statistics.user summed every completed ride's share and every tip, so a
pending, failed or refunded card ride and a tip whose charge had not come
back showed as earned while the balance left them out. It now takes the
figure from Earnings.earned, the sum the balance is made of, and the
separate query is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: a card the limit refuses is detached at the processor

The provider attaches the card when a setup finishes, before the server
counts the account's cards again. A refusal rolled the row back and left
the card attached with nothing to remove it through; it is now detached
after the rollback, and a failed detach is logged without changing the
409 the rider gets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* JavaAPI: URLEncoder and URLDecoder check the charset when it is named

A charset was only used when a character needed converting, so an unknown
name was accepted for plain text where the JDK throws
UnsupportedEncodingException. The name is now checked at entry, by a table
of the charsets every runtime converts, since the native getBytes writes
UTF-8 for a name it does not know instead of refusing it. US-ASCII and
ISO-8859-1 are converted in Java too, so they answer the JDK's bytes on
every runtime.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* JavaAPI: charset names are looked up in Java, and refused as the JDK refuses them

String.getBytes(String), new String(byte[], [off, len,] String),
InputStreamReader and OutputStreamWriter handed the charset name to the
runtime's native, which never refused one. For a name it did not know the C
native wrote UTF-8 and read UTF-8 on Apple targets and ISO-8859-1 elsewhere;
UTF-16 and ISO-8859-2 worked only where NSString exists (Linux and Windows
wrote UTF-8 and read Latin-1 for them); the JavaScript port's encoder ignored
the name and always wrote UTF-8, and its decoder read ISO-8859-1 and US-ASCII
as windows-1252. A null name meant UTF-8.

com.codename1.impl.charset.CharsetSupport now holds the one list of charset
names (canonical names plus the JDK's aliases for UTF-8, ISO-8859-1,
US-ASCII, UTF-16, UTF-16BE, UTF-16LE and ISO-8859-2). String, the reader and
writer, Charset.forName and URLEncoder/URLDecoder all look the name up there
first: null is a NullPointerException and any other unknown name, including
the empty one, an UnsupportedEncodingException, on every runtime. Only UTF-8
still reaches the conversion natives, plus the compact Latin-1 fast path for
ISO-8859-1 and US-ASCII; every other charset is converted in Java, so UTF-16
and ISO-8859-2 work identically on every target.

Comparing with the JDK found two UTF-8 bugs in both native implementations:
an unpaired surrogate was written as U+FFFD where the JDK writes '?', and an
encoded surrogate (ED A0..BF ..) was replaced a byte at a time where the JDK
replaces the sequence once. The JavaScript decoder also stripped a leading
U+FEFF. All fixed. OutputStreamWriter writes UTF-16's byte order mark once
per stream rather than once per write.

CharsetCodecTest runs CharsetCodecApp on the JDK, on the clean C target and
on the JavaScript target under Node, and requires identical output.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Charsets a feed or page declares fall back to UTF-8 instead of throwing

The previous commit made String, InputStreamReader and OutputStreamWriter
refuse a charset name the class library does not convert, as the JDK does.
For a name the APPLICATION passes that is right. For a name the DATA
declares it was a regression: a feed labelled Shift_JIS or KOI8-R used to
decode on iOS and the JavaScript port, approximately, and would now fail
there while the simulator and Android, whose JDKs know the name, kept
working -- a difference nobody could see before shipping.

com.codename1.io.DeclaredCharset is the one place that takes a declared
name: it accepts a bare name, a charset= parameter or a whole Content-Type
value (quotes, white space and other parameters dropped), reads or writes
in that charset when the platform has it, and otherwise uses UTF-8, the way
a browser treats a label it does not know, logging each unsupported name
once. A media type with no charset parameter declares nothing.

Call sites that take a charset from the data now go through it:
- RSSService: the Content-Type header and the XML declaration. The
  declaration was parsed by an indexOf whose -1 check could never fail, so
  a declaration with no encoding handed text from the version attribute to
  InputStreamReader, and single quotes were not recognised; a quoted header
  value was used with its quotes. Both are parsed properly now, and an XML
  declaration cut off by the end of the stream no longer loops forever.
- AsyncDocumentRequestHandlerImpl and WebBrowser: the request body of an
  HTML form post, whose encoding is the form's enctype.
- HTMLComponent.streamReady: only the charset a media type carries is
  looked up; an unsupported one still goes through HTMLCallback's
  ERROR_ENCODING before falling back, as before.
CSSParser already caught the refusal for @charset and @media and continued.
Every other core reader or writer names UTF-8 or a charset the application
passed in, and those keep throwing.

windows-1252 -- the label the web most often gets wrong -- is now converted
by CharsetSupport, under its JDK aliases, and CharsetCodecApp compares it
with the JDK on the C and JavaScript targets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* MapView animates in a desktop Window, not only in a Form

getComponentForm() is null inside a Window, so move() never registered the map
and wheel zoom, double-tap zoom and the glide after a fling stopped after one
frame. It now registers with getTopLevelContainer() and deregisters from the
top level it remembered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: an offer asks again whether the chosen driver still fits

Choosing a driver and offering the ride are two transactions. A driver who went
off line, drove out of reach, lost their approval or was blocked in between
still got the offer and held the rider for the whole timeout. The offer now
re-runs the matcher's checks once it holds the driver, and the search chooses
again (up to three times) when it refuses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: time on line across midnight is split between the two days

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: the pricing row exists from the start, so saves only update it

Two admins saving prices before anyone had both inserted id 1 and one failed.
V6 seeds the row (updated_at 0 means the settings' prices are still in force)
and a save is one blind UPDATE.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline tests: PaymentsTest's people get names of their own

PaymentsTest registered the same accounts as PricingAndStatsTest, RideFlowTest,
MatchingTest and ModerationTest. Whether that failed depended on which classes
the compiled run put in one context; adding a test class made
PricingAndStatsTest fail with 409 on a name PaymentsTest had already taken.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Website CI: stop wrangler as a process group, on a free port

The redirects step of run 38724184374 tested a server it did not start.
build.sh runs check-javadoc-urls.sh on its default port 8788 and stopped
it with `kill $!`, which kills npx and leaves wrangler's node, esbuild and
workerd children behind. The later redirects step also used 8788: its
readiness curl and all 140 redirect cases were answered by that leftover
within a second, before the new wrangler had written its first log line
(log named 11-14-54_317, redirects done at 11:14:54.136); the new proxy
workerd then died on "Address already in use; 127.0.0.1:8788", and when
the leftover went away test_search.mjs got ERR_CONNECTION_REFUSED. The
runner listed two orphaned workerd processes at the end of the job, and
green runs list orphaned node/esbuild from the same check. Reproduced
locally with wrangler 4.129.0: an orphaned server answers the curl and
the new one logs the identical bind failure. The file watcher is not
involved: writing into the served directory does not restart workerd.

scripts/website/pages-dev-server.sh now starts wrangler in its own
process group and stops the whole group, picks a free port when none is
given, refuses a port that already answers, and only reports ready while
its own process is alive. check-javadoc-urls.sh and the workflow's
redirects step use it; neither pins a port any more.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Initializr template parity after the review fixes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* XMLParser: the read-ahead buffer belongs to the parser, and eventParser empties it

XMLParser read through a STATIC 8KB buffer that only parse() reset. When an
eventParser run was ended early by its callback -- RSSService stops at its
item limit by throwing FinishParsing -- the unread rest of that document
stayed in the buffer, and the next eventParser call anywhere in the process
consumed it before its own input. The next feed came back with the previous
feed's leftover items, or with none.

RSSServiceCharsetTest caught it in CI: there AdditionalServicesCoverageTest's
limit-2 feed of three items runs immediately before it, and the next parse
returned the title "3". The local macOS run ordered the classes differently,
which is why it passed there; replaying CI's order reproduces both failures.

The buffer is now an instance field, allocated on first read, and both entry
points reset it. That also stops parsers on different threads from sharing
one buffer, and a parse started from inside another parser's callback from
wiping out the outer parse's read-ahead. XMLParserBufferTest covers both
cases and fails on the old parser.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: the minimal project layout, without platform modules

The javase, android and ios modules held nothing but what the archetype
generates (the desktop stub and the default NativeTheme.res), and Wayline has
no native interfaces. common now builds every platform itself through its
cn1-host-* profiles, as a project generated with the default
-DplatformModules=none does: the native theme moves to
common/src/desktop/resources, the javase profile is no longer active by
default, and common's pom drops the designer-jar arguments the archetype no
longer has.

build-android-app.sh and build-ios-app.sh look for the generated Gradle and
Xcode projects in common/target when the application has no android or ios
module, so CN1_APP_DIR can name a minimal project. The scripts' JDK notes say
JDK 17 or newer, and server.sh no longer lists a native toolchain.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline guides: written for the developer who generated the project

The reader starts from the Initializr's ride-hailing template and has never
seen the Codename One repository, so the chapters no longer point at
scripts/wayline, the CI workflow, the template sync script or tests that stay
in the repository. The server needs JDK 17 or newer, and the native build is
one command; the toolchain list is gone. The module table reflects the
minimal layout, with no platform modules.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Backend: send push notifications through the Codename One push service

com.codename1.backend.push adds CloudPush, which posts a schema-3 envelope to
the V3 messages API with a push-scoped server API key; PushNotification, the
server's builder for that envelope (including the widget and Live Activity
surface commands, whose state is serialized with sorted keys as the app does);
PushTarget, which normalizes provider aliases and reads classic cn1- device
keys; and PushResult, which reports refusals and Retry-After as values rather
than exceptions. Core's PushMessage is not shared because it parses through
JSONParser, which the server does not compile.

Tested against a loopback stub of the service. Documented in the backend web
chapter, with a cross-link from the push chapter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ORM: the client ManagedSessionTest reads bulk results after clear()

65900f8bd0 made executeUpdate (JPQL and native) leave the session as it is,
as JPA and Spring Data do, and updated the backend's ManagedSessionTest to
match. The client copy in maven/javase runs the same scenarios against the
client ORM and still expected the session to be emptied: nine tests read a
still-managed entity after a bulk statement and saw its pre-statement value.

Apply the same changes here: a clear() before every re-read that expects the
bulk result, and the contains() check now asserts the entity stays managed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: push notifications for every step of a ride

The app registers with PushClient when it comes to the foreground and hands
its provider token to the server for whoever is signed in; signing out takes
it back first, and closing the account forgets every device. A tapped
notification opens the home that shows the ride, as rider or driver.

The server sends through the backend push API once a ride change has
committed: the rider hears of the driver accepting, arriving, starting and
completing the trip, a cancellation and no drivers found; the driver of a
new offer (living only as long as the offer) and of a rider's cancellation.
Each message carries the ride id, state and role, with a collapse key per
ride and role. The Notifications switches in settings are honoured: ride
updates and receipts silence the notification only.

The server side of the rider's Live Activity is here too: the app records
the activity id against the ride, each state change carries the new state
or ends the activity, and a moving car updates the minutes at most every
wayline.push.activity.seconds, claimed with a conditional update.

wayline.push.provider is cloud, console or recording (the test profile), and
a production server missing its app id or key logs [config] and keeps
serving rides. PushTest covers registration, every step, cancellations, the
Live Activity, the settings and a phone changing hands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: the ride on the lock screen while the driver is on the way

RideCard starts a Live Activity when a driver accepts: the driver, the car,
the plate, the minutes to the pickup and a bar through on the way, arrived,
the trip and its end. The rider screen moves it on with every change it
sees, off the event thread, and posts the activity id so the server can keep
it current by push once the app is put away. A completed ride stays with its
last state; a canceled one is dismissed.

surfaces.json declares live activities only, and ios.surfaces.frequentUpdates
asks iOS for the update rate a moving car needs. It shows on the iPhone lock
screen and Dynamic Island, as an ongoing notification on Android, and in a
window on the desktop and in the simulator; a browser shows nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: an online driver keeps reporting from the background

Shift begins when the server says the driver is online and ends when they go
offline, sign out or switch to the rider's side. While the app is in the
background it reports the position through the same driver status call the
screen uses, when the car has moved 25 m and at least every 20 s, well
inside the minute after which the server stops offering rides.

Locator asks for precise, frequent fixes only while a shift is on, and puts
the position search down in the background when there is none, so the
location background mode does not keep a rider's map running.

iOS keeps the app running through the location background mode, with the
Always prompt's text in NSLocationAlwaysAndWhenInUseUsageDescription.
Android runs a foreground service of the location type with a "You're
online" notification. The simulator and the browser report nothing from the
background.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline guides: notifications, the ride on the lock screen, background driving

The users guide says what reaches a phone that is not looking: the
notifications of each step, the Live Activity and where it shows, what the
Notifications switches now silence, and the driver who keeps reporting with
the app in the background. The implementors guide adds a section for each:
how the app registers and the server decides what to send, turning on the
Codename One push service, the Live Activity on both sides, and the shift
with its build hints, every listing included from the project's sources.
External Surfaces gets an anchor to link to.

The Initializr template is synced with the sample.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ParparVM: RecordMethodsTest gets the application it runs

The test's RecordMethodsApp was committed as a license header alone, so the
JDK leg had no class to run. It now holds records of every primitive kind, a
String, a nested record, a list, an enum, null components, NaN and -0.0, and
prints their equals, hashCode and toString on one RESULT line. A record with
an enum component prints no hashCode, since an enum hashes by identity.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: Android builds out of the box, with push switched on by the Firebase file

A build that uses PushClient stops without google-services.json or
agconnect-services.json, so a freshly generated project could not build for
Android. The template sets android.messagingService=none until the developer
adds the file; the Implementors guide says to delete that line then. The
catalog now documents the hint's values, none among them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: settings file restored after a local Android build rewrote it; guide prose

A local Android build stored the sample's codenameone_settings.properties
back through Properties.store, which dropped its comments, reordered it and
added a machine-local keystore path; that copy was committed and broke the
Initializr template parity check. The file is restored with only the
android.messagingService line added. Four sentences LanguageTool flagged in
the push and Live Activity sections are reworded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: hold the ride while a Live Activity attaches, cap moved push devices, sign out of the old server on switch

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Perf overlay: bimodal AMD family 26 Windows x64 hello RAM

Hello RAM is bimodal on every runner: one run's rounds read about 1.0 to 1.2,
another's about 0.75 to 0.85. On AMD family 26 model 2 the gate failed unchanged
code at 1.02 against 0.75. Baseline is the median of all ten rounds from runs
38688282220 and 38758240099 (0.999), memory tolerance 0.35 as the other Windows
hello rows carry. Time is kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* BackendWebApp: unlink a symbolic link in the output instead of emptying its target

Replacing the staged web app, or a copy destination, walked the old tree with
listFiles(), which follows a link to a directory, so a link pointing outside the
tree had the external directory's contents deleted. A dangling link was left
behind. Links are now removed as links and never descended into.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Screenshot suite: the two native video tests get five times the default budget

VideoIODecodedFrames timed out at 90s on the cross-compiled Windows build
(run 38758239027) and its PNG arrived during the test after next, matching
its reference: slow under a runner stall, not hung. Neither video test is
retry-safe, so the budget is the only slack they have.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* DeclaredCharset: take the charset from a parameter named charset, not from a substring

A search for "charset=" anywhere in a Content-Type also matched a parameter
whose name ends in charset (x-charset=windows-1252) and text inside another
parameter's quoted value, and RSSService then decoded the feed in that charset.
The declaration is now parsed into parameters on their delimiters, outside
quoted strings, and only a parameter named charset declares one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* OutputStreamWriter: hold a high surrogate across writes for every charset

The UTF-8 path already joined a pair split across two writes; the getBytes path
used for every other charset encoded each half alone, so UTF-16 wrote two U+FFFD
and a single byte charset two '?' where the JDK writes the character, or one '?'.
The held half survives a flush and is replaced at close, as the JDK's encoder
does. CharsetCodecApp compares the split writes with the JDK for every charset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: push registration holds the account, stale ride changes say nothing

- PushDevices.register holds the account's profile row before reading or
  writing devices: refused once the account is closed (no orphan device),
  and concurrent registrations serialize so the cap cannot be overrun.
- RidePushes.compose sends nothing when the ride's committed state (or an
  offer's driver) no longer matches the change it was called for; the later
  transition's own call ends any Live Activity.
- PhoneVerification: comment on why the previous code's count already
  includes post-resend guesses (takeGuess increments both counters).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Charsets: back to the platform's behaviour; only UTF-8 and ISO-8859-1 are promised

Reverts the charset rework (CharsetSupport, DeclaredCharset, the
String/reader/writer/Charset lookups, the native and JavaScript codec
changes, the OutputStreamWriter surrogate holding and their tests). This
class library is not the JDK: UTF-8 and ISO-8859-1 are the charsets it
supports everywhere, and any other name is whatever the platform makes of
it. URLEncoder and URLDecoder say so instead of checking the name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: a closed account keeps no application; desktop magnify steps are gestures

Applications.hold() ignored a zero profile hold, so a save or upload
authorized before Accounts.erase committed recreated the application and
stored identity documents after forget() ran. It answers 404 now, as
PushDevices.register does.

JavaSE's trackpad magnify reports 1.14/0.88 steps with no gesture phases,
while Component.pinch() is the scale since the gesture began. MapView read
every step as the same one step and never left its pinch. Each step is now
delimited as a gesture of its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Initializr: resync the Wayline template with the application closure fix

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: an unresolved card tip keeps its card; flags and stale profiles follow closure

- Payments: removing a card or closing the account also waits on a card
  tip whose charge nobody can vouch for. Its retry charges the ride's card
  under the same key, so with the card gone a tip that may have been
  charged was cleared as refused.
- Accounts.flag holds the profile first, so a flag racing the account's
  closure cannot record a moderation row after erase() forgot them.
- Session.refreshUser drops an answer from a server the app has since
  been moved off.
- BackendWebApp: following symbolic links in the copied web output is
  intended; the comment says why.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: a sign-in from a server left behind installs nothing; closed accounts get no new rows

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: a half-done refund stays recorded; maps drop overzoom tiles the view left

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline and Initializr templates are MIT No Attribution; brand tints follow the scheme; label halos take their room

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: answers from an ended session are dropped; device state belongs to an account on one server

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: a restore from an ended session is dropped; the hosted browser app keeps its server

Backend.dispatch decorates a chosen status and its own 404 as the listener
does; the backend goals read cn1.backend.webapp.output; a shaded jar's
application classes are scanned beside the runtime it carries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: a Live Activity is forgotten once its end is sent; shadowed dependency classes are not scanned

An end the push provider refused stays marked and is sent again by a sweep,
for as long as iOS would keep the activity on screen. The dependency scan
claims every class name before its annotation test, so the definition the
JVM loads first always wins. A shared module's calls are checked unrewritten,
because the server runtime has no rewrites either.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: the hardening a production deployment adds is listed, not built

Keyed phone-code digests, retried push unregistration, sign-out ending a
ride's Live Activity and an activity per device are listed in the
implementor's guide; the code says why the sample stops short of them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: a live ticket is not held against account closure; it expires within a minute and opens nothing

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: a document's pixel size is checked from its header; Gradle's backend tasks share the web-app output

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: server-switch and token races are left to heal, and the code says why

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: a Live Activity is forgotten when the push service confirms its end; a pool thread keeps the generation it was made in

The push sender reports acceptance through a callback, so an end the
service refuses on its own thread, or never answers, stays for the sweep.
RunnableWrapper takes a worker's generation when the worker is created,
under the pool lock, not when it is first scheduled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: a customer orphaned by a lost answer and a rename is left at the processor, and the code says why

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: a driver owed money cannot close the account; leaving driver mode says so to the server

Closing an account is refused while the driver's earnings balance is above
zero, since the retired name could never cash it out. Leaving the driver's
side while the session is still there reports the driver off line, and a
driver-status answer arriving after navigation no longer restarts the shift.
Sign-out revocation and charges past the retry window are left as they are,
and the code says why.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: an unsent-change mark is cleared only for its own account; the settlement sweep takes the oldest rides first

A save answered after another account signed in no longer erases that
account's unsent mark. The payment sweep reads its page oldest first, so a
backlog cannot keep old rides behind new ones until they age out. A stale
account load still completes, and the JavaScript port's XHR listeners are
plain worker closures freed with the request; the code says why.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Maps: an overzoomed ancestor that failed waits out its back-off for every piece of it

The failure of a level fetched for overzoomed pieces was recorded only
against the pieces then waiting, so each further piece of the same tile --
one per sibling within a paint when the source refuses at once, or every
piece a pan brings into view -- asked the source for it again with no
back-off. It is now recorded under the ancestor's own key and consulted
before the ancestor is asked for.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: a seeded card tip carries its charge; the browser build gets the outer build's profiles

The demo fortnight's card tips had no tip reference, so the driver's
earnings and a refund skipped them while the receipts showed them. The
nested JavaScript build of backend-webapp now receives the profiles turned
on and off with -P. The demo seeding marker stays an account, and the code
says why.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* JavaScript port: location requests share two callbacks instead of minting one each

A callback handed to the page keeps an entry in the runtime's worker
callback table for good, so a new GeoCallback per getCurrentLocation and
per watch was never released. The manager now owns one callback for
one-shot answers, taken by whoever is waiting, and one for watches.
URLDecoder leaves an unknown encoding to the first escape, and the code
says why.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wayline: a closed driver's old rides take no tips; a phone-code guess holds the profile first

A tip for a ride whose driver has closed the account is refused, since it
would be credited to a name nobody can cash out. A guess at the phone code
takes the profile hold before the code row, the order a closure takes
them in. Withdrawing the driver role with earnings owed stays allowed, and
the code says why.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Backend packaging reads the source encoding from the compile execution first

backend-package and backend-test recompile the module's sources, and took
their encoding from the compiler plugin's own configuration only, so a
module declaring <encoding> on its compile execution was recompiled with a
different charset than the lifecycle used. The execution already selected
for the other compiler options is now read first. The tip-in-flight comment
is corrected, and URLEncoder says why an unknown encoding waits for the
first escape.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ORM: the backend's Spring Boot naming has no switch back, and the code says why

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* JavaScript port: a one-shot timer releases its callback when it fires

Window.setTimeout handed every Java handler a permanent worker callback
id, and the host kept a proxy for it, so each timeout leaked both. A
one-shot timer now forgets both sides when it fires or is cleared, and
the semantic-refresh timer reuses one stable handler.

A browser bundle with a link back to its own ancestor is refused when
the link is reached instead of being copied into itself. The Gradle
task's comment now points at the never-up-to-date registration, and the
duplicate of that registration is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.

RFE: JavaSE-style Process API for all desktop platforms and backend

1 participant