You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Implement the MOBILE_ANDROID setup profile promised by #4849 so CLI, Java, MCP, and engine runtime share one pinned Appium/Android owner. A reviewed plan must be able to install and verify Appium 3, the Inspector plugin, UiAutomator2, Android command-line tools, platform-tools, API platform, build-tools/aapt2, Emulator, one host-compatible system image, and a SHAFT-owned AVD; start/stop/logs must own the emulator and Appium server without hidden downloads or global environment mutation.
deletes/replaces extraction targets without shared setup receipts/rollback;
treats any adb ... device row as emulator readiness and never proves sys.boot_completed=1;
starts Appium with --relaxed-security by default and owns neither durable lease nor log identity;
is usable only through the MCP inspector-recording path. CLI/Java report MOBILE_ANDROID unsupported.
Current release pins are Node 24.19.0, Appium 3.6.0, Inspector plugin 2026.7.1, UiAutomator2 8.2.2, Android command-line tools 15859902, API 36, device pixel_8, tag google_apis, RAM 4096, cores 2. npm metadata confirms the three Appium packages support Node 24 and Appium 3.
Official command-line-tools 15859902 SHA-256 values: Windows 90ae805d...fb04a, macOS x64 c5a6378a...050f3, macOS arm64 835b62a2...2c4e, Linux x64 4e4c464f...df583: https://developer.android.com/studio#command-tools
Resolved design
Ownership and packaging
Add AndroidSetupProvider, planner/manifest, installer, status verifier, and lifecycle owner to shaft-infrastructure; register it in InfrastructureSetupService.builtIn(). This is the only download/install/process owner.
Refactor the already verified portable Node owner out of reporting into a shared internal service; Appium and reporting must use the same Node lock/destination and retain reporting plan compatibility.
Package an exact Appium package.json/package-lock.json containing appium@3.6.0, appium-uiautomator2-driver@8.2.2, and appium-inspector-plugin@2026.7.1. Run npm ci --ignore-scripts --no-audit --no-fund in staging, verify exact versions and Appium driver/plugin lists, then atomically publish. Do not globally install npm packages and do not call mutable Appium extension installation after publication.
Package a canonical Android release manifest binding command-line-tools URL/SHA-256/size by supported host, API 36, exact build-tools revision, platform-tools, emulator, platforms;android-36, and system-image package by architecture. sdkmanager is the upstream package installer, but the exact package set and command-line-tools bootstrap are plan/receipt bound. Stable channel only; --no_https, alternate repository OS, and implicit upgrades are forbidden.
Use ShaftCachePaths: archives/npm cache in downloads/cache, versioned Appium and Android SDK under tools, AVD data/leases/logs under durable data. Reject relative roots, linked/reparse ancestors and non-regular executables before reads, writes, or execution.
Selection and public adapters
Add an immutable AndroidSetupRequest rather than overloading SetupOptions. It binds AVD name, API, device profile, image tag, host-compatible ABI, RAM, cores, and server port. Defaults reproduce the release manifest. Normalize and validate all values before URI/path creation. Expose additive coordinator and SHAFT.Infrastructure overloads.
Add CLI options on status|doctor|plan|install|verify|start: --api-level, --device-profile, --image-tag, --abi, --avd-name, --ram-mb, --cores, and --port. install reconstructs the request from the reviewed plan; repeated selectors are optional but must match. Persisted plan actions remain authoritative.
Replace MCP install/start code with a compatibility adapter over the shared coordinator/lifecycle. Preserve existing tool responses and proposal confirmation semantics, but translate the confirmed proposal into the exact plan/approval/license flow. Delete the duplicate downloader/extractor/npm/sdkmanager owner after parity proof.
Engine local Appium bootstrap uses the shared runtime only when setup mode is managed and a compatible receipt exists. An explicit non-local execution address always wins and triggers zero local setup. Child-only environment receives APPIUM_HOME, ANDROID_HOME, ANDROID_SDK_ROOT, ANDROID_AVD_HOME, and PATH additions; process-global environment remains untouched.
Licenses, integrity, offline, and privilege
Bind the Android SDK license agreement identifier and all installed package license IDs into plan actions. CLI/Java/MCP must receive explicit matching acceptance before the first directory, process, or network action. Remove unconditional "y\\n".repeat(...) consent.
EXTERNAL is read-only and executes no probes that can initialize caches. MANAGED/HYBRID installation is exact-plan only. offline=true succeeds only from a complete verified installed state or complete verified artifact/npm/sdk cache; otherwise it fails before directories/processes/network.
Hypervisor, BIOS virtualization, Linux KVM group access, Windows Hypervisor Platform, macOS host entitlement, USB/device trust, and JDK availability are diagnostic prerequisites. Use emulator -accel-check; never enable features, elevate, edit shell profiles, or install host drivers.
Appium binds only 127.0.0.1, does not enable --relaxed-security by default, has bounded/redacted logs, and is READY only after /status returns a compatible build. The emulator is READY only after its exact serial is online, getprop sys.boot_completed is 1, package manager responds, and the selected AVD/image identity matches.
Atomicity and lifecycle
One normalized-root JVM lock plus OS file lock protects shared Node, Appium, Android SDK package install, AVD creation, receipts, and leases. Recheck under the lock. Separate JVM/process acceptance must converge.
Archive extraction rejects absolute/traversal/drive/UNC/ADS paths, links/devices, duplicate/case-fold collisions, reserved Windows names, excessive entries/sizes/ratios, and linked ancestors. Downloads are size bounded and SHA-256 verified before extraction.
Each install action is atomic. Known-good destinations are quarantined only after replacement is verified; rollback/recovery preserves the last usable copy. A partial failure exposes the failed action and partial receipt but writes no final profile receipt. Retrying reuses verified completed actions.
start creates or reuses only SHAFT-owned leases. Start emulator first, wait for full boot, then start Appium and verify /status. On any later failure, tear down resources started by that call and retain logs. close/stop validates PID/start-instant/command/root/endpoint before terminating descendants then parent with one bounded deadline. Unknown ports/PIDs are never adopted or killed. logs reads only the lease-bound bounded files.
MOBILE_ANDROID is no longer catalog-only. CLI, Java, MCP, and managed engine execution agree on one exact plan/report/receipt and one owned Appium+emulator lifecycle. A clean supported host can reach a real UiAutomator2 session with aapt2 present after explicit reviewed approval/licenses; external/default/remote/offline-denial paths perform zero hidden mutation; no duplicate installer remains in MCP; every acceptance above has mutation-sensitive automated proof and all required CI/publication/documentation gates are green.
Objective
Implement the
MOBILE_ANDROIDsetup profile promised by #4849 so CLI, Java, MCP, and engine runtime share one pinned Appium/Android owner. A reviewed plan must be able to install and verify Appium 3, the Inspector plugin, UiAutomator2, Android command-line tools, platform-tools, API platform, build-tools/aapt2, Emulator, one host-compatible system image, and a SHAFT-owned AVD; start/stop/logs must own the emulator and Appium server without hidden downloads or global environment mutation.Parent: #4849
Current evidence (researched 2026-08-13)
The only current installer is package-private
McpMobileToolchainService. It:npm install, then Appium extension CLI installs;yintosdkmanager --licenseswithout binding accepted license IDs to the reviewed plan;platform-tools,emulator,platforms;android-<api>, and a system image, but omitsbuild-tools, soaapt2is unavailable (the concrete Establish honest real-provider acceptance for Appium screen recording #4751 failure);adb ... devicerow as emulator readiness and never provessys.boot_completed=1;--relaxed-securityby default and owns neither durable lease nor log identity;MOBILE_ANDROIDunsupported.Current release pins are Node
24.19.0, Appium3.6.0, Inspector plugin2026.7.1, UiAutomator28.2.2, Android command-line tools15859902, API36, devicepixel_8, taggoogle_apis, RAM4096, cores2. npm metadata confirms the three Appium packages support Node 24 and Appium 3.Primary contracts:
APPIUM_HOMErules: https://appium.io/docs/en/latest/guides/managing-exts/aapt2is supplied bybuild-tools;<version>: https://developer.android.com/tools/aapt215859902SHA-256 values: Windows90ae805d...fb04a, macOS x64c5a6378a...050f3, macOS arm64835b62a2...2c4e, Linux x644e4c464f...df583: https://developer.android.com/studio#command-toolsResolved design
Ownership and packaging
AndroidSetupProvider, planner/manifest, installer, status verifier, and lifecycle owner toshaft-infrastructure; register it inInfrastructureSetupService.builtIn(). This is the only download/install/process owner.package.json/package-lock.jsoncontainingappium@3.6.0,appium-uiautomator2-driver@8.2.2, andappium-inspector-plugin@2026.7.1. Runnpm ci --ignore-scripts --no-audit --no-fundin staging, verify exact versions and Appium driver/plugin lists, then atomically publish. Do not globally install npm packages and do not call mutable Appium extension installation after publication.36, exactbuild-toolsrevision,platform-tools,emulator,platforms;android-36, and system-image package by architecture.sdkmanageris the upstream package installer, but the exact package set and command-line-tools bootstrap are plan/receipt bound. Stable channel only;--no_https, alternate repository OS, and implicit upgrades are forbidden.ShaftCachePaths: archives/npm cache in downloads/cache, versioned Appium and Android SDK under tools, AVD data/leases/logs under durable data. Reject relative roots, linked/reparse ancestors and non-regular executables before reads, writes, or execution.Selection and public adapters
AndroidSetupRequestrather than overloadingSetupOptions. It binds AVD name, API, device profile, image tag, host-compatible ABI, RAM, cores, and server port. Defaults reproduce the release manifest. Normalize and validate all values before URI/path creation. Expose additive coordinator andSHAFT.Infrastructureoverloads.status|doctor|plan|install|verify|start:--api-level,--device-profile,--image-tag,--abi,--avd-name,--ram-mb,--cores, and--port.installreconstructs the request from the reviewed plan; repeated selectors are optional but must match. Persisted plan actions remain authoritative.APPIUM_HOME,ANDROID_HOME,ANDROID_SDK_ROOT,ANDROID_AVD_HOME, and PATH additions; process-global environment remains untouched.Licenses, integrity, offline, and privilege
"y\\n".repeat(...)consent.EXTERNALis read-only and executes no probes that can initialize caches.MANAGED/HYBRIDinstallation is exact-plan only.offline=truesucceeds only from a complete verified installed state or complete verified artifact/npm/sdk cache; otherwise it fails before directories/processes/network.emulator -accel-check; never enable features, elevate, edit shell profiles, or install host drivers.127.0.0.1, does not enable--relaxed-securityby default, has bounded/redacted logs, and is READY only after/statusreturns a compatible build. The emulator is READY only after its exact serial is online,getprop sys.boot_completedis1, package manager responds, and the selected AVD/image identity matches.Atomicity and lifecycle
startcreates or reuses only SHAFT-owned leases. Start emulator first, wait for full boot, then start Appium and verify/status. On any later failure, tear down resources started by that call and retain logs.close/stopvalidates PID/start-instant/command/root/endpoint before terminating descendants then parent with one bounded deadline. Unknown ports/PIDs are never adopted or killed.logsreads only the lease-bound bounded files.Caller matrix
SHAFT.InfrastructureSetupApproval; privileged work rejectedState/failure matrix
Acceptance-to-proof map
aapt2includedbuild-toolsexact revision;aapt2 versionand APK badging flow passadb devicewithout boot completion times out and cleans owned process/status, lease, logs, refcountSequential RED → GREEN delivery
build-toolsand accepted license IDs.Definition of done
MOBILE_ANDROIDis no longer catalog-only. CLI, Java, MCP, and managed engine execution agree on one exact plan/report/receipt and one owned Appium+emulator lifecycle. A clean supported host can reach a real UiAutomator2 session withaapt2present after explicit reviewed approval/licenses; external/default/remote/offline-denial paths perform zero hidden mutation; no duplicate installer remains in MCP; every acceptance above has mutation-sensitive automated proof and all required CI/publication/documentation gates are green.