### start: launch service thread and process Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Starts the runtime by setting up the process, host call handler, and a runner thread. Returns an error if already started. The runner thread runs the process and handles pending commands on exit. ```cpp bool LibraryRuntime::start(const LibraryRuntimeOptions& options, std::string& error) { { std::lock_guard lock(impl_->mutex); if (impl_->started) { error = "guest library runtime was already started"; return false; } impl_->started = true; } Impl* impl = impl_.get(); impl->process.set_sysroot(options.sysroot); impl->process.set_host_call_handler( [impl](std::uint32_t index, GuestThread& thread) { return impl->handle_host_call(index, thread); }); std::vector argv = {options.zbhost, std::to_string(options.target_sdk)}; if (!options.preload.empty()) argv.push_back(options.preload); impl->runner = std::thread([impl, argv, options] { const int status = impl->process.run(options.zbhost, argv, options.envp); std::deque> pending; { std::lock_guard lock(impl->mutex); impl->finished = true; if (!impl->ready && impl->startup_error.empty()) impl->startup_error = exit_message(status); pending.swap(impl->commands); } impl->cv.notify_all(); for (const auto& command : pending) command->done.set_value({false, std::nullopt, exit_message(status)}); }); } ``` -------------------------------- ### LibraryRuntime::start - start guest runtime with options Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Starts the guest library runtime with the provided options. Sets sysroot and host call handler, launches a runner thread, and waits for readiness or timeout. Returns false with an error message if already started or if zbhost fails to report ready. ```cpp bool LibraryRuntime::start(const LibraryRuntimeOptions& options, std::string& error) { { std::lock_guard lock(impl_->mutex); if (impl_->started) { error = "guest library runtime was already started"; return false; } impl_->started = true; } Impl* impl = impl_.get(); impl->process.set_sysroot(options.sysroot); impl->process.set_host_call_handler( [impl](std::uint32_t index, GuestThread& thread) { return impl->handle_host_call(index, thread); }); std::vector argv = {options.zbhost, std::to_string(options.target_sdk)}; if (!options.preload.empty()) argv.push_back(options.preload); impl->runner = std::thread([impl, argv, options] { const int status = impl->process.run(options.zbhost, argv, options.envp); std::deque> pending; { std::lock_guard lock(impl->mutex); impl->finished = true; if (!impl->ready && impl->startup_error.empty()) impl->startup_error = exit_message(status); pending.swap(impl->commands); } impl->cv.notify_all(); impl->carrier_cv.notify_all(); for (const auto& command : pending) command->done.set_value({false, std::nullopt, exit_message(status)}); }); std::unique_lock lock(impl->mutex); const bool settled = impl->cv.wait_for(lock, options.ready_timeout, [impl] { return impl->ready || impl->finished || !impl->startup_error.empty(); }); if (impl->ready) return true; error = settled ? impl->startup_error : "zbhost did not report ready within " + std::to_string(options.ready_timeout.count()) + " ms"; return false; } ``` -------------------------------- ### Runtime start and service API checks Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Starts the runtime with options, verifies the guest thread count and service protocol version, and checks that calling malloc on the service thread fails. ```cpp std::string error; CHECK(runtime.start(runtime_options(argv), error)); CHECK(runtime.guest_thread_count() == 1); CHECK(runtime.service_api().version == ZB_SERVICE_PROTOCOL_VERSION); CHECK(!runtime.call_on_current(runtime.service_api().malloc_fn, zb::GuestCall{})); ``` -------------------------------- ### Runtime setup and host call handler Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Initializes a zb::LibraryRuntime with atomic counters and a host call handler that intercepts index 0xFD00, increments call counts, checks for misuse, loads a library on the service thread, and performs a nested call. ```cpp zb::LibraryRuntime runtime; std::atomic chained_function{0}; std::atomic chained_calls{0}; std::atomic chained_on_service{true}; runtime.set_host_call_handler([&](std::uint32_t index, zb::GuestThread& thread) { if (index != 0xFD00) return false; ++chained_calls; std::string misuse; CHECK(!runtime.borrow(misuse)); CHECK(misuse.find("call_on_current") != std::string::npos); if (chained_on_service) { misuse.clear(); CHECK(runtime.load_library(argv[3], ZB_GUEST_RTLD_NOW, misuse) == 0); CHECK(misuse.find("service thread") != std::string::npos); } const auto nested = runtime.call_on_current(chained_function, zb::GuestCall{}); CHECK(nested && nested->r0 == 42); thread.regs()[0] += nested->r0; return true; }); ``` -------------------------------- ### handle_ready: validate API and start service thread Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Handles the service-ready host call. Validates the API version, sets the service thread and ID, marks ready, and then enters the serve loop. ```cpp bool handle_ready(GuestThread& thread) { { std::unique_lock lock(mutex); if (!ready) { std::string error; if (!validate_api(thread.regs()[0], error)) { startup_error = std::move(error); lock.unlock(); cv.notify_all(); thread.regs()[0] = 1; return true; } service = &thread; service_id = std::this_thread::get_id(); ready = true; lock.unlock(); cv.notify_all(); } } serve(thread); return true; } ``` -------------------------------- ### zb_probe_install_usr1: install SIGUSR1 handler Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Installs a handler for SIGUSR1 that records the thread ID and thread-local storage pointer. Returns 0 on success, -1 on failure. ```c DATA volatile int32_t zb_usr1_count; DATA volatile int32_t zb_usr1_tid; DATA volatile uint32_t zb_usr1_tls; static void on_usr1(int sig) { (void)sig; zb_usr1_tid = (int32_t)syscall(__NR_gettid); zb_usr1_tls = (uint32_t)(uintptr_t)__builtin_thread_pointer(); ++zb_usr1_count; } API int32_t zb_probe_install_usr1(void) { struct sigaction sa; memset(&sa, 0, sizeof sa); sa.sa_handler = on_usr1; return sigaction(SIGUSR1, &sa, NULL); } ``` -------------------------------- ### check_preload_failure: Verify preload failure handling Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Forks a child process to test that runtime.start() fails with a non-existent preload library. Expects an error containing "status 4" and exits with code 0 on success, 10 if start unexpectedly succeeds, 11 if error message is wrong. ```cpp // start() reports a failed preload; runs in a child because a runtime is process-lifetime. void check_preload_failure(char** argv) { std::fflush(stdout); const pid_t child = fork(); CHECK(child >= 0); if (child == 0) { zb::LibraryRuntime runtime; zb::LibraryRuntimeOptions options = runtime_options(argv); options.preload = "libzb-does-not-exist.so"; std::string error; if (runtime.start(options, error)) std::_Exit(10); std::fprintf(stderr, "expected start error: %s\n", error.c_str()); std::_Exit(error.find("status 4") != std::string::npos ? 0 : 11); } int status = 0; CHECK(waitpid(child, &status, 0) == child); CHECK(WIFEXITED(status) && WEXITSTATUS(status) == 0); } ``` -------------------------------- ### set_host_call_handler: set chained handler before start Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Sets the chained host call handler. Aborts if called after start. ```cpp void LibraryRuntime::set_host_call_handler(Process::HostCallHandler handler) { std::lock_guard lock(impl_->mutex); if (impl_->started) { log("LibraryRuntime::set_host_call_handler called after start"); std::abort(); } impl_->chained = std::move(handler); } ``` -------------------------------- ### Build the guest tree Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-17-phase7a-native-surface.md Builds the guest libraries and checks that libEGL.so and libandroid.so exist. tools/build_guest.sh must learn libEGL the same way it builds libGLESv2; add it there if the build fails with "no rule". ```bash tools/build_guest.sh; ls -la build/guest/lib/libEGL.so build/guest/lib/libandroid.so ``` -------------------------------- ### Build guest and run host and guest tests Source: https://github.com/zailoxtt/zettabridge/blob/main/CLAUDE.md Builds the guest with tools/build_guest.sh, runs host tests with ctest, and runs guest tests with tools/run_guest_tests.sh. Requires the host build to be configured first. ```bash tools/build_guest.sh; ctest --test-dir build/host --output-on-failure; tools/run_guest_tests.sh ``` -------------------------------- ### main: Entry point with argument checks and RTLD flag validation Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Main function that checks argc == 4, runs preload failure check, and validates ZB_GUEST_RTLD flag values. Uses CHECK macros for assertions. ```cpp int main(int argc, char** argv) { CHECK(argc == 4); const std::string probe = argv[3]; const std::string libdir = std::filesystem::path(probe).parent_path(); check_preload_failure(argv); CHECK(ZB_GUEST_RTLD_NOW == 0u && ZB_GUEST_RTLD_LAZY == 1u && ZB_GUEST_RTLD_GLOBAL == 2u); CHECK(ZB_GUEST_RTLD_NOLOAD == 4u && ZB_GUEST_RTLD_NODELETE == 0x1000u && ZB_GUEST_RTLD_DEFAULT == 0xFFFFFFFFu); } ``` -------------------------------- ### Regenerate stubs and check index rule Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-17-phase7a-native-surface.md Runs the generator and greps for key symbols in hostcalls.inc. Expected: AAssetManager_fromJava still 145, AAsset_read still 157, ANativeWindow_* starts at 160, egl* starts after window names. If asset indices moved, fix the generator, not asset_hostcalls.h. ```bash python3 tools/gen_stubs.py; grep -n "AAssetManager_fromJava\|AAsset_read\|ANativeWindow_acquire\|eglCreateContext" core/src/gen/hostcalls.inc ``` -------------------------------- ### RuntimeReport GL section example output Source: https://github.com/zailoxtt/zettabridge/blob/main/AGENTS.md Example output from the gl_chain_test showing the four new text() lines: gl-calls, gl-first-call, gl-egl-context-current, and gl-first-error. The gl-first-error line shows '(none)' when no error is seen, and would show 'glGetError 0x0502' when the first non-zero result is seen. ```text gl-calls: 1 gl-first-call: glClear tid=4242 gl-egl-context-current: yes gl-first-error: (none) ``` -------------------------------- ### Run GREEN: build and run host_looper_test, platform_compat_test, proxy_runtime_test Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-17-phase7a-native-surface.md Commands to build and run the host_looper_test, platform_compat_test, and proxy_runtime_test after implementation. Expected all pass, with platform_compat_test now expecting eight remaining non-looper fallbacks. ```bash ninja -C build/host host_looper_test platform_compat_test proxy_runtime_test build/host/tests/host/host_looper_test build/host/tests/host/platform_compat_test build/host/tests/host/proxy_runtime_test ``` -------------------------------- ### LibraryRuntime header declaration (library_runtime.h) Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Declares the LibraryRuntime class and LibraryRuntimeOptions for a guest process in library mode. The runtime is process-lifetime; guest threads cannot be torn down, so after a successful start() the destructor logs and aborts, and tests end with std::_Exit. Host calls outside the runtime range 0xFE00-0xFEFF are received via set_host_call_handler before start(). ```cpp #pragma once #include #include #include #include #include #include #include #include "zb/guest_memory.h" #include "zb/guest_thread.h" #include "zb/library_protocol.h" #include "zb/native_call.h" #include "zb/process.h" namespace zb { struct LibraryRuntimeOptions { std::string zbhost; // host path of the arm32 zbhost executable std::string sysroot; // host directory with the arm32 system files std::uint32_t target_sdk = 0; std::vector envp; // guest environment, e.g. LD_LIBRARY_PATH=... std::string preload; // guest path dlopen'ed RTLD_GLOBAL before READY; empty: none std::chrono::milliseconds ready_timeout{10000}; }; // A guest process in library mode: zbhost runs on a service guest thread that owns the boot // JIT and serves requests from inside its READY host call. // // The runtime is process-lifetime. Guest threads cannot be torn down, so after a successful // start() the destructor logs and aborts; tests end with std::_Exit. class LibraryRuntime { public: LibraryRuntime(); ~LibraryRuntime(); LibraryRuntime(const LibraryRuntime&) = delete; LibraryRuntime& operator=(const LibraryRuntime&) = delete; // Receives every host call outside the runtime range 0xFE00-0xFEFF. Call before start(). void set_host_call_handler(Process::HostCallHandler handler); bool start(const LibraryRuntimeOptions& options, std::string& error); // Guest dlopen/dlsym/dlerror on the service thread. Flags are ZB_GUEST_RTLD_* values. // Return 0 and set error (guest dlerror text) on failure. std::uint32_t load_library(const std::string& path, std::uint32_t guest_flags, std::string& error); std::uint32_t find_symbol(std::uint32_t handle, const std::string& name, std::string& error); std::optional call_on_service(std::uint32_t function, const GuestCall& args); // Nested call on the guest thread the calling host thread already runs (for host-call // handlers). nullopt if the calling host thread runs no guest code. std::optional call_on_current(std::uint32_t function, const GuestCall& args); GuestMemory& memory(); // Valid after a successful start(). const zb_service_api& service_api() const; // Real guest pthreads (service, carriers, guest-created threads); borrowers are not counted. std::size_t guest_thread_count() const; private: struct Impl; std::unique_ptr impl_; }; } // namespace zb ``` -------------------------------- ### LibraryRuntime::guest_thread_count - Get guest thread count Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Returns the number of guest threads in the process. ```cpp std::size_t LibraryRuntime::guest_thread_count() const { return impl_->process.thread_count(); } ``` -------------------------------- ### Implementation file core/src/library_runtime.cpp (partial content) Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md The exact content for core/src/library_runtime.cpp as specified in the task. Includes includes, namespace, constants, and internal Response and Command structs. The file is to be written with exactly this content. ```cpp #include "zb/library_runtime.h" #include #include #include #include #include #include #include #include #include #include #include "zb/log.h" namespace zb { namespace { constexpr std::chrono::milliseconds kCarrierParkTimeout{10000}; struct Response { bool ok = false; std::optional result; std::string error; }; struct Command { enum class Kind { Load, Symbol, Call, SpawnCarrier }; Kind kind = Kind::Call; std::uint32_t value = 0; std::uint32_t flags = 0; std::string text; GuestCall args; std::promise done; }; ``` -------------------------------- ### Get guest tid and tls from carrier Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Returns the guest thread ID and thread-local storage pointer from the borrower thread. ```cpp std::int32_t LibraryRuntime::Carrier::guest_tid() const { return state_->borrower->tid; } std::uint32_t LibraryRuntime::Carrier::guest_tls() const { return state_->borrower->tls(); } ``` -------------------------------- ### Build and run all tests Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Builds the guest, host, runs all tests, and checks git status. ```sh tools/build_guest.sh; ninja -C build/host; ctest --test-dir build/host --output-on-failure; tools/run_guest_tests.sh; git status --short ``` -------------------------------- ### LibraryRuntime constructor and destructor Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Constructor initializes the implementation. Destructor aborts if the runtime was started and not finished, otherwise joins the runner thread. ```cpp LibraryRuntime::LibraryRuntime() : impl_(std::make_unique()) {} LibraryRuntime::~LibraryRuntime() { if (!impl_->runner.joinable()) return; { std::lock_guard lock(impl_->mutex); if (impl_->ready || !impl_->finished) { log("LibraryRuntime destroyed after start; the runtime is process-lifetime"); std::abort(); } } impl_->runner.join(); } ``` -------------------------------- ### Build and run guest probe (RED) Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-17-phase7a-native-surface.md Commands to build the guest probe and run the host_looper_guest test, expecting failure because callback dispatch is not yet implemented. ```bash tools/build_guest.sh ctest --test-dir build/host -R host_looper_guest --output-on-failure ``` -------------------------------- ### Expected test output for carrier latency Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Example output from the library_runtime_test showing carrier latency timings and test PASS. Timings vary by machine. ```text carrier latency: borrow 30.92 ms, first call 0.43 ms, warm call 0.001 ms library_runtime_test PASS ``` -------------------------------- ### Initialize submodules and apply Dynarmic patches Source: https://github.com/zailoxtt/zettabridge/blob/main/README.md Run this command to initialize the Dynarmic submodule and apply the required patches for Thumb32 ARMv8 and ASIMD narrowing. This is the first step in the build process. ```bash git submodule update --init; git -C third_party/dynarmic apply ../patches/dynarmic-0001-thumb32-armv8.patch ../patches/dynarmic-0002-asimd-narrowing.patch ``` -------------------------------- ### Stopped inside Thumb IT block with E bit set Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Verifies that a call starting with a clean ITSTATE and little-endian data restores the stopped CPSR exactly. ```cpp // Stopped inside a Thumb IT block with the E bit set: the call must start with a clean // ITSTATE and little-endian data, then restore the stopped CPSR exactly. const std::uint32_t it_cpsr = kCpsrUser | kCpsrThumb | kCpsrItEqOne | kCpsrEndian; thread.set_cpsr(it_cpsr); const auto it_result = thread.call(0x10041, thumb, [](const zb::Stop&) { return false; }); CHECK(it_result && it_result->r0 == 7); CHECK(thread.cpsr() == it_cpsr); thread.set_cpsr(kCpsrUser); ``` -------------------------------- ### Build and test commands Source: https://github.com/zailoxtt/zettabridge/blob/main/AGENTS.md Commands to build the host, run host tests, build the guest, and run guest tests. Use these for local verification. ```shell ninja -C build/host; ctest --test-dir build/host --output-on-failure; tools/build_guest.sh; tools/run_guest_tests.sh ``` -------------------------------- ### zb_probe_altstack_sp: get alternate signal stack pointer Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Returns the stack pointer of the enabled alternate signal stack, or 0 if disabled. Uses sigaltstack to query. ```c /* ss_sp of the enabled alternate signal stack, or 0. */ API uint32_t zb_probe_altstack_sp(void) { stack_t ss; if (sigaltstack(NULL, &ss) != 0 || (ss.ss_flags & SS_DISABLE) != 0) return 0; return (uint32_t)(uintptr_t)ss.ss_sp; } ``` -------------------------------- ### Crash report output Source: https://github.com/zailoxtt/zettabridge/blob/main/AGENTS.md Runtime report from the installed APK after waiting 15 seconds, showing the guest SIGSEGV in libc.so at offset 0x674c0 with zero EGL activity. ```text proxy-loads: 1 proxy-failures: 0 proxy-loaded: libflutter.so jni=0x00010004 jni-onload-calls: 1 jni-onload: libflutter.so ok jni=0x00010004 registered-natives: 42 unimplemented-host-calls: 0 guest-exit: guest SIGSEGV: read of 0x0000000f, pc 0xfdb3c4c0 in libc.so offset 0x674c0 gl-calls: 0 egl-swaps: 0 ``` -------------------------------- ### serve() - Service loop with signal handling and parking Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Loops until a signal must be delivered (r0 = AGAIN) or the guest is exiting. Pops commands from a queue, executes them, and parks the thread when idle. ```cpp // Serves commands until a signal must be delivered (r0 = AGAIN) or the guest is exiting. void serve(GuestThread& thread) { for (;;) { const std::uint32_t token = thread.park_token(); if (thread.has_pending_signals(thread.sigmask)) { thread.regs()[0] = ZB_SERVICE_AGAIN; return; } std::shared_ptr command; { std::lock_guard lock(mutex); if (!commands.empty()) { command = commands.front(); commands.pop_front(); } } if (!command) { thread.park(token); continue; } command->done.set_value(execute(thread, *command)); if (process.exiting()) { thread.regs()[0] = 1; return; } } } ``` -------------------------------- ### Host build and test command (Step 6) Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4a-jni-host-units.md Configures and builds the host test, then runs the native_thunk_test with ctest. Expected output is '100% tests passed'. ```bash cmake -S . -B build/host -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ && ninja -C build/host native_thunk_test && ctest --test-dir build/host -R native_thunk_test --output-on-failure ``` -------------------------------- ### Run full regression suite Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4a-jni-host-units.md Runs the host build and tests, then the guest build and tests. Expects '100% tests passed, 0 tests failed out of 10' and 'all guest tests passed'. ```bash ninja -C build/host && ctest --test-dir build/host --output-on-failure && tools/build_guest.sh && tools/run_guest_tests.sh ``` -------------------------------- ### Build T7 test locally Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/phase4-device-test.md Commands to build the guest, ZettaBridge components, and the T7 APK. Requires Android SDK and Gradle 8.11.1; uses the AndroidIDE wrapper or a normal Gradle installation. ```sh tools/build_guest.sh ninja -C build/android-arm64 zbridge zbproxy tools/make_t7_bundle.sh ANDROID_HOME="$HOME/android-sdk" ANDROID_SDK_ROOT="$HOME/android-sdk" \ bash /sdcard/AndroidIDEProjects/ZettaBridge/gradlew \ -p "$PWD/android/t7/project" :app:assembleDebug --no-daemon ``` -------------------------------- ### Native thunk pool header (core/include/zb/native_thunks.h) Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4a-jni-host-units.md Defines the NativeTarget struct, NativeDispatcher function pointer type, and NativeSlots class for managing thunk slots. Includes constants and function declarations for setting the dispatcher and getting thunk addresses. ```cpp #pragma once #include #include #include #include #include #include #include "zb/native_call.h" namespace zb { // Number of precompiled thunks; must match the .rept count in core/src/jni/thunks.S. constexpr std::size_t kNativeThunkCount = 16384; // What a registered native method runs: a guest function and how to marshal its arguments. struct NativeTarget { std::uint32_t guest_function = 0; // Thumb bit included std::string shorty; // return type first bool is_static = false; }; // Receives every thunk call with the slot number. It reads the arguments from regs and stores // the result in regs.x[0] / regs.d[0]. using NativeDispatcher = void (*)(std::uint32_t slot, NativeRegs& regs); void set_native_dispatcher(NativeDispatcher dispatcher); // Address of a thunk, usable as the fnPtr of RegisterNatives; nullptr when out of range. void* native_thunk_address(std::uint32_t slot); // Assigns thunk slots to native methods. Slots are never freed (UnregisterNatives keeps them), // so target() needs no lock. class NativeSlots { public: // capacity is capped at kNativeThunkCount. explicit NativeSlots(std::size_t capacity = kNativeThunkCount); // The slot number, or -1 when every slot is taken. std::int32_t allocate(NativeTarget target); // The target of an allocated slot, or nullptr. const NativeTarget* target(std::uint32_t slot) const; private: std::size_t capacity_; std::mutex mutex_; std::unique_ptr targets_; std::atomic count_{0}; }; } // namespace zb ``` -------------------------------- ### Build guest probe with build_guest.sh Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-17-phase7a-native-surface.md Builds the guest probe and lists it to confirm the file exists. ```bash tools/build_guest.sh; ls -la build/guest/zbeglprobe ``` -------------------------------- ### Host build and test commands Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-16-phase5-gles.md Commands to configure and build the host environment with CMake and Ninja, then run guest tests and ctest. ```bash cmake -S . -B build/host -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++; ninja -C build/host ``` ```bash tools/build_guest.sh; ctest --test-dir build/host --output-on-failure; tools/run_guest_tests.sh ``` -------------------------------- ### JNI export decoder header (core/include/zb/jni_mangle.h) Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4a-jni-host-units.md Declares the JniExport struct and the decode_jni_export function. The struct holds the class name, method name, and optional argument descriptor. The function returns nullopt for malformed symbols and cannot decode name components starting with '0' through '3' after a separator. ```cpp #pragma once #include #include #include namespace zb { // A native method named by a JNI export symbol "Java__[__]". struct JniExport { std::string class_name; // binary name with slashes, e.g. "org/haxe/lime/Lime" std::string method; // e.g. "onTouch" // Argument part of the descriptor for overloaded exports, e.g. "(IFFIFF)"; no return type. std::optional arguments; }; // Returns nullopt when the symbol is not a well-formed JNI export name. A name component after // a separator cannot be decoded when it starts with '0' through '3', because JNI mangling makes // those spellings indistinguishable from an escape beginning at the separator. std::optional decode_jni_export(std::string_view symbol); } // namespace zb ``` -------------------------------- ### Device loop commands for rebuilding and running the guest Source: https://github.com/zailoxtt/zettabridge/blob/main/AGENTS.md Commands to rebuild the Android ARM64 guest, create a launcher bundle, build the APK, and copy it to the device. The report file path and logcat command are also shown. ```bash ninja -C build/android-arm64 ``` ```bash tools/make_launcher_bundle.sh ``` ```bash cd android/launcher && ANDROID_HOME=$HOME/android-sdk ./gradlew --offline -q assembleRelease ``` ```bash su -c "logcat -b all --pid=$(su -c pidof com.zettabridge.launcher:guest)" ``` -------------------------------- ### load: Load library via guest dlopen Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Copies the path to the scratch buffer, invokes guest dlopen, and returns the handle. Sets an error message on failure, using last_dlerror if the handle is null. ```cpp std::uint32_t load(const Invoke& invoke, std::uint32_t buffer, std::uint32_t size, const std::string& path, std::uint32_t guest_flags, std::string& error) { if (!copy_text(buffer, size, path, error)) return 0; GuestCall args; args.regs = {buffer, guest_flags, 0, 0}; const auto result = invoke(api.dlopen_fn, args); if (!result) { error = "guest dlopen call failed"; return 0; } if (result->r0 == 0) error = last_dlerror(invoke); return result->r0; } ``` -------------------------------- ### Build and run egl_marshal_test (ninja) Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-17-phase7a-native-surface.md Compiles the test target. Expected to fail with 'zb/host_egl.h: No such file' before implementation. ```bash ninja -C build/host egl_marshal_test ``` -------------------------------- ### Run guest tests Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-13-phase1-zbrun-dynarmic.md Builds guest test binaries with the NDK and runs them under zbrun, diffing stdout and exit codes against expected outputs. ```bash tools/build_guest.sh; tools/run_guest_tests.sh ``` -------------------------------- ### zbhost library-mode guest service implementation (C) Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Full C implementation of the zbhost library-mode guest service. It sets the linker target SDK, preloads libzbcompat.so and an optional library with RTLD_GLOBAL, publishes zb_service_api through READY, and serves host requests. Carriers are guest pthreads that park in PARK until a host thread borrows and releases them. Includes _Static_asserts for RTLD flag values and uses SVC instructions for host calls. ```c /* Library-mode guest service. Usage: zbhost [] * Sets the linker target SDK, preloads libzbcompat.so and the optional library with * RTLD_GLOBAL, publishes zb_service_api through READY, and then serves host requests inside * that host call. Carriers are guest pthreads that park in PARK until a host thread has * borrowed and released them. */ #include #include #include #include #include #include "zb/library_protocol.h" _Static_assert(ZB_GUEST_RTLD_NOW == RTLD_NOW, "guest RTLD_NOW"); _Static_assert(ZB_GUEST_RTLD_LAZY == RTLD_LAZY, "guest RTLD_LAZY"); _Static_assert(ZB_GUEST_RTLD_GLOBAL == RTLD_GLOBAL, "guest RTLD_GLOBAL"); _Static_assert(ZB_GUEST_RTLD_NOLOAD == RTLD_NOLOAD, "guest RTLD_NOLOAD"); _Static_assert(ZB_GUEST_RTLD_NODELETE == RTLD_NODELETE, "guest RTLD_NODELETE"); static char scratch[ZB_SERVICE_SCRATCH_SIZE]; static uint32_t host_call(uint32_t index, uint32_t arg) { register uint32_t r0 __asm__("r0") = arg; if (index == ZB_SERVICE_READY_INDEX) { __asm__ volatile("svc #0x5afe00" : "+r"(r0) : : "memory"); } else { __asm__ volatile("svc #0x5afe01" : "+r"(r0) : : "memory"); } return r0; } static uint32_t service_dlopen(const char* path, uint32_t flags) { return (uint32_t)(uintptr_t)dlopen(path, (int)flags); } static uint32_t service_dlsym(uint32_t handle, const char* name) { return (uint32_t)(uintptr_t)dlsym((void*)(uintptr_t)handle, name); } static uint32_t service_dlerror(void) { return (uint32_t)(uintptr_t)dlerror(); } static uint32_t service_malloc(uint32_t size) { return (uint32_t)(uintptr_t)malloc(size); } static void service_free(uint32_t pointer) { free((void*)(uintptr_t)pointer); } static void* carrier_main(void* unused) { (void)unused; while (host_call(ZB_CARRIER_PARK_INDEX, 0) == ZB_SERVICE_AGAIN) { } return NULL; } static uint32_t spawn_carrier(void) { pthread_t thread; const int rc = pthread_create(&thread, NULL, carrier_main, NULL); if (rc == 0) pthread_detach(thread); return (uint32_t)rc; } static int preload(const char* path) { if (dlopen(path, RTLD_NOW | RTLD_GLOBAL) != NULL) return 1; const char* error = dlerror(); fprintf(stderr, "zbhost: cannot preload %s: %s\n", path, error != NULL ? error : "unknown error"); return 0; } int main(int argc, char** argv) { if (argc != 2 && argc != 3) return ZB_HOST_EXIT_USAGE; void* dl_android = dlopen("libdl_android.so", RTLD_NOW); void (*set_target_sdk)(unsigned) = dl_android != NULL ? (void (*)(unsigned))dlsym(dl_android, "android_set_application_target_sdk_version") : NULL; if (set_target_sdk == NULL) return ZB_HOST_EXIT_TARGET_SDK; set_target_sdk((unsigned)strtoul(argv[1], NULL, 10)); if (!preload("libzbcompat.so")) return ZB_HOST_EXIT_PRELOAD; if (argc == 3 && !preload(argv[2])) return ZB_HOST_EXIT_PRELOAD; const struct zb_service_api api = { sizeof(api), ZB_SERVICE_PROTOCOL_VERSION, (uint32_t)(uintptr_t)service_dlopen, (uint32_t)(uintptr_t)service_dlsym, (uint32_t)(uintptr_t)service_dlerror, (uint32_t)(uintptr_t)spawn_carrier, (uint32_t)(uintptr_t)service_malloc, (uint32_t)(uintptr_t)service_free, (uint32_t)(uintptr_t)scratch, sizeof(scratch), }; uint32_t status; do { status = host_call(ZB_SERVICE_READY_INDEX, (uint32_t)(uintptr_t)&api); } while (status == ZB_SERVICE_AGAIN); return (int)status; } ``` -------------------------------- ### Build guest and host tests with ninja Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Shell command to build the guest and then run ninja for the host targets library_runtime_test and zbhost_protocol_test. Expected: guest build succeeds, host build fails because zb/library_runtime.h does not exist and zb_service_api has no malloc_fn. ```sh tools/build_guest.sh; ninja -C build/host library_runtime_test zbhost_protocol_test ``` -------------------------------- ### Full local regression commands Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-17-phase7a-native-surface.md Runs all generation checks, builds the host, runs host tests, builds and runs guest tests, builds Android targets, and creates the launcher bundle. ```bash python3 tools/gen_gles.py --check python3 tools/gen_egl.py --check python3 tools/gen_jni.py --check ninja -C build/host ctest --test-dir build/host --output-on-failure tools/build_guest.sh tools/run_guest_tests.sh ninja -C build/android-arm64 zbridge zbproxy tools/make_launcher_bundle.sh ``` -------------------------------- ### Build native_window_test with ninja Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-17-phase7a-native-surface.md Builds the native_window_test target. Expected to fail with 'zb/host_native_window.h: No such file'. ```bash ninja -C build/host native_window_test ``` -------------------------------- ### Verification commands and results Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/reviews/2026-09-15-phase4d-task5-review.md Shows the build and test commands used to verify the proxy runtime and guest JNI engine, along with their passing results. ```text ninja -C build/host proxy_runtime_test guest_jni_engine_test PASS ctest -R 'proxy_runtime_test|guest_jni_engine_test_' 3/3 PASS proxy_runtime_test repeated 50 times 50/50 PASS ``` -------------------------------- ### Build and test host_call_dispatch_test Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Builds the guest tools, compiles the host test, and runs the host_call_dispatch_test via ctest with output on failure. ```sh tools/build_guest.sh; ninja -C build/host host_call_dispatch_test; ctest --test-dir build/host -R '^host_call_dispatch_test$' --output-on-failure ``` -------------------------------- ### Run RED: build and run host_looper_test Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-17-phase7a-native-surface.md Command to build and run the failing host_looper_test. Expected to fail compilation because zb/host_looper.h does not exist yet. ```bash ninja -C build/host host_looper_test && build/host/tests/host/host_looper_test ``` -------------------------------- ### Build command for host_call_dispatch_test and library_runtime_test Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Builds the host call dispatch test and library runtime test using ninja. Expected to fail because Process::create_borrower, Process::destroy_borrower, and LibraryRuntime::borrow do not exist yet. ```sh ninja -C build/host host_call_dispatch_test library_runtime_test ``` -------------------------------- ### Build and test command Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Run from the repository root of the Phase 4b worktree. Builds guest libraries, compiles the host build, and runs tests with output on failure. ```sh tools/build_guest.sh; ninja -C build/host; ctest --test-dir build/host --output-on-failure ``` -------------------------------- ### hello_static.c - ARM32 guest test program Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-13-phase1-zbrun-dynarmic.md C program that prints a greeting, checks argc/argv, allocates memory, uses mmap, clock_gettime, and getpid. Returns exit code 7. Used to test syscall emulation in zbrun. ```c #include #include #include #include #include #include int main(int argc, char** argv) { printf("hello arm32\n"); printf("argc=%d argv1=%s\n", argc, argc > 1 ? argv[1] : "(none)"); char* big = malloc(1 << 20); memset(big, 0x5a, 1 << 20); printf("malloc=%s\n", big[12345] == 0x5a ? "PASS" : "FAIL"); free(big); void* p = mmap(NULL, 65536, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); printf("mmap=%s\n", p != MAP_FAILED ? "PASS" : "FAIL"); ((char*)p)[65535] = 1; munmap(p, 65536); struct timespec ts; printf("clock=%s\n", clock_gettime(CLOCK_MONOTONIC, &ts) == 0 ? "PASS" : "FAIL"); printf("pid=%s\n", getpid() > 0 ? "PASS" : "FAIL"); return 7; } ``` -------------------------------- ### runtime_options: Build LibraryRuntimeOptions from argv Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Constructs zb::LibraryRuntimeOptions from command-line arguments. Sets sysroot, zbhost, target_sdk to 16, and envp with LD_LIBRARY_PATH derived from argv[3]'s parent path. ```cpp zb::LibraryRuntimeOptions runtime_options(char** argv) { zb::LibraryRuntimeOptions options; options.sysroot = argv[1]; options.zbhost = argv[2]; options.target_sdk = 16; options.envp = {"LD_LIBRARY_PATH=" + std::filesystem::path(argv[3]).parent_path().string()}; return options; } ``` -------------------------------- ### Build script for zbhost (Shell) Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Shell command to compile the zbhost guest binary with the core include path and link against libdl. ```sh "$CC" -O2 -Wall -I"$ROOT/core/include" -o "$OUT/zbhost" \ "$ROOT/guest/zbhost/zbhost.c" -ldl ``` -------------------------------- ### Android build command (Step 7) Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4a-jni-host-units.md Configures and builds the Android ARM64 library to verify linking. Expected output is 'Linking CXX shared library core/libzbridge.so' with no errors. ```bash N=$HOME/android-ndk-r29; cmake -S . -B build/android-arm64 -G Ninja -DCMAKE_TOOLCHAIN_FILE=$N/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-29 -DCMAKE_BUILD_TYPE=Release -DZB_BUILD_TESTS=OFF -DBoost_INCLUDE_DIR=$PWD/build/boost-headers && ninja -C build/android-arm64 zbridge zbrun ``` -------------------------------- ### serve loop for guest thread commands Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-14-phase4b-library-runtime.md Runs the service loop for a guest thread, parking when no commands are pending and returning with ZB_SERVICE_AGAIN when signals are pending or with 1 when the process is exiting. ```cpp void serve(GuestThread& thread) { for (;;) { const std::uint32_t token = thread.park_token(); if (thread.has_pending_signals(thread.sigmask)) { thread.regs()[0] = ZB_SERVICE_AGAIN; return; } std::shared_ptr command; { std::lock_guard lock(mutex); if (!commands.empty()) { command = commands.front(); commands.pop_front(); } } if (!command) { thread.park(token); continue; } command->done.set_value(execute(thread, *command)); if (process.exiting()) { thread.regs()[0] = 1; return; } } } ``` -------------------------------- ### Run full host test suite Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-17-phase7a-native-surface.md Builds and runs all host tests, expecting all to pass including the existing 37. ```bash ninja -C build/host; ctest --test-dir build/host --output-on-failure ``` -------------------------------- ### Build launcher APK and copy to device Source: https://github.com/zailoxtt/zettabridge/blob/main/AGENTS.md Builds the ZettaBridge launcher APK using ninja, a bundle script, and Gradle, then copies the APK to /sdcard/ZettaBridge-debug.apk. Requires ANDROID_HOME and ANDROID_SDK_ROOT set to the Android SDK path. ```shell ninja -C build/android-arm64 zbridge zbproxy; tools/make_launcher_bundle.sh; cd android/launcher; ANDROID_HOME=$HOME/android-sdk ANDROID_SDK_ROOT=$HOME/android-sdk ./gradlew --no-daemon assembleDebug; cd -; cp android/launcher/app/build/outputs/apk/debug/app-debug.apk /sdcard/ZettaBridge-debug.apk ``` -------------------------------- ### Build and run guest probe with removal case (GREEN) Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-17-phase7a-native-surface.md Rebuilds the guest probe and runs the host_looper test, expecting both unit and translated guest modes to pass. ```bash tools/build_guest.sh ctest --test-dir build/host -R host_looper --output-on-failure ``` -------------------------------- ### Commit the changes Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-17-phase7a-native-surface.md Stage and commit the new implementation and test files with a descriptive message. ```bash git add core/src/gl/egl_manual.cpp tests/host/egl_marshal_test.cpp; git commit -m "egl: hand-written cases for config arrays, strings and proc addresses" ``` -------------------------------- ### Build host with CMake and Ninja Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-13-phase1-zbrun-dynarmic.md Configures and builds the host project with CMake and Ninja, then runs the host tests via ctest. Uses clang and clang++ as compilers and RelWithDebInfo build type. ```bash cmake -S . -B build/host -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++; ninja -C build/host; ctest --test-dir build/host --output-on-failure ``` -------------------------------- ### Build and run failing tests Source: https://github.com/zailoxtt/zettabridge/blob/main/docs/superpowers/plans/2026-09-17-phase7a-native-surface.md Run this command to build and execute the egl_marshal_test. Expected to fail with undefined zbegl_manual_eglChooseConfig or wrong values. ```bash ninja -C build/host egl_marshal_test; ctest --test-dir build/host -R egl_marshal_test --output-on-failure ```