Mobile support implementation plan¶
Status: proposed implementation sequence, 2026-10-12. No mobile deployment is
qualified by this plan. The baseline audit is 850e48e; recheck it before each
implementation slice. Maintain this page as the mobile milestone owner and use
the platform porting checklist for subsystem coverage and
evidence. Existing API comments and module designs remain contract owners.
Goal and initial scope¶
Run one shared Ludus game on an iPhone 16 Pro, iPad Pro 11-inch (M4), and the owner's Galaxy Flip. The reported name “Galaxy Flip V” has not been resolved to an exact model: record its model number, OS build and GPU during M0 instead of assuming a generation or Vulkan feature set. All three devices are available for acceptance; none has been tested for this plan.
Start Apple and Android implementation together after the shared M0 contracts are agreed. Apple uses an iOS/iPadOS UIKit host with Metal; Android starts with an ARM64 GameActivity host and Vulkan. These are proposed integration choices, not claims that the desktop backends already work on phones. Qualify real devices first; Apple Simulator and Android emulator builds are separate profiles. Mac Catalyst, other Android ABIs, the Flip cover display, stylus features, mobile editor hosting and store distribution are outside the first deployment gate.
The desktop editor remains the authoring host. Mobile games statically link game code initially; desktop shared-module live reload is not a mobile runtime requirement. Include interpreted behavior and cooked content in later gates.
Baseline blockers and reuse candidates¶
| Area | Observed baseline | Port action |
|---|---|---|
| Target identity | Foundation recognizes Android/iOS; config/behavior_profiles.json marks both pending |
Preserve detection; admit profiles only with build and runtime evidence |
| FoundationBase | Its CMake guard accepts Linux/Darwin or Emscripten with Clang | Add explicit mobile assertion/emergency/debugger boundaries and compiler qualification |
| Platform | Cocoa is selected only for Darwin; other native targets can reach the null path | Add explicit UIKit and Android selections; mobile shipping configuration must reject an accidental null backend |
| Metal | RHI's broad APPLE branch links AppKit and calls the Cocoa configuration helper |
Separate macOS from iOS build selection and native view ownership; reuse portable Metal resource code only after audit |
| Vulkan | Presentation accepts Wayland descriptors; current retirement uses maintenance1 features | Add Android surface ownership and device feature negotiation; establish safe retirement before presenting |
| Filesystem | Native storage/persistence selection accepts Linux/Darwin; mobile selects unsupported implementations | Add bundle/APK asset sources and writable sandbox mounts, including background reads and persistence |
| Runtime/tooling | Packaging accepts Linux, macOS and web; native game host contains shared-module loading | Add static mobile host and separate mobile packaging/SDK profiles |
| Input/audio | Existing keyboard reduction and private audio integration offer reuse candidates | Add bounded touch vocabulary and verify mobile audio sessions, interruptions and routes |
Audit FoundationTime, memory, threading, logging/profiling, resources, scripting, networking, renderer, text/localization and UI explicitly using the checklist. A POSIX-looking API or an existing third-party backend is not acceptance evidence.
Parallel implementation and merge order¶
Use one shared contract branch and separate Apple and Android branches/worktrees. Merge shared contracts through reviewed PRs before both tracks consume them. Assign each shared change one owner; coordinate edits to root CMake, presets, Foundation headers, native descriptors and Input rather than making divergent platform versions. Neither track waits for the other's backend completion.
| Phase | Shared work | Apple track | Android track | Exit gate |
|---|---|---|---|---|
| M0: contracts and tools | Scope/profile matrix, dependency inventory, lifecycle and touch contracts | SDK/compiler probe, signing/device inventory | SDK/NDK/compiler probe, Galaxy capability inventory | Explicit profiles and blockers recorded; both minimal toolchain probes work |
| M1: runtime boot | Static game-host path, target-safe Foundation, diagnostics | UIKit scene host, tick scheduling, Foundation consumer | GameActivity/native loop, JNI boundary, Foundation consumer | Installed app boots and reports target facts on each device |
| M2: surface and rendering | Surface generation/retirement contract, shared clear/triangle fixture | UIKit view and Metal drawable integration | Android native window and Vulkan surface/swapchain | Clear/triangle survives surface and lifecycle transitions on all devices |
| M3: playable content | Touch reducer, mounts/save contract, small cooked scene | Bundle/sandbox adapters, touch/insets | APK assets/private storage adapters, touch/insets | Same packaged interactive scene and durable save work on all devices |
| M4: complete runtime | Audio, behavior/resources, text/UI, jobs and memory pressure | Audio session/route lifecycle and iPad resizing | Audio route lifecycle and fold/recreation tests | Required runtime subsystems pass interruption/failure journeys |
| M5: performance and qualification | Budgets, conformance, SDK/install/CI and setup repair | Device captures, sanitizer availability, Release build | Device captures, page-size compatibility, Release build | Reproducible supported profiles and reviewed acceptance evidence |
| M6: distribution | Release metadata, symbol retention, upgrade/uninstall policy | Signed archive/TestFlight/store workflow | APK/AAB signing and Play workflow | Separate distribution acceptance; publish only when explicitly authorized |
These phases describe dependency order rather than calendar estimates. A track may reach M3 while the other fixes M2; shared readiness is the minimum completed gate across required devices. Avoid treating a triangle as full engine support.
M0: establish contracts before platform branches diverge¶
- [ ] Record real device/OS identities and available graphics capabilities; select minimum deployment OS/API levels after probes, not from device names.
- [ ] Pin mobile toolchain/dependency versions and qualify C++23 support. The upstream Clang 18 rule must not silently become AppleClang/NDK support. Propose a reviewed toolchain-policy update with SDK/compiler/linker evidence; retain reference Clang 18 format/tidy checks and existing native/browser gates.
- [ ] Separate macOS host cookers/shader tools from target libraries; never run an ARM64 mobile executable as a build-time tool. Audit Conan profiles, imported libraries, Objective-C++ flags, third-party licenses and SDK export closure.
- [ ] Define bounded events for activation, suspension, memory pressure, drawable availability, resize/insets and surface generation. Specify callback thread, ordering, ownership, overflow and explicit failure behavior.
- [ ] Specify touch IDs, begin/move/end/cancel, coordinate units/conversion, multitouch capacity and focus cancellation in Input's owning contract. Keep UI safe areas and physical drawable pixels distinct.
- [ ] Agree frame scheduling, monotonic clock behavior and resume delta policy. Suspension must not produce a giant simulation step or busy render loop.
- [ ] Create independently selectable configure/build/test profiles for Apple devices and Android ARM64. Test execution needs a device runner and must never accidentally execute target binaries on the Mac. Simulator/emulator profiles are optional and independently named/qualified.
Exit: both SDK probes compile/link on their real target toolchains; proposed toolchain policy, contracts and checklist rows have owners and concrete blockers.
M1 and M2: boot and present independently¶
Apple: implement scene-aware UIKit lifecycle and a small Objective-C++ boundary. Specify the active scene's view ownership and main-thread obligations, and use an OS-driven frame callback. Audit Metal code for AppKit, desktop-only feature assumptions, drawable availability, scale and shader library packaging. Keep GPU device/resource ownership in RHI rather than Platform. Initially support one game scene; document explicit handling of additional scene requests.
Android: integrate a pinned GameActivity dependency with a small Java/Kotlin
shell and private JNI/native adapter. Distinguish UI and native-loop threads;
retain/release native windows explicitly. Add VK_KHR_android_surface selection
and negotiate the actual Galaxy's features. If current presentation-retirement
extensions are unavailable, implement and validate an alternative retirement
contract or report a blocker; do not remove safety checks to get a frame.
Both: supply static game-host startup/shutdown, bounded ordinary diagnostics and an independent assertion emergency path. Surface destruction does not imply the game world is destroyed. Stop presentation when no usable drawable exists; never access an old surface after its ownership ends. Application termination may omit orderly teardown, so persistence must not depend on a final callback.
Exit: install from a clean target build and run boot plus clear/triangle on all three devices. Exercise rotation, lock/unlock, Home/app switching, repeated resume and surface replacement. Capture logs, device identities, shader package identity and commit. Verify repeated teardown/recreation without stale handles.
M3: make the same game playable¶
- [ ] Extend Input with touch and cancellation; map touch to shared game actions without synthetic keyboard events. Test simultaneous contacts, ID reuse, overflow, orientation and cancellation during background transitions.
- [ ] Mount immutable cooked content from the Apple bundle and Android package; avoid assuming APK entries are ordinary paths or uncompressed mapped files. Define writable save/cache roots, quotas/errors and output preservation.
- [ ] Validate worker reads, cancellation during shutdown, corrupt/missing packs, bounded allocations and interruption-safe save replacement.
- [ ] Package a small shared scene with mesh, texture, camera, basic UI and a touch action. Cook Metal/SPIR-V variants on the host; verify shader reflection, packing and capability admission against existing RHI/renderer contracts.
- [ ] Save one game-state value, relaunch after process termination and verify recovery. Cover schema mismatch and failed writes explicitly.
Exit: the same content revision is interactive and reloads a durable save on all devices. iPad resizing and Galaxy fold/unfold do not stretch input coordinates, retain stale contacts or require a desktop keyboard.
M4: qualify the required runtime surface¶
Audit each checklist row; classify unavailable features as unsupported with explicit behavior rather than omitting them. Verify audio start/stop, silence on interruption, route changes and resume with the existing private audio dependency before choosing a replacement. Establish audio-session ownership on Apple. Test script/behavior profile admission, resource lifetime, jobs, timers, localization/text/UI and the sample's required networking path. Confirm memory pressure and low-storage failure degrade gracefully. Virtual keyboard/IME is a required feature only if the sample accepts text; otherwise mark it deferred.
Device journeys include iPhone safe areas/rotation, iPad window resizing under the installed OS, and Galaxy fold/unfold, configuration changes and Activity recreation. Distinguish live surface recovery from cold process restart and save recovery. Record cover-display, Pencil, controller and multi-scene limitations explicitly; none is implied by core touch support.
Exit: required module contracts, platform-independent reducer tests, and actual device interruption/failure journeys pass with evidence attached to their rows.
M5 and M6: qualification and distribution¶
Choose measurable frame-time, peak-memory, startup and package-size budgets at M0/M3; record resolution, scene, refresh setting and build flavor. At M5 run repeatable sustained workloads (initial protocol: at least 20 minutes per device), reporting p50/p95/p99 frame times, memory growth, thermal conditions and audio/input interruptions. The protocol is an acceptance proposal, not a claim these powerful devices represent low-end phones. Do not mandate desktop compute, ray or optional RHI features on the mobile minimum profile.
Build warning-clean target libraries and an installed-SDK consumer in Debug, Development and Release. Run reference format/tidy, portable unit tests and available target sanitizer tests. Document exact sanitizer/tool limitations; simulator or desktop tests do not replace physical-device acceptance. CI should build target artifacts and portable tests; an explicit device-run result remains required where unattended device testing is unavailable.
Use the selected CMake to list configure/build/test presets. Verify SDK/compiler, Ninja, host shader tools and IDE preset mode through the shared CLI/Editor setup workflow. Loading/checking is read-only; explicit repair preserves custom presets/settings, regenerates owned ignored settings and refreshes stale caches. Test fresh clone, missing presets, moved SDK/toolchain and repeated repair, then perform a real configure/build/device test before reporting repaired setup.
Android qualification includes native library and APK alignment, dependencies, and 16 KB page-size runtime evidence in an appropriate emulator or device; the Galaxy alone may not offer that configuration. Pin compatible NDK/build tools after testing. Store-policy requirements are rechecked when M6 begins. Apple device signing and distribution use separate configurations; keep private keys, provisioning material and developer identities out of public docs.
M5 admits only named, evidenced runtime profiles and updates the existing capability/status pages, behavior admission and package validation in the same implementation change. M6 adds signed distribution, clean install/upgrade, symbolication and store compliance; development installation is not distribution acceptance. Deferred features remain visible after a platform is admitted.
Milestone tracker¶
Update a cell when its gate is met; link the implementation PR and evidence.
Use not started, in progress, blocked: reason, or passed: evidence.
Device/tool versions and logs belong in evidence, not speculative completion dates.
| Gate | Shared | iPhone 16 Pro | iPad Pro M4 | Galaxy Flip |
|---|---|---|---|---|
| M0 | not started | not started | not started | not started |
| M1 | not started | not started | not started | not started |
| M2 | not started | not started | not started | not started |
| M3 | not started | not started | not started | not started |
| M4 | not started | not started | not started | not started |
| M5 | not started | not started | not started | not started |
| M6 | not started | not started | not started | not started |
Subsystem port ledger¶
Initial coverage from the baseline audit. Track ownership by workstream until a
contributor takes a row; implementation PRs and runtime evidence are pending for
every row. Status applies to the proposed mobile profiles only. Expand a cell
with a blocker, PR and evidence link as work progresses, using the checklist's
record format. reuse candidate still requires target compilation and testing.
| Subsystem | Workstream owner | Apple status | Android status | Next action / gate |
|---|---|---|---|---|
| Target identity | Shared | reuse candidate | reuse candidate | Real SDK/ABI probes, M0 |
| Toolchain/dependencies | Shared with both tracks | needs port | needs port | Pin/qualify compilers, libraries and host cookers, M0 |
| FoundationBase runtime | Both platform tracks | needs port | needs port | Replace rejection with explicit target runtime, M1 |
| Memory/containers | Shared | unreviewed | unreviewed | Alignment/allocation/atomics tests, M1/M4 |
| Time/threading | Shared | unreviewed | unreviewed | Target clock/jobs and suspend policy, M1/M4 |
| Logging/profiling | Both platform tracks | unreviewed | unreviewed | Device sinks and emergency diagnostics, M1 |
| Filesystem | Shared contract, both adapters | needs port | needs port | Bundle/package mounts and durable saves, M3 |
| Platform/host | Both platform tracks | needs port | needs port | UIKit/GameActivity and lifecycle, M1/M2 |
| Input | Shared reducer, both adapters | needs port | needs port | Bounded touch and cancellation, M3 |
| RHI | Both platform tracks | needs port | needs port | Remove AppKit coupling/add Android surface, M2 |
| Renderer/graph | Shared | reuse candidate | reuse candidate | Mobile variants and same scene, M3/M5 |
| Text/localization/UI | Shared with both tracks | unreviewed | unreviewed | Scale/insets and target dependencies, M3/M4 |
| Content/resources | Shared | unreviewed | unreviewed | Cook/load closure and pressure handling, M3/M4 |
| Runtime/game host | Shared with both tracks | needs port | needs port | Static host/deployment path, M1/M3 |
| Behavior/scripting | Shared | needs port | needs port | Interpreter conformance/profile admission, M4/M5 |
| Gameplay/physics | Shared | unreviewed | unreviewed | Scoped fixtures and resume ticks, M4 |
| Audio | Both platform tracks | unreviewed | unreviewed | Existing dependency/session/route probes, M4 |
| Networking | Shared with both tracks | unreviewed | unreviewed | Define required sample scope, reconnect tests, M4 |
| SDK/projects/editor tools | Shared | needs port | needs port | Target presets, export and setup repair, M5 |
| Packaging/distribution | Both platform tracks | needs port | needs port | Development bundle/APK, M1; distribution, M6 |
| CI/documentation | Shared | needs port | needs port | Cross builds, device evidence and support matrix, M5 |
First implementation slices: M0 contracts/toolchain qualification, M1 Apple boot and M1 Android boot. Each platform's M2 rendering slice depends on its own M1 plus the shared surface contract. M3 depends on its own M2 and shared input, storage and content work. This permits simultaneous progress with small PRs.
Sources and related contracts¶
Thanks to Apple, Managing your app's life cycle, for the scene/application lifecycle distinction informing the proposed UIKit host. Thanks to Google, GameActivity, for the native loop, input and framework integration model, and Support 16 KB page sizes, for native binary/package and page-size validation requirements. These sources inform the plan; no upstream implementation code was copied. Implementation slices must preserve attribution beside code informed by these sources.
Existing owners: target detection, macOS Platform, RHI contracts, filesystem, audio, project setup, and packaging.