@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.
@@ -5,10 +5,8 @@ import { ExecutableOptions } from '@orkestrel/process';
5
5
  import { ExecuteInput } from '@orkestrel/process';
6
6
  import { ExecuteOptions } from '@orkestrel/process';
7
7
  import { ExecuteResult } from '@orkestrel/process';
8
- import { ExecuteResult as ExecuteResult_2 } from '@orkestrel/process';
9
8
  import { ExecuteSyncOptions } from '@orkestrel/process';
10
9
  import { ProcessCommand } from '@orkestrel/process';
11
- import { ProcessCommand as ProcessCommand_2 } from '@orkestrel/process';
12
10
  import { ProcessEventMap } from '@orkestrel/process';
13
11
  import { ProcessExit } from '@orkestrel/process';
14
12
  import { ProcessInterface } from '@orkestrel/process';
@@ -16,6 +14,9 @@ import { ProcessManagerEventMap } from '@orkestrel/process';
16
14
  import { ProcessManagerInterface } from '@orkestrel/process';
17
15
  import { ProcessManagerOptions } from '@orkestrel/process';
18
16
  import { ProcessOptions } from '@orkestrel/process';
17
+ import { SessionEventMap } from '@orkestrel/process';
18
+ import { SessionInterface } from '@orkestrel/process';
19
+ import { SessionOptions } from '@orkestrel/process';
19
20
  import { SpawnInput } from '@orkestrel/process';
20
21
 
21
22
  /**
@@ -117,6 +118,30 @@ export declare function buildPlatformSpawn(command: ProcessCommand, file: string
117
118
  */
118
119
  export declare function buildSpawn(command: ProcessCommand, options?: ExecutableOptions): SpawnInput;
119
120
 
121
+ /**
122
+ * Bounds one delivered stream chunk to the bytes a capture still has room for.
123
+ *
124
+ * @remarks
125
+ * A chunk that is not a buffer contributes nothing and reports `undefined` rather than throwing,
126
+ * because a stream `data` listener receives an `unknown` payload. The cut is byte-exact and might
127
+ * land inside a multibyte sequence, because {@link buildExecuteResult} performs the single
128
+ * code-point-boundary trim over the whole capture rather than over each chunk. Give the capture one
129
+ * byte more room than its limit, so that final trim can read the first excluded byte and retreat off
130
+ * a split sequence. A chunk that fits its room is returned as the delivered buffer itself rather
131
+ * than a copy, because a capture appending it copies again and never writes through it; a chunk that
132
+ * overruns its room returns a copy of the bytes that fit. Treat the return as read-only either way.
133
+ *
134
+ * @param chunk - The delivered chunk, ignored when it is not a buffer
135
+ * @param room - The bytes the capture still accepts
136
+ * @returns The bytes to retain, or `undefined` when the chunk contributes none
137
+ *
138
+ * @example
139
+ * ```ts
140
+ * captureChunk(Buffer.from('hello'), 3) // <Buffer 68 65 6c>
141
+ * ```
142
+ */
143
+ export declare function captureChunk(chunk: unknown, room: number): Buffer_2 | undefined;
144
+
120
145
  /**
121
146
  * Creates one supervised child process.
122
147
  *
@@ -151,6 +176,25 @@ export declare function createProcess(options: ProcessOptions): ProcessInterface
151
176
  */
152
177
  export declare function createProcessManager(options?: ProcessManagerOptions): ProcessManagerInterface;
153
178
 
179
+ /**
180
+ * Creates one raw byte session over a supervised child process.
181
+ *
182
+ * @param options - Command, workspace, termination, evidence, stdin, and observation settings
183
+ * @returns The launched {@link SessionInterface}
184
+ *
185
+ * @example
186
+ * ```ts
187
+ * import { createSession } from '@orkestrel/process/server'
188
+ *
189
+ * const session = createSession({
190
+ * command: { file: 'node', arguments: ['server.js', '--stdio'] },
191
+ * workspace: process.cwd(),
192
+ * grace: 5000,
193
+ * })
194
+ * ```
195
+ */
196
+ export declare function createSession(options: SessionOptions): SessionInterface;
197
+
154
198
  /**
155
199
  * Spawns one command as a detached process and returns without waiting for it.
156
200
  *
@@ -170,7 +214,7 @@ export declare function createProcessManager(options?: ProcessManagerOptions): P
170
214
  * detach({ file: 'node', arguments: ['daemon.js'] }, { workspace: process.cwd() })
171
215
  * ```
172
216
  */
