Runtime¶
Repository: tidemarksh/runtime
Tidemark Runtime owns browser-side execution orchestration. It is the layer that turns kernel WebAssembly exports into running guest processes by coordinating workers, process handles, filesystem snapshots, stdio, network bridges, and state synchronization.
The runtime is written in TypeScript. The current package metadata identifies
the package as runtime at version 0.0.0.
Design Intent¶
The runtime is deliberately not the Linux semantic authority. It should not decide what a syscall means. Its job is to preserve the kernel's guest-visible state across browser execution boundaries.
Its responsibilities are:
- Instantiate kernel WebAssembly bytes.
- Create and manage the kernel worker.
- Create process owner workers and thread workers.
- Move explicit state snapshots between workers.
- Coordinate process lifecycle, blocking, resume, fork/vfork/execve, and exit events.
- Expose generic filesystem operations and file layer application.
- Bridge stdout, stdin, PTY/pipe modes, and network connections to the host application.
- Provide diagnostics without making diagnostics define production semantics.
Reference Sources¶
Runtime design is grounded in platform APIs and the kernel ABI, not in workload-specific behavior.
| Area | Reference source |
|---|---|
| WebAssembly host integration | WebAssembly specifications and browser WebAssembly APIs |
| Shared memory substrate | SharedArrayBuffer and Atomics |
| Worker execution model | Web Workers API |
| Node-compatible worker execution | Node.js worker_threads |
| Guest semantics | Kernel WebAssembly ABI and kernel tests |
The runtime can use workload failures to locate orchestration bugs, but generic runtime behavior should not branch on package manager names, language runtime names, URL shapes, or registry behavior.
Execution Model¶
The runtime has three main execution roles:
flowchart TB
API["Runtime API"]
KernelWorker["kernel worker<br/>canonical runtime-facing state"]
ProcessOwner["process owner worker<br/>lifecycle and scheduling"]
ThreadWorker["thread worker<br/>guest execution step loop"]
Host["host bridges<br/>stdio, network, file operations"]
Kernel["kernel wasm exports"]
API --> KernelWorker
API --> ProcessOwner
API --> Host
ProcessOwner <--> KernelWorker
ProcessOwner <--> ThreadWorker
ThreadWorker <--> Kernel
KernelWorker <--> Kernel
ProcessOwner <--> Host
This topology exists because guest programs expect process, fd/OFD, pipe, socket, filesystem, and signal state to remain coherent even though the browser isolates execution across workers and asynchronous host events.
State Synchronization Philosophy¶
Runtime state movement is explicit. The runtime message contracts include kernel state, fd snapshots, OFD snapshots, pipe slots, socket state, child-exit records, guest memory writes, and blocking/resume hints.
That is intentional. The runtime should make ownership transitions visible rather than hide them behind broad global mutation.
Examples of runtime-owned coordination:
- parent/child process lifecycle,
- selected process ownership,
- fork and vfork/execve ordering,
- worker-local wait and resume,
- fd/OFD and pipe state sync,
- runtime filesystem snapshot publication,
- network bridge connection lifecycle.
Threaded Guest Workloads¶
Thread workers are not only an implementation detail for parallel JavaScript execution. They are the runtime mechanism that maps guest thread execution onto browser or Node worker infrastructure while keeping shared process memory and kernel-visible state coherent.
Each thread worker executes a guest thread step loop against the process memory prepared by the process owner. When execution stops, the thread worker returns structured state: status, registers, syscall details, fd/OFD snapshots, pipe slots, socket state, memory writes, child-exit records, and sync effects. The process owner uses that state to continue, block, resume, synchronize with the kernel worker, or publish lifecycle changes.
This is the substrate needed by threaded Linux userland workloads such as language runtimes, compiler drivers, build tools, thread pools, futex waits, and signal-aware runtimes. Those workloads exercise the same generic runtime design; the runtime should not contain language-specific threading logic.
Test Strategy¶
Runtime tests are organized by what they verify, not by helper language or file location.
The current test structure has three major families:
- generic runtime invariants and ownership boundaries,
- language, runtime, and toolchain workload checks,
- shared harness code for workload and snapshot tests.
Current runtime invariant tests cover:
- public Runtime and Process API behavior,
- bridge and runtime-state behavior,
- filesystem and page-cache synchronization,
- kernel-worker lifecycle and primitive state,
- thread-worker execution, blocking, session, signal, and sync-effect behavior,
- worker lifecycle, scheduler, status handling, stdio, process identity, kernel RPC, fork, execve, and ownership transitions.
Current workload tests cover broad guest behavior across shells, dynamic startup, script runtimes, package module drivers, toolchains, large file I/O, network streams, and language/runtime-specific startup or toolchain execution.
flowchart TB
RuntimeTests["generic invariants"]
Workloads["guest workload checks"]
Support["shared harnesses"]
Runtime["runtime implementation"]
Kernel["kernel wasm"]
GuestFiles["external guest files"]
Runtime --> RuntimeTests
Runtime --> Workloads
Kernel --> RuntimeTests
Kernel --> Workloads
GuestFiles --> Workloads
Support --> RuntimeTests
Support --> Workloads
The invariant tests should lead. Workload tests are valuable, but they should confirm behavior after the relevant runtime ownership or synchronization gate is understood.