httk.workflow.supervision

Structured, argv-only process supervision for native runners.

Every event is dispatched to the in-process monitors and to the executable checkers under one supervisor-wide lock, so a monitor is never entered concurrently with itself or with another monitor, and a checker never receives an interleaved line on its stdin. A monitor therefore does not have to be thread-safe, but it must return quickly: it delays the whole event stream.

Attributes

DEFAULT_TICK_INTERVAL

Seconds between the tick events delivered to monitors and checkers.

DEFAULT_FOLLOW_INTERVAL

Seconds between polls of a followed file that produced no new data.

DEFAULT_CAPTURE_LIMIT

Bytes of a stream retained in the report when no output path is given.

DEFAULT_TAIL_LIMIT

Bytes of a stream retained in the report when an output path is given.

DEFAULT_DIAGNOSTIC_LIMIT

Diagnostics retained in one report before the middle is dropped.

Classes

SourceEvent

One event delivered to an in-process or executable checker.

Diagnostic

A structured observation made while supervising a program.

FollowSource

A file to follow while the child process is running.

CheckerSpec

A versioned executable checker.

ProcessReport

The complete result of one supervised command.

ProcessSupervisor

Run one command, stream its output, and terminate its process group safely.

Module Contents

httk.workflow.supervision.DEFAULT_TICK_INTERVAL = 1.0[source]

Seconds between the tick events delivered to monitors and checkers.

httk.workflow.supervision.DEFAULT_FOLLOW_INTERVAL = 0.25[source]

Seconds between polls of a followed file that produced no new data.

httk.workflow.supervision.DEFAULT_CAPTURE_LIMIT = 4194304[source]

Bytes of a stream retained in the report when no output path is given.

httk.workflow.supervision.DEFAULT_TAIL_LIMIT = 65536[source]

Bytes of a stream retained in the report when an output path is given.

httk.workflow.supervision.DEFAULT_DIAGNOSTIC_LIMIT = 512[source]

Diagnostics retained in one report before the middle is dropped.

class httk.workflow.supervision.SourceEvent[source]

One event delivered to an in-process or executable checker.

event: Literal['start', 'line', 'tick', 'source-eof', 'process-exit'][source]
source: str[source]
line: str | None = None[source]
timestamp: str = ''[source]
as_mapping() dict[str, object][source]
class httk.workflow.supervision.Diagnostic[source]

A structured observation made while supervising a program.

code: str[source]
severity: DiagnosticSeverity[source]
summary: str[source]
source: str[source]
evidence: str | None = None[source]
stop: bool = False[source]
as_mapping() dict[str, object][source]
class httk.workflow.supervision.FollowSource[source]

A file to follow while the child process is running.

path: pathlib.Path[source]
name: str | None = None[source]
inactivity_timeout: float | None = None[source]
class httk.workflow.supervision.CheckerSpec[source]

A versioned executable checker.

argv: tuple[str, Ellipsis][source]
required: bool = True[source]
sources: tuple[FollowSource, Ellipsis] = ()[source]
classmethod from_mapping(value: collections.abc.Mapping[str, object]) CheckerSpec[source]
class httk.workflow.supervision.ProcessReport[source]

The complete result of one supervised command.

stdout and stderr are bounded: when an output path was given they hold at most the run’s tail limit and the file named by stdout_path or stderr_path is authoritative; otherwise they hold at most the run’s capture limit. stdout_bytes and stderr_bytes always count every byte the program produced, and stdout_truncated and stderr_truncated say whether anything was dropped from the retained tail.

argv: tuple[str, Ellipsis][source]
started_at: str[source]
finished_at: str[source]
returncode: int[source]
termination: str[source]
stdout: bytes[source]
stderr: bytes[source]
diagnostics: tuple[Diagnostic, Ellipsis][source]
stdout_path: str | None = None[source]
stderr_path: str | None = None[source]
stdout_bytes: int = 0[source]
stderr_bytes: int = 0[source]
stdout_truncated: bool = False[source]
stderr_truncated: bool = False[source]
dropped_diagnostics: int = 0[source]
property timed_out: bool[source]
as_mapping() dict[str, object][source]
write(path: str | os.PathLike[str]) pathlib.Path[source]
class httk.workflow.supervision.ProcessSupervisor(*, monitors: collections.abc.Sequence[EventMonitor] = (), checkers: collections.abc.Sequence[CheckerSpec] = (), follow: collections.abc.Sequence[FollowSource] = ())[source]

Run one command, stream its output, and terminate its process group safely.

Monitors and checkers observe the same event stream under one lock, so an in-process monitor does not have to be thread-safe. Whatever happens during a run - including an exception raised by the caller’s monitor - the signal handlers are restored, the child’s process group is terminated and reaped, the reader threads are joined, and the output handles are closed before run() returns or propagates.

monitors = ()[source]
checker_specs = ()[source]
follow = ()[source]
run(argv: collections.abc.Sequence[str], *, timeout: float | None = None, cwd: str | os.PathLike[str] | None = None, environment: collections.abc.Mapping[str, str] | None = None, termination_grace: float = 10.0, stdout_path: str | os.PathLike[str] | None = None, stderr_path: str | os.PathLike[str] | None = None, tick_interval: float = DEFAULT_TICK_INTERVAL, follow_interval: float = DEFAULT_FOLLOW_INTERVAL, capture_limit: int = DEFAULT_CAPTURE_LIMIT, tail_limit: int = DEFAULT_TAIL_LIMIT, diagnostic_limit: int = DEFAULT_DIAGNOSTIC_LIMIT) ProcessReport[source]

Run one command to completion and return its structured report.