173
- export declare function detach(command: ProcessCommand_2, options?: DetachOptions): void;
217
+ export declare function detach(command: ProcessCommand, options?: DetachOptions): void;
174
218
 
175
219
  /**
176
220
  * Runs one command to completion, buffering its output, and settles with the outcome.
@@ -179,7 +223,9 @@ export declare function detach(command: ProcessCommand_2, options?: DetachOption
179
223
  * The executable is resolved through {@link buildSpawn}, so no run uses a shell. On a POSIX host the
180
224
  * child is detached, which is what lets its whole process group be terminated. Standard output and
181
225
  * error are each byte-bounded by `limit` (default {@link PROCESS_OUTPUT}) and `truncated` reports
182
- * whether either stream exceeded it. A positive `timeout` and an aborting `signal` both terminate the
226
+ * whether either stream exceeded it. Each capture keeps one byte beyond `limit`, so the single
227
+ * code-point-boundary trim in {@link buildExecuteResult} reads the first excluded byte and never
228
+ * delivers a split multibyte sequence. A positive `timeout` and an aborting `signal` both terminate the
183
229
  * child through the same bounded stop, and only the earliest is recorded: a timeout reports
184
230
  * `expired` and an abort reports `aborted`, never both. After termination the outcome is awaited for
185
231
  * a bounded window, so a descendant holding the child's stdio cannot keep the run pending. That bound
@@ -205,7 +251,7 @@ export declare function detach(command: ProcessCommand_2, options?: DetachOption
205
251
  * const result = await execute({ file: 'git', arguments: ['status'] }, { workspace: process.cwd() })
206
252
  * ```
207
253
  */
208
- export declare function execute(command: ProcessCommand_2, options?: ExecuteOptions): Promise<ExecuteResult_2>;
254
+ export declare function execute(command: ProcessCommand, options?: ExecuteOptions): Promise<ExecuteResult>;
209
255
 
210
256
  /**
211
257
  * Runs one command to completion synchronously, buffering its output, and returns the outcome.
@@ -231,7 +277,7 @@ export declare function execute(command: ProcessCommand_2, options?: ExecuteOpti
231
277
  * const result = executeSync({ file: 'git', arguments: ['--version'] }, { strict: false })
232
278
  * ```
233
279
  */
234
- export declare function executeSync(command: ProcessCommand_2, options?: ExecuteSyncOptions): ExecuteResult_2;
280
+ export declare function executeSync(command: ProcessCommand, options?: ExecuteSyncOptions): ExecuteResult;
235
281
 
236
282
  /**
237
283
  * Renders one command into its diagnostic command line.
@@ -694,45 +740,105 @@ export declare function readVariable(environment: Readonly<Record<string, string
694
740
  export declare function resolveExecutable(file: string, options?: ExecutableOptions): string | undefined;
695
741
 
696
742
  /**
697
- * Accumulates byte totals while retaining a bounded stream head.
743
+ * Supervises one child and publishes its standard output as raw bytes.
744
+ *
745
+ * @remarks
746
+ * This is the transport face of the supervision engine `Process` also composes. It frames nothing,
747
+ * retains nothing, and decodes nothing on the output side: every chunk the host delivers becomes one
748
+ * `stdout` event carrying that chunk's bytes, in arrival order, so a consumer speaking a
749
+ * length-prefixed or delimiter-framed protocol reads exactly what the child wrote and frames it
750
+ * itself. Standard error is decoded and forwarded as `stderr`, with the same byte-bounded `evidence`
751
+ * tail a `Process` retains, because a diagnostic stream is read rather than parsed.
752
+ *
753
+ * Each emitted chunk is this session's own copy, and a plain `Uint8Array` rather than the host buffer
754
+ * the read produced, so a consumer keeps it, mutates it, concatenates it, and reads its whole backing
755
+ * buffer without reaching memory the host still manages and without depending on a host type.
756
+ *
757
+ * The standard-input channel is open from the spawn, and `end` closes it without terminating
758
+ * anything. That is the member a cooperative protocol reaches for: the child observes end of input
759
+ * and exits on its own, which `ending` reports. `stop` and `destroy` remain the terminations, and
760
+ * `exit` remains the terminal moment — the native exit plus at most `drain` while a descendant holds
761
+ * the inherited read ends.
698
762
  *
699
763
  * @example
700
764
  * ```ts
701
- * const retention = new Retention()
702
- * retention.retain(Buffer.from('hello'), 3)?.toString('utf8') // 'hel'
703
- * retention.retained // 3
765
+ * import { Session } from '@orkestrel/process/server'
766
+ *
767
+ * const session = new Session({
768
+ * command: { file: 'node', arguments: ['-e', 'process.stdin.pipe(process.stdout)'] },
769
+ * workspace: process.cwd(),
770
+ * })
704
771
  * ```
705
772
  */
