docs(mojo): STATUS BLOCKED on single-file binaries

Builds for linux-arm64 and passes the shared suite locally (host and
qemu), but every Mojo binary needs libKGENCompilerRTShared.so and
Carloku's binary kind takes one file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Paul Campbell pushed by claude agent, operated by paul@keymail.dev cff9f8c97daf75f5f6112c67b0a9ba89ae241a47 parent 5de4c9d
1 file changed, +57 −0
  • apps/mojo/STATUS.md +57 −0
diff --git a/apps/mojo/STATUS.md b/apps/mojo/STATUS.md
new file mode 100644
index 0000000..b8cb175
--- /dev/null
+++ b/apps/mojo/STATUS.md
@@ -0,0 +1,57 @@
+BLOCKED platform: single-file binaries only (Mojo needs libKGENCompilerRTShared.so)
+
+## Where it got stuck
+
+The app is finished and tested; it can't be shipped as Carloku's binary
+kind, which takes a single file (`carlos deploy --target`: "binary kind,
+single file").
+
+What works, at commit `a874c81` (2026-10-23):
+
+- `make test`: 19 unit tests plus a process-level smoke test (unix
+ socket, keep-alive, cookie round trip, clean exit on SIGTERM) pass.
+- Shared behaviour suite against the host build
+ (`dist/app --listen 127.0.0.1:39517`): **67 passed, 3 skipped**, the
+ same as the reference fixture.
+- `make build-arm64` produces `dist/app-linux-arm64` inside the arm64
+ root (about 45 s for the app once SQLite is compiled; SQLite itself
+ takes about 15 minutes emulated, once).
+- The shared suite against that arm64 binary under qemu: **67 passed,
+ 3 skipped**. `scripts/boot-check.sh dist/app-linux-arm64`: `/healthz`
+ 200, `/api/version` 200 `a874c81`, clean exit on SIGTERM.
+
+Why it isn't deployed:
+
+- `readelf -d dist/app-linux-arm64` shows `NEEDED
+ libKGENCompilerRTShared.so` (besides `libc.so.6`) and `RUNPATH
+ /root/.pixi/envs/mojo/lib`. That library in turn needs `libstdc++`,
+ `libMSupportGlobals.so` and `libAsyncRTRuntimeGlobals.so`. Boot-check
+ and the qemu run only pass because `qemu-aarch64-static -L <arm64 root>`
+ finds them in the root's pixi install; a Carloku instance sees only its
+ own build.
+- I looked for a supported static route and found none: Mojo 1.2.0 ships
+ no static archive of its runtime (no `libKGEN*.a` in either the x86 or
+ the arm64 pixi env, only the `.so`), and `mojo build` has no static or
+ standalone option (`--emit` offers `exe`, `object`, `shared-lib` and
+ IR formats; `--help-hidden` adds nothing for linking the runtime). The
+ runtime also starts 16 worker threads before `main`, so even
+ `--emit object` output depends on it.
+- As the brief says, I didn't bundle, embed or self-extract the
+ libraries to get around the single-file rule, and I didn't create the
+ Carloku app or instance, since nothing could be deployed to it.
+
+What would unblock it: either Carloku's binary kind accepting a binary
+plus its shared libraries (a directory or archive release), or Modular
+shipping a static `libKGENCompilerRTShared` (and its dependencies). With
+either, `make build-arm64 && make deploy` after the three first-time
+`carlos` commands in BRIEF.md should be all that's left.
+
+Notes for the report:
+
+- SIGTERM: the Mojo runtime installs its own SIGTERM handler, which ends
+ the process with status 143, and its threads exist before `main`, so a
+ signal mask or `signalfd` can't catch it. The app installs a C-ABI
+ handler that writes to a pipe its poll loop watches (`src/libc.mojo`).
+- Mojo's standard library has no sockets or SQLite binding, so both go
+ through `external_call` to libc and to SQLite compiled from the
+ amalgamation.