Expand description
Worker lifecycle + boot orchestration. The pure state machine (state) plus the OS-facing boot
path: config/argv (config), token handshake (token), spawn + pipe drain (launch), the
Windows Job Object kill-guard (job_object), framed TCP transport (conn), and boot/handshake
(boot). Health-driven RESPAWN wiring (re-boot a crashed worker mid-session) is still M1.
Modules§
- boot
- Boot orchestration (spec §4/§5). Host is the TCP server; the worker connects back and proves itself with a token+version init handshake. A racing local process without the token is rejected and the accept loop keeps going until the boot deadline (agy risk note A: a silent stall here is often an EDR/firewall intercept of the unsigned Java process, not a code bug — check that first).
- config
- Worker launch configuration + launcher argv (spec §3/§4). The argv build is a pure function so
it is unit-tested without a Ghidra install. Attach-only (
-process, not-import) because v1 attaches to already-analyzed projects (spec §8.1); writable (NOT-readOnly) since M2a’srenamewrite tool needs DomainFile.save(); the worker.javablocks in its socket loop soanalyzeHeadlessnever returns and the JVM stays resident (spike D1). - conn
- Framed JSON-RPC 2.0 request/response over the worker’s TCP stream (spec §5). One request in flight at a time (the worker services calls single-threaded on the Ghidra thread). Uses the existing ghidra-ipc frame codec (4-byte BE length prefix) and RpcRequest/RpcResponse types.
- job_
object - Re-export shim. The kill-guard moved to the
proc-guardcrate, butcrate::job_object::JobObjectstays a stable path for the worker lifecycle (launch.rs) — on Windows a Job Object withKILL_ON_JOB_CLOSE, on Unix asetsidprocess group, and a no-op stub everywhere else. - launch
- Spawn the headless launcher and shield host stdout (spike D4). Both child pipes are drained on
dedicated threads into the host’s STDERR so ~16 KB of Ghidra log spam per run never contaminates
host stdout (reserved for MCP JSON-RPC, M1). The child is wrapped in a kill-guard (Windows Job
Object or Unix process group) so the whole host->shell->java.exe tree dies with the host.
On targets that are neither (e.g. WASM) the guard is a no-op and that guarantee does not hold:
only the direct child is killed when
WorkerProcessis dropped. - state
- Pure worker-lifecycle state machine (spec §4). No I/O: models the states and the one-shot WORKER_RESTARTED notice so lifecycle decisions are unit-testable without spawning a JVM.
- token
- Connection token for the loopback-TCP transport (spec §5/§6). The host generates a 128-bit token, hands it to the worker out-of-band via a short-lived 0600 file, and verifies the worker echoes it in the init handshake — so another local process that races the ephemeral port is rejected. Not a long-term secret: it exists only for the boot window and the file is deleted right after the handshake (see boot.rs).