@orkestrel/process 0.0.7 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -267,6 +267,10 @@ export declare const PROCESS_TIMER = 2147483647;
267
267
  * backlog, a byte-bounded stderr tail, a live stderr event, a writable stdin channel, a typed
268
268
  * lifecycle {@link ProcessEventMap} emitter, and bounded termination. The low-level streaming
269
269
  * primitive.
270
+ * - **{@link SessionInterface}** — the same supervised child observed as raw bytes: an owned
271
+ * `Uint8Array` per stdout chunk, an open stdin channel closed by `end` rather than by a switch,
272
+ * the child's own `ending` beside the terminal `exit`, and a typed {@link SessionEventMap}
273
+ * emitter. The transport primitive, for a child speaking a framed protocol.
270
274
  * - **{@link ExecuteResult} / execute** — a one-shot spawn that buffers a child to completion and settles
271
275
  * with its output and exit, the ergonomic layer for fire-and-collect commands.
272
276
  * - **{@link ProcessManagerInterface}** — a keyed registry of live {@link ProcessInterface}
@@ -699,6 +703,241 @@ export declare interface ProcessOptions {
699
703
  readonly signal?: AbortSignal;
700
704
  }
701
705
 
706
+ /**
707
+ * The push observation surface of a {@link SessionInterface} — the moments a byte-oriented observer
708
+ * subscribes to, alongside the `ending` and `exit` promises.
709
+ *
710
+ * @remarks
711
+ * Declared as a `type` alias so it satisfies the emitter's `EventMap` constraint structurally.
712
+ *
713
+ * `stdout` carries one owned `Uint8Array` per chunk the host delivered, in arrival order, framed by
714
+ * nothing and decoded by nothing. The array is the session's own copy and a plain `Uint8Array`
715
+ * rather than the host buffer the read produced, so a consumer keeps it, mutates it, concatenates
716
+ * it, and reads its whole backing buffer without reaching memory the host still manages and without
717
+ * depending on a host type. A chunk boundary is the host's, so one event is not one message and a
718
+ * line feed inside a payload starts no new event; a consumer that needs messages frames the
719
+ * concatenated bytes itself.
720
+ *
721
+ * `stderr` carries decoded text instead, because a diagnostic stream is read rather than parsed, and
722
+ * {@link SessionInterface.evidence} bounds those same bytes. The `error` event carries a child fault
723
+ * — a failure to spawn, a process-level error, or a host-reported standard-input channel fault. A
724
+ * surfaced standard-input fault is wrapped in a {@link ProcessError} coded `protocol` with the host
725
+ * fault as its cause. The event is distinct from the `error` handler in {@link SessionOptions}: a
726
+ * listener throw is isolated by the emitter and routed to that handler, never emitted as this
727
+ * `error` event.
728
+ */
729
+ export declare type SessionEventMap = {
730
+ /** A standard-output chunk arrived, as an owned `Uint8Array` the consumer may keep and mutate. */
731
+ readonly stdout: readonly [chunk: Uint8Array];
732
+ /** A decoded standard-error chunk arrived. */
733
+ readonly stderr: readonly [chunk: string];
734
+ /** The child or its open standard-input channel reported a fault, carrying the host cause directly or through a `protocol` {@link ProcessError}. */
735
+ readonly error: readonly [error: unknown];
736
+ /** The child settled — its terminal state, delivered once. */
737
+ readonly exit: readonly [exit: ProcessExit];
738
+ };
739
+
740
+ /**
741
+ * One supervised child process read as raw bytes, with an open standard-input channel and bounded
742
+ * termination.
743
+ *
744
+ * @remarks
745
+ * A session is the transport face of the same supervision {@link ProcessInterface} exposes. It
746
+ * publishes the child's standard output as `stdout` events carrying owned bytes rather than framed
747
+ * lines, so a consumer speaking a length-prefixed or delimiter-framed protocol reads the bytes the
748
+ * child wrote and frames them itself. Nothing here retains output: a session holds no backlog and
749
+ * pauses nothing, so it omits `lines`, `truncated`, `backlog`, and `send` rather than reporting them
750
+ * as facts that do not apply. `evidence` is the decoded, byte-bounded stderr tail — the diagnostic to
751
+ * attach to a failed exit — and the typed `emitter` carries the live `stdout` and `stderr` payloads,
752
+ * the child `error` cause, and the terminal `exit`.
753
+ *
754
+ * **Two endings, named apart.** `ending` settles at the child's own native exit and resolves no
755
+ * value, because `code` and `signal` already carry the terminal facts as soon as the host records
756
+ * them. `exit` settles at the terminal moment, which is the native exit plus at most `drain` when a
757
+ * descendant that inherited the child's stdio still holds the read ends open. A caller racing a
758
+ * cooperative shutdown window therefore awaits `ending`, and a caller collecting the final
759
+ * observation awaits `exit`. `settled`, the `exit` event, and `evidence` freezing all name that same
760
+ * terminal moment, exactly as they do on {@link ProcessInterface}.
761
+ *
762
+ * **`end` is not a termination.** It closes the standard-input channel and leaves the child running,
763
+ * which is how a cooperative protocol asks a child to finish its own work. `stop` and `destroy` are
764
+ * the terminations, they are idempotent, and none of the three rejects.
765
+ *
766
+ * The spawn is eager, so `pid` is fixed by the time construction returns; a spawn that produced no
767
+ * child reports `undefined` for that child's whole lifetime. An assigned id survives the exit and
768
+ * reports no liveness on its own, because the host reuses a dead child's id. Derive liveness as
769
+ * `pid !== undefined && code === null && signal === null`, and derive it again before every use of
770
+ * the id.
771
+ */
772
+ export declare interface SessionInterface {
773
+ /** The host process id, fixed when construction returns, or `undefined` when the spawn produced none. */
774
+ readonly pid: number | undefined;
775
+ /** The exit code the host recorded, or `null` while the child has not exited and when a signal ended it. A spawn fault reports the host's negative errno. */
776
+ readonly code: number | null;
777
+ /** The terminating signal name the host recorded, or `null` while the child has not exited and when it exited on its own. */
778
+ readonly signal: string | null;
779
+ /** The typed lifecycle observation surface. */
780
+ readonly emitter: EmitterInterface<SessionEventMap>;
781
+ /**
782
+ * The decoded byte-bounded stderr tail.
783
+ *
784
+ * @remarks
785
+ * The live tail before the terminal moment and the frozen value after it, on every path — a
786
+ * natural exit, `stop`, `destroy`, an abort of the `signal` option, and a spawn fault. Every read
787
+ * after that moment returns the same string. When {@link ProcessExit.drained} is false the frozen
788
+ * value is the tail as of the cutoff, and later diagnostics may have existed.
789
+ */
790
+ readonly evidence: string;
791
+ /**
792
+ * True after the `exit` promise settled.
793
+ *
794
+ * @remarks
795
+ * The terminal moment has arrived: `evidence` is frozen, no further `stdout` or `stderr` event
796
+ * fires, and the {@link ProcessExit} value exists. Reached on every path, including a spawn that
797
+ * produced no child.
798
+ */
799
+ readonly settled: boolean;
800
+ /**
801
+ * True after a termination began.
802
+ *
803
+ * @remarks
804
+ * Monotonic. It turns true when `stop`, `destroy`, or an abort of the `signal` option begins a
805
+ * termination, and it stays true from then on, including after `settled` turns true. `end` never
806
+ * turns it true, because closing the input channel terminates nothing. A child that exited on its
807
+ * own reports `false` here with `settled` true.
808
+ */
809
+ readonly stopping: boolean;
810
+ /**
811
+ * The child's own ending, awaited without the terminal moment's drain window.
812
+ *
813
+ * @remarks
814
+ * Never rejects, and resolves no value: `code` and `signal` carry the terminal facts as soon as
815
+ * the host records them, so a second copy of those facts here could only drift from them. It
816
+ * settles at the native exit, and at the terminal moment for a spawn that produced no native exit
817
+ * at all, so it can never outlive the supervision. Await this rather than `exit` when a
818
+ * cooperative shutdown window is racing the child's own exit: `exit` waits out `drain` for a
819
+ * descendant holding the pipe, and a caller racing that promise escalates against a child that
820
+ * already ended.
821
+ */
822
+ readonly ending: Promise<void>;
823
+ /**
824
+ * The terminal child state, delivered once.
825
+ *
826
+ * @remarks
827
+ * Never rejects. It settles at the terminal moment: when the child's streams close, or when the
828
+ * `drain` bound elapsed first. The native exit arms that bound as well as an initiated
829
+ * termination, so a child nobody terminates still settles it within `drain` of ending.
830
+ */
831
+ readonly exit: Promise<ProcessExit>;
832
+ /**
833
+ * Write raw bytes to the open standard-input channel.
834
+ *
835
+ * @remarks
836
+ * Never rejects, and adds no framing: the bytes reach the child exactly as given, with no
837
+ * terminator appended, so a caller speaking a framed protocol composes its own header and
838
+ * delimiter. `true` means the host accepted the bytes without reporting a fault; it does not
839
+ * prove that the child read them. An ordinary write settles when the kernel accepts it, and only
840
+ * a full pipe can hold one unconfirmed, which the `delivery` option bounds.
841
+ *
842
+ * It resolves `false` without throwing when the channel was closed by `end`, destroyed by a
843
+ * termination, failed, or left the write unconfirmed through `delivery`, and when `stop` or
844
+ * `destroy` has begun, because teardown cannot confirm delivery for bytes it is about to discard.
845
+ *
846
+ * The host can queue the payload, so treat the array as owned by the channel until the returned
847
+ * promise settles: bytes mutated inside that window are the bytes the child receives.
848
+ *
849
+ * @param bytes - The payload to write, already framed by the caller
850
+ * @returns True when the host accepted the bytes without reporting a fault; false when the channel was closed, destroyed, ended, failed, or remained unconfirmed through `delivery`
851
+ */
852
+ write(bytes: Uint8Array): Promise<boolean>;
853
+ /**
854
+ * Close the standard-input channel and leave the child running.
855
+ *
856
+ * @remarks
857
+ * Never rejects, and terminates nothing: `stopping` stays false, no signal is sent, no drain
858
+ * window is armed, and the terminal moment does not arrive. The child observes end of input, which
859
+ * is how a cooperative protocol asks it to finish and exit on its own; await `ending` for that
860
+ * exit and `stop` when it does not come.
861
+ *
862
+ * Every call shares one barrier, and it resolves after the host flushes the writes it had already
863
+ * accepted. That flush carries no bound of its own: a child that stops reading its input leaves
864
+ * the accepted bytes in the pipe, and the barrier stays pending for as long as they sit there. A
865
+ * caller that needs a bound races this promise against a window of its own rather than awaiting it
866
+ * bare. A `write` after this call resolves `false`, because the channel is no longer writable.
867
+ * The closed channel then stays quiet for its remaining life: a later host fault on it settles
868
+ * pending writes and emits no `error` event. After `stop` or `destroy` has begun the call resolves
869
+ * and changes nothing.
870
+ *
871
+ * @returns The stable barrier shared by every call
872
+ */
873
+ end(): Promise<void>;
874
+ /**
875
+ * Terminate the child process tree, await its observed exit, and reach the terminal moment.
876
+ *
877
+ * @remarks
878
+ * Never rejects. On Windows the whole tree is killed immediately through `taskkill`, with a
879
+ * direct kill as the fallback; on a POSIX host the process group receives `SIGTERM`, then
880
+ * `SIGKILL` after `grace`. No signal is initiated after the child's native exit is observed.
881
+ *
882
+ * Observation ends here as well as under `destroy`, bounded by `drain`: `evidence` freezes, the
883
+ * `stdout` and `stderr` events stop, and `exit` settles. A caller that stops a child and keeps
884
+ * listening therefore reaches the end of the stream and needs no second call to release it.
885
+ *
886
+ * @returns True when the child's native exit was observed; false when the confirmation deadline elapsed without it
887
+ */
888
+ stop(): Promise<boolean>;
889
+ /**
890
+ * Stop the child, close its standard-input channel, reach the terminal moment, and destroy the
891
+ * observation emitter.
892
+ *
893
+ * @remarks
894
+ * Always resolves, including when termination was never confirmed. The barrier settles after the
895
+ * terminal moment, so `evidence` is frozen and `exit` has settled by the time a caller resumes.
896
+ * The wait for the child's streams is bounded by `drain`, so a descendant holding an inherited
897
+ * pipe cannot hold this barrier open, and {@link ProcessExit.drained} reports which way the moment
898
+ * arrived. The emitter is destroyed after the frozen state exists, so a consumer watching the
899
+ * `stderr` event and a consumer reading `evidence` end on the same bytes.
900
+ *
901
+ * @returns The stable barrier shared by every call
902
+ */
903
+ destroy(): Promise<void>;
904
+ }
905
+
906
+ /**
907
+ * Construction options for one raw byte session over a supervised child.
908
+ *
909
+ * @remarks
910
+ * This is {@link ProcessOptions} without `backlog` and without `writable`. A session frames nothing
911
+ * and retains no lines, so no backlog bound applies to it; its standard-input channel is open from
912
+ * the spawn until {@link SessionInterface.end}, so no switch selects whether one exists. `grace`,
913
+ * `drain`, `evidence`, `delivery`, and `signal` carry the meanings {@link ProcessOptions} documents
914
+ * for them, and `command.input` is still written immediately after the spawn. `on` installs initial
915
+ * {@link SessionEventMap} listeners and `error` receives isolated listener failures.
916
+ *
917
+ * Every option and command property is read once, before the child is spawned, so a caller's own
918
+ * getter runs while nothing has started and a getter that throws strands no process. Every numeric
919
+ * option is validated in that same window: a timer value outside `[0, PROCESS_TIMER]`, or a negative
920
+ * or fractional byte value, throws a {@link ProcessError} coded `invalid` before anything is
921
+ * spawned.
922
+ */
923
+ export declare interface SessionOptions {
924
+ readonly on?: EmitterHooks<SessionEventMap>;
925
+ readonly error?: EmitterErrorHandler;
926
+ readonly command: ProcessCommand;
927
+ /** The working directory the child runs in. */
928
+ readonly workspace: string;
929
+ /** Cooperative POSIX window in milliseconds between `SIGTERM` and `SIGKILL`. Default: {@link PROCESS_GRACE}. */
930
+ readonly grace?: number;
931
+ /** Milliseconds the package waits for the child's read ends to close after the native exit or an initiated termination, before cutting them off; `0` cuts them off as soon as the bound is armed. Default: {@link PROCESS_DRAIN}. */
932
+ readonly drain?: number;
933
+ /** Maximum retained stderr tail in bytes. Default: {@link PROCESS_EVIDENCE}. */
934
+ readonly evidence?: number;
935
+ /** Milliseconds an unconfirmed {@link SessionInterface.write} waits before resolving `false`. `0` or omitted disables the bound. */
936
+ readonly delivery?: number;
937
+ /** Aborting this signal terminates the child through the same bounded `stop`. */
938
+ readonly signal?: AbortSignal;
939
+ }
940
+
702
941
  /**
703
942
  * The resolved spawn form of one command: the executable to launch, the argument vector to pass,
704
943
  * and whether the host receives that vector verbatim.
@@ -267,6 +267,10 @@ export declare const PROCESS_TIMER = 2147483647;
267
267
  * backlog, a byte-bounded stderr tail, a live stderr event, a writable stdin channel, a typed
268
268
  * lifecycle {@link ProcessEventMap} emitter, and bounded termination. The low-level streaming
269
269
  * primitive.
270
+ * - **{@link SessionInterface}** — the same supervised child observed as raw bytes: an owned
271
+ * `Uint8Array` per stdout chunk, an open stdin channel closed by `end` rather than by a switch,
272
+ * the child's own `ending` beside the terminal `exit`, and a typed {@link SessionEventMap}
273
+ * emitter. The transport primitive, for a child speaking a framed protocol.
270
274
  * - **{@link ExecuteResult} / execute** — a one-shot spawn that buffers a child to completion and settles
271
275
  * with its output and exit, the ergonomic layer for fire-and-collect commands.
272
276
  * - **{@link ProcessManagerInterface}** — a keyed registry of live {@link ProcessInterface}
@@ -699,6 +703,241 @@ export declare interface ProcessOptions {
699
703
  readonly signal?: AbortSignal;
700
704
  }
701
705
 
706
+ /**
707
+ * The push observation surface of a {@link SessionInterface} — the moments a byte-oriented observer
708
+ * subscribes to, alongside the `ending` and `exit` promises.
709
+ *
710
+ * @remarks
711
+ * Declared as a `type` alias so it satisfies the emitter's `EventMap` constraint structurally.
712
+ *
713
+ * `stdout` carries one owned `Uint8Array` per chunk the host delivered, in arrival order, framed by
714
+ * nothing and decoded by nothing. The array is the session's own copy and a plain `Uint8Array`
715
+ * rather than the host buffer the read produced, so a consumer keeps it, mutates it, concatenates
716
+ * it, and reads its whole backing buffer without reaching memory the host still manages and without
717
+ * depending on a host type. A chunk boundary is the host's, so one event is not one message and a
718
+ * line feed inside a payload starts no new event; a consumer that needs messages frames the
719
+ * concatenated bytes itself.
720
+ *
721
+ * `stderr` carries decoded text instead, because a diagnostic stream is read rather than parsed, and
722
+ * {@link SessionInterface.evidence} bounds those same bytes. The `error` event carries a child fault
723
+ * — a failure to spawn, a process-level error, or a host-reported standard-input channel fault. A
724
+ * surfaced standard-input fault is wrapped in a {@link ProcessError} coded `protocol` with the host
725
+ * fault as its cause. The event is distinct from the `error` handler in {@link SessionOptions}: a
726
+ * listener throw is isolated by the emitter and routed to that handler, never emitted as this
727
+ * `error` event.
728
+ */
729
+ export declare type SessionEventMap = {
730
+ /** A standard-output chunk arrived, as an owned `Uint8Array` the consumer may keep and mutate. */
731
+ readonly stdout: readonly [chunk: Uint8Array];
732
+ /** A decoded standard-error chunk arrived. */
733
+ readonly stderr: readonly [chunk: string];
734
+ /** The child or its open standard-input channel reported a fault, carrying the host cause directly or through a `protocol` {@link ProcessError}. */
735
+ readonly error: readonly [error: unknown];
736
+ /** The child settled — its terminal state, delivered once. */
737
+ readonly exit: readonly [exit: ProcessExit];
738
+ };
739
+
740
+ /**
741
+ * One supervised child process read as raw bytes, with an open standard-input channel and bounded
742
+ * termination.
743
+ *
744
+ * @remarks
745
+ * A session is the transport face of the same supervision {@link ProcessInterface} exposes. It
746
+ * publishes the child's standard output as `stdout` events carrying owned bytes rather than framed
747
+ * lines, so a consumer speaking a length-prefixed or delimiter-framed protocol reads the bytes the
748
+ * child wrote and frames them itself. Nothing here retains output: a session holds no backlog and
749
+ * pauses nothing, so it omits `lines`, `truncated`, `backlog`, and `send` rather than reporting them
750
+ * as facts that do not apply. `evidence` is the decoded, byte-bounded stderr tail — the diagnostic to
751
+ * attach to a failed exit — and the typed `emitter` carries the live `stdout` and `stderr` payloads,
752
+ * the child `error` cause, and the terminal `exit`.
753
+ *
754
+ * **Two endings, named apart.** `ending` settles at the child's own native exit and resolves no
755
+ * value, because `code` and `signal` already carry the terminal facts as soon as the host records
756
+ * them. `exit` settles at the terminal moment, which is the native exit plus at most `drain` when a
757
+ * descendant that inherited the child's stdio still holds the read ends open. A caller racing a
758
+ * cooperative shutdown window therefore awaits `ending`, and a caller collecting the final
759
+ * observation awaits `exit`. `settled`, the `exit` event, and `evidence` freezing all name that same
760
+ * terminal moment, exactly as they do on {@link ProcessInterface}.
761
+ *
762
+ * **`end` is not a termination.** It closes the standard-input channel and leaves the child running,
763
+ * which is how a cooperative protocol asks a child to finish its own work. `stop` and `destroy` are
764
+ * the terminations, they are idempotent, and none of the three rejects.
765
+ *
766
+ * The spawn is eager, so `pid` is fixed by the time construction returns; a spawn that produced no
767
+ * child reports `undefined` for that child's whole lifetime. An assigned id survives the exit and
768
+ * reports no liveness on its own, because the host reuses a dead child's id. Derive liveness as
769
+ * `pid !== undefined && code === null && signal === null`, and derive it again before every use of
770
+ * the id.
771
+ */
772
+ export declare interface SessionInterface {
773
+ /** The host process id, fixed when construction returns, or `undefined` when the spawn produced none. */
774
+ readonly pid: number | undefined;
775
+ /** The exit code the host recorded, or `null` while the child has not exited and when a signal ended it. A spawn fault reports the host's negative errno. */
776
+ readonly code: number | null;
777
+ /** The terminating signal name the host recorded, or `null` while the child has not exited and when it exited on its own. */
778
+ readonly signal: string | null;
779
+ /** The typed lifecycle observation surface. */
780
+ readonly emitter: EmitterInterface<SessionEventMap>;
781
+ /**
782
+ * The decoded byte-bounded stderr tail.
783
+ *
784
+ * @remarks
785
+ * The live tail before the terminal moment and the frozen value after it, on every path — a
786
+ * natural exit, `stop`, `destroy`, an abort of the `signal` option, and a spawn fault. Every read
787
+ * after that moment returns the same string. When {@link ProcessExit.drained} is false the frozen
788
+ * value is the tail as of the cutoff, and later diagnostics may have existed.
789
+ */
790
+ readonly evidence: string;
791
+ /**
792
+ * True after the `exit` promise settled.
793
+ *
794
+ * @remarks
795
+ * The terminal moment has arrived: `evidence` is frozen, no further `stdout` or `stderr` event
796
+ * fires, and the {@link ProcessExit} value exists. Reached on every path, including a spawn that
797
+ * produced no child.
798
+ */
799
+ readonly settled: boolean;
800
+ /**
801
+ * True after a termination began.
802
+ *
803
+ * @remarks
804
+ * Monotonic. It turns true when `stop`, `destroy`, or an abort of the `signal` option begins a
805
+ * termination, and it stays true from then on, including after `settled` turns true. `end` never
806
+ * turns it true, because closing the input channel terminates nothing. A child that exited on its
807
+ * own reports `false` here with `settled` true.
808
+ */
809
+ readonly stopping: boolean;
810
+ /**
811
+ * The child's own ending, awaited without the terminal moment's drain window.
812
+ *
813
+ * @remarks
814
+ * Never rejects, and resolves no value: `code` and `signal` carry the terminal facts as soon as
815
+ * the host records them, so a second copy of those facts here could only drift from them. It
816
+ * settles at the native exit, and at the terminal moment for a spawn that produced no native exit
817
+ * at all, so it can never outlive the supervision. Await this rather than `exit` when a
818
+ * cooperative shutdown window is racing the child's own exit: `exit` waits out `drain` for a
819
+ * descendant holding the pipe, and a caller racing that promise escalates against a child that
820
+ * already ended.
821
+ */
822
+ readonly ending: Promise<void>;
823
+ /**
824
+ * The terminal child state, delivered once.
825
+ *
826
+ * @remarks
827
+ * Never rejects. It settles at the terminal moment: when the child's streams close, or when the
828
+ * `drain` bound elapsed first. The native exit arms that bound as well as an initiated
829
+ * termination, so a child nobody terminates still settles it within `drain` of ending.
830
+ */
831
+ readonly exit: Promise<ProcessExit>;
832
+ /**
833
+ * Write raw bytes to the open standard-input channel.
834
+ *
835
+ * @remarks
836
+ * Never rejects, and adds no framing: the bytes reach the child exactly as given, with no
837
+ * terminator appended, so a caller speaking a framed protocol composes its own header and
838
+ * delimiter. `true` means the host accepted the bytes without reporting a fault; it does not
839
+ * prove that the child read them. An ordinary write settles when the kernel accepts it, and only
840
+ * a full pipe can hold one unconfirmed, which the `delivery` option bounds.
841
+ *
842
+ * It resolves `false` without throwing when the channel was closed by `end`, destroyed by a
843
+ * termination, failed, or left the write unconfirmed through `delivery`, and when `stop` or
844
+ * `destroy` has begun, because teardown cannot confirm delivery for bytes it is about to discard.
845
+ *
846
+ * The host can queue the payload, so treat the array as owned by the channel until the returned
847
+ * promise settles: bytes mutated inside that window are the bytes the child receives.
848
+ *
849
+ * @param bytes - The payload to write, already framed by the caller
850
+ * @returns True when the host accepted the bytes without reporting a fault; false when the channel was closed, destroyed, ended, failed, or remained unconfirmed through `delivery`
851
+ */
852
+ write(bytes: Uint8Array): Promise<boolean>;
853
+ /**
854
+ * Close the standard-input channel and leave the child running.
855
+ *
856
+ * @remarks
857
+ * Never rejects, and terminates nothing: `stopping` stays false, no signal is sent, no drain
858
+ * window is armed, and the terminal moment does not arrive. The child observes end of input, which
859
+ * is how a cooperative protocol asks it to finish and exit on its own; await `ending` for that
860
+ * exit and `stop` when it does not come.
861
+ *
862
+ * Every call shares one barrier, and it resolves after the host flushes the writes it had already
863
+ * accepted. That flush carries no bound of its own: a child that stops reading its input leaves
864
+ * the accepted bytes in the pipe, and the barrier stays pending for as long as they sit there. A
865
+ * caller that needs a bound races this promise against a window of its own rather than awaiting it
866
+ * bare. A `write` after this call resolves `false`, because the channel is no longer writable.
867
+ * The closed channel then stays quiet for its remaining life: a later host fault on it settles
868
+ * pending writes and emits no `error` event. After `stop` or `destroy` has begun the call resolves
869
+ * and changes nothing.
870
+ *
871
+ * @returns The stable barrier shared by every call
872
+ */
873
+ end(): Promise<void>;
874
+ /**
875
+ * Terminate the child process tree, await its observed exit, and reach the terminal moment.
876
+ *
877
+ * @remarks
878
+ * Never rejects. On Windows the whole tree is killed immediately through `taskkill`, with a
879
+ * direct kill as the fallback; on a POSIX host the process group receives `SIGTERM`, then
880
+ * `SIGKILL` after `grace`. No signal is initiated after the child's native exit is observed.
881
+ *
882
+ * Observation ends here as well as under `destroy`, bounded by `drain`: `evidence` freezes, the
883
+ * `stdout` and `stderr` events stop, and `exit` settles. A caller that stops a child and keeps
884
+ * listening therefore reaches the end of the stream and needs no second call to release it.
885
+ *
886
+ * @returns True when the child's native exit was observed; false when the confirmation deadline elapsed without it
887
+ */
888
+ stop(): Promise<boolean>;
889
+ /**
890
+ * Stop the child, close its standard-input channel, reach the terminal moment, and destroy the
891
+ * observation emitter.
892
+ *
893
+ * @remarks
894
+ * Always resolves, including when termination was never confirmed. The barrier settles after the
895
+ * terminal moment, so `evidence` is frozen and `exit` has settled by the time a caller resumes.
896
+ * The wait for the child's streams is bounded by `drain`, so a descendant holding an inherited
897
+ * pipe cannot hold this barrier open, and {@link ProcessExit.drained} reports which way the moment
898
+ * arrived. The emitter is destroyed after the frozen state exists, so a consumer watching the
899
+ * `stderr` event and a consumer reading `evidence` end on the same bytes.
900
+ *
901
+ * @returns The stable barrier shared by every call
902
+ */
903
+ destroy(): Promise<void>;
904
+ }
905
+
906
+ /**
907
+ * Construction options for one raw byte session over a supervised child.
908
+ *
909
+ * @remarks
910
+ * This is {@link ProcessOptions} without `backlog` and without `writable`. A session frames nothing
911
+ * and retains no lines, so no backlog bound applies to it; its standard-input channel is open from
912
+ * the spawn until {@link SessionInterface.end}, so no switch selects whether one exists. `grace`,
913
+ * `drain`, `evidence`, `delivery`, and `signal` carry the meanings {@link ProcessOptions} documents
914
+ * for them, and `command.input` is still written immediately after the spawn. `on` installs initial
915
+ * {@link SessionEventMap} listeners and `error` receives isolated listener failures.
916
+ *
917
+ * Every option and command property is read once, before the child is spawned, so a caller's own
918
+ * getter runs while nothing has started and a getter that throws strands no process. Every numeric
919
+ * option is validated in that same window: a timer value outside `[0, PROCESS_TIMER]`, or a negative
920
+ * or fractional byte value, throws a {@link ProcessError} coded `invalid` before anything is
921
+ * spawned.
922
+ */
923
+ export declare interface SessionOptions {
924
+ readonly on?: EmitterHooks<SessionEventMap>;
925
+ readonly error?: EmitterErrorHandler;
926
+ readonly command: ProcessCommand;
927
+ /** The working directory the child runs in. */
928
+ readonly workspace: string;
929
+ /** Cooperative POSIX window in milliseconds between `SIGTERM` and `SIGKILL`. Default: {@link PROCESS_GRACE}. */
930
+ readonly grace?: number;
931
+ /** Milliseconds the package waits for the child's read ends to close after the native exit or an initiated termination, before cutting them off; `0` cuts them off as soon as the bound is armed. Default: {@link PROCESS_DRAIN}. */
932
+ readonly drain?: number;
933
+ /** Maximum retained stderr tail in bytes. Default: {@link PROCESS_EVIDENCE}. */
934
+ readonly evidence?: number;
935
+ /** Milliseconds an unconfirmed {@link SessionInterface.write} waits before resolving `false`. `0` or omitted disables the bound. */
936
+ readonly delivery?: number;
937
+ /** Aborting this signal terminates the child through the same bounded `stop`. */
938
+ readonly signal?: AbortSignal;
939
+ }
940
+
702
941
  /**
703
942
  * The resolved spawn form of one command: the executable to launch, the argument vector to pass,
704
943
  * and whether the host receives that vector verbatim.