Skip to main content

Module driver

Module driver 

Source
Expand description

@arch:layer(kg_store) @arch:role(substrate) @arch:see(.yah/docs/working/yah-task-runs.md)

PTY subprocess driver — spawn commands, capture output as append-only chunks, handle SIGTERM/SIGKILL with a grace period, and mark stale Running runs as Lost when the daemon restarts.

§Tier 2 side-channel (yah-log shims)

When SpawnOpts::log_fd_enabled is true (the default), the driver creates a named pipe (FIFO) and exports two env vars into the child:

  • YAH_TASK_RUN — the TaskRunId as a hyphenated UUID string.
  • YAH_LOG_PIPE — absolute path to the FIFO.

The child opens YAH_LOG_PIPE for writing and emits JSON-lines. The driver reads those lines in a background thread and stores them as [EventSource::Shim] events.

Why FIFO instead of a raw fd? portable-pty calls close_random_fds() in its pre_exec hook, closing every fd ≥ 3 before exec. A raw-pipe write fd is always ≥ 3 and would be closed before the child could use it. Opening a FIFO by path requires no fd inheritance.

Wire format — one JSON object per line:

{"level":"info","target":"myapp::module","msg":"text","fields":{"key":"val"}}

Optional shim-identity keys: "_lib" (string), "_lib_ver" (string). Unknown keys in fields pass through as freeform JSON.

The driver holds the write end of the FIFO open until the run lifecycle task completes, which triggers EOF for the receiver thread. The FIFO file is deleted after the receiver thread drains the last line.

On non-Unix platforms YAH_TASK_RUN and YAH_LOG_PIPE are not exported. Shim libraries must treat absent YAH_TASK_RUN as “not inside a TaskRun”.

@yah:ticket(R617-F6, “Reattach-by-run_id replaces Lost-on-disappear for origin=terminal shells”) @yah:at(2026-07-20T18:38:27Z) @yah:status(open) @yah:phase(P3) @yah:parent(R617) @yah:next(“TaskDriver::new (driver.rs:199) marks every leftover Running run Lost on construction — correct for ordinary jobs, fatal for a shell meant to survive a restart. Split the behaviour on origin: a terminal shell whose host process is still alive is re-adopted (control channel rebuilt, reader thread restarted against the surviving PTY) rather than tombstoned.”) @yah:verify(“Manual: open a shell, run sleep 300, quit and relaunch the desktop — the run is still Running, not Lost”) @yah:gotcha(“This is an oss/qed crate — changes land in-tree under oss/task-runs and flow outward via scripts/export-oss.sh. Keep the reattach seam generic (origin-agnostic policy hook), not yah-terminal-specific, since the crate ships standalone.”) @yah:gotcha(“Reattach only makes sense once the PTY outlives the desktop (S5 decides the host). Landing it before that gives a reattach path with nothing to reattach to.”) @arch:see(.yah/docs/working/W280-durable-terminal-sessions.md) @yah:depends_on(R617-S5)

@yah:ticket(R617-B9, “Pre-existing: task-runs log_pipe_events_land_in_store never completes (233 pass / 1 fail)”) @yah:at(2026-07-20T21:19:08Z) @yah:status(open) @yah:phase(P1) @yah:parent(R617) @yah:next(“The run never reaches Done/Lost within the 20s deadline, so the FIFO assertions are never reached. Child writes one JSON line via printf ... >> \"$YAH_LOG_PIPE\"; suspect the child blocks or the lifecycle never observes its exit. mkfifo itself works on this machine.”) @yah:verify(“cd oss/qed && cargo test -p task-runs –lib log_pipe_events_land_in_store”) @yah:gotcha(“Confirmed pre-existing during R617-B1, not caused by the DriverChannels output tap: swapping driver.rs + lib.rs to their HEAD versions reproduces the identical failure. Anyone touching this file (R617-F6 lands here) will meet a red suite that is not theirs.”)

Structs§

DriverChannels
Optional side-channels a driver can publish to. Both are fire-and-forget: a closed receiver never stalls or fails a run.
SpawnOpts
Options for TaskDriver::spawn_run.
TaskDriver
Manages in-flight task runs for a single camp.

Enums§

DriverError