706
- export declare class Retention implements RetentionInterface {
773
+ export declare class Session implements SessionInterface {
707
774
  #private;
708
- /** The bytes delivered by the stream. */
709
- get delivered(): number;
710
- /** The bytes retained from the stream head. */
711
- get retained(): number;
712
775
  /**
713
- * Retains a delivered chunk within a byte limit.
776
+ * Spawn one child process and begin byte capture.
714
777
  *
715
- * @param chunk - The delivered chunk, ignored when it is not a buffer
716
- * @param limit - The maximum retained byte count
717
- * @returns The retained slice, or `undefined` when the chunk contributes no retained bytes
778
+ * @param options - Command, workspace, termination, evidence, stdin, and observation settings
779
+ * @throws A {@link ProcessError} coded `invalid` when an option or command string is malformed
718
780
  */
719
- retain(chunk: unknown, limit: number): Buffer_2 | undefined;
720
- }
721
-
722
- /** Exposes byte totals and bounded stream-head retention. */
723
- export declare interface RetentionInterface {
724
- /** The bytes delivered by the stream. */
725
- readonly delivered: number;
726
- /** The bytes retained from the stream head. */
727
- readonly retained: number;
781
+ constructor(options: SessionOptions);
782
+ /** The host process id, fixed when construction returns, or `undefined` when the spawn produced none. */
783
+ get pid(): number | undefined;
784
+ /** The exit code the host recorded, or `null` while the child has not exited and when a signal ended it. */
785
+ get code(): number | null;
786
+ /** The terminating signal name the host recorded, or `null` while the child has not exited and when it exited on its own. */
787
+ get signal(): string | null;
788
+ /** The typed lifecycle observation surface. */
789
+ get emitter(): EmitterInterface<SessionEventMap>;
790
+ /** The decoded byte-bounded stderr tail, frozen at the terminal moment. */
791
+ get evidence(): string;
792
+ /** True after the terminal moment arrived and `exit` settled. */
793
+ get settled(): boolean;
794
+ /** True after termination began, including after the terminal moment. `end` never turns it true. */
795
+ get stopping(): boolean;
796
+ /** The child's own ending, awaited without the terminal moment's drain window. */
797
+ get ending(): Promise<void>;
798
+ /** The terminal child state, observed once after stream close or the drain cutoff. */
799
+ get exit(): Promise<ProcessExit>;
728
800
  /**
729
- * Retains a delivered chunk within a byte limit.
801
+ * Writes raw bytes to the open standard-input channel.
730
802
  *
731
- * @param chunk - The delivered chunk, ignored when it is not a buffer
732
- * @param limit - The maximum retained byte count
733
- * @returns The retained slice, or `undefined` when the chunk contributes no retained bytes
803
+ * @remarks
804
+ * Never rejects, and appends no terminator: the child receives exactly these bytes. `true` means
805
+ * the host accepted them without reporting a fault; it does not prove that the child read them.
806
+ * The channel can queue the payload, so treat the array as owned by the channel until the
807
+ * returned promise settles.
808
+ *
809
+ * @param bytes - The payload to write, already framed by the caller
810
+ * @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`
811
+ */
812
+ write(bytes: Uint8Array): Promise<boolean>;
813
+ /**
814
+ * Closes the standard-input channel and leaves the child running.
815
+ *
816
+ * @remarks
817
+ * Never rejects and terminates nothing: `stopping` stays false and the terminal moment does not
818
+ * arrive. Every call shares one barrier, which resolves after the host flushes the writes it had
819
+ * already accepted. A later `write` resolves `false`.
820
+ *
821
+ * @returns The stable barrier shared by every call
734
822
  */
735
- retain(chunk: unknown, limit: number): Buffer_2 | undefined;
823
+ end(): Promise<void>;
824
+ /**
825
+ * Terminates the child process tree and reaches the terminal observation moment.
826
+ *
827
+ * @remarks
828
+ * Never rejects, and every call shares one termination bounded by `grace` and `drain`.
829
+ *
830
+ * @returns True when the child's native exit was observed; false when the confirmation deadline elapsed without it
831
+ */
832
+ stop(): Promise<boolean>;
833
+ /**
834
+ * Stops the child and destroys the observation emitter after the terminal state freezes.
835
+ *
836
+ * @remarks
837
+ * Always resolves, including when termination was never confirmed. Every call shares one barrier.
838
+ *
839
+ * @returns The stable barrier shared by every call
840
+ */
841
+ destroy(): Promise<void>;
736
842
  }
737
843
 
738
844
  /**
@@ -787,9 +893,12 @@ export declare function stopChild(child: ProcessChild, grace: number, confirm: n
787
893
  * Trims a buffer to at most `limit` leading bytes without splitting a UTF-8 sequence.
788
894
  *
789
895
  * @remarks
790
- * Keeps the head — the captured start of a one-shot run's output. When the cut point lands inside
791
- * a multibyte sequence, the end retreats to the sequence's start so the retained bytes always end
792
- * on a code-point boundary and decode without a replacement character.
896
+ * Keeps the head — the captured start of a one-shot run's output. The end retreats only when a
897
+ * sequence genuinely spans the cut: the byte at `limit` carries the continuation bit pattern, and a
898
+ * lead byte within the preceding three bytes declares a length that reaches it. The retained bytes
899
+ * then end on a code-point boundary and decode without a replacement character. A byte at `limit`
900
+ * that carries the continuation pattern without such a lead byte is invalid UTF-8 rather than a
901
+ * split sequence, so the full `limit` survives instead of a valid byte being dropped for it.
793
902
  *
794
903
  * @param bytes - The accumulated bytes
795
904
  * @param limit - The maximum retained byte count
@@ -5,10 +5,8 @@ import { ExecutableOptions } from '@orkestrel/process';
5
5
  import { ExecuteInput } from '@orkestrel/process';
6
6
  import { ExecuteOptions } from '@orkestrel/process';
7
7
  import { ExecuteResult } from '@orkestrel/process';
8
- import { ExecuteResult as ExecuteResult_2 } from '@orkestrel/process';
9
8
  import { ExecuteSyncOptions } from '@orkestrel/process';
10
9
  import { ProcessCommand } from '@orkestrel/process';
11
- import { ProcessCommand as ProcessCommand_2 } from '@orkestrel/process';
12
10
  import { ProcessEventMap } from '@orkestrel/process';
13
11
  import { ProcessExit } from '@orkestrel/process';
14
12
  import { ProcessInterface } from '@orkestrel/process';
@@ -16,6 +14,9 @@ import { ProcessManagerEventMap } from '@orkestrel/process';
16
14
  import { ProcessManagerInterface } from '@orkestrel/process';
17
15
  import { ProcessManagerOptions } from '@orkestrel/process';
18
16
  import { ProcessOptions } from '@orkestrel/process';
17
+ import { SessionEventMap } from '@orkestrel/process';
18
+ import { SessionInterface } from '@orkestrel/process';
19
+ import { SessionOptions } from '@orkestrel/process';
19
20
  import { SpawnInput } from '@orkestrel/process';
20
21
 
21
22
  /**
@@ -117,6 +118,30 @@ export declare function buildPlatformSpawn(command: ProcessCommand, file: string
117
118
  */
118
119
  export declare function buildSpawn(command: ProcessCommand, options?: ExecutableOptions): SpawnInput;
119
120
 
121
+ /**
122
+ * Bounds one delivered stream chunk to the bytes a capture still has room for.
123
+ *
124
+ * @remarks
125
+ * A chunk that is not a buffer contributes nothing and reports `undefined` rather than throwing,
126
+ * because a stream `data` listener receives an `unknown` payload. The cut is byte-exact and might
127
+ * land inside a multibyte sequence, because {@link buildExecuteResult} performs the single
128
+ * code-point-boundary trim over the whole capture rather than over each chunk. Give the capture one
129
+ * byte more room than its limit, so that final trim can read the first excluded byte and retreat off
130
+ * a split sequence. A chunk that fits its room is returned as the delivered buffer itself rather
131
+ * than a copy, because a capture appending it copies again and never writes through it; a chunk that
132
+ * overruns its room returns a copy of the bytes that fit. Treat the return as read-only either way.
133
+ *
134
+ * @param chunk - The delivered chunk, ignored when it is not a buffer
135
+ * @param room - The bytes the capture still accepts
136
+ * @returns The bytes to retain, or `undefined` when the chunk contributes none
137
+ *
138
+ * @example
139
+ * ```ts
140
+ * captureChunk(Buffer.from('hello'), 3) // <Buffer 68 65 6c>
141
+ * ```
142
+ */
143
+ export declare function captureChunk(chunk: unknown, room: number): Buffer_2 | undefined;
144
+
120
145
  /**
121
146
  * Creates one supervised child process.
122
147
  *
@@ -151,6 +176,25 @@ export declare function createProcess(options: ProcessOptions): ProcessInterface
151
176
  */
152
177
  export declare function createProcessManager(options?: ProcessManagerOptions): ProcessManagerInterface;
153
178
 
179
+ /**
180
+ * Creates one raw byte session over a supervised child process.
181
+ *
182
+ * @param options - Command, workspace, termination, evidence, stdin, and observation settings
183
+ * @returns The launched {@link SessionInterface}
184
+ *
185
+ * @example
186
+ * ```ts
187
+ * import { createSession } from '@orkestrel/process/server'
188
+ *
189
+ * const session = createSession({
190
+ * command: { file: 'node', arguments: ['server.js', '--stdio'] },
191
+ * workspace: process.cwd(),
192
+ * grace: 5000,
193
+ * })
194
+ * ```
195
+ */
196
+ export declare function createSession(options: SessionOptions): SessionInterface;
197
+
154
198
  /**
155
199
  * Spawns one command as a detached process and returns without waiting for it.
156
200
  *
@@ -170,7 +214,7 @@ export declare function createProcessManager(options?: ProcessManagerOptions): P
170
214
  * detach({ file: 'node', arguments: ['daemon.js'] }, { workspace: process.cwd() })
171
215
  * ```
172
216
  */
173
- export declare function detach(command: ProcessCommand_2, options?: DetachOptions): void;
217
+ export declare function detach(command: ProcessCommand, options?: DetachOptions): void;
174
218
 
175
219
  /**
176
220
  * Runs one command to completion, buffering its output, and settles with the outcome.
@@ -179,7 +223,9 @@ export declare function detach(command: ProcessCommand_2, options?: DetachOption
179
223
  * The executable is resolved through {@link buildSpawn}, so no run uses a shell. On a POSIX host the
180
224
  * child is detached, which is what lets its whole process group be terminated. Standard output and
181
225
  * error are each byte-bounded by `limit` (default {@link PROCESS_OUTPUT}) and `truncated` reports
182
- * whether either stream exceeded it. A positive `timeout` and an aborting `signal` both terminate the
226
+ * whether either stream exceeded it. Each capture keeps one byte beyond `limit`, so the single
227
+ * code-point-boundary trim in {@link buildExecuteResult} reads the first excluded byte and never
228
+ * delivers a split multibyte sequence. A positive `timeout` and an aborting `signal` both terminate the
183
229
  * child through the same bounded stop, and only the earliest is recorded: a timeout reports
184
230
  * `expired` and an abort reports `aborted`, never both. After termination the outcome is awaited for
185
231
  * a bounded window, so a descendant holding the child's stdio cannot keep the run pending. That bound
@@ -205,7 +251,7 @@ export declare function detach(command: ProcessCommand_2, options?: DetachOption
205
251
  * const result = await execute({ file: 'git', arguments: ['status'] }, { workspace: process.cwd() })
206
252
  * ```
207
253
  */
208
- export declare function execute(command: ProcessCommand_2, options?: ExecuteOptions): Promise<ExecuteResult_2>;
254
+ export declare function execute(command: ProcessCommand, options?: ExecuteOptions): Promise<ExecuteResult>;
209
255
 
210
256
  /**
211
257
  * Runs one command to completion synchronously, buffering its output, and returns the outcome.
@@ -231,7 +277,7 @@ export declare function execute(command: ProcessCommand_2, options?: ExecuteOpti
231
277
  * const result = executeSync({ file: 'git', arguments: ['--version'] }, { strict: false })
232
278
  * ```
233
279
  */
234
- export declare function executeSync(command: ProcessCommand_2, options?: ExecuteSyncOptions): ExecuteResult_2;
280
+ export declare function executeSync(command: ProcessCommand, options?: ExecuteSyncOptions): ExecuteResult;
235
281
 
236
282
  /**
237
283
  * Renders one command into its diagnostic command line.
@@ -694,45 +740,105 @@ export declare function readVariable(environment: Readonly<Record<string, string
694
740
  export declare function resolveExecutable(file: string, options?: ExecutableOptions): string | undefined;
695
741
 
696
742
  /**
697
- * Accumulates byte totals while retaining a bounded stream head.
743
+ * Supervises one child and publishes its standard output as raw bytes.
744
+ *
745
+ * @remarks
746
+ * This is the transport face of the supervision engine `Process` also composes. It frames nothing,
747
+ * retains nothing, and decodes nothing on the output side: every chunk the host delivers becomes one
748
+ * `stdout` event carrying that chunk's bytes, in arrival order, so a consumer speaking a
749
+ * length-prefixed or delimiter-framed protocol reads exactly what the child wrote and frames it
750
+ * itself. Standard error is decoded and forwarded as `stderr`, with the same byte-bounded `evidence`
751
+ * tail a `Process` retains, because a diagnostic stream is read rather than parsed.
752
+ *
753
+ * Each emitted chunk is this session's own copy, and a plain `Uint8Array` rather than the host buffer
754
+ * the read produced, so a consumer keeps it, mutates it, concatenates it, and reads its whole backing
755
+ * buffer without reaching memory the host still manages and without depending on a host type.
756
+ *
757
+ * The standard-input channel is open from the spawn, and `end` closes it without terminating
758
+ * anything. That is the member a cooperative protocol reaches for: the child observes end of input
759
+ * and exits on its own, which `ending` reports. `stop` and `destroy` remain the terminations, and
760
+ * `exit` remains the terminal moment — the native exit plus at most `drain` while a descendant holds
761
+ * the inherited read ends.
698
762
  *
699
763
  * @example
700
764
  * ```ts
701
- * const retention = new Retention()
702
- * retention.retain(Buffer.from('hello'), 3)?.toString('utf8') // 'hel'
703
- * retention.retained // 3
765
+ * import { Session } from '@orkestrel/process/server'
766
+ *
767
+ * const session = new Session({
768
+ * command: { file: 'node', arguments: ['-e', 'process.stdin.pipe(process.stdout)'] },
769
+ * workspace: process.cwd(),
770
+ * })
704
771
  * ```
705
772
  */
706
- export declare class Retention implements RetentionInterface {
773
+ export declare class Session implements SessionInterface {
707
774
  #private;
708
- /** The bytes delivered by the stream. */
709
- get delivered(): number;
710
- /** The bytes retained from the stream head. */
711
- get retained(): number;
712
775
  /**
713
- * Retains a delivered chunk within a byte limit.
776
+ * Spawn one child process and begin byte capture.
714
777
  *
715
- * @param chunk - The delivered chunk, ignored when it is not a buffer
716
- * @param limit - The maximum retained byte count
717
- * @returns The retained slice, or `undefined` when the chunk contributes no retained bytes
778
+ * @param options - Command, workspace, termination, evidence, stdin, and observation settings
779
+ * @throws A {@link ProcessError} coded `invalid` when an option or command string is malformed
718
780
  */
719
- retain(chunk: unknown, limit: number): Buffer_2 | undefined;
720
- }
721
-
722
- /** Exposes byte totals and bounded stream-head retention. */
723
- export declare interface RetentionInterface {
724
- /** The bytes delivered by the stream. */
725
- readonly delivered: number;
726
- /** The bytes retained from the stream head. */
727
- readonly retained: number;
781
+ constructor(options: SessionOptions);
782
+ /** The host process id, fixed when construction returns, or `undefined` when the spawn produced none. */
783
+ get pid(): number | undefined;
784
+ /** The exit code the host recorded, or `null` while the child has not exited and when a signal ended it. */
785
+ get code(): number | null;
786
+ /** The terminating signal name the host recorded, or `null` while the child has not exited and when it exited on its own. */
787
+ get signal(): string | null;
788
+ /** The typed lifecycle observation surface. */
789
+ get emitter(): EmitterInterface<SessionEventMap>;
790
+ /** The decoded byte-bounded stderr tail, frozen at the terminal moment. */
791
+ get evidence(): string;
792
+ /** True after the terminal moment arrived and `exit` settled. */
793
+ get settled(): boolean;
794
+ /** True after termination began, including after the terminal moment. `end` never turns it true. */
795
+ get stopping(): boolean;
796
+ /** The child's own ending, awaited without the terminal moment's drain window. */
797
+ get ending(): Promise<void>;
798
+ /** The terminal child state, observed once after stream close or the drain cutoff. */
799
+ get exit(): Promise<ProcessExit>;
728
800
  /**
729
- * Retains a delivered chunk within a byte limit.
801
+ * Writes raw bytes to the open standard-input channel.
730
802
  *
731
- * @param chunk - The delivered chunk, ignored when it is not a buffer
732
- * @param limit - The maximum retained byte count
733
- * @returns The retained slice, or `undefined` when the chunk contributes no retained bytes
803
+ * @remarks
804
+ * Never rejects, and appends no terminator: the child receives exactly these bytes. `true` means
805
+ * the host accepted them without reporting a fault; it does not prove that the child read them.
806
+ * The channel can queue the payload, so treat the array as owned by the channel until the
807
+ * returned promise settles.
808
+ *
809
+ * @param bytes - The payload to write, already framed by the caller
810
+ * @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`
811
+ */
812
+ write(bytes: Uint8Array): Promise<boolean>;
813
+ /**
814
+ * Closes the standard-input channel and leaves the child running.
815
+ *
816
+ * @remarks
817
+ * Never rejects and terminates nothing: `stopping` stays false and the terminal moment does not
818
+ * arrive. Every call shares one barrier, which resolves after the host flushes the writes it had
819
+ * already accepted. A later `write` resolves `false`.
820
+ *
821
+ * @returns The stable barrier shared by every call
734
822
  */
735
- retain(chunk: unknown, limit: number): Buffer_2 | undefined;
823
+ end(): Promise<void>;
824
+ /**
825
+ * Terminates the child process tree and reaches the terminal observation moment.
826
+ *
827
+ * @remarks
828
+ * Never rejects, and every call shares one termination bounded by `grace` and `drain`.
829
+ *
830
+ * @returns True when the child's native exit was observed; false when the confirmation deadline elapsed without it
831
+ */
832
+ stop(): Promise<boolean>;
833
+ /**
834
+ * Stops the child and destroys the observation emitter after the terminal state freezes.
835
+ *
836
+ * @remarks
837
+ * Always resolves, including when termination was never confirmed. Every call shares one barrier.
838
+ *
839
+ * @returns The stable barrier shared by every call
840
+ */
841
+ destroy(): Promise<void>;
736
842
  }
737
843
 
738
844
  /**
@@ -787,9 +893,12 @@ export declare function stopChild(child: ProcessChild, grace: number, confirm: n
787
893
  * Trims a buffer to at most `limit` leading bytes without splitting a UTF-8 sequence.
788
894
  *
789
895
  * @remarks
790
- * Keeps the head — the captured start of a one-shot run's output. When the cut point lands inside
791
- * a multibyte sequence, the end retreats to the sequence's start so the retained bytes always end
792
- * on a code-point boundary and decode without a replacement character.
896
+ * Keeps the head — the captured start of a one-shot run's output. The end retreats only when a
897
+ * sequence genuinely spans the cut: the byte at `limit` carries the continuation bit pattern, and a
898
+ * lead byte within the preceding three bytes declares a length that reaches it. The retained bytes
899
+ * then end on a code-point boundary and decode without a replacement character. A byte at `limit`
900
+ * that carries the continuation pattern without such a lead byte is invalid UTF-8 rather than a
901
+ * split sequence, so the full `limit` survives instead of a valid byte being dropped for it.
793
902
  *
794
903
  * @param bytes - The accumulated bytes
795
904
  * @param limit - The maximum retained byte count