@orkestrel/console 0.0.10 → 0.0.12

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.
@@ -3,21 +3,21 @@ import { EmitterHooks } from '@orkestrel/emitter';
3
3
  import { EmitterInterface } from '@orkestrel/emitter';
4
4
 
5
5
  /**
6
- * Pad (or, when over budget, truncate) `text` to exactly `target` VISIBLE columns, positioning
6
+ * Pads (or, when over budget, truncates) `text` to exactly `columns` visible columns, positioning
7
7
  * it by `alignment`. The width primitive the box / table renderers align every cell with.
8
8
  *
9
9
  * @remarks
10
10
  * Measures with {@link width} (visible code points, ANSI-aware), so a styled string aligns by
11
- * its visible content, not its escape codes. When `width(text) < target`, the deficit is added
11
+ * its visible content, not its escape codes. When `width(text) < columns`, the deficit is added
12
12
  * as spaces — all trailing (`left`), all leading (`right`), or split with the extra space on
13
- * the right (`center`). When `width(text) > target`, the VISIBLE characters are sliced to
14
- * `target` (a defensive guard — the renderers size columns to fit, so this is rarely hit; it
13
+ * the right (`center`). When `width(text) > columns`, the visible characters are sliced to
14
+ * `columns` (a defensive guard — the renderers size columns to fit, so this is rarely hit; it
15
15
  * slices the stripped text, so it never bisects an escape sequence into a broken half).
16
16
  *
17
17
  * @param text - The cell content (may be styled)
18
- * @param target - The visible column count to fit `text` into
19
- * @param alignment - Where to position `text` within the width; defaults to `left`
20
- * @returns `text` fitted to exactly `target` visible columns
18
+ * @param columns - The visible column count to fit `text` into
19
+ * @param alignment - Where to position `text` within that budget; defaults to `left`
20
+ * @returns `text` fitted to exactly `columns` visible columns
21
21
  *
22
22
  * @example
23
23
  * ```ts
@@ -26,12 +26,12 @@ import { EmitterInterface } from '@orkestrel/emitter';
26
26
  * align('hi', 5, 'center') // ' hi '
27
27
  * ```
28
28
  */
29
- export declare function align(text: string, target: number, alignment?: Alignment): string;
29
+ export declare function align(text: string, columns: number, alignment?: Alignment): string;
30
30
 
31
31
  /**
32
- * Horizontal text alignment within a fixed-width cell — the conventional three-value set a
32
+ * Names the horizontal text alignment within a fixed-width cell — the conventional three-value set a
33
33
  * {@link ColumnSpec} (and the box / separator title) aligns by. A value pair / set, not a
34
- * binary toggle (§4.4), so it stays a union.
34
+ * binary toggle, so it stays a union.
35
35
  */
36
36
  export declare type Alignment = 'left' | 'center' | 'right';
37
37
 
@@ -39,13 +39,13 @@ export declare type Alignment = 'left' | 'center' | 'right';
39
39
  * Matches any ANSI/VT escape sequence — CSI (SGR color/style plus cursor/erase/scroll,
40
40
  * including colon-parameterized SGR), OSC / DCS / PM / APC / SOS string sequences
41
41
  * (titles, hyperlinks, device strings), the `nF` charset-select family, and the
42
- * two-byte `Fp` / `Fe` / `Fs` sequences (e.g. `ESC 7`, `ESC D`, `ESC c` RIS). Global, so
42
+ * two-byte `Fp` / `Fe` / `Fs` sequences (for example `ESC 7`, `ESC D`, `ESC c` RIS). Global, so
43
43
  * `strip` removes every occurrence.
44
44
  *
45
45
  * @remarks
46
- * A global `RegExp` carries a mutable `lastIndex`; a scan must build a FRESH `RegExp`
46
+ * A global `RegExp` carries a mutable `lastIndex`; a scan must build a fresh `RegExp`
47
47
  * from this one's `source` + `flags` rather than reuse this instance's `lastIndex`. This
48
- * is the canonical definition, not a shared scanner. The alternation is ORDERED so the
48
+ * is the canonical definition, not a shared scanner. The alternation is ordered so the
49
49
  * CSI / string-family arms (which can start with a byte a later single-byte arm would
50
50
  * also match) win first; every arm uses disjoint, non-nested character classes, so the
51
51
  * match is linear in input length — no catastrophic backtracking (ReDoS-safe) even on an
@@ -55,14 +55,14 @@ export declare type Alignment = 'left' | 'center' | 'right';
55
55
  export declare const ANSI_PATTERN: RegExp;
56
56
 
57
57
  /**
58
- * The cross-environment default {@link RendererInterface} — renders style DATA as ANSI
58
+ * Implements the cross-environment default {@link RendererInterface} — renders style data as ANSI
59
59
  * SGR escape codes, exactly as `Scheduler` is the `setTimeout` default for its seam. It
60
60
  * is the single styling output the whole console / terminal system uses in a terminal;
61
- * the browser `%c` / CSS renderer (the C-f branch) implements the SAME contract over
62
- * the SAME {@link Style}, so retargeting changes the renderer, never the style model.
61
+ * the browser `%c` / CSS renderer implements the same contract over
62
+ * the same {@link Style}, so retargeting changes the renderer, never the style model.
63
63
  *
64
64
  * @remarks
65
- * - **Style is DATA in, SGR string out.** It reads the style's `foreground` /
65
+ * - **Style is data in, SGR string out.** It reads the style's `foreground` /
66
66
  * `background` / `attributes` and emits one `ESC[…m` sequence whose parameters are the
67
67
  * mapped SGR numbers (foreground 30–37 / 90–97, background 40–47 / 100–107, attributes
68
68
  * 1 / 2 / 3 / 4 / 7 / 9), followed by `text`, terminated by the reset `ESC[0m`.
@@ -71,24 +71,24 @@ export declare const ANSI_PATTERN: RegExp;
71
71
  * - **`default` and unset colors emit no code** — a `default` (or absent) `foreground` /
72
72
  * `background` leaves the terminal's own ink.
73
73
  * - **The empty style and the empty string pass through** — when there is nothing to
74
- * apply (no colors, no attributes) or `text` is `''`, `text` is returned VERBATIM with
74
+ * apply (no colors, no attributes) or `text` is `''`, `text` is returned verbatim with
75
75
  * no escape codes, so an unstyled render never injects a stray reset.
76
76
  * - **Stateless and event-free** — no fields, no events; safe to share one instance.
77
77
  */
78
78
  export declare class ANSIRenderer implements RendererInterface {
79
79
  #private;
80
80
  /**
81
- * Wrap `text` in the SGR codes for `style`. Returns `text` unchanged when the style
81
+ * Wraps `text` in the SGR codes for `style`. Returns `text` unchanged when the style
82
82
  * is empty or `text` is `''`.
83
83
  */
84
84
  render(style: Style, text: string): string;
85
85
  }
86
86
 
87
87
  /**
88
- * A text-style attribute — the six standard SGR text effects.
88
+ * Names a text-style attribute — the standard SGR text effects.
89
89
  *
90
90
  * @remarks
91
- * Style as DATA: an `Attribute` is a name. The ANSI renderer maps each to its SGR
91
+ * Style as data: an `Attribute` is a name. The ANSI renderer maps each to its SGR
92
92
  * on-code (`bold` → 1, `dim` → 2, `italic` → 3, `underline` → 4, `inverse` → 7,
93
93
  * `strikethrough` → 9), composing several at once; a browser renderer maps the same
94
94
  * names to CSS (`font-weight`, `font-style`, `text-decoration`, …).
@@ -96,43 +96,70 @@ export declare class ANSIRenderer implements RendererInterface {
96
96
  export declare type Attribute = 'bold' | 'dim' | 'italic' | 'underline' | 'inverse' | 'strikethrough';
97
97
 
98
98
  /**
99
- * Each {@link Attribute}'s SGR "on" parameter — `bold` 1, `dim` 2, `italic` 3,
99
+ * Maps each {@link Attribute} to its SGR "on" parameter — `bold` 1, `dim` 2, `italic` 3,
100
100
  * `underline` 4, `inverse` 7, `strikethrough` 9. The renderer composes several by
101
101
  * joining their codes with `;` in one SGR sequence.
102
102
  */
103
103
  export declare const ATTRIBUTE_CODES: Readonly<Record<Attribute, number>>;
104
104
 
105
105
  /**
106
- * Every {@link Attribute}, frozen — the attributes the styler exposes as chainable
106
+ * Lists every {@link Attribute}, frozen — the attributes the styler exposes as chainable
107
107
  * accessors. The source of truth for the attribute axis.
108
108
  */
109
109
  export declare const ATTRIBUTES: readonly Attribute[];
110
110
 
111
111
  /**
112
- * Each {@link Color}'s SGR BACKGROUND parameter — the 8 base colors at 40–47 and their
112
+ * Maps each {@link Color} to its SGR background parameter — the 8 base colors at 40–47 and their
113
113
  * bright variants at 100–107. `default` is intentionally absent (it emits no code).
114
114
  */
115
115
  export declare const BACKGROUND_CODES: Readonly<Record<Exclude<Color, 'default'>, number>>;
116
116
 
117
117
  /**
118
- * The default EMPTY-cell glyph {@link import('./helpers.js').renderBar} draws the remaining run of a
118
+ * Holds the default empty-cell glyph {@link import('./helpers.js').renderBar} draws the remaining run of a
119
119
  * progress bar with — the light-shade block `░` (U+2591). A single visible cell; a consumer overrides
120
- * it via {@link import('./types.js').ProgressBarOptions}`.empty`.
120
+ * it through {@link import('./types.js').BarOptions}`.empty`.
121
121
  */
122
122
  export declare const BAR_EMPTY = "\u2591";
123
123
 
124
124
  /**
125
- * The default FILLED-cell glyph {@link import('./helpers.js').renderBar} draws the completed run of a
126
- * progress bar with — the full block `█` (U+2588). A single visible cell; a consumer overrides it via
127
- * {@link import('./types.js').ProgressBarOptions}`.fill`.
125
+ * Holds the default filled-cell glyph {@link import('./helpers.js').renderBar} draws the completed run of a
126
+ * progress bar with — the full block `█` (U+2588). A single visible cell; a consumer overrides it
127
+ * through {@link import('./types.js').BarOptions}`.fill`.
128
128
  */
129
129
  export declare const BAR_FILL = "\u2588";
130
130
 
131
- /** The BEL control character (`U+0007`) that can terminate an OSC sequence. */
131
+ /**
132
+ * Configures the pure {@link import('./helpers.js').renderBar} renderer — a determinate progress
133
+ * bar string (`█████░░░░░ 50% (5/10)`), width-aware and styler-optional.
134
+ *
135
+ * @remarks
136
+ * - `current` / `total` — the filled fraction is `current / total`, clamped to `[0, total]` (a
137
+ * `current` past `total` renders a full bar, a negative one an empty bar) — so a caller's overrun
138
+ * never produces an over-long bar. A `total` of `0` (or below) renders a full bar (nothing to do).
139
+ * - `width` — the visible cell count of the bar track (the glyph run between no brackets); defaults
140
+ * to {@link DEFAULT_BAR_WIDTH}. The percentage + `(current/total)` count follow the track.
141
+ * - `fill` — the filled-cell glyph; defaults to {@link BAR_FILL} (`█`). `empty` — the empty-cell
142
+ * glyph; defaults to {@link BAR_EMPTY} (`░`). Sized in visible columns ({@link
143
+ * import('./helpers.js').width}), so a multi-cell glyph still yields a `width`-wide track.
144
+ * - `styler` — colors the filled run when supplied (the empty run + the trailing label stay plain);
145
+ * the layout is identical with or without color, since the track is measured on visible width.
146
+ * - `style` — an optional by-value style rendered through `styler` for the filled run.
147
+ */
148
+ export declare interface BarOptions {
149
+ readonly current: number;
150
+ readonly total: number;
151
+ readonly width?: number;
152
+ readonly fill?: string;
153
+ readonly empty?: string;
154
+ readonly styler?: StylerInterface;
155
+ readonly style?: Style;
156
+ }
157
+
158
+ /** Holds the BEL control character (`U+0007`) that can terminate an OSC sequence. */
132
159
  export declare const BEL: string;
133
160
 
134
161
  /**
135
- * The complete {@link BorderChars} junction set for each {@link BorderStyle} — the standard
162
+ * Holds the complete {@link BorderChars} junction set for each {@link BorderStyle} — the standard
136
163
  * Unicode box-drawing glyphs at the four line weights. The renderers ({@link
137
164
  * import('./helpers.js').renderBox} / {@link import('./helpers.js').renderTable}) look the
138
165
  * style up here, so no glyph literal lives in a renderer. Deeply frozen.
@@ -143,7 +170,7 @@ export declare const BEL: string;
143
170
  export declare const BORDER_CHARS: Readonly<Record<BorderStyle, BorderChars>>;
144
171
 
145
172
  /**
146
- * One complete box-drawing junction set for a {@link BorderStyle} — every glyph the box /
173
+ * Represents one complete box-drawing junction set for a {@link BorderStyle} — every glyph the box /
147
174
  * table renderers need to frame content and rule a table. Plain data (the value lives in
148
175
  * {@link BORDER_CHARS}); the renderers read these so no glyph literal is hard-coded in a
149
176
  * renderer.
@@ -171,7 +198,7 @@ export declare interface BorderChars {
171
198
  }
172
199
 
173
200
  /**
174
- * A box-drawing border style — the four standard Unicode line weights the renderers frame
201
+ * Names a box-drawing border style — the four standard Unicode line weights the renderers frame
175
202
  * with. Each selects a full junction set in {@link BORDER_CHARS} (corners, edges, and the
176
203
  * `T` / cross junctions a table needs). A named, fixed set (an external-spec value family),
177
204
  * never a toggle — so it stays a union.
@@ -184,14 +211,14 @@ export declare interface BorderChars {
184
211
  export declare type BorderStyle = 'single' | 'double' | 'round' | 'heavy';
185
212
 
186
213
  /**
187
- * Options for {@link import('./helpers.js').renderBox} — content framed in box-drawing
214
+ * Configures {@link import('./helpers.js').renderBox} — content framed in box-drawing
188
215
  * characters.
189
216
  *
190
217
  * @remarks
191
218
  * - `content` — the body text; embedded newlines split it into lines, each framed on its own
192
219
  * row. Every row is padded to the inner width measured by {@link import('./helpers.js').width}
193
- * (the VISIBLE width), so ANSI-styled content stays aligned inside the frame.
194
- * - `title` — an optional caption embedded in the TOP border.
220
+ * (the visible width), so ANSI-styled content stays aligned inside the frame.
221
+ * - `title` — an optional caption embedded in the top border.
195
222
  * - `padding` — horizontal cells of blank padding inside each vertical edge; defaults to
196
223
  * {@link DEFAULT_PADDING}.
197
224
  * - `border` — the {@link BorderStyle}; defaults to {@link DEFAULT_BORDER} (`single`).
@@ -213,32 +240,32 @@ export declare interface BoxOptions {
213
240
  }
214
241
 
215
242
  /**
216
- * An observable console interceptor (AGENTS §13) — it takes control of the global `console.*` on
217
- * the READ side. While `active`, every configured `console.x` call is captured as a frozen
243
+ * Implements an observable console interceptor — it takes control of the global `console.*` on
244
+ * the read side. While `active`, every configured `console.x` call is captured as a frozen
218
245
  * {@link CapturedMessage}, buffered (total + by level, bounded), emitted on `capture`, and — per
219
- * options — mirrored to the real console and/or forwarded to a {@link SinkInterface}.
246
+ * options — mirrored to the real console, forwarded to a {@link SinkInterface}, or both.
220
247
  *
221
248
  * @remarks
222
- * - **Snapshot-at-start (the no-capture-loop principle).** `start()` snapshots the CURRENT
249
+ * - **Snapshot-at-start (the no-capture-loop principle).** `start()` snapshots the current
223
250
  * `console[level]` for each configured {@link CaptureLevel}, then installs the wrappers. The
224
- * mirror writes through that snapshot — so our OWN console sink output (the Logger / Reporter,
251
+ * mirror writes through that snapshot — so our own console sink output (the Logger / Reporter,
225
252
  * which snapshot the real `console` at creation) is never recaptured: `Capture` catches
226
- * THIRD-PARTY `console.*`, not our writes. Create your loggers BEFORE installing a capture.
227
- * - **Idempotent + PROCESS-GLOBAL + NON-REENTRANT.** `start()` while already `active` is a no-op
228
- * (never double-patches); `stop()` while inactive is a no-op. It patches the ONE global
229
- * `console`, so at most ONE capture may be active at a time — running two concurrently
253
+ * third-party `console.*`, not our writes. Create your loggers before installing a capture.
254
+ * - **Idempotent + process-global + non-reentrant.** `start()` while already `active` is a no-op
255
+ * (never double-patches); `stop()` while inactive is a no-op. It patches the one global
256
+ * `console`, so at most one capture may be active at a time — running two concurrently
230
257
  * interleaves their buffers and clobbers each other's restore.
231
258
  * - **Bounded buffers.** `messages()` / `messages(level)` — the total buffer and each by-level
232
259
  * bucket are each capped at `limit`
233
260
  * (oldest dropped first), never unbounded — the same retention precedent as {@link Logger}.
234
- * - **Lifecycle (§10).** `start` / `stop` toggle interception (emitting `start` / `stop`);
261
+ * - **Lifecycle.** `start` / `stop` toggle interception (emitting `start` / `stop`);
235
262
  * `destroy()` stops (restoring `console`) then destroys the emitter.
236
263
  *
237
264
  * @example
238
265
  * ```ts
239
266
  * const capture = new Capture({ levels: ['warn', 'error'], mirror: true })
240
267
  * capture.start()
241
- * console.warn('third-party noise') // captured AND mirrored to the real console
268
+ * console.warn('third-party noise') // captured and mirrored to the real console
242
269
  * capture.messages('warn') // [{ level: 'warn', text: 'third-party noise', time: … }]
243
270
  * capture.stop() // console.warn restored
244
271
  * ```
@@ -257,7 +284,7 @@ export declare class Capture implements CaptureInterface {
257
284
  }
258
285
 
259
286
  /**
260
- * Each {@link CaptureLevel}'s {@link LogLevel} for the optional sink forward — the projection the
287
+ * Maps each {@link CaptureLevel} to its {@link LogLevel} for the optional sink forward — the projection the
261
288
  * Capture routes through when writing an intercepted call to a {@link
262
289
  * import('./types.js').SinkInterface} (`sink.write(text, CAPTURE_LEVEL_MAP[level])`). `warn` /
263
290
  * `error` / `debug` / `info` map to their matching {@link LogLevel}; `log` maps to `info` (a plain
@@ -267,7 +294,7 @@ export declare class Capture implements CaptureInterface {
267
294
  export declare const CAPTURE_LEVEL_MAP: Readonly<Record<CaptureLevel, LogLevel>>;
268
295
 
269
296
  /**
270
- * Every {@link CaptureLevel}, frozen — the `console.*` methods a {@link
297
+ * Lists every {@link CaptureLevel}, frozen — the `console.*` methods a {@link
271
298
  * import('./types.js').CaptureInterface} intercepts by default (and the source of truth for the
272
299
  * capture-level axis; drives exhaustive tests). The universal console methods: `log`, `info`,
273
300
  * `warn`, `error`, `debug`.
@@ -275,7 +302,7 @@ export declare const CAPTURE_LEVEL_MAP: Readonly<Record<CaptureLevel, LogLevel>>
275
302
  export declare const CAPTURE_LEVELS: readonly CaptureLevel[];
276
303
 
277
304
  /**
278
- * One captured console call — an immutable, serializable record of a single intercepted
305
+ * Represents one captured console call — an immutable, serializable record of a single intercepted
279
306
  * `console.*` invocation. A {@link CaptureInterface} builds one per call, freezes it, buffers it
280
307
  * (total + by level), and emits it on `capture`; every consumer reads this exact shape.
281
308
  *
@@ -296,108 +323,108 @@ export declare interface CapturedMessage {
296
323
  }
297
324
 
298
325
  /**
299
- * The observable events a {@link CaptureInterface} emits (AGENTS §13).
326
+ * Declares the observable events a {@link CaptureInterface} emits.
300
327
  *
301
328
  * @remarks
302
- * - `capture` — the core event: fires for EVERY intercepted `console.*` call (one per call,
329
+ * - `capture` — the core event: fires for every intercepted `console.*` call (one per call,
303
330
  * while active), carrying the frozen {@link CapturedMessage}. The hook a live console viewer /
304
331
  * tee rides.
305
332
  * - `start` / `stop` — the lifecycle signals: `start` fires when interception is installed (the
306
333
  * first `start()` on an inactive capture), `stop` when it is torn down (a `stop()` on an active
307
334
  * capture, and from `destroy()`); both are pure signals (empty tuples) so a consumer can mirror
308
- * the global-patch lifecycle (e.g. log that capture is engaged). They earn their place by
335
+ * the global-patch lifecycle (for example log that capture is engaged). They earn their place by
309
336
  * bracketing the process-global side effect a consumer needs to observe.
310
337
  *
311
- * Listener isolation is the emitter's (§13): a listener throw routes to the emitter's `error`
338
+ * Listener isolation is the emitter's: a listener throw routes to the emitter's `error`
312
339
  * handler, never onto this map — so a buggy `capture` listener can never perturb interception (or
313
340
  * the underlying program's own `console.*` call). Declared as a `type` alias (not
314
- * `interface extends EventMap`, §4.5): a type-literal satisfies the `EventMap` constraint
341
+ * `interface extends EventMap`): a type-literal satisfies the `EventMap` constraint
315
342
  * structurally, whereas an interface lacks the index signature.
316
343
  */
317
344
  export declare type CaptureEventMap = {
318
- /** An intercepted `console.*` call — the frozen {@link CapturedMessage}. */
345
+ /** Fires on an intercepted `console.*` call — the frozen {@link CapturedMessage}. */
319
346
  readonly capture: readonly [message: CapturedMessage];
320
- /** Interception was installed (an inactive capture's `start()`). */
347
+ /** Fires after interception was installed (an inactive capture's `start()`). */
321
348
  readonly start: readonly [];
322
- /** Interception was torn down (an active capture's `stop()` / `destroy()`). */
349
+ /** Fires after interception was torn down (an active capture's `stop()` / `destroy()`). */
323
350
  readonly stop: readonly [];
324
351
  };
325
352
 
326
353
  /**
327
- * An observable console interceptor (AGENTS §13) — it takes control of the global `console.*` on
328
- * the READ side: while `active`, every configured `console.x` call is captured as a frozen
354
+ * Declares an observable console interceptor — it takes control of the global `console.*` on
355
+ * the read side: while `active`, every configured `console.x` call is captured as a frozen
329
356
  * {@link CapturedMessage}, buffered (total + by level, bounded), emitted on `capture`, and —
330
- * per options — mirrored to the real console and/or forwarded to a {@link SinkInterface}.
357
+ * per options — mirrored to the real console, forwarded to a {@link SinkInterface}, or both.
331
358
  *
332
359
  * @remarks
333
- * - **Snapshot-at-start.** `start()` snapshots the CURRENT `console[level]` for each configured
360
+ * - **Snapshot-at-start.** `start()` snapshots the current `console[level]` for each configured
334
361
  * {@link CaptureLevel}, then installs the wrappers. The mirror writes through that snapshot, so
335
- * our OWN console sink output (the Logger / Reporter, which snapshot the real `console` at
336
- * creation) is never recaptured — `Capture` catches THIRD-PARTY `console.*`, not our writes
337
- * (the no-capture-loop principle). Create your loggers BEFORE installing a capture.
362
+ * our own console sink output (the Logger / Reporter, which snapshot the real `console` at
363
+ * creation) is never recaptured — `Capture` catches third-party `console.*`, not our writes
364
+ * (the no-capture-loop principle). Create your loggers before installing a capture.
338
365
  * - **Idempotent + non-reentrant.** `start()` while already `active` is a no-op (it never
339
- * double-patches), and `stop()` while inactive is a no-op. It is PROCESS-GLOBAL — it patches the
340
- * one global `console` — so at most ONE capture may be active at a time; running two
366
+ * double-patches), and `stop()` while inactive is a no-op. It is process-global — it patches the
367
+ * one global `console` — so at most one capture may be active at a time; running two
341
368
  * concurrently interleaves their buffers and clobbers each other's restore.
342
369
  * - **Bounded buffers.** `messages()` returns a copy of the whole buffer (oldest first);
343
370
  * `messages(level)` a copy of one {@link CaptureLevel}'s bucket — each capped at `limit`
344
- * (oldest dropped first), never unbounded. `clear()` empties them (it does NOT stop interception).
345
- * - **Lifecycle (§10).** `start` / `stop` toggle interception; `destroy()` stops (restoring
371
+ * (oldest dropped first), never unbounded. `clear()` empties them (it does not stop interception).
372
+ * - **Lifecycle.** `start` / `stop` toggle interception; `destroy()` stops (restoring
346
373
  * `console`) then destroys the emitter (its listeners go).
347
374
  */
348
375
  export declare interface CaptureInterface {
349
376
  readonly emitter: EmitterInterface<CaptureEventMap>;
350
- /** Whether interception is currently installed (between `start()` and `stop()`). */
377
+ /** Reports whether interception is installed (between `start()` and `stop()`). */
351
378
  readonly active: boolean;
352
- /** Snapshot the configured `console.*` and install the interceptors — a no-op when already `active`. */
379
+ /** Snapshots the configured `console.*` and installs the interceptors — a no-op when already `active`. */
353
380
  start(): void;
354
- /** Restore the snapshot-original `console.*` — a no-op when not `active`. */
381
+ /** Restores the snapshot-original `console.*` — a no-op when not `active`. */
355
382
  stop(): void;
356
- /** A copy of the whole captured buffer, oldest first (capped at `limit`). */
383
+ /** Returns a copy of the whole captured buffer, oldest first (capped at `limit`). */
357
384
  messages(): readonly CapturedMessage[];
358
- /** A copy of the captured buffer for ONE {@link CaptureLevel}, oldest first (capped at `limit`). */
385
+ /** Returns a copy of the captured buffer for one {@link CaptureLevel}, oldest first (capped at `limit`). */
359
386
  messages(level: CaptureLevel): readonly CapturedMessage[];
360
- /** Drop every buffered message (total + by level); does NOT stop interception. */
387
+ /** Drops every buffered message (total + by level); does not stop interception. */
361
388
  clear(): void;
362
- /** Tear down — `stop()` (restoring `console`) then destroy the emitter. */
389
+ /** Tears down — `stop()` (restoring `console`) then destroys the emitter. */
363
390
  destroy(): void;
364
391
  }
365
392
 
366
393
  /**
367
- * One intercepted `console` method — the names a {@link CaptureInterface} patches and reports
394
+ * Identifies one intercepted `console` method — the names a {@link CaptureInterface} patches and reports
368
395
  * under. A fixed set keyed off the universal `console.*` methods (`console.log` / `info` / `warn`
369
396
  * / `error` / `debug`); a named value family (it indexes {@link CAPTURE_LEVEL_MAP} to a
370
397
  * {@link LogLevel} for the optional sink forward), never a binary toggle — so it stays a union.
371
398
  *
372
399
  * @remarks
373
- * DISTINCT from {@link LogLevel}: a `CaptureLevel` names the ORIGINATING console method (which
400
+ * distinct from {@link LogLevel}: a `CaptureLevel` names the originating console method (which
374
401
  * `console.x` was called), not a severity threshold — there is no ordering and no gating (every
375
402
  * configured method is captured). `log` and `info` are separate methods (both default-stream),
376
403
  * mapped to the sink's default / `info` stream respectively; `warn` / `error` / `debug` map to
377
- * their matching {@link LogLevel}. The default configured set is {@link DEFAULT_CAPTURE_LEVELS}.
404
+ * their matching {@link LogLevel}. The default configured set is {@link CAPTURE_LEVELS}.
378
405
  */
379
406
  export declare type CaptureLevel = 'log' | 'info' | 'warn' | 'error' | 'debug';
380
407
 
381
408
  /**
382
- * Options for `createCapture` / the {@link CaptureInterface} constructor.
409
+ * Configures the {@link import('./Capture.js').Capture} constructor.
383
410
  *
384
411
  * @remarks
385
- * - `on` — the reserved {@link EmitterHooks} key (§8): initial listeners for the
386
- * {@link CaptureEventMap}, wired at construction (e.g. `{ capture: (m) => tee(m) }`).
387
- * - `error` — the emitter's listener-error handler (§13); a listener throw routes here.
388
- * - `levels` — which `console.*` methods to intercept; defaults to {@link DEFAULT_CAPTURE_LEVELS}
389
- * (all five). Only the listed methods are patched — an unlisted method is left untouched and
390
- * its calls pass through normally.
391
- * - `mirror` — when `true`, each intercepted call is ALSO forwarded to the snapshot-original
412
+ * - `on` — the reserved {@link EmitterHooks} key: initial listeners for the
413
+ * {@link CaptureEventMap}, wired at construction (for example `{ capture: (m) => tee(m) }`).
414
+ * - `error` — the emitter's listener-error handler; a listener throw routes here.
415
+ * - `levels` — which `console.*` methods to intercept; defaults to {@link CAPTURE_LEVELS}. Only the
416
+ * listed methods are patched — an unlisted method is left untouched and its calls pass through
417
+ * normally.
418
+ * - `mirror` — when `true`, each intercepted call is also forwarded to the snapshot-original
392
419
  * `console` method, so the program's own console output still appears while being captured;
393
- * defaults to `false` (capture silently). Mirrors through the method snapshotted AT `start()`,
420
+ * defaults to `false` (capture silently). Mirrors through the method snapshotted at `start()`,
394
421
  * never the live (re-patched) one — no echo loop.
395
422
  * - `sink` — an optional {@link SinkInterface} each intercepted call is also written to
396
- * (`sink.write(text, level)` with the {@link CaptureLevel} mapped to a {@link LogLevel} via
423
+ * (`sink.write(text, level)` with the {@link CaptureLevel} mapped to a {@link LogLevel} through
397
424
  * {@link CAPTURE_LEVEL_MAP}), to tee captured output into the logging pipeline / a file. Absent
398
425
  * ⇒ no forward.
399
426
  * - `limit` — the bounded buffer cap: at most this many recent messages are retained per buffer
400
- * (the total buffer and EACH by-level bucket; oldest dropped first). Defaults to
427
+ * (the total buffer and each by-level bucket; oldest dropped first). Defaults to
401
428
  * {@link DEFAULT_CAPTURE_LIMIT}; never unbounded (a long capture can't grow without bound — the
402
429
  * same retention precedent as {@link LoggerInterface}).
403
430
  */
@@ -411,7 +438,7 @@ export declare interface CaptureOptions {
411
438
  }
412
439
 
413
440
  /**
414
- * The structured outcome of {@link import('./helpers.js').withCapture} — the wrapped function's
441
+ * Represents the structured outcome of {@link import('./factories.js').createCaptureResult} — the wrapped function's
415
442
  * own return `value` plus the {@link CapturedMessage}s intercepted while it ran.
416
443
  *
417
444
  * @remarks
@@ -425,7 +452,7 @@ export declare interface CaptureResult<T> {
425
452
  }
426
453
 
427
454
  /**
428
- * The cell at `index` of a (possibly ragged) row — `''` when the row is shorter than the
455
+ * Returns the cell at `index` of a (possibly ragged) row — `''` when the row is shorter than the
429
456
  * column count, so a short row pads out instead of throwing (the ragged-row guard
430
457
  * {@link renderTable} reads every cell through).
431
458
  *
@@ -436,31 +463,31 @@ export declare interface CaptureResult<T> {
436
463
  export declare function cellAt(row: readonly string[], index: number): string;
437
464
 
438
465
  /**
439
- * A named terminal color — the 8 standard base colors, their 8 bright variants, and
466
+ * Names a terminal color — the 8 standard base colors, their 8 bright variants, and
440
467
  * `default` (the target's own default ink, emitting no color code).
441
468
  *
442
469
  * @remarks
443
- * Style as DATA: a `Color` is a name, not an escape sequence. The renderer maps it to
470
+ * Style as data: a `Color` is a name, not an escape sequence. The renderer maps it to
444
471
  * its target's codes — the ANSI renderer to SGR 30–37 / 90–97 (foreground) and 40–47 /
445
- * 100–107 (background); a browser renderer maps the SAME names to CSS colors.
472
+ * 100–107 (background); a browser renderer maps the same names to CSS colors.
446
473
  * `default` means "leave the target's default" and contributes no code.
447
474
  */
448
475
  export declare type Color = 'black' | 'red' | 'green' | 'yellow' | 'blue' | 'magenta' | 'cyan' | 'white' | 'brightBlack' | 'brightRed' | 'brightGreen' | 'brightYellow' | 'brightBlue' | 'brightMagenta' | 'brightCyan' | 'brightWhite' | 'default';
449
476
 
450
477
  /**
451
- * Every named {@link Color} except `default`, frozen — the colors the styler exposes as
478
+ * Lists every named {@link Color} except `default`, frozen — the colors the styler exposes as
452
479
  * chainable accessors. The source of truth for the color axis; the styler drives its
453
480
  * accessors from this array so the literals live in one place.
454
481
  */
455
482
  export declare const COLORS: ReadonlyArray<Exclude<Color, 'default'>>;
456
483
 
457
484
  /**
458
- * One column of a {@link TableOptions} — its header label and how its cells align.
485
+ * Represents one column of a {@link TableOptions} — its header label and how its cells align.
459
486
  *
460
487
  * @remarks
461
488
  * - `label` — the header text shown in the table's first row.
462
489
  * - `align` — how this column's header and cells align within the column width; defaults to
463
- * {@link DEFAULT_ALIGN} (`left`). The column is sized to the widest VISIBLE content
490
+ * {@link DEFAULT_ALIGN} (`left`). The column is sized to the widest visible content
464
491
  * (header or any cell, measured by {@link import('./helpers.js').width}), so a styled cell
465
492
  * never breaks the column.
466
493
  */
@@ -470,12 +497,12 @@ export declare interface ColumnSpec {
470
497
  }
471
498
 
472
499
  /**
473
- * An error thrown by the console layer.
500
+ * Represents an error thrown by the console layer.
474
501
  *
475
502
  * @remarks
476
503
  * Carries a {@link ConsoleErrorCode} and an optional `context` bag. Thrown for: an
477
504
  * internal invariant violated at a defensive, structurally-unreachable guard
478
- * (`INVARIANT`) — the one throw site in this codebase today.
505
+ * (`INVARIANT`).
479
506
  */
480
507
  export declare class ConsoleError extends Error {
481
508
  readonly code: ConsoleErrorCode;
@@ -484,280 +511,148 @@ export declare class ConsoleError extends Error {
484
511
  }
485
512
 
486
513
  /**
487
- * A machine-readable error code for a {@link import('./errors.js').ConsoleError}.
514
+ * Names a machine-readable error code for a {@link import('./errors.js').ConsoleError}.
488
515
  *
489
516
  * @remarks
490
- * `INVARIANT` — an internal invariant / unreachable-guard was violated (a defensive
491
- * check that should be structurally impossible to trip). The sole code today; §21
492
- * forbids speculating a richer taxonomy before a second throw site exists.
517
+ * `INVARIANT` — an internal invariant or unreachable guard was violated (a defensive check that is
518
+ * structurally impossible to trip). It is the only code the package throws.
493
519
  */
494
520
  export declare type ConsoleErrorCode = 'INVARIANT';
495
521
 
522
+ /**
523
+ * Names the console-method shape a {@link CaptureInterface} snapshots and swaps at the patch
524
+ * boundary — a variadic sink of arbitrary arguments.
525
+ *
526
+ * @remarks
527
+ * It is exactly the universal `console.log` / `info` / `warn` / `error` / `debug` signature, so it
528
+ * types the global `console` viewed as a record keyed by {@link CaptureLevel}. Every
529
+ * `CaptureLevel` is a real `Console` method, so `console` is assignable to that view with no type
530
+ * assertion, which keeps the global-patch boundary honest.
531
+ */
496
532
  export declare type ConsoleMethod = (...args: unknown[]) => void;
497
533
 
498
534
  /**
499
- * Matches every C0 control character EXCEPT `\t` / `\n` / `\r` (which are meaningful
535
+ * Matches every C0 control character except `\t` / `\n` / `\r` (which are meaningful
500
536
  * whitespace), plus DEL (`0x7F`) — the non-printing bytes {@link
501
537
  * import('./helpers.js').stripControls} removes. Global, ASCII-only source (no raw
502
538
  * control-character literal), so a scan builds a fresh `RegExp` the same way as
503
539
  * {@link ANSI_PATTERN} to avoid a mutated `lastIndex`.
504
540
  *
505
541
  * @remarks
506
- * Deliberately SEPARATE from {@link ANSI_PATTERN}: `strip()` must stay pure ANSI-escape
542
+ * Deliberately separate from {@link ANSI_PATTERN}: `strip()` must stay pure ANSI-escape
507
543
  * removal (width / alignment computations depend on it leaving raw C0 bytes alone), while
508
- * C0-stripping is an ADDITIONAL, orthogonal pass a non-TTY output sink applies on top.
544
+ * C0-stripping is an additional, orthogonal pass a non-TTY output sink applies on top.
509
545
  */
510
546
  export declare const CONTROL_PATTERN: RegExp;
511
547
 
512
548
  /**
513
- * Create the cross-environment default {@link RendererInterface} the ANSI / SGR
514
- * renderer that turns style DATA into terminal escape codes. The default behind
515
- * {@link createStyler}; construct one directly to render a {@link import('./types.js').Style}
516
- * without the fluent surface, or to share one instance across stylers.
549
+ * Runs `fn` with the global `console.*` captured for its duration, returning the function's `value`
550
+ * plus the {@link import('./types.js').CapturedMessage}s it logged the scoped, self-restoring
551
+ * ergonomic form of the {@link Capture} class.
552
+ *
553
+ * @param fn - The async function to run under capture (returns `Promise<T>`)
554
+ * @param options - See {@link CaptureOptions} (`levels` / `mirror` / `sink` / `limit` / `on` /
555
+ * `error`); the capture is started for the duration of `fn` regardless
556
+ * @returns A `Promise<CaptureResult<T>>` — awaited, then `console` restored
517
557
  *
518
- * @returns A stateless ANSI {@link RendererInterface}
558
+ * @remarks
559
+ * - **Always restores.** `start()` runs before `fn`; `destroy()` (which calls `stop()`) runs on
560
+ * every path — sync success, sync throw, and each async handler — so `console` is restored even
561
+ * if `fn` throws / rejects (the throw / rejection still propagates). The capture is local —
562
+ * created, used, and destroyed within the call.
563
+ * - **Sync vs async.** A `fn` returning a `Promise` is detected and awaited before `stop()`, so
564
+ * captures during the async work are included; a plain `fn` stops synchronously. The return type
565
+ * follows `fn`'s (overloaded).
566
+ * - **process-global caveat.** Like the {@link Capture} class, this patches the one global
567
+ * `console`. Concurrent `createCaptureResult` calls (or one around other capturing code)
568
+ * interleave — each captures every `console.*` call in flight, and the inner `stop()` restores
569
+ * whatever the outer had installed. Use it for sequential, scoped capture, not overlapping captures.
519
570
  *
520
571
  * @example
521
572
  * ```ts
522
- * import { createANSIRenderer } from '@src/core'
573
+ * import { createCaptureResult } from '@orkestrel/console'
523
574
  *
524
- * const renderer = createANSIRenderer()
525
- * renderer.render({ foreground: 'red', attributes: ['bold'] }, 'alert') // '\x1b[1;31malert\x1b[0m'
575
+ * // The async call is awaited before `console` is restored, so the capture covers the async work.
576
+ * const out = await createCaptureResult(async () => {
577
+ * console.warn('async noise')
578
+ * return 'done'
579
+ * })
580
+ * out.value // 'done'
581
+ * out.messages.map((m) => m.text) // ['async noise']
526
582
  * ```
527
583
  */
528
- export declare function createANSIRenderer(): RendererInterface;
584
+ export declare function createCaptureResult<T>(fn: () => Promise<T>, options?: CaptureOptions): Promise<CaptureResult<T>>;
529
585
 
530
586
  /**
531
- * Create an observable {@link CaptureInterface} console interception on the READ side. While
532
- * `active`, every configured `console.*` call is captured as a frozen
533
- * {@link import('./types.js').CapturedMessage}, buffered (total + by level, bounded), emitted on
534
- * `capture`, and — per options — mirrored to the real console and/or forwarded to a
535
- * {@link SinkInterface}.
587
+ * Runs `fn` with the global `console.*` captured for its duration, returning the function's `value`
588
+ * plus the {@link import('./types.js').CapturedMessage}s it logged, synchronously.
536
589
  *
590
+ * @param fn - The synchronous function to run under capture (returns `T`)
537
591
  * @param options - See {@link CaptureOptions}
538
- * @returns A {@link CaptureInterface} (inactive until `start()`)
539
- *
540
- * @remarks
541
- * - **Snapshot-at-start — no capture loop.** `start()` snapshots the CURRENT `console[level]` per
542
- * configured level, then patches; the mirror writes through that snapshot. Our OWN console sink
543
- * output (the Logger / Reporter, which snapshot `console` at creation) is never recaptured —
544
- * `Capture` catches THIRD-PARTY `console.*`, not our writes. Create your loggers FIRST.
545
- * - **PROCESS-GLOBAL + NON-REENTRANT.** It patches the one global `console`, so at most ONE
546
- * capture may be active at a time; two concurrent captures interleave and clobber each other's
547
- * restore. Prefer {@link withCapture} for a scoped, self-restoring capture.
548
- * - **Bounded.** `options.limit` (default {@link import('./constants.js').DEFAULT_CAPTURE_LIMIT})
549
- * caps both the total buffer and each by-level bucket; never unbounded.
592
+ * @returns A {@link CaptureResult}`<T>` `{ value, messages }`, with `console` already restored
550
593
  *
551
594
  * @example
552
595
  * ```ts
553
- * import { createCapture } from '@src/core'
596
+ * import { createCaptureResult } from '@orkestrel/console'
554
597
  *
555
- * const capture = createCapture({ levels: ['warn', 'error'] })
556
- * capture.start()
557
- * console.error('boom') // captured, NOT mirrored (mirror defaults to false)
558
- * capture.messages('error') // [{ level: 'error', text: 'boom', time: … }]
559
- * capture.stop()
598
+ * // The sync call returns the result directly — no `await`, `console` already restored.
599
+ * const { value, messages } = createCaptureResult(() => {
600
+ * console.log('working')
601
+ * return 42
602
+ * })
603
+ * value // 42
604
+ * messages.map((m) => m.text) // ['working']
560
605
  * ```
561
606
  */
562
- export declare function createCapture(options?: CaptureOptions): CaptureInterface;
607
+ export declare function createCaptureResult<T>(fn: () => T, options?: CaptureOptions): CaptureResult<T>;
563
608
 
564
609
  /**
565
- * Create the default {@link SinkInterface} — a console sink that routes by level and writes
566
- * through the `console` methods SNAPSHOTTED at creation. The default output target behind
567
- * {@link createLogger}.
610
+ * Creates the default {@link SinkInterface} — a console sink that routes by level and writes
611
+ * through the `console` methods snapshotted at creation. The default output target behind the
612
+ * {@link import('./loggers/Logger.js').Logger}.
568
613
  *
569
614
  * @returns A console {@link SinkInterface}
570
615
  *
571
616
  * @remarks
572
617
  * - **Snapshotted — no capture loop.** It captures `console.log` / `console.warn` /
573
- * `console.error` AT CALL TIME and writes through those references. So when a later
574
- * `Capture` (C-d) PATCHES `console.*`, this sink still reaches the REAL streams — the
618
+ * `console.error` at call time and writes through those references. So when a later
619
+ * `Capture` patches `console.*`, this sink still reaches the real streams — the
575
620
  * writer and the capturer never feed each other (the no-capture-loop principle). Create
576
- * the sink (or the logger) BEFORE installing a capture for this to hold.
621
+ * the sink (or the logger) before installing a capture for this to hold.
577
622
  * - **Routes by level.** `error` → the snapshotted `console.error`, `warn` →
578
623
  * `console.warn`, every other level → `console.log`. The `level` is supplied by the
579
- * logger; an omitted `level` goes to `console.log`.
624
+ * logger; an omitted `level` goes to `console.log`. The decision is
625
+ * {@link import('./helpers.js').selectWriter}'s, shared with the browser and server sinks.
580
626
  *
581
627
  * @example
582
628
  * ```ts
583
- * import { createConsoleSink } from '@src/core'
629
+ * import { createConsoleSink } from '@orkestrel/console'
584
630
  *
585
- * const sink = createConsoleSink() // snapshots console.* now
631
+ * const sink = createConsoleSink() // snapshots console.* at construction
586
632
  * sink.write('boom', 'error') // → the real console.error, even after a later console patch
587
633
  * ```
588
634
  */
589
635
  export declare function createConsoleSink(): SinkInterface;
590
636
 
591
637
  /**
592
- * Create an observable, leveled {@link LoggerInterface} — the entry point into structured
593
- * logging. Each `debug` / `info` / `warn` / `error` call builds a frozen
594
- * {@link import('./types.js').LogRecord}, gates it by severity, retains a bounded tail,
595
- * ALWAYS emits it on `entry` (the transport seam), and — unless `silent` — writes a styled
596
- * line to its sink.
597
- *
598
- * @param options - See {@link LoggerOptions}
599
- * @returns A {@link LoggerInterface}
600
- *
601
- * @remarks
602
- * - **Record + event = transport (§13).** Subscribe `logger.emitter.on('entry', …)` to tee
603
- * records to a file / JSON / remote transport; the event fires for every accepted record,
604
- * even when `silent` (silence suppresses only the SINK WRITE).
605
- * - **Bounded retention.** `entries()` returns the recent records, capped at `options.limit`
606
- * (default {@link DEFAULT_LOG_LIMIT}); never unbounded.
607
- * - **Sink + styler defaults.** `options.sink` defaults to {@link createConsoleSink} (the
608
- * snapshotted, level-routing console sink); `options.styler` to {@link createStyler} (ANSI).
609
- * Styling is orthogonal to level — a level only chooses a label color.
610
- *
611
- * @example
612
- * ```ts
613
- * import { createLogger } from '@src/core'
614
- *
615
- * const logger = createLogger({ name: 'http', level: 'info' })
616
- * logger.info('request', { method: 'GET', path: '/' })
617
- * logger.debug('verbose') // dropped — below the info threshold
618
- * ```
619
- */
620
- export declare function createLogger(options?: LoggerOptions): LoggerInterface;
621
-
622
- /**
623
- * Create an event-free {@link LoggerManagerInterface} — a §9 registry of named loggers plus
624
- * a convenience fan-out. It mints + stores {@link LoggerInterface}s keyed by name (its
625
- * defaults flowing into each), looks them up, removes them, and broadcasts a one-off log to
626
- * every registered logger.
627
- *
628
- * @param options - See {@link LoggerManagerOptions}
629
- * @returns A {@link LoggerManagerInterface}
630
- *
631
- * @remarks
632
- * - **Defaults flow in.** `options.level` / `sink` / `styler` / `limit` / `silent` are the
633
- * defaults flowed into every `register`ed logger unless that call's options override them.
634
- * - **Event-free.** The manager carries NO emitter (each registered logger owns its own
635
- * observable `emitter`) — it is a pure registry.
636
- *
637
- * @example
638
- * ```ts
639
- * import { createLoggerManager } from '@src/core'
640
- *
641
- * const loggers = createLoggerManager({ level: 'warn' })
642
- * loggers.register('http')
643
- * loggers.register('db', { level: 'debug' }) // overrides the default
644
- * loggers.warn('slow', { ms: 900 }) // fans out to both
645
- * ```
646
- */
647
- export declare function createLoggerManager(options?: LoggerManagerOptions): LoggerManagerInterface;
648
-
649
- /**
650
- * Create an update-driven, observable {@link ProgressInterface} — a live progress bar. Each
651
- * `update(current)` recomputes the bar, writes `\r` + bar to its sink, and emits `{ current, total }`
652
- * on `update`; `complete` / `failure` commit a final line. The leading `\r` is the sink's to redraw on —
653
- * a TTY sink (C-g) overwrites, a plain sink (C-f) degrades to a fresh line. NO self-timer — the caller
654
- * drives the bar.
655
- *
656
- * @param options - See {@link ProgressOptions} (`total` is required)
657
- * @returns A {@link ProgressInterface}
658
- *
659
- * @remarks
660
- * - **Universal + update-driven.** Built on the one styler + the one sink (no `node:*`, no
661
- * `process.stdout`); progress advances only when the caller reports it. `current` is always clamped
662
- * to `[0, total]`. `options.sink` defaults to {@link createConsoleSink}, `options.styler` to
663
- * {@link createStyler} (ANSI).
664
- * - **Observable (§13).** Subscribe `progress.emitter.on('update', …)` to mirror progress without a
665
- * terminal; `complete` signals a successful finish.
666
- *
667
- * @example
668
- * ```ts
669
- * import { createProgress } from '@src/core'
670
- *
671
- * const progress = createProgress({ total: 100, message: 'downloading' })
672
- * progress.update(40)
673
- * progress.complete('done')
674
- * ```
675
- */
676
- export declare function createProgress(options: ProgressOptions): ProgressInterface;
677
-
678
- /**
679
- * Create a lean, event-free {@link ReporterInterface} — the entry point into narrative
680
- * reporting. Each verb (`section` / `step` / `timing` / `status` / `table` / `tree` / `box` /
681
- * `line` / `blank`) formats through the shared styler + the pure layout renderers and writes to
682
- * the sink — human / build-run narration over the SAME substrate the logger uses.
683
- *
684
- * @param options - See {@link ReporterOptions}
685
- * @returns A {@link ReporterInterface}
686
- *
687
- * @remarks
688
- * - **One styler, one sink.** `options.styler` defaults to {@link createStyler} (ANSI) and
689
- * `options.sink` to {@link createConsoleSink} (the snapshotted, level-routing console sink) —
690
- * no second colorizer. A `status('error', …)` routes to the sink's error stream.
691
- * - **Width-aware.** `options.width` (default {@link DEFAULT_WIDTH}) sizes `section` and a
692
- * `box` with no explicit width; the renderers align on VISIBLE width so styled content keeps
693
- * its columns.
694
- * - **Event-free (§13).** The reporter carries no emitter — a pure formatting front-end, like
695
- * the renderers and `Scheduler`. Reach for a {@link createLogger} when you need observable,
696
- * leveled, transportable records instead.
697
- *
698
- * @example
699
- * ```ts
700
- * import { createReporter } from '@src/core'
701
- *
702
- * const reporter = createReporter()
703
- * reporter.section('Build')
704
- * reporter.step('bundling', { index: 2, total: 5 }) // [2/5] bundling
705
- * reporter.status('success', 'built in 1.2s') // ✔ built in 1.2s
706
- *
707
- * // Disable color (a non-TTY) — every line is plain.
708
- * const plain = createReporter({ styler: createStyler({ enabled: false }) })
709
- * ```
710
- */
711
- export declare function createReporter(options?: ReporterOptions): ReporterInterface;
712
-
713
- /**
714
- * Create a self-driving, observable {@link SpinnerInterface} — a live activity spinner. `start()`
715
- * arms a periodic timer that advances a glyph cycle, writing each `\r` + frame line to its sink and
716
- * emitting it on `frame`; `success` / `failure` commit a final `✔` / `✖` line. The leading `\r` is the
717
- * sink's to redraw on — a TTY sink (C-g) overwrites for a smooth animation, a plain sink (C-f)
718
- * degrades to a fresh line.
719
- *
720
- * @param options - See {@link SpinnerOptions}
721
- * @returns A {@link SpinnerInterface} (inactive until `start()`)
722
- *
723
- * @remarks
724
- * - **Universal + leak-free.** Built on `setInterval` + the one styler + the one sink (no `node:*`,
725
- * no `process.stdout`); the timer is ALWAYS cleared on `success` / `failure` / `stop` / `destroy`, so
726
- * it never leaks. `start()` is idempotent (no second timer while `active`).
727
- * - **Observable (§13).** Subscribe `spinner.emitter.on('frame', …)` to mirror the animation without
728
- * a terminal; `start` / `stop` bracket the timer lifecycle. `options.sink` defaults to
729
- * {@link createConsoleSink}, `options.styler` to {@link createStyler} (ANSI).
730
- *
731
- * @example
732
- * ```ts
733
- * import { createSpinner } from '@src/core'
734
- *
735
- * const spinner = createSpinner({ message: 'building' })
736
- * spinner.start()
737
- * spinner.success('built in 1.2s') // ✔ built in 1.2s — timer cleared, line committed
738
- * ```
739
- */
740
- export declare function createSpinner(options?: SpinnerOptions): SpinnerInterface;
741
-
742
- /**
743
- * Create the fluent, composable {@link StylerInterface} — the consumer-facing styling
638
+ * Creates the fluent, composable {@link StylerInterface} — the consumer-facing styling
744
639
  * API. It builds a {@link import('./types.js').Style} under the hood and renders it
745
- * through a {@link RendererInterface} (the ANSI default), so `styler.red.bold('hi')`
746
- * yields styled text. Chains are immutable, so a base styler is freely reusable.
640
+ * through a {@link import('./types.js').RendererInterface} (the ANSI default), so
641
+ * `styler.red.bold('hi')` yields styled text. Chains are immutable, so a base styler is freely reusable.
747
642
  *
748
643
  * @param options - See {@link StylerOptions}
749
644
  * @returns A base {@link StylerInterface}
750
645
  *
751
646
  * @remarks
752
647
  * - `options.renderer` swaps the output target without touching the style model — pass a
753
- * browser `%c` / CSS renderer (the C-f branch) to retarget; defaults to the ANSI
648
+ * browser `%c` / CSS renderer (the browser branch) to retarget; defaults to the ANSI
754
649
  * renderer (the cross-environment default).
755
650
  * - `options.enabled` is the no-color switch: when `false`, the styler returns text
756
- * VERBATIM (for a non-TTY, `NO_COLOR`, or piped output); defaults to `true`.
651
+ * verbatim (for a non-TTY, `NO_COLOR`, or piped output); defaults to `true`.
757
652
  *
758
653
  * @example
759
654
  * ```ts
760
- * import { createStyler } from '@src/core'
655
+ * import { createStyler } from '@orkestrel/console'
761
656
  *
762
657
  * const style = createStyler()
763
658
  * style.red.bold('error') // bold red
@@ -771,7 +666,7 @@ export declare function createSpinner(options?: SpinnerOptions): SpinnerInterfac
771
666
  export declare function createStyler(options?: StylerOptions): StylerInterface;
772
667
 
773
668
  /**
774
- * Create a {@link Theme} — the app-wide semantic style vocabulary, merged role by role over
669
+ * Creates a {@link Theme} — the app-wide semantic style vocabulary, merged role by role over
775
670
  * {@link DEFAULT_THEME}. Hand one theme to a logger / reporter / spinner / progress and every
776
671
  * surface speaks it; omit `options` for the defaults.
777
672
  *
@@ -779,8 +674,8 @@ export declare function createStyler(options?: StylerOptions): StylerInterface;
779
674
  * @returns A frozen {@link Theme}
780
675
  *
781
676
  * @remarks
782
- * - **Merges per ROLE, not per theme.** An omitted role keeps its default, and `levels` /
783
- * `statuses` merge per ENTRY — `{ levels: { warn: … } }` restyles the `warn` label and
677
+ * - **Merges per role, not per theme.** An omitted role keeps its default, and `levels` /
678
+ * `statuses` merge per entry — `{ levels: { warn: … } }` restyles the `warn` label and
784
679
  * leaves `debug` / `info` / `error` untouched.
785
680
  * - **Frozen and shareable.** The factory snapshots and deep-freezes every style leaf. The
786
681
  * returned theme and its `levels` / `statuses` records are frozen. Each status record is also
@@ -788,7 +683,7 @@ export declare function createStyler(options?: StylerOptions): StylerInterface;
788
683
  *
789
684
  * @example
790
685
  * ```ts
791
- * import { createStyler, createTheme } from '@src/core'
686
+ * import { createStyler, createTheme } from '@orkestrel/console'
792
687
  *
793
688
  * const styler = createStyler()
794
689
  * const theme = createTheme({
@@ -800,63 +695,56 @@ export declare function createStyler(options?: StylerOptions): StylerInterface;
800
695
  */
801
696
  export declare function createTheme(options?: ThemeOptions): Theme;
802
697
 
803
- /** The Control Sequence Introducer (`ESC[`) that opens every SGR sequence. */
698
+ /** Holds the Control Sequence Introducer (`ESC[`) that opens every SGR sequence. */
804
699
  export declare const CSI: string;
805
700
 
806
- /** The default cell {@link Alignment} a {@link import('./types.js').ColumnSpec} uses when none is given — `left`. */
701
+ /** Sets the default cell {@link Alignment} a {@link import('./types.js').ColumnSpec} uses when none is given — `left`. */
807
702
  export declare const DEFAULT_ALIGN: Alignment;
808
703
 
809
704
  /**
810
- * The default visible cell count of a progress-bar TRACK — the glyph run {@link
705
+ * Sets the default visible cell count of a progress-bar track — the glyph run {@link
811
706
  * import('./helpers.js').renderBar} fills (and a {@link import('./types.js').ProgressInterface} sizes
812
- * its bar to). Thirty cells is a compact, terminal-friendly default; a consumer overrides it via
707
+ * its bar to). Thirty cells is a compact, terminal-friendly default; a consumer overrides it through
813
708
  * `options.width`. Distinct from {@link DEFAULT_WIDTH} (the renderers' 80-column line width) — a bar
814
709
  * track is one inline element, not a full-width rule.
815
710
  */
816
711
  export declare const DEFAULT_BAR_WIDTH = 30;
817
712
 
818
- /** The default {@link BorderStyle} the box / table renderers frame with when none is given — `single`. */
713
+ /** Sets the default {@link BorderStyle} the box / table renderers frame with when none is given — `single`. */
819
714
  export declare const DEFAULT_BORDER: BorderStyle;
820
715
 
821
716
  /**
822
- * The default set of {@link CaptureLevel}s a Capture patches when `options.levels` is omitted —
823
- * all five universal `console.*` methods ({@link CAPTURE_LEVELS}). A consumer narrows it (e.g. just
824
- * `['warn', 'error']`) via `options.levels`.
825
- */
826
- export declare const DEFAULT_CAPTURE_LEVELS: readonly CaptureLevel[];
827
-
828
- /**
829
- * The default bounded-buffer cap for a {@link import('./types.js').CaptureInterface} — at most this
830
- * many recent {@link CapturedMessage}s are retained per buffer (the total buffer AND each by-level
831
- * bucket; oldest dropped first). Capture retention is ALWAYS bounded so a long-running capture can
717
+ * Sets the default bounded-buffer cap for a {@link import('./types.js').CaptureInterface} at most this
718
+ * many recent {@link CapturedMessage}s are retained per buffer (the total buffer and each by-level
719
+ * bucket; oldest dropped first). Capture retention is always bounded so a long-running capture can
832
720
  * never grow without bound (the same retention precedent as {@link DEFAULT_LOG_LIMIT}); a consumer
833
- * overrides it via `options.limit`.
721
+ * overrides it through `options.limit`.
834
722
  */
835
723
  export declare const DEFAULT_CAPTURE_LIMIT = 1000;
836
724
 
837
- /** The default {@link LogLevel} threshold a logger gates at when none is supplied — `info`. */
725
+ /** Sets the default {@link LogLevel} threshold a logger gates at when none is supplied — `info`. */
838
726
  export declare const DEFAULT_LOG_LEVEL: LogLevel;
839
727
 
840
728
  /**
841
- * The default bounded-retention cap for a {@link import('./types.js').LoggerInterface} — at
842
- * most this many recent records are kept (oldest dropped first). Retention is ALWAYS bounded
843
- * (never the unbounded buffer scsr leaked); a consumer overrides it via `options.limit`.
729
+ * Sets the default bounded-retention cap for a {@link import('./types.js').LoggerInterface} — at
730
+ * most this many recent records are kept (oldest dropped first). Retention is always bounded — the
731
+ * oldest record is dropped after the cap is reached; a consumer overrides it through `options.limit`.
844
732
  */
845
733
  export declare const DEFAULT_LOG_LIMIT = 1000;
846
734
 
847
- /** The default horizontal padding inside a box's edges ({@link import('./helpers.js').renderBox}) — one cell. */
735
+ /** Sets the default horizontal padding inside a box's edges ({@link import('./helpers.js').renderBox}) — one cell. */
848
736
  export declare const DEFAULT_PADDING = 1;
849
737
 
850
738
  /**
851
- * The default timer period in milliseconds between a {@link import('./types.js').SpinnerInterface}'s
739
+ * Sets the default timer period in milliseconds between a {@link import('./types.js').SpinnerInterface}'s
852
740
  * frames — the `setInterval` interval `start()` arms. Eighty milliseconds (≈12.5 frames/second) is
853
741
  * the conventional spinner cadence: fast enough to read as motion, slow enough not to thrash a
854
- * terminal. A consumer overrides it via `options.interval`.
742
+ * terminal. A consumer overrides it through `options.interval`.
855
743
  */
856
744
  export declare const DEFAULT_SPINNER_INTERVAL = 80;
857
745
 
858
746
  /**
859
- * The default {@link Theme} — every role bound to its default {@link Style}, deeply frozen.
747
+ * Holds the default {@link Theme} — every role bound to its default {@link Style}, deeply frozen.
860
748
  * The base {@link import('./factories.js').createTheme} merges over, and the theme every
861
749
  * entity uses when none is supplied.
862
750
  *
@@ -871,34 +759,34 @@ export declare const DEFAULT_SPINNER_INTERVAL = 80;
871
759
  export declare const DEFAULT_THEME: Theme;
872
760
 
873
761
  /**
874
- * The default visible column width for the width-aware renderers — the separator rule and a
762
+ * Sets the default visible column width for the width-aware renderers — the separator rule and a
875
763
  * {@link import('./helpers.js').renderBox} with no explicit `width`, and the reporter's
876
- * `section` rule. A sane terminal default (80 columns); a caller overrides it per-call or via
764
+ * `section` rule. A sane terminal default (80 columns); a caller overrides it per-call or through
877
765
  * {@link import('./types.js').ReporterOptions}`.width`.
878
766
  */
879
767
  export declare const DEFAULT_WIDTH = 80;
880
768
 
881
769
  /**
882
- * The EMPTY {@link Style} — no foreground, no background, no attributes — frozen. The
770
+ * Holds the empty {@link Style} — no foreground, no background, no attributes — frozen. The
883
771
  * neutral starting point a base styler builds from, and what a renderer passes through
884
772
  * unchanged (it carries no codes). Deeply frozen, so it is safe to share as the base.
885
773
  */
886
774
  export declare const EMPTY_STYLE: Style;
887
775
 
888
776
  /**
889
- * The ESC control character (`U+001B`) that begins every ANSI escape sequence. Built
777
+ * Holds the ESC control character (`U+001B`) that begins every ANSI escape sequence. Built
890
778
  * with `String.fromCharCode` so no raw control character appears in source.
891
779
  */
892
780
  export declare const ESC: string;
893
781
 
894
782
  /**
895
- * Each {@link Color}'s SGR FOREGROUND parameter — the 8 base colors at 30–37 and their
783
+ * Maps each {@link Color} to its SGR foreground parameter — the 8 base colors at 30–37 and their
896
784
  * bright variants at 90–97. `default` is intentionally absent (it emits no code).
897
785
  */
898
786
  export declare const FOREGROUND_CODES: Readonly<Record<Exclude<Color, 'default'>, number>>;
899
787
 
900
788
  /**
901
- * Stringify a captured `console.*` argument list into ONE line — the text of a {@link
789
+ * Stringifies a captured `console.*` argument list into one line — the text of a {@link
902
790
  * import('./types.js').CapturedMessage}. Each argument is rendered by {@link stringifyValue} and
903
791
  * the parts are space-joined, mirroring how a console concatenates its arguments.
904
792
  *
@@ -919,7 +807,7 @@ export declare const FOREGROUND_CODES: Readonly<Record<Exclude<Color, 'default'>
919
807
  export declare function formatArgs(args: readonly unknown[]): string;
920
808
 
921
809
  /**
922
- * Format a millisecond duration as a compact human string — `…ms` below one second, `…s`
810
+ * Formats a millisecond duration as a compact human string — `…ms` below one second, `…s`
923
811
  * (seconds to 2 decimal places) at or above one second. The timing rendering behind
924
812
  * {@link import('./types.js').ReporterInterface.timing}.
925
813
  *
@@ -933,7 +821,7 @@ export declare function formatArgs(args: readonly unknown[]): string;
933
821
  export declare function formatDuration(ms: number): string;
934
822
 
935
823
  /**
936
- * Format a {@link LogRecord} into a single styled line — the default human line layout a
824
+ * Formats a {@link LogRecord} into a single styled line — the default human line layout a
937
825
  * {@link import('./types.js').LoggerInterface} writes to its sink.
938
826
  *
939
827
  * @remarks
@@ -942,7 +830,7 @@ export declare function formatDuration(ms: number): string;
942
830
  * the originating logger's `name` in brackets (omitted when absent), the message, and the
943
831
  * structured `data` appended as compact JSON (omitted when absent / empty). Coloring flows
944
832
  * through the injected `styler`, so a disabled styler yields a plain line and a browser
945
- * `%c` styler (C-f) retargets it — the layout never changes. Pure: same record + styler →
833
+ * `%c` styler retargets it — the layout never changes. Pure: same record + styler →
946
834
  * same line.
947
835
  *
948
836
  * @param record - The {@link LogRecord} to render
@@ -963,10 +851,10 @@ export declare function formatDuration(ms: number): string;
963
851
  export declare function formatRecord(record: LogRecord, styler: StylerInterface, theme: Theme): string;
964
852
 
965
853
  /**
966
- * Format a {@link LogRecord}'s `time` (epoch milliseconds) as an ISO-8601 timestamp string.
854
+ * Formats a {@link LogRecord}'s `time` (epoch milliseconds) as an ISO-8601 timestamp string.
967
855
  *
968
856
  * @remarks
969
- * Deterministic and serializable — `new Date(time).toISOString()`, e.g.
857
+ * Deterministic and serializable — `new Date(time).toISOString()`, for example
970
858
  * `1716900000000 → '2024-05-28T12:40:00.000Z'`. The timestamp portion of the formatted log
971
859
  * line; kept a pure helper so the line layout and the logger stay decoupled.
972
860
  *
@@ -976,7 +864,7 @@ export declare function formatRecord(record: LogRecord, styler: StylerInterface,
976
864
  export declare function formatTime(time: number): string;
977
865
 
978
866
  /**
979
- * Snapshot and deeply freeze one {@link Style} value.
867
+ * Snapshots and deeply freezes one {@link Style} value.
980
868
  *
981
869
  * @param style - The caller-owned style to snapshot
982
870
  * @returns A frozen style record with an independently frozen attributes list
@@ -993,10 +881,10 @@ export declare function formatTime(time: number): string;
993
881
  export declare function freezeStyle(style: Style): Style;
994
882
 
995
883
  /**
996
- * Narrow an unknown caught value to a {@link ConsoleError}.
884
+ * Narrows an unknown caught value to a {@link ConsoleError}.
997
885
  *
998
886
  * @param value - The value to test (typically a `catch` binding)
999
- * @returns `true` when `value` is a {@link ConsoleError}
887
+ * @returns True if `value` is a {@link ConsoleError}; false otherwise
1000
888
  *
1001
889
  * @example
1002
890
  * ```ts
@@ -1010,8 +898,8 @@ export declare function freezeStyle(style: Style): Style;
1010
898
  export declare function isConsoleError(value: unknown): value is ConsoleError;
1011
899
 
1012
900
  /**
1013
- * Each {@link LogLevel}'s default label {@link Color} — the level's VISUAL treatment, which
1014
- * is a styling choice ORTHOGONAL to the level itself (never a separate pseudo-level). The
901
+ * Maps each {@link LogLevel} to its default label {@link Color} — the level's visual treatment, which
902
+ * is a styling choice orthogonal to the level itself (never a separate pseudo-level). The
1015
903
  * logger colors the level label through its styler with these; swapping a color never
1016
904
  * changes leveling. `debug` is cyan, `info` blue, `warn` yellow, `error` red.
1017
905
  *
@@ -1022,21 +910,21 @@ export declare function isConsoleError(value: unknown): value is ConsoleError;
1022
910
  export declare const LEVEL_COLORS: Readonly<Record<LogLevel, Exclude<Color, 'default'>>>;
1023
911
 
1024
912
  /**
1025
- * Each {@link LogLevel}'s numeric SEVERITY — the ascending order the level gate compares
913
+ * Maps each {@link LogLevel} to its numeric severity — the ascending order the level gate compares
1026
914
  * through (`debug` 0 < `info` 1 < `warn` 2 < `error` 3). A record is kept when its level's
1027
915
  * severity is at or above the logger's threshold. The source of truth for level ordering.
1028
916
  */
1029
917
  export declare const LEVEL_SEVERITY: Readonly<Record<LogLevel, number>>;
1030
918
 
1031
919
  /**
1032
- * Every {@link LogLevel}, in ascending severity order — the levels a logger exposes as
920
+ * Lists every {@link LogLevel}, in ascending severity order — the levels a logger exposes as
1033
921
  * methods and the manager fans out to. The source of truth for the level axis (drives
1034
922
  * exhaustive tests); aligned with {@link LEVEL_SEVERITY}.
1035
923
  */
1036
- export declare const LEVELS: readonly LogLevel[];
924
+ export declare const LOG_LEVELS: readonly LogLevel[];
1037
925
 
1038
926
  /**
1039
- * The line layout a logger writes — one {@link LogRecord} plus the styling substrate in,
927
+ * Represents the line layout a logger writes — one {@link LogRecord} plus the styling substrate in,
1040
928
  * one finished line out. {@link import('./helpers.js').formatRecord} is the default.
1041
929
  *
1042
930
  * @param record - The frozen record to lay out
@@ -1044,10 +932,10 @@ export declare const LEVELS: readonly LogLevel[];
1044
932
  * {@link StylerInterface.render} for a {@link Theme} role) so a disabled styler yields a
1045
933
  * plain line with no second code path
1046
934
  * @param theme - The logger's {@link Theme} — the level label style, the chrome surround
1047
- * @returns The line to write, WITHOUT a trailing terminator (the sink's target supplies it)
935
+ * @returns The line to write, without a trailing terminator (the sink's target supplies it)
1048
936
  *
1049
937
  * @remarks
1050
- * The formatter owns the LINE; the `entry` event owns the RECORD. A transport that wants
938
+ * The formatter owns the line; the `entry` event owns the record. A transport that wants
1051
939
  * structure rides the event rather than parsing a line back out of this. A formatter throw
1052
940
  * propagates to the caller of `logger.info` and prevents that line's write, so keep it total.
1053
941
  * A manager fans out sequentially; a formatter throw stops the remaining loggers for that call.
@@ -1055,25 +943,25 @@ export declare const LEVELS: readonly LogLevel[];
1055
943
  export declare type LogFormatFunction = (record: LogRecord, styler: StylerInterface, theme: Theme) => string;
1056
944
 
1057
945
  /**
1058
- * An observable, leveled logger (AGENTS §13) — the entry point into the structured-logging
946
+ * Implements an observable, leveled logger — the entry point into the structured-logging
1059
947
  * pipeline. Each `debug` / `info` / `warn` / `error` call builds a frozen {@link LogRecord},
1060
- * gates it by severity, retains a bounded tail of accepted records, ALWAYS emits it on
948
+ * gates it by severity, retains a bounded tail of accepted records, always emits it on
1061
949
  * `entry` (the transport seam), and — unless `silent` — formats it into a styled line and
1062
950
  * writes it to its {@link SinkInterface}.
1063
951
  *
1064
952
  * @remarks
1065
- * - **Record + event = transport (§13).** An accepted record is frozen and emitted on
1066
- * `entry` BEFORE anything else observable — every file / JSON / remote transport rides
953
+ * - **Record + event = transport.** An accepted record is frozen and emitted on
954
+ * `entry` before anything else observable — every file / JSON / remote transport rides
1067
955
  * `emitter.on('entry')`. The event fires even when `silent`: silence suppresses only the
1068
- * SINK WRITE, never the record or the event, so transports keep flowing.
956
+ * sink write, never the record or the event, so transports keep flowing.
1069
957
  * - **Leveled gate.** A record whose {@link LogLevel} is below the logger's `level` threshold
1070
- * is dropped ENTIRELY — no record built past the level check, no event, no retention, no
958
+ * is dropped entirely — no record built past the level check, no event, no retention, no
1071
959
  * write (see {@link meetsLevel}).
1072
960
  * - **Bounded retention.** Accepted records accrue in a ring capped at `limit` (default
1073
961
  * {@link DEFAULT_LOG_LIMIT}); the oldest is dropped when full. `entries()` returns a copy,
1074
- * oldest first; `clear()` empties it. NEVER unbounded (scsr's leak).
962
+ * oldest first; `clear()` empties it. Never unbounded retention is capped at `limit`.
1075
963
  * - **Styled write, orthogonal to level.** The line ({@link formatRecord}) is colored through
1076
- * the injected `styler` (the ANSI default, or a browser `%c` styler at C-f) — a level only
964
+ * the injected `styler` (the ANSI default, or a browser `%c` styler) — a level only
1077
965
  * chooses a label color; styling is not a level. A disabled styler yields a plain line.
1078
966
  * - **Snapshotted sink.** The default {@link createConsoleSink} writes to the `console`
1079
967
  * methods captured at creation, so a later `Capture` patching `console` can't loop the
@@ -1104,25 +992,25 @@ export declare class Logger implements LoggerInterface {
1104
992
  }
1105
993
 
1106
994
  /**
1107
- * The observable events a {@link LoggerInterface} emits (AGENTS §13) — the transport seam.
995
+ * Declares the observable events a {@link LoggerInterface} emits — the transport seam.
1108
996
  *
1109
997
  * @remarks
1110
- * `entry` fires for EVERY accepted record (one that passed the level gate), carrying the
998
+ * `entry` fires for every accepted record (one that passed the level gate), carrying the
1111
999
  * frozen {@link LogRecord} — even when the logger is `silent` (silence suppresses only the
1112
- * SINK WRITE, never the event, so transports keep receiving records). Listener isolation is
1113
- * the emitter's (§13): a listener throw routes to the emitter's `error` handler, never onto
1000
+ * sink write, never the event, so transports keep receiving records). Listener isolation is
1001
+ * the emitter's: a listener throw routes to the emitter's `error` handler, never onto
1114
1002
  * this map — so a buggy transport can never perturb logging.
1115
1003
  *
1116
- * Declared as a `type` alias (not `interface extends EventMap`, §4.5): a type-literal
1004
+ * Declared as a `type` alias (not `interface extends EventMap`): a type-literal
1117
1005
  * satisfies the `EventMap` constraint structurally, whereas an interface lacks the index signature.
1118
1006
  */
1119
1007
  export declare type LoggerEventMap = {
1120
- /** A record was logged (passed the level gate) — the frozen {@link LogRecord}. */
1008
+ /** Fires after a record was logged (passed the level gate) — the frozen {@link LogRecord}. */
1121
1009
  readonly entry: readonly [record: LogRecord];
1122
1010
  };
1123
1011
 
1124
1012
  /**
1125
- * An observable, leveled logger — builds a frozen {@link LogRecord} per call, gates it by
1013
+ * Declares an observable, leveled logger — builds a frozen {@link LogRecord} per call, gates it by
1126
1014
  * severity, retains a bounded tail, emits it on `entry`, and (unless silent) writes a
1127
1015
  * styled line to its {@link SinkInterface}.
1128
1016
  *
@@ -1130,7 +1018,7 @@ export declare type LoggerEventMap = {
1130
1018
  * - **Leveled.** Each of `debug` / `info` / `warn` / `error` builds a record at that
1131
1019
  * {@link LogLevel}; a record below the logger's `level` threshold is dropped entirely (no
1132
1020
  * event, no retention, no write).
1133
- * - **Transport seam (§13).** An accepted record ALWAYS fires `entry` (even when `silent`),
1021
+ * - **Transport seam.** An accepted record always fires `entry` (even when `silent`),
1134
1022
  * carrying the frozen {@link LogRecord} — the hook every file / JSON / remote transport rides.
1135
1023
  * - **Bounded retention.** `entries()` returns the recent records, capped at `limit` (oldest
1136
1024
  * dropped first) — never an unbounded buffer. `clear()` empties it.
@@ -1143,39 +1031,40 @@ export declare interface LoggerInterface {
1143
1031
  readonly emitter: EmitterInterface<LoggerEventMap>;
1144
1032
  readonly level: LogLevel;
1145
1033
  readonly name?: string;
1146
- /** Log at `debug` — dropped unless the logger's `level` is `debug`. */
1034
+ /** Logs at `debug` — dropped unless the logger's `level` is `debug`. */
1147
1035
  debug(message: string, data?: Record<string, unknown>): void;
1148
- /** Log at `info`. */
1036
+ /** Logs at `info`. */
1149
1037
  info(message: string, data?: Record<string, unknown>): void;
1150
- /** Log at `warn`. */
1038
+ /** Logs at `warn`. */
1151
1039
  warn(message: string, data?: Record<string, unknown>): void;
1152
- /** Log at `error`. */
1040
+ /** Logs at `error`. */
1153
1041
  error(message: string, data?: Record<string, unknown>): void;
1154
- /** The bounded tail of recent {@link LogRecord}s, oldest first (capped at `limit`). */
1042
+ /** Returns the bounded tail of recent {@link LogRecord}s, oldest first (capped at `limit`). */
1155
1043
  entries(): readonly LogRecord[];
1156
- /** Drop every retained record (does not touch listeners). */
1044
+ /** Drops every retained record (does not touch listeners). */
1157
1045
  clear(): void;
1158
- /** Tear down — clear retention and destroy the emitter. */
1046
+ /** Tears down — clears retention and destroys the emitter. */
1159
1047
  destroy(): void;
1160
1048
  }
1161
1049
 
1162
1050
  /**
1163
- * An event-free registry of named {@link Logger}s plus a convenience fan-out — the §9
1051
+ * Implements an event-free registry of named {@link Logger}s plus a convenience fan-out — the
1164
1052
  * manager over the logging layer (a registry, never observable itself; each {@link Logger}
1165
1053
  * owns its own `emitter`).
1166
1054
  *
1167
1055
  * @remarks
1168
- * - **Registry (§9).** Loggers live in an insertion-ordered `Map` keyed by `name`.
1056
+ * - **Registry.** Loggers live in an insertion-ordered `Map` keyed by `name`.
1169
1057
  * `register(name, options?)` mints a {@link Logger} named `name` — the manager's default
1170
1058
  * `level` / `sink` / `styler` / `theme` / `format` / `limit` / `silent` flow in unless
1171
- * `options` OVERRIDES them
1059
+ * `options` overrides them
1172
1060
  * (`name` is always the registry key, so any `options.name` is ignored) — stores it (a
1173
- * re-`register` of the same name OVERWRITES, last write wins), and returns it. `count` is
1061
+ * re-`register` of the same name overwrites, last write wins), and returns it. `count` is
1174
1062
  * the map size, `logger(name)` looks one up, `loggers()` lists them in insertion order.
1175
- * - **Removal (§9.2).** `remove()` clears ALL, `remove(name)` drops ONE (`true` if present),
1176
- * `remove(names)` drops a batch (`true` if any was removed).
1177
- * (Removal does NOT `destroy` the returned loggers a caller still holding one keeps using
1178
- * it; the manager simply stops tracking it.)
1063
+ * - **Removal.** `remove()` clears all, `remove(name)` drops one (`true` if present),
1064
+ * `remove(names)` drops a batch (`true` only when every name was present; an empty list
1065
+ * succeeds vacuously). Every listed name is attempted whatever the result.
1066
+ * (Removal does not `destroy` the returned loggers a caller still holding one keeps using
1067
+ * it; the manager stops tracking it.)
1179
1068
  * - **Fan-out.** `debug` / `info` / `warn` / `error(message, data?)` forward the one call to
1180
1069
  * every registered logger in insertion order; each gates / emits / writes per its own `level`
1181
1070
  * and `sink`. A formatter throw is a programmer error and propagates, stopping the remaining
@@ -1209,17 +1098,18 @@ export declare class LoggerManager implements LoggerManagerInterface {
1209
1098
  }
1210
1099
 
1211
1100
  /**
1212
- * An event-free registry of named {@link LoggerInterface}s plus a convenience fan-out — the
1213
- * §9 manager over the logging layer. It mints + stores loggers keyed by `name`, looks them
1214
- * up, removes them, and broadcasts a one-off log to EVERY registered logger.
1101
+ * Declares an event-free registry of named {@link LoggerInterface}s plus a convenience fan-out — the
1102
+ * manager over the logging layer. It mints + stores loggers keyed by `name`, looks them
1103
+ * up, removes them, and broadcasts a one-off log to every registered logger.
1215
1104
  *
1216
1105
  * @remarks
1217
- * - **Registry (§9).** `register(name, options?)` mints a {@link LoggerInterface} (named
1106
+ * - **Registry.** `register(name, options?)` mints a {@link LoggerInterface} (named
1218
1107
  * `name`, the manager's defaults flowing in unless `options` overrides them), stores it
1219
- * (a re-`register` of the same name OVERWRITES — last write wins), and returns it.
1108
+ * (a re-`register` of the same name overwrites — last write wins), and returns it.
1220
1109
  * `logger(name)` looks one up; `loggers()` lists them in insertion order; `count` is the size.
1221
- * - **Removal (§9.2).** `remove()` clears ALL, `remove(name)` drops ONE, `remove(names)` drops
1222
- * a batch (`true` when any was removed).
1110
+ * - **Removal.** `remove()` clears all, `remove(name)` drops one, `remove(names)` drops
1111
+ * a batch (`true` only when every name was present; an empty list succeeds vacuously).
1112
+ * Every listed name is attempted whatever the result.
1223
1113
  * - **Fan-out.** `debug` / `info` / `warn` / `error(message, data?)` forward the call to every
1224
1114
  * registered logger (each gates / emits / writes per its own `level` and `sink`).
1225
1115
  * - **Event-free.** No emitter, no events — each logger carries its own observability; the
@@ -1230,13 +1120,13 @@ export declare interface LoggerManagerInterface {
1230
1120
  register(name: string, options?: LoggerOptions): LoggerInterface;
1231
1121
  logger(name: string): LoggerInterface | undefined;
1232
1122
  loggers(): readonly LoggerInterface[];
1233
- /** Fan out a `debug` log to every registered logger. */
1123
+ /** Fans out a `debug` log to every registered logger. */
1234
1124
  debug(message: string, data?: Record<string, unknown>): void;
1235
- /** Fan out an `info` log to every registered logger. */
1125
+ /** Fans out an `info` log to every registered logger. */
1236
1126
  info(message: string, data?: Record<string, unknown>): void;
1237
- /** Fan out a `warn` log to every registered logger. */
1127
+ /** Fans out a `warn` log to every registered logger. */
1238
1128
  warn(message: string, data?: Record<string, unknown>): void;
1239
- /** Fan out an `error` log to every registered logger. */
1129
+ /** Fans out an `error` log to every registered logger. */
1240
1130
  error(message: string, data?: Record<string, unknown>): void;
1241
1131
  remove(): void;
1242
1132
  remove(name: string): boolean;
@@ -1244,12 +1134,12 @@ export declare interface LoggerManagerInterface {
1244
1134
  }
1245
1135
 
1246
1136
  /**
1247
- * Options for `createLoggerManager` / the {@link LoggerManagerInterface} constructor.
1137
+ * Configures the {@link import('./loggers/LoggerManager.js').LoggerManager} constructor.
1248
1138
  *
1249
1139
  * @remarks
1250
- * The manager is an event-free registry (§9) — it carries NO emitter of its own (each
1140
+ * The manager is an event-free registry — it carries no emitter of its own (each
1251
1141
  * registered {@link LoggerInterface} owns its observable `emitter`). These options supply
1252
- * the DEFAULTS flowed into every logger the manager mints, unless a per-`register` override
1142
+ * the defaults flowed into every logger the manager mints, unless a per-`register` override
1253
1143
  * wins: `level` (default threshold), `sink` (shared output target), `styler` (shared
1254
1144
  * coloring), `theme` (semantic styles), `format` (line layout), `limit` (retention cap),
1255
1145
  * and `silent`.
@@ -1265,13 +1155,13 @@ export declare interface LoggerManagerOptions {
1265
1155
  }
1266
1156
 
1267
1157
  /**
1268
- * Options for `createLogger` / the {@link LoggerInterface} constructor.
1158
+ * Configures the {@link import('./loggers/Logger.js').Logger} constructor.
1269
1159
  *
1270
1160
  * @remarks
1271
- * - `on` — the reserved {@link EmitterHooks} key (§8): initial listeners for the
1272
- * {@link LoggerEventMap}, wired at construction (e.g. `{ entry: (r) => sink2.write(...) }`).
1273
- * - `error` — the emitter's listener-error handler (§13); a listener throw routes here.
1274
- * - `level` — the severity THRESHOLD; records below it are dropped. Defaults to `info`.
1161
+ * - `on` — the reserved {@link EmitterHooks} key: initial listeners for the
1162
+ * {@link LoggerEventMap}, wired at construction (for example `{ entry: (r) => sink2.write(...) }`).
1163
+ * - `error` — the emitter's listener-error handler; a listener throw routes here.
1164
+ * - `level` — the severity threshold; records below it are dropped. Defaults to `info`.
1275
1165
  * - `name` — the logger's name, stamped onto every {@link LogRecord} (`record.name`) and
1276
1166
  * shown in the formatted line. A manager registers each logger under its name.
1277
1167
  * - `sink` — where formatted lines are written; defaults to
@@ -1284,7 +1174,7 @@ export declare interface LoggerManagerOptions {
1284
1174
  * {@link import('./helpers.js').formatRecord}.
1285
1175
  * - `limit` — the bounded retention cap: at most this many recent records are kept
1286
1176
  * (oldest dropped first). Defaults to {@link DEFAULT_LOG_LIMIT}; never unbounded.
1287
- * - `silent` — when `true`, suppresses the SINK WRITE only; `entry` still fires and the
1177
+ * - `silent` — when `true`, suppresses the sink write only; `entry` still fires and the
1288
1178
  * record is still retained. Defaults to `false`.
1289
1179
  */
1290
1180
  export declare interface LoggerOptions {
@@ -1301,19 +1191,19 @@ export declare interface LoggerOptions {
1301
1191
  }
1302
1192
 
1303
1193
  /**
1304
- * The severity level of a {@link LogRecord} — one coherent, ascending-severity scale.
1194
+ * Names the severity level of a {@link LogRecord} — one coherent, ascending-severity scale.
1305
1195
  *
1306
1196
  * @remarks
1307
1197
  * Ordered least-to-most severe: `debug` < `info` < `warn` < `error`. A {@link LoggerInterface}
1308
- * gates by THRESHOLD — a record at or above the logger's `level` is kept (and written),
1198
+ * gates by threshold — a record at or above the logger's `level` is kept (and written),
1309
1199
  * one below it is dropped (see {@link LEVEL_SEVERITY} for the numeric order). A level is a
1310
- * level — its visual treatment (color) is a separate styling concern, NEVER a pseudo-level
1200
+ * level — its visual treatment (color) is a separate styling concern, never a pseudo-level
1311
1201
  * like `success` / `ready`.
1312
1202
  */
1313
1203
  export declare type LogLevel = 'debug' | 'info' | 'warn' | 'error';
1314
1204
 
1315
1205
  /**
1316
- * One immutable, serializable log entry — the universal record the whole logging system
1206
+ * Represents one immutable, serializable log entry — the universal record the whole logging system
1317
1207
  * carries. A {@link LoggerInterface} builds one per call, freezes it, retains a bounded
1318
1208
  * tail of them, and emits it on `entry`; every sink / transport consumes this exact shape.
1319
1209
  *
@@ -1325,9 +1215,9 @@ export declare type LogLevel = 'debug' | 'info' | 'warn' | 'error';
1325
1215
  * - `name` — the originating logger's `name`, when it has one (a manager-registered logger
1326
1216
  * is keyed by name; an anonymous logger omits it).
1327
1217
  * - `data` — optional structured context (a flat `Record<string, unknown>`), absent when
1328
- * no context was supplied. The top-level object is a FROZEN COPY taken at log time (a
1218
+ * no context was supplied. The top-level object is a frozen copy taken at log time (a
1329
1219
  * later mutation of the caller's original object never reaches the retained record);
1330
- * nested values remain BY REFERENCE (only the top level is copied + frozen).
1220
+ * nested values remain by reference (only the top level is copied + frozen).
1331
1221
  * - The value is frozen at construction — a consumer reads it, never mutates it.
1332
1222
  */
1333
1223
  export declare interface LogRecord {
@@ -1339,17 +1229,17 @@ export declare interface LogRecord {
1339
1229
  }
1340
1230
 
1341
1231
  /**
1342
- * Whether a record at `level` passes a logger gated at `threshold` — i.e. its severity is
1343
- * at or above the threshold's.
1232
+ * Checks whether a record at `level` passes a logger gated at `threshold` — that is, its severity
1233
+ * is at or above the threshold's.
1344
1234
  *
1345
1235
  * @remarks
1346
- * The level gate (AGENTS §5 — the comparison lives here, not inlined in the logger). Reads
1236
+ * The level gate (the comparison lives here, not inlined in the logger). Reads
1347
1237
  * the ascending {@link LEVEL_SEVERITY} order: `meetsLevel('warn', 'error')` is `true`
1348
1238
  * (error ≥ warn), `meetsLevel('warn', 'info')` is `false` (info < warn).
1349
1239
  *
1350
1240
  * @param threshold - The logger's configured minimum {@link LogLevel}
1351
1241
  * @param level - The record's {@link LogLevel}
1352
- * @returns `true` when `level` is at least as severe as `threshold`
1242
+ * @returns True if `level` is at least as severe as `threshold`; false otherwise
1353
1243
  *
1354
1244
  * @example
1355
1245
  * ```ts
@@ -1360,12 +1250,12 @@ export declare interface LogRecord {
1360
1250
  export declare function meetsLevel(threshold: LogLevel, level: LogLevel): boolean;
1361
1251
 
1362
1252
  /**
1363
- * Color `text` through `styler`, or return it verbatim when `styler` is `undefined` — the
1253
+ * Colors `text` through `styler`, or returns it verbatim when `styler` is `undefined` — the
1364
1254
  * single optional-styling primitive every renderer applies to its border / title / connector
1365
- * glyphs (AGENTS §5 — the ONE styler seam, shared, never re-hand-rolled per renderer).
1255
+ * glyphs (the one styler seam, shared, never re-hand-rolled per renderer).
1366
1256
  *
1367
1257
  * @remarks
1368
- * The renderers all take an OPTIONAL `styler`: present ⇒ glyphs are colored, absent ⇒ plain.
1258
+ * The renderers all take an optional `styler`: present ⇒ glyphs are colored, absent ⇒ plain.
1369
1259
  * Folding that `styler === undefined ? text : styler(text)` ternary into one exported helper
1370
1260
  * keeps the renderers terse and the styling decision in one tested place. A disabled styler
1371
1261
  * (`enabled: false`) is still a styler — it returns its text verbatim — so passing one paints
@@ -1379,31 +1269,31 @@ export declare function meetsLevel(threshold: LogLevel, level: LogLevel): boolea
1379
1269
  export declare function paint(styler: StylerInterface | undefined, text: string, style?: Style): string;
1380
1270
 
1381
1271
  /**
1382
- * An update-driven, observable progress bar (AGENTS §13) — {@link update} recomputes the bar via
1272
+ * Implements an update-driven, observable progress bar — {@link update} recomputes the bar through
1383
1273
  * {@link renderBar}, writes `\r` + bar to its {@link SinkInterface}, and emits the `{ current, total }`
1384
- * on `update`. The leading `\r` is what an overwrite-capable sink (the C-g TTY sink) redraws on; a
1385
- * plain sink (C-f) degrades to a fresh, non-overwriting line — the line-OVERWRITE is the SINK's job.
1386
- * UNIVERSAL — the one {@link StylerInterface} + the one {@link SinkInterface}, no `node:*`, no
1387
- * `process.stdout`. NO self-timer (unlike {@link import('./Spinner.js').Spinner}) — the caller drives it.
1274
+ * on `update`. The leading `\r` is what an overwrite-capable sink (the TTY sink) redraws on; a
1275
+ * plain sink degrades to a fresh, non-overwriting line — the line-overwrite is the sink's job.
1276
+ * Universal — the one {@link StylerInterface} + the one {@link SinkInterface}, no `node:*`, no
1277
+ * `process.stdout`. No self-timer (unlike {@link import('./Spinner.js').Spinner}) — the caller drives it.
1388
1278
  *
1389
1279
  * @remarks
1390
1280
  * - **Update-driven.** Each {@link update} clamps `current` to `[0, total]`, renders the bar (filled
1391
- * to `current / total`, with the trailing `percent (current/total)` + message) via {@link renderBar},
1281
+ * to `current / total`, with the trailing `percent (current/total)` + message) through {@link renderBar},
1392
1282
  * emits `update`, and writes `'\r' + bar`. Progress advances only when the caller reports it.
1393
- * - **Outcome lines.** {@link complete} renders a FULL bar (`current = total`) + message, terminated by
1394
- * a newline, emits a final `update` then `complete`, and marks `completed`. {@link failure} renders the
1395
- * bar at its CURRENT fill + message + newline and routes to the sink's error stream (no `complete` —
1283
+ * - **Outcome lines.** {@link succeed} renders a full bar (`current = total`) + message, terminated by
1284
+ * a newline, emits a final `update` then `succeed`, and marks `succeeded`. {@link fail} renders the
1285
+ * bar at its current fill + message + newline and routes to the sink's error stream (no `succeed` —
1396
1286
  * the work did not finish). Both are terminal: a later {@link update} is ignored once `active` is false.
1397
- * - **Bounded.** `current` is always clamped to `[0, total]`; {@link completed} reports whether
1398
- * {@link complete} has run; {@link active} is `true` until a {@link complete} / {@link failure}.
1399
- * - **Lifecycle (§10).** {@link destroy} destroys the emitter (there is no timer to clear).
1287
+ * - **Bounded.** `current` is always clamped to `[0, total]`; {@link succeeded} reports whether
1288
+ * {@link succeed} has run; {@link active} is `true` until a {@link succeed} / {@link fail}.
1289
+ * - **Lifecycle.** {@link destroy} destroys the emitter (there is no timer to clear).
1400
1290
  *
1401
1291
  * @example
1402
1292
  * ```ts
1403
1293
  * const progress = new Progress({ total: 100, message: 'downloading' })
1404
1294
  * progress.update(40) // ████████████░░░░░░░░░░░░░░░░░░ 40% (40/100) downloading
1405
1295
  * progress.update(80, 'almost there')
1406
- * progress.complete('done') // a full bar, committed with a newline
1296
+ * progress.succeed('done') // a full bar, committed with a newline
1407
1297
  * ```
1408
1298
  */
1409
1299
  export declare class Progress implements ProgressInterface {
@@ -1411,125 +1301,95 @@ export declare class Progress implements ProgressInterface {
1411
1301
  constructor(options: ProgressOptions);
1412
1302
  get emitter(): EmitterInterface<ProgressEventMap>;
1413
1303
  get active(): boolean;
1414
- get completed(): boolean;
1304
+ get succeeded(): boolean;
1415
1305
  get current(): number;
1416
1306
  get total(): number;
1417
1307
  update(current: number, message?: string): void;
1418
- complete(message?: string): void;
1419
- failure(message?: string): void;
1308
+ succeed(message?: string): void;
1309
+ fail(message?: string): void;
1420
1310
  destroy(): void;
1421
1311
  }
1422
1312
 
1423
1313
  /**
1424
- * Options for the pure {@link import('./helpers.js').renderBar} renderer — a determinate progress
1425
- * bar string (`█████░░░░░ 50% (5/10)`), width-aware and styler-optional.
1314
+ * Declares the observable events a {@link ProgressInterface} emits.
1426
1315
  *
1427
1316
  * @remarks
1428
- * - `current` / `total` — the filled fraction is `current / total`, clamped to `[0, total]` (a
1429
- * `current` past `total` renders a full bar, a negative one an empty bar) — so a caller's overrun
1430
- * never produces an over-long bar. A `total` of `0` (or below) renders a full bar (nothing to do).
1431
- * - `width` — the visible cell count of the bar TRACK (the glyph run between no brackets); defaults
1432
- * to {@link DEFAULT_BAR_WIDTH}. The percentage + `(current/total)` count follow the track.
1433
- * - `fill` — the filled-cell glyph; defaults to {@link BAR_FILL} (`█`). `empty` — the empty-cell
1434
- * glyph; defaults to {@link BAR_EMPTY} (`░`). Sized in VISIBLE columns ({@link
1435
- * import('./helpers.js').width}), so a multi-cell glyph still yields a `width`-wide track.
1436
- * - `styler` — colors the FILLED run when supplied (the empty run + the trailing label stay plain);
1437
- * the layout is identical with or without color, since the track is measured on visible width.
1438
- * - `style` — an optional by-value style rendered through `styler` for the filled run.
1439
- */
1440
- export declare interface ProgressBarOptions {
1441
- readonly current: number;
1442
- readonly total: number;
1443
- readonly width?: number;
1444
- readonly fill?: string;
1445
- readonly empty?: string;
1446
- readonly styler?: StylerInterface;
1447
- readonly style?: Style;
1448
- }
1449
-
1450
- /**
1451
- * The observable events a {@link ProgressInterface} emits (AGENTS §13).
1452
- *
1453
- * @remarks
1454
- * - `update` — the core event: fires on every `update(current)` (and on `complete` / `failure`),
1317
+ * - `update` — the core event: fires on every `update(current)` (and on `succeed` / `fail`),
1455
1318
  * carrying the `{ current, total }` progress (the clamped `current`). The hook a non-sink consumer
1456
1319
  * rides to observe progress without a terminal.
1457
- * - `complete` — the terminal signal: fires once from `complete()` (a successful finish), a pure
1458
- * signal (empty tuple) so a consumer can observe the bar reaching its end. (`failure()` emits a final
1459
- * `update` and routes its line to the error stream, but is NOT a `complete` — completion means the
1460
- * work finished successfully.)
1320
+ * - `succeed` — the terminal signal: fires once from `succeed()` (a successful finish), a pure
1321
+ * signal (empty tuple) so a consumer can observe the bar reaching its end. (`fail()` emits a final
1322
+ * `update` and routes its line to the error stream, but is not a `succeed` — the bar's positive
1323
+ * outcome is the same word the spinner and the reporter use.)
1461
1324
  *
1462
- * Listener isolation is the emitter's (§13). Declared as a `type` alias (not
1463
- * `interface extends EventMap`, §4.5): a type-literal satisfies the `EventMap` constraint
1325
+ * Listener isolation is the emitter's. Declared as a `type` alias (not
1326
+ * `interface extends EventMap`): a type-literal satisfies the `EventMap` constraint
1464
1327
  * structurally, whereas an interface lacks the index signature.
1465
1328
  */
1466
1329
  export declare type ProgressEventMap = {
1467
- /** Progress advanced — the clamped `{ current, total }` (fires on `update` and on `complete` / `failure`). */
1468
- readonly update: readonly [progress: {
1469
- readonly current: number;
1470
- readonly total: number;
1471
- }];
1472
- /** The bar reached its end via `complete()` (a successful finish). */
1473
- readonly complete: readonly [];
1330
+ /** Reports progress advancing — the clamped `{ current, total }` (fires on `update` and on `succeed` / `fail`). */
1331
+ readonly update: readonly [progress: ProgressReport];
1332
+ /** Fires after the bar reached its end through `succeed()` (a successful finish). */
1333
+ readonly succeed: readonly [];
1474
1334
  };
1475
1335
 
1476
1336
  /**
1477
- * An update-driven, observable progress bar (AGENTS §13) — `update(current)` recomputes the bar via
1337
+ * Declares an update-driven, observable progress bar — `update(current)` recomputes the bar through
1478
1338
  * {@link import('./helpers.js').renderBar}, writes `\r` + bar to its {@link SinkInterface}, and emits
1479
- * the `{ current, total }` on `update`. The line-OVERWRITE is the sink's job (a TTY sink overwrites
1480
- * on the `\r`; a plain sink degrades to a fresh line). NO self-timer — the caller drives it.
1339
+ * the `{ current, total }` on `update`. The line-overwrite is the sink's job (a TTY sink overwrites
1340
+ * on the `\r`; a plain sink degrades to a fresh line). No self-timer — the caller drives it.
1481
1341
  *
1482
1342
  * @remarks
1483
1343
  * - **Update-driven.** Each `update(current, message?)` clamps `current` to `[0, total]`, renders
1484
1344
  * the bar (filled to `current / total`, with the trailing `percent (current/total)` + message),
1485
1345
  * emits `update`, and writes `'\r' + bar`. There is no internal timer (unlike {@link
1486
1346
  * SpinnerInterface}) — progress advances only when the caller reports it.
1487
- * - **Outcome lines.** `complete(message?)` renders a FULL bar (`current = total`) + message,
1488
- * terminated by a newline, emits a final `update` then `complete`, and marks `completed`.
1489
- * `failure(message?)` renders the bar at its CURRENT fill + message + newline and routes to the sink's
1490
- * error stream (no `complete` — the work did not finish). Both are terminal: a later `update` after
1491
- * a `complete` / `failure` is ignored (`active` is `false`).
1492
- * - **Bounded.** `current` is always clamped to `[0, total]`; `completed` reports whether
1493
- * `complete()` has run; `active` is `true` until a `complete` / `failure`.
1347
+ * - **Outcome lines.** `succeed(message?)` renders a full bar (`current = total`) + message,
1348
+ * terminated by a newline, emits a final `update` then `succeed`, and marks `succeeded`.
1349
+ * `fail(message?)` renders the bar at its current fill + message + newline and routes to the sink's
1350
+ * error stream (no `succeed` — the work did not finish). Both are terminal: a later `update` after
1351
+ * a `succeed` / `fail` is ignored (`active` is `false`).
1352
+ * - **Bounded.** `current` is always clamped to `[0, total]`; `succeeded` reports whether
1353
+ * `succeed()` has run; `active` is `true` until a `succeed` / `fail`.
1494
1354
  */
1495
1355
  export declare interface ProgressInterface {
1496
1356
  readonly emitter: EmitterInterface<ProgressEventMap>;
1497
- /** Whether the bar is still advancing (before any `complete()` / `failure()`). */
1357
+ /** Reports whether the bar is still advancing (before any `succeed()` / `fail()`). */
1498
1358
  readonly active: boolean;
1499
- /** Whether `complete()` has run (the bar finished successfully). */
1500
- readonly completed: boolean;
1501
- /** The current value, clamped to `[0, total]`. */
1359
+ /** Reports whether `succeed()` has run (the bar finished successfully). */
1360
+ readonly succeeded: boolean;
1361
+ /** Holds the current value, clamped to `[0, total]`. */
1502
1362
  readonly current: number;
1503
- /** The target value the bar fills toward. */
1363
+ /** Holds the target value the bar fills toward. */
1504
1364
  readonly total: number;
1505
- /** Report progress: clamp `current`, re-render the bar, emit `update`, write `\r` + bar. Ignored once terminal. */
1365
+ /** Reports progress: clamps `current`, re-renders the bar, emits `update`, writes `\r` + bar. Ignored once terminal. */
1506
1366
  update(current: number, message?: string): void;
1507
- /** Finish successfully — render a FULL bar + newline, emit a final `update` then `complete`. */
1508
- complete(message?: string): void;
1509
- /** Finish unsuccessfully — render the bar at its current fill + newline to the error stream (no `complete`). */
1510
- failure(message?: string): void;
1511
- /** Tear down — destroy the emitter. */
1367
+ /** Finishes successfully — renders a full bar + newline, emits a final `update` then `succeed`. */
1368
+ succeed(message?: string): void;
1369
+ /** Finishes unsuccessfully — renders the bar at its current fill + newline to the error stream (no `succeed`). */
1370
+ fail(message?: string): void;
1371
+ /** Tears down — destroys the emitter. */
1512
1372
  destroy(): void;
1513
1373
  }
1514
1374
 
1515
1375
  /**
1516
- * Options for `createProgress` / the {@link ProgressInterface} constructor.
1376
+ * Configures the {@link import('./Progress.js').Progress} constructor.
1517
1377
  *
1518
1378
  * @remarks
1519
- * - `on` — the reserved {@link EmitterHooks} key (§8): initial listeners for the
1379
+ * - `on` — the reserved {@link EmitterHooks} key: initial listeners for the
1520
1380
  * {@link ProgressEventMap}, wired at construction.
1521
- * - `error` — the emitter's listener-error handler (§13); a listener throw routes here.
1522
- * - `total` — the value `current` advances toward (the `100%` point); the only REQUIRED option.
1381
+ * - `error` — the emitter's listener-error handler; a listener throw routes here.
1382
+ * - `total` — the value `current` advances toward (the `100%` point); the only required option.
1523
1383
  * - `message` — text shown after the bar; defaults to `''`. Overridden per-`update` and by a
1524
- * `complete` / `failure` argument.
1384
+ * `succeed` / `fail` argument.
1525
1385
  * - `width` — the bar track's visible cell count, handed to {@link import('./helpers.js').renderBar};
1526
1386
  * defaults to {@link DEFAULT_BAR_WIDTH}.
1527
1387
  * - `fill` / `empty` — the filled and empty track glyphs handed to
1528
1388
  * {@link import('./helpers.js').renderBar}; default to {@link BAR_FILL} / {@link BAR_EMPTY}.
1529
1389
  * - `sink` — where each `\r` + bar line is written; defaults to
1530
- * {@link import('./factories.js').createConsoleSink}. A TTY sink (C-g) overwrites on the `\r`.
1390
+ * {@link import('./factories.js').createConsoleSink}. A TTY sink overwrites on the `\r`.
1531
1391
  * - `styler` — the {@link StylerInterface} the filled run is colored through; defaults to
1532
- * {@link import('./factories.js').createStyler} (ANSI). The ONE styler the whole system shares.
1392
+ * {@link import('./factories.js').createStyler} (ANSI). The one styler the whole system shares.
1533
1393
  * - `theme` — the {@link Theme} supplying the filled run's accent role; defaults to
1534
1394
  * {@link DEFAULT_THEME}.
1535
1395
  */
@@ -1547,26 +1407,41 @@ export declare interface ProgressOptions {
1547
1407
  }
1548
1408
 
1549
1409
  /**
1550
- * Render a determinate progress bar stringa filled / empty glyph track followed by the percentage
1551
- * and the `(current/total)` count (`█████░░░░░ 50% (5/10)`). Pure: same {@link ProgressBarOptions}
1552
- * same string. The animation-layer sibling of the C-c `render*` renderers (box / table / tree /
1410
+ * Reports one advance of a {@link ProgressInterface} the clamped `{ current, total }` payload
1411
+ * carried by the `update` event of {@link ProgressEventMap}.
1412
+ *
1413
+ * @remarks
1414
+ * `current` is always the value after clamping into `[0, total]`, so a listener never sees an
1415
+ * overrun or a negative. `total` is the bar's fixed target, repeated on every report so a listener
1416
+ * needs no reference to the bar itself. The same record is emitted from `update`, `succeed`, and
1417
+ * `fail`.
1418
+ */
1419
+ export declare interface ProgressReport {
1420
+ readonly current: number;
1421
+ readonly total: number;
1422
+ }
1423
+
1424
+ /**
1425
+ * Renders a determinate progress bar string — a filled / empty glyph track followed by the percentage
1426
+ * and the `(current/total)` count (`█████░░░░░ 50% (5/10)`). Pure: same {@link BarOptions} →
1427
+ * same string. The animation-layer sibling of the `render*` renderers (box / table / tree /
1553
1428
  * separator), shared so a {@link import('./types.js').ProgressInterface} and any direct caller draw
1554
- * the ONE bar — never a second, hand-rolled one (AGENTS §5; scsr shipped three).
1429
+ * the one bar — never a second, hand-rolled one.
1555
1430
  *
1556
1431
  * @remarks
1557
1432
  * - **Fill fraction, clamped.** The filled cell count is `round((current / total) · width)` with
1558
1433
  * `current` clamped to `[0, total]`, so an overrun never over-fills and a negative never under-fills.
1559
- * A `total <= 0` renders a FULL track (there is nothing to fill toward — the work is trivially done).
1434
+ * A `total <= 0` renders a full track (there is nothing to fill toward — the work is trivially done).
1560
1435
  * - **Width-aware track.** The filled run is `fill` tiled to the filled cell count and the empty run
1561
- * `empty` tiled to the remainder, each via {@link repeatTo} — so the TRACK is exactly `width` VISIBLE
1436
+ * `empty` tiled to the remainder, each through {@link repeatTo} — so the track is exactly `width` visible
1562
1437
  * columns even for a multi-cell glyph (its escape codes / extra cells never break the width).
1563
- * - **Styling.** `options.styler` colors the FILLED run only (the empty run + the trailing
1438
+ * - **Styling.** `options.styler` colors the filled run only (the empty run + the trailing
1564
1439
  * `percent (count)` label stay plain), through {@link paint}; the layout is identical with or
1565
1440
  * without color, since the track is measured on visible width.
1566
- * - **Label.** The percentage is the rounded `current / total` (e.g. `50%`); the count is the CLAMPED
1441
+ * - **Label.** The percentage is the rounded `current / total` (for example `50%`); the count is the clamped
1567
1442
  * `current` over `total` (`(5/10)`), a single space separating the track, the percent, and the count.
1568
1443
  *
1569
- * @param options - See {@link ProgressBarOptions}
1444
+ * @param options - See {@link BarOptions}
1570
1445
  * @returns The rendered bar line (no trailing newline)
1571
1446
  *
1572
1447
  * @example
@@ -1575,19 +1450,22 @@ export declare interface ProgressOptions {
1575
1450
  * renderBar({ current: 10, total: 10, width: 4 }) // '████ 100% (10/10)'
1576
1451
  * ```
1577
1452
  */
1578
- export declare function renderBar(options: ProgressBarOptions): string;
1453
+ export declare function renderBar(options: BarOptions): string;
1579
1454
 
1580
1455
  /**
1581
- * Render `content` framed in box-drawing characters, optionally captioned, width-aware so
1456
+ * Renders `content` framed in box-drawing characters, optionally captioned, width-aware so
1582
1457
  * styled content stays aligned inside the frame. Pure: same {@link BoxOptions} → same string.
1583
1458
  *
1584
1459
  * @remarks
1585
- * - **Lines.** `content` is split on `\n`; each line is padded (left-aligned) to the inner
1586
- * width by {@link align} measured on VISIBLE width, so a styled line never breaks the
1460
+ * - **Lines.** `content` is split on `\n` or `\r\n`, so caller text written on Windows frames
1461
+ * exactly as the same text written on POSIX; a lone `\r` is kept inside its line (it is a
1462
+ * cursor control — the animation frame prefix — not a line separator). Each line is padded
1463
+ * (left-aligned) to the inner
1464
+ * width by {@link align} — measured on visible width, so a styled line never breaks the
1587
1465
  * right edge. The inner width is the widest line's visible width (or `width − borders −
1588
1466
  * 2·padding` when an explicit `width` is given and is wider), plus `padding` blank cells
1589
1467
  * inside each {@link BorderChars.vertical} edge.
1590
- * - **Title.** An optional `title` is embedded in the TOP border (` title `), the remaining
1468
+ * - **Title.** An optional `title` is embedded in the top border (` title `), the remaining
1591
1469
  * top edge drawn as fill; a title wider than the inner width widens the box to fit it.
1592
1470
  * - **Border + styling.** The {@link BorderStyle} (`options.border`, default
1593
1471
  * {@link DEFAULT_BORDER}) selects the glyph set from {@link BORDER_CHARS}; `options.styler`
@@ -1601,21 +1479,21 @@ export declare function renderBar(options: ProgressBarOptions): string;
1601
1479
  export declare function renderBox(options: BoxOptions): string;
1602
1480
 
1603
1481
  /**
1604
- * A swappable style renderer — the seam that turns style DATA into output for ONE
1482
+ * Declares a swappable style renderer — the seam that turns style data into output for one
1605
1483
  * target. The cross-environment default is the ANSI renderer (SGR escape codes); a
1606
- * browser `%c` / CSS renderer implements the SAME contract over the SAME {@link Style}
1607
- * model, so it drops in without touching the style data (the C-f browser branch).
1484
+ * browser `%c` / CSS renderer implements the same contract over the same {@link Style}
1485
+ * model, so it drops in without touching the style data (the browser branch).
1608
1486
  */
1609
1487
  export declare interface RendererInterface {
1610
1488
  /**
1611
- * Render `text` wrapped in the target codes for `style`. The EMPTY style (no colors,
1489
+ * Renders `text` wrapped in the target codes for `style`. The empty style (no colors,
1612
1490
  * no attributes) and the empty string both return `text` unchanged — no wrapping.
1613
1491
  */
1614
1492
  render(style: Style, text: string): string;
1615
1493
  }
1616
1494
 
1617
1495
  /**
1618
- * Render a horizontal rule — an optional centered title embedded in a line of fill characters,
1496
+ * Renders a horizontal rule — an optional centered title embedded in a line of fill characters,
1619
1497
  * to a fixed visible width. Pure: same {@link SeparatorOptions} → same string.
1620
1498
  *
1621
1499
  * @remarks
@@ -1624,10 +1502,10 @@ export declare interface RendererInterface {
1624
1502
  * side) in the line, splitting the remaining fill between the two sides (the extra column,
1625
1503
  * when the remainder is odd, goes to the right). The visible width stays exactly `width`,
1626
1504
  * even when the title is styled (the title's escape codes don't count toward the budget) —
1627
- * a title at least as wide as `width` yields just the gapped title (no fill).
1505
+ * a title at least as wide as `width` yields only the gapped title (no fill).
1628
1506
  * - **Styling.** When `options.styler` is given, the fill runs (and the embedded title) are
1629
1507
  * colored through it; the layout is identical with or without color, since width is measured
1630
- * on the visible content (AGENTS — width-aware via {@link width}).
1508
+ * on the visible content (width-aware through {@link width}).
1631
1509
  *
1632
1510
  * @param options - See {@link SeparatorOptions}
1633
1511
  * @returns The rule line (no trailing newline)
@@ -1641,17 +1519,17 @@ export declare interface RendererInterface {
1641
1519
  export declare function renderSeparator(options: SeparatorOptions): string;
1642
1520
 
1643
1521
  /**
1644
- * Render a bordered grid of `columns` + `rows` with per-column alignment and width-aware
1522
+ * Renders a bordered grid of `columns` + `rows` with per-column alignment and width-aware
1645
1523
  * column sizing. Pure: same {@link TableOptions} → same string.
1646
1524
  *
1647
1525
  * @remarks
1648
- * - **Column sizing — visible width.** Each column is sized to the widest VISIBLE width
1526
+ * - **Column sizing — visible width.** Each column is sized to the widest visible width
1649
1527
  * ({@link width}) among its header label and its cells, so an already-styled cell never
1650
1528
  * breaks the column (its escape codes don't count toward the width).
1651
1529
  * - **Ragged rows.** A row shorter than the column count is padded with empty cells; a longer
1652
1530
  * row is truncated to the column count — a ragged input never throws.
1653
1531
  * - **Alignment.** Each cell is positioned by its column's {@link ColumnSpec.align} (default
1654
- * {@link DEFAULT_ALIGN}) via {@link align}.
1532
+ * {@link DEFAULT_ALIGN}) through {@link align}.
1655
1533
  * - **Frame.** The {@link BorderStyle} (`options.border`, default {@link DEFAULT_BORDER})
1656
1534
  * draws the outer frame, the header rule (a `teeRight … cross … teeLeft` line), and the
1657
1535
  * `vertical` column separators; `options.styler` colors the frame + header labels when
@@ -1664,7 +1542,7 @@ export declare function renderSeparator(options: SeparatorOptions): string;
1664
1542
  export declare function renderTable(options: TableOptions): string;
1665
1543
 
1666
1544
  /**
1667
- * Render a nested {@link TreeNode} tree with box-drawing connectors. Pure: same
1545
+ * Renders a nested {@link TreeNode} tree with box-drawing connectors. Pure: same
1668
1546
  * {@link TreeOptions} → same string.
1669
1547
  *
1670
1548
  * @remarks
@@ -1689,13 +1567,13 @@ export declare function renderTable(options: TableOptions): string;
1689
1567
  export declare function renderTree(options: TreeOptions): string;
1690
1568
 
1691
1569
  /**
1692
- * Render the connector-prefixed lines for a {@link TreeNode} list — the recursive core
1570
+ * Renders the connector-prefixed lines for a {@link TreeNode} list — the recursive core
1693
1571
  * behind {@link renderTree}. Each child is drawn as `prefix` + its connector (`├─ ` for
1694
1572
  * any but the last, `└─ ` for the last) + its label, with its own descendants recursed
1695
1573
  * beneath under the carried guide (`│ ` under a non-last node, ` ` under the last).
1696
1574
  *
1697
1575
  * @remarks
1698
- * A centralized, exported recursion branch (AGENTS §5) so it is directly testable and
1576
+ * A centralized, exported recursion branch so it is directly testable and
1699
1577
  * reusable outside {@link renderTree}'s top-level `root.label` framing.
1700
1578
  *
1701
1579
  * @param nodes - The sibling {@link TreeNode}s to render at this depth
@@ -1713,17 +1591,17 @@ export declare function renderTree(options: TreeOptions): string;
1713
1591
  export declare function renderTreeChildren(nodes: readonly TreeNode[], prefix: string, options: Required<Pick<TreeOptions, 'border'>> & Pick<TreeOptions, 'style' | 'styler'>): readonly string[];
1714
1592
 
1715
1593
  /**
1716
- * Repeat `unit` until it fills exactly `count` VISIBLE columns, trimming a trailing partial
1594
+ * Repeats `unit` until it fills exactly `columns` visible columns, trimming a trailing partial
1717
1595
  * unit so the run is never over-wide — the fill primitive the separator + box edges draw with.
1718
1596
  *
1719
1597
  * @remarks
1720
1598
  * Counts in code points ({@link width}-consistent), so a multi-cell or astral `unit` is laid
1721
- * down whole and the result is sliced to exactly `count` visible columns. `count <= 0` (or an
1599
+ * down whole and the result is sliced to exactly `columns` visible columns. `columns <= 0` (or an
1722
1600
  * empty / zero-width `unit`) yields `''`.
1723
1601
  *
1724
1602
  * @param unit - The (possibly multi-character) fill unit
1725
- * @param count - The visible column count to fill
1726
- * @returns `unit` tiled to exactly `count` visible columns
1603
+ * @param columns - The visible column count to fill
1604
+ * @returns `unit` tiled to exactly `columns` visible columns
1727
1605
  *
1728
1606
  * @example
1729
1607
  * ```ts
@@ -1731,27 +1609,27 @@ export declare function renderTreeChildren(nodes: readonly TreeNode[], prefix: s
1731
1609
  * repeatTo('=-', 5) // '=-=-='
1732
1610
  * ```
1733
1611
  */
1734
- export declare function repeatTo(unit: string, count: number): string;
1612
+ export declare function repeatTo(unit: string, columns: number): string;
1735
1613
 
1736
1614
  /**
1737
- * A lean, event-free narrative reporter (AGENTS §13) — the composable verb set for human /
1738
- * build-run output. Each verb FORMATS its line through the shared {@link StylerInterface} and
1615
+ * Implements a lean, event-free narrative reporter — the composable verb set for human /
1616
+ * build-run output. Each verb formats its line through the shared {@link StylerInterface} and
1739
1617
  * the pure layout renderers ({@link renderSeparator} / {@link renderBox} / {@link renderTable}
1740
- * / {@link renderTree}) and WRITES it to a {@link SinkInterface} — the SAME styler + sink
1618
+ * / {@link renderTree}) and writes it to a {@link SinkInterface} — the same styler + sink
1741
1619
  * substrate the logger uses, never a second colorizer.
1742
1620
  *
1743
1621
  * @remarks
1744
- * - **A SMALL set, not a grab-bag.** `section` / `step` / `timing` / `status` / `table` /
1622
+ * - **A small set, not a grab-bag.** `section` / `step` / `timing` / `status` / `table` /
1745
1623
  * `tree` / `box` / `line` / `blank`. No spinner / bar (the animation chunk), no buffering /
1746
- * capture (the capture chunk), no level retention (the logger). Just format + write.
1747
- * - **`status` is a narrative OUTCOME, not a log level.** Its {@link StatusLevel} (`success` /
1624
+ * capture (the capture chunk), no level retention (the logger). Format and write, nothing more.
1625
+ * - **`status` is a narrative outcome, not a log level.** Its {@link StatusLevel} (`success` /
1748
1626
  * `error` / `warn` / `info`) is distinct from {@link import('./types.js').LogLevel}: an icon
1749
1627
  * supplied theme status icon + style, with `error` routed to the sink's
1750
1628
  * error stream (the `level` hint forwarded to {@link SinkInterface.write}) — there is no
1751
1629
  * gating and no severity ordering.
1752
1630
  * - **Width-aware.** `section` (and a `box` with no explicit `width`) lay out to the reporter's
1753
- * `#width`; the renderers measure on VISIBLE width (ANSI-aware), so styled content aligns.
1754
- * - **Event-free (§13).** No `#emitter` — a pure formatting front-end with no observable
1631
+ * `#width`; the renderers measure on visible width (ANSI-aware), so styled content aligns.
1632
+ * - **Event-free.** No `#emitter` — a pure formatting front-end with no observable
1755
1633
  * lifecycle (like the renderers and `Scheduler`). It is reusable and holds no per-call state.
1756
1634
  *
1757
1635
  * @example
@@ -1778,61 +1656,61 @@ export declare class Reporter implements ReporterInterface {
1778
1656
  }
1779
1657
 
1780
1658
  /**
1781
- * A lean, event-free narrative reporter — the composable verb set for human / build-run
1659
+ * Declares a lean, event-free narrative reporter — the composable verb set for human / build-run
1782
1660
  * output (sections, steps, timings, outcomes, tables, trees, boxes), formatting through the
1783
1661
  * shared {@link StylerInterface} + layout renderers and writing to a {@link SinkInterface}.
1784
1662
  *
1785
1663
  * @remarks
1786
- * - **A SMALL composable set**, not a grab-bag: `section` / `step` / `timing` / `status` /
1787
- * `table` / `tree` / `box` / `line` / `blank`. Coloring is the ONE styler; layout is the
1664
+ * - **A small composable set**, not a grab-bag: `section` / `step` / `timing` / `status` /
1665
+ * `table` / `tree` / `box` / `line` / `blank`. Coloring is the one styler; layout is the
1788
1666
  * pure renderers ({@link import('./helpers.js').renderSeparator} /
1789
1667
  * {@link import('./helpers.js').renderBox} / {@link import('./helpers.js').renderTable} /
1790
1668
  * {@link import('./helpers.js').renderTree}). No second colorizer, no spinner / bar (that
1791
1669
  * is the animation chunk), no buffering / capture (that is the capture chunk).
1792
1670
  * - **`status` is a narrative outcome, not a log level.** Its {@link StatusLevel} is
1793
- * `success` / `error` / `warn` / `info` (DISTINCT from {@link LogLevel}); `error` routes to
1671
+ * `success` / `error` / `warn` / `info` (distinct from {@link LogLevel}); `error` routes to
1794
1672
  * the sink's error stream.
1795
- * - **Event-free (§13).** No emitter — a pure formatting front-end. Each verb FORMATS then
1796
- * WRITES immediately; there is no retained state worth observing.
1673
+ * - **Event-free.** No emitter — a pure formatting front-end. Each verb formats then
1674
+ * writes immediately; there is no retained state worth observing.
1797
1675
  */
1798
1676
  export declare interface ReporterInterface {
1799
- /** Write a titled separator block — a section heading framed by a horizontal rule. */
1677
+ /** Writes a titled separator block — a section heading framed by a horizontal rule. */
1800
1678
  section(title: string): void;
1801
- /** Write a step line, optionally prefixed with its `[index/total]` {@link StepPosition}. */
1679
+ /** Writes a step line, optionally prefixed with its `[index/total]` {@link StepPosition}. */
1802
1680
  step(message: string, position?: StepPosition): void;
1803
- /** Write a timing line — `label … 1.23s` (sub-second shown as `…ms`). */
1681
+ /** Writes a timing line — `label … 1.23s` (sub-second shown as `…ms`). */
1804
1682
  timing(label: string, ms: number): void;
1805
- /** Write an icon + colored outcome line for `level` (`error` routes to the error stream). */
1683
+ /** Writes an icon + colored outcome line for `level` (`error` routes to the error stream). */
1806
1684
  status(level: StatusLevel, message: string): void;
1807
- /** Render a {@link TableOptions} grid through {@link import('./helpers.js').renderTable} and write it. */
1685
+ /** Renders a {@link TableOptions} grid through {@link import('./helpers.js').renderTable} and writes it. */
1808
1686
  table(options: TableOptions): void;
1809
- /** Render a {@link TreeOptions} tree through {@link import('./helpers.js').renderTree} and write it. */
1687
+ /** Renders a {@link TreeOptions} tree through {@link import('./helpers.js').renderTree} and writes it. */
1810
1688
  tree(options: TreeOptions): void;
1811
- /** Render a {@link BoxOptions} frame through {@link import('./helpers.js').renderBox} and write it. */
1689
+ /** Renders a {@link BoxOptions} frame through {@link import('./helpers.js').renderBox} and writes it. */
1812
1690
  box(options: BoxOptions): void;
1813
- /** Write one raw line, colored through the styler if any styling is embedded — no prefix, no icon. */
1691
+ /** Writes one raw line, colored through the styler if any styling is embedded — no prefix, no icon. */
1814
1692
  line(text: string): void;
1815
- /** Write `count` blank lines (default `1`). */
1693
+ /** Writes `count` blank lines (default `1`). */
1816
1694
  blank(count?: number): void;
1817
1695
  }
1818
1696
 
1819
1697
  /**
1820
- * Options for {@link createReporter} / the {@link ReporterInterface} constructor.
1698
+ * Configures the {@link import('./Reporter.js').Reporter} constructor.
1821
1699
  *
1822
1700
  * @remarks
1823
1701
  * - `sink` — where every formatted line is written; defaults to
1824
1702
  * {@link import('./factories.js').createConsoleSink} (the snapshotted, level-routing console
1825
- * sink) — the SAME seam the logger writes through. A `status('error', …)` passes the
1703
+ * sink) — the same seam the logger writes through. A `status('error', …)` passes the
1826
1704
  * `error` level so a stream-aware sink routes it to `stderr`.
1827
1705
  * - `styler` — the {@link StylerInterface} every line is colored through; defaults to
1828
- * {@link import('./factories.js').createStyler} (ANSI). The ONE styler the whole system
1706
+ * {@link import('./factories.js').createStyler} (ANSI). The one styler the whole system
1829
1707
  * shares — no second colorizer. A disabled styler yields plain narration.
1830
1708
  * - `theme` — the {@link Theme} supplying status, accent, and chrome roles; defaults to
1831
1709
  * {@link DEFAULT_THEME}.
1832
1710
  * - `width` — the default column width handed to the separator / box renderers (the section
1833
1711
  * rule, a `box` with no explicit width); defaults to {@link DEFAULT_WIDTH}.
1834
1712
  *
1835
- * Event-free (§13): the reporter has no `on` / `error` — it is a formatting front-end with no
1713
+ * Event-free: the reporter has no `on` / `error` — it is a formatting front-end with no
1836
1714
  * observable lifecycle, so (like the renderers and `Scheduler`) it carries no emitter.
1837
1715
  */
1838
1716
  export declare interface ReporterOptions {
@@ -1842,37 +1720,128 @@ export declare interface ReporterOptions {
1842
1720
  readonly width?: number;
1843
1721
  }
1844
1722
 
1845
- /** The full SGR reset sequence (`ESC[0m`) appended after a styled run. */
1723
+ /** Holds the full SGR reset sequence (`ESC[0m`) appended after a styled run. */
1846
1724
  export declare const RESET: string;
1847
1725
 
1848
- /** The SGR RESET parameter (0) — terminates a styled run, clearing all colors and attributes. */
1726
+ /** Holds the SGR RESET parameter (0) — terminates a styled run, clearing all colors and attributes. */
1849
1727
  export declare const RESET_CODE = 0;
1850
1728
 
1851
1729
  /**
1852
- * The number of milliseconds at or above which {@link import('./helpers.js').formatDuration}
1730
+ * Implements the bounded, level-keyed retention engine both captures buffer through — one capped total buffer
1731
+ * plus one capped bucket per level, generic over the record type each capture carries.
1732
+ *
1733
+ * @remarks
1734
+ * - **One engine, two captures.** The core `Capture` retains
1735
+ * {@link import('./types.js').CapturedMessage}s keyed by
1736
+ * {@link import('./types.js').CaptureLevel}, and the server `ProcessCapture` retains chunks keyed
1737
+ * by its stream level; both compose this, so their retention semantics cannot drift apart.
1738
+ * - **Bounded on both axes.** `add` appends to the total buffer and to the record's bucket, then
1739
+ * drops the oldest of whichever exceeded `limit`, so neither grows without bound.
1740
+ * - **Buckets are fixed at construction.** Only the levels passed to the constructor get a bucket.
1741
+ * A record at any other level still joins the total buffer, and `records(level)` for a level with
1742
+ * no bucket returns an empty list.
1743
+ * - **Copies out.** `records` returns a fresh list each call, so retained state is never reachable
1744
+ * for mutation through a returned value.
1745
+ *
1746
+ * @example
1747
+ * ```ts
1748
+ * const retention = new Retention<{ level: 'warn' | 'error'; text: string }>(['warn'], 2)
1749
+ * retention.add({ level: 'warn', text: 'first' })
1750
+ * retention.add({ level: 'error', text: 'second' }) // no bucket, still in the total buffer
1751
+ * retention.records().length // 2
1752
+ * retention.records('warn').map((record) => record.text) // ['first']
1753
+ * retention.clear()
1754
+ * retention.records() // []
1755
+ * ```
1756
+ */
1757
+ export declare class Retention<T extends {
1758
+ readonly level: string;
1759
+ }> implements RetentionInterface<T> {
1760
+ #private;
1761
+ constructor(levels: ReadonlyArray<T['level']>, limit: number);
1762
+ add(record: T): void;
1763
+ records(): readonly T[];
1764
+ records(level: T['level']): readonly T[];
1765
+ clear(): void;
1766
+ }
1767
+
1768
+ /**
1769
+ * Declares the bounded, level-keyed retention buffer a capture keeps its records in — one capped total
1770
+ * buffer plus one capped bucket per level configured at construction.
1771
+ *
1772
+ * @remarks
1773
+ * - **Bounded on both axes.** The total buffer and each bucket are capped at the same `limit`,
1774
+ * dropping the oldest record first, so neither can grow without bound.
1775
+ * - **Buckets are fixed at construction.** A record whose `level` has no bucket still joins the
1776
+ * total buffer, and `records(level)` for an unconfigured level returns an empty list rather than
1777
+ * failing.
1778
+ * - **Copies out.** Each `records` call returns a fresh list, so a caller can never mutate the
1779
+ * retained state through the value it receives.
1780
+ */
1781
+ export declare interface RetentionInterface<T extends {
1782
+ readonly level: string;
1783
+ }> {
1784
+ /** Retains one record — appends it to the total buffer and to its level's bucket, evicting the oldest of each past the cap. */
1785
+ add(record: T): void;
1786
+ /** Returns a copy of the whole retained buffer, oldest first. */
1787
+ records(): readonly T[];
1788
+ /** Returns a copy of one level's bucket, oldest first; empty for a level with no bucket. */
1789
+ records(level: T['level']): readonly T[];
1790
+ /** Drops every retained record from the total buffer and every bucket. */
1791
+ clear(): void;
1792
+ }
1793
+
1794
+ /**
1795
+ * Sets the number of milliseconds at or above which {@link import('./helpers.js').formatDuration}
1853
1796
  * (and so `Reporter.timing`) switches from a `…ms` rendering to a `…s` (seconds, 2 d.p.)
1854
1797
  * rendering — exactly one second.
1855
1798
  */
1856
1799
  export declare const SECOND_MS = 1000;
1857
1800
 
1858
- /** The default fill character {@link import('./helpers.js').renderSeparator} draws its rule with — `─`. */
1801
+ /**
1802
+ * Selects the member of a {@link WriterSet} a {@link LogLevel} routes to — `error` to `error`,
1803
+ * `warn` to `warn`, every other level and an omitted level to `log`.
1804
+ *
1805
+ * @remarks
1806
+ * The single owner of the level-to-target decision every sink backend shares, so core's console
1807
+ * sink, the browser `%c` sink, and the server stream sink cannot drift apart. A backend that sends
1808
+ * two levels to one destination passes the same member twice: the server sink routes `warn`
1809
+ * alongside `error` by supplying its error stream for both, which matches `console.warn` writing
1810
+ * to `stderr`. The member type is the caller's, so the same leaf selects a bound console method, a
1811
+ * stream target, or a per-target styling fact.
1812
+ *
1813
+ * @param level - The originating record's {@link LogLevel}, or `undefined` when the caller has none
1814
+ * @param writers - See {@link WriterSet}
1815
+ * @returns The member `level` routes to
1816
+ *
1817
+ * @example
1818
+ * ```ts
1819
+ * selectWriter('error', { log: 'stdout', warn: 'stderr', error: 'stderr' }) // 'stderr'
1820
+ * selectWriter('warn', { log: 'stdout', warn: 'stderr', error: 'stderr' }) // 'stderr'
1821
+ * selectWriter('debug', { log: 'stdout', warn: 'stderr', error: 'stderr' }) // 'stdout'
1822
+ * selectWriter(undefined, { log: 'stdout', warn: 'stderr', error: 'stderr' }) // 'stdout'
1823
+ * ```
1824
+ */
1825
+ export declare function selectWriter<T>(level: LogLevel | undefined, writers: WriterSet<T>): T;
1826
+
1827
+ /** Holds the default fill character {@link import('./helpers.js').renderSeparator} draws its rule with — `─`. */
1859
1828
  export declare const SEPARATOR_FILL = "\u2500";
1860
1829
 
1861
1830
  /**
1862
- * The single padding cell on each side of a separator's embedded title (` title `) — keeps the
1831
+ * Holds the single padding cell on each side of a separator's embedded title (` title `) — keeps the
1863
1832
  * title from butting against the rule. One space.
1864
1833
  */
1865
1834
  export declare const SEPARATOR_TITLE_GAP = " ";
1866
1835
 
1867
1836
  /**
1868
- * Options for {@link import('./helpers.js').renderSeparator} — a horizontal rule, optionally
1837
+ * Configures {@link import('./helpers.js').renderSeparator} — a horizontal rule, optionally
1869
1838
  * carrying a centered title.
1870
1839
  *
1871
1840
  * @remarks
1872
- * - `title` — text to embed in the rule (e.g. a section heading). Omitted ⇒ an unbroken line.
1841
+ * - `title` — text to embed in the rule (for example a section heading). Omitted ⇒ an unbroken line.
1873
1842
  * - `width` — the visible column count of the whole rule; defaults to {@link DEFAULT_WIDTH}.
1874
1843
  * - `fill` — the single character the rule is drawn with; defaults to {@link SEPARATOR_FILL}
1875
- * (`─`). The VISIBLE width of the rule is `width` regardless of the fill's escape codes.
1844
+ * (`─`). The visible width of the rule is `width` regardless of the fill's escape codes.
1876
1845
  * - `styler` — colors the rule (and the embedded title) when supplied; the layout is
1877
1846
  * identical with or without it, since width is measured on the visible content.
1878
1847
  * - `style` — an optional by-value style rendered through `styler` for the rule and title.
@@ -1886,41 +1855,41 @@ export declare interface SeparatorOptions {
1886
1855
  }
1887
1856
 
1888
1857
  /**
1889
- * The minimal output primitive — the seam every formatted line is written through. A
1890
- * `Sink` is the ONE place text leaves the logging system; redirect output (to a file, a
1858
+ * Declares the minimal output primitive — the seam every formatted line is written through. A
1859
+ * `Sink` is the one place text leaves the logging system; redirect output (to a file, a
1891
1860
  * buffer, a test recorder, the browser `%c` path, a server TTY) by supplying a different
1892
1861
  * `SinkInterface`, with no change to the logger.
1893
1862
  *
1894
1863
  * @remarks
1895
1864
  * - **`write(text)` is the whole contract.** A custom sink (file / buffer / recorder)
1896
- * implements just `write(text)` and ignores the rest — the optional `level` exists ONLY so
1897
- * a stream-aware sink can ROUTE. The logger passes the originating record's {@link LogLevel}.
1865
+ * implements only `write(text)` and ignores the rest — the optional `level` exists only so
1866
+ * a stream-aware sink can route. The logger passes the originating record's {@link LogLevel}.
1898
1867
  * - **The default {@link import('./factories.js').createConsoleSink} routes by level** —
1899
1868
  * `error` → `console.error`, `warn` → `console.warn`, everything else → `console.log` — and
1900
- * writes to the UNDERLYING `console` methods SNAPSHOTTED at creation, so a later `Capture`
1869
+ * writes to the underlying `console` methods snapshotted at creation, so a later `Capture`
1901
1870
  * that patches `console` can never feed the sink's own output back into itself (the
1902
- * no-capture-loop principle). The same `level` seam lets the C-g server TTY sink send
1871
+ * no-capture-loop principle). The same `level` seam lets the server TTY sink send
1903
1872
  * `error` / `warn` to `stderr`.
1904
1873
  */
1905
1874
  export declare interface SinkInterface {
1906
1875
  /**
1907
- * Write one already-formatted chunk of output. `text` receives ONE LINE WITHOUT its
1908
- * terminator — the sink's target supplies it (e.g. `console.log`; the server TTY sink
1909
- * appends one) — UNLESS `text` begins with `\r`: that is an in-place REDRAW frame (the
1876
+ * Writes one already-formatted chunk of output. `text` receives one line without its
1877
+ * terminator — the sink's target supplies it (for example `console.log`; the server TTY sink
1878
+ * appends one) — unless `text` begins with `\r`: that is an in-place redraw frame (the
1910
1879
  * Spinner / Progress animation protocol), written verbatim. A tick frame carries no
1911
1880
  * terminator; a final frame carries its own.
1912
1881
  * `level` is the originating record's {@link LogLevel} — supplied so a stream-aware sink
1913
- * can route (e.g. `error` to `stderr`); a plain sink ignores it.
1882
+ * can route (for example `error` to `stderr`); a plain sink ignores it.
1914
1883
  */
1915
1884
  write(text: string, level?: LogLevel): void;
1916
1885
  }
1917
1886
 
1918
1887
  /**
1919
- * A self-driving, observable activity spinner (AGENTS §13) — a glyph cycle that advances on a
1888
+ * Implements a self-driving, observable activity spinner — a glyph cycle that advances on a
1920
1889
  * periodic timer, writing each `\r` + frame line to its {@link SinkInterface} and emitting it on
1921
- * `frame`. The leading `\r` is what an overwrite-capable sink (the C-g TTY sink) redraws on; a plain
1922
- * sink (C-f) degrades to a fresh, non-overwriting line — the line-OVERWRITE is the SINK's job, never
1923
- * the spinner's. UNIVERSAL — `setInterval` + the one {@link StylerInterface} + the one
1890
+ * `frame`. The leading `\r` is what an overwrite-capable sink (the TTY sink) redraws on; a plain
1891
+ * sink degrades to a fresh, non-overwriting line — the line-overwrite is the sink's job, never
1892
+ * the spinner's. Universal — `setInterval` + the one {@link StylerInterface} + the one
1924
1893
  * {@link SinkInterface}, no `node:*`, no `process.stdout`.
1925
1894
  *
1926
1895
  * @remarks
@@ -1929,16 +1898,16 @@ export declare interface SinkInterface {
1929
1898
  * current frame, emits it on `frame`, writes `'\r' + line` to the sink, then advances the frame
1930
1899
  * index (wrapping). A test drives frames by calling {@link tick} directly, or arms a real short
1931
1900
  * `interval` and proves the timer arms / clears through the sink it writes to.
1932
- * - **Leak-free timer.** The interval is ALWAYS cleared on {@link success} / {@link failure} /
1901
+ * - **Leak-free timer.** The interval is always cleared on {@link succeed} / {@link fail} /
1933
1902
  * {@link stop} / {@link destroy} — `#handle` is the single source of `active`, set on arm and unset
1934
1903
  * on clear, so a spinner never leaks a running interval.
1935
1904
  * - **Idempotent `start`.** A {@link start} while already `active` is a no-op (it never arms a second
1936
1905
  * timer).
1937
- * - **Outcome lines.** {@link success} / {@link failure} clear the timer then write + emit a FINAL line —
1906
+ * - **Outcome lines.** {@link succeed} / {@link fail} clear the timer then write + emit a final line —
1938
1907
  * the supplied theme status icon + style (`✔` / `✖` by default) + the message — terminated
1939
- * by a newline (the activity is over; the line is committed, not overwritten). {@link failure} routes to
1908
+ * by a newline (the activity is over; the line is committed, not overwritten). {@link fail} routes to
1940
1909
  * the sink's error stream.
1941
- * - **Lifecycle (§10).** {@link stop} clears the timer and LEAVES the current line; {@link destroy}
1910
+ * - **Lifecycle.** {@link stop} clears the timer and leaves the current line; {@link destroy}
1942
1911
  * stops then destroys the emitter. {@link update} swaps the message and re-renders immediately when
1943
1912
  * `active`.
1944
1913
  *
@@ -1947,7 +1916,7 @@ export declare interface SinkInterface {
1947
1916
  * const spinner = new Spinner({ message: 'building' })
1948
1917
  * spinner.start() // arms the timer, paints the first frame to the sink
1949
1918
  * spinner.update('bundling') // message changes, re-rendered at once
1950
- * spinner.success('built in 1.2s') // ✔ built in 1.2s — timer cleared, line committed
1919
+ * spinner.succeed('built in 1.2s') // ✔ built in 1.2s — timer cleared, line committed
1951
1920
  * ```
1952
1921
  */
1953
1922
  export declare class Spinner implements SpinnerInterface {
@@ -1959,16 +1928,16 @@ export declare class Spinner implements SpinnerInterface {
1959
1928
  start(): void;
1960
1929
  tick(): void;
1961
1930
  update(message: string): void;
1962
- success(message?: string): void;
1963
- failure(message?: string): void;
1931
+ succeed(message?: string): void;
1932
+ fail(message?: string): void;
1964
1933
  stop(): void;
1965
1934
  destroy(): void;
1966
1935
  }
1967
1936
 
1968
1937
  /**
1969
- * The default spinner frame cycle a {@link import('./types.js').SpinnerInterface} advances through —
1938
+ * Holds the default spinner frame cycle a {@link import('./types.js').SpinnerInterface} advances through —
1970
1939
  * the ten braille-pattern glyphs (U+2800 block) that read as a smoothly rotating dot, the universal
1971
- * terminal-spinner convention. Frozen; a consumer swaps the whole cycle via `options.frames`.
1940
+ * terminal-spinner convention. Frozen; a consumer swaps the whole cycle through `options.frames`.
1972
1941
  *
1973
1942
  * @remarks
1974
1943
  * Braille glyphs are single visible cells, so every frame occupies one column — the spinner glyph
@@ -1977,95 +1946,95 @@ export declare class Spinner implements SpinnerInterface {
1977
1946
  export declare const SPINNER_FRAMES: readonly string[];
1978
1947
 
1979
1948
  /**
1980
- * The observable events a {@link SpinnerInterface} emits (AGENTS §13).
1949
+ * Declares the observable events a {@link SpinnerInterface} emits.
1981
1950
  *
1982
1951
  * @remarks
1983
1952
  * - `frame` — the core event: fires once per advance (every `tick()`, whether driven by the internal
1984
- * timer or called directly) AND on the final `success` / `failure` line, carrying the rendered frame
1985
- * line (the SAME text written to the sink, minus the leading `\r`). The hook a non-sink consumer
1953
+ * timer or called directly) and on the final `succeed` / `fail` line, carrying the rendered frame
1954
+ * line (the same text written to the sink, minus the leading `\r`). The hook a non-sink consumer
1986
1955
  * (a test, a remote mirror) rides to observe the animation without a terminal.
1987
1956
  * - `start` / `stop` — the lifecycle signals bracketing the internal timer: `start` fires when the
1988
1957
  * timer is armed (the first `start()` on an inactive spinner), `stop` when it is cleared (a
1989
- * `stop()` / `success()` / `failure()` on an active spinner, and from `destroy()`); both pure signals
1958
+ * `stop()` / `succeed()` / `fail()` on an active spinner, and from `destroy()`); both pure signals
1990
1959
  * (empty tuples) so a consumer can observe the activity lifecycle.
1991
1960
  *
1992
- * Listener isolation is the emitter's (§13): a listener throw routes to the emitter's `error`
1993
- * handler, never onto this map. Declared as a `type` alias (not `interface extends EventMap`, §4.5):
1961
+ * Listener isolation is the emitter's: a listener throw routes to the emitter's `error`
1962
+ * handler, never onto this map. Declared as a `type` alias (not `interface extends EventMap`):
1994
1963
  * a type-literal satisfies the `EventMap` constraint structurally, whereas an interface lacks the
1995
1964
  * index signature.
1996
1965
  */
1997
1966
  export declare type SpinnerEventMap = {
1998
- /** A frame was produced (a `tick()` advance or the final `success` / `failure` line) — the rendered line. */
1967
+ /** Fires after a frame was produced (a `tick()` advance or the final `succeed` / `fail` line) — the rendered line. */
1999
1968
  readonly frame: readonly [line: string];
2000
- /** The internal timer was armed (an inactive spinner's `start()`). */
1969
+ /** Fires after the internal timer was armed (an inactive spinner's `start()`). */
2001
1970
  readonly start: readonly [];
2002
- /** The internal timer was cleared (an active spinner's `stop()` / `success()` / `failure()` / `destroy()`). */
1971
+ /** Fires after the internal timer was cleared (an active spinner's `stop()` / `succeed()` / `fail()` / `destroy()`). */
2003
1972
  readonly stop: readonly [];
2004
1973
  };
2005
1974
 
2006
1975
  /**
2007
- * A self-driving, observable activity spinner (AGENTS §13) — a glyph cycle that advances on a
1976
+ * Declares a self-driving, observable activity spinner — a glyph cycle that advances on a
2008
1977
  * periodic timer, writing each `\r` + frame line to its {@link SinkInterface} and emitting it on
2009
- * `frame`. The line-OVERWRITE is the sink's job (a TTY sink overwrites on the `\r`; a plain sink
1978
+ * `frame`. The line-overwrite is the sink's job (a TTY sink overwrites on the `\r`; a plain sink
2010
1979
  * degrades to a fresh line).
2011
1980
  *
2012
1981
  * @remarks
2013
1982
  * - **Self-driving but deterministically testable.** `start()` arms a `setInterval` (universal — no
2014
1983
  * `node:*`) that calls `tick()` each `interval`; each `tick()` advances the frame index, builds the
2015
1984
  * styled `glyph + message` line, emits it on `frame`, and writes `'\r' + line` to the sink. A test
2016
- * drives frames by calling `tick()` directly (NO real clock) and proves the timer arms / clears
2017
- * with fake timers — the timer is ALWAYS cleared on `success` / `failure` / `stop` / `destroy`, so it
1985
+ * drives frames by calling `tick()` directly (no real clock) and proves the timer arms / clears
1986
+ * with fake timers — the timer is always cleared on `succeed` / `fail` / `stop` / `destroy`, so it
2018
1987
  * never leaks.
2019
1988
  * - **Idempotent `start`.** A `start()` while already `active` is a no-op (it never arms a second
2020
- * timer). `active` reflects whether the timer is currently armed.
2021
- * - **Outcome lines.** `success(message?)` / `failure(message?)` clear the timer, then write + emit a
2022
- * FINAL line — the theme's success / error status icon + style (`✔` / `✖` by default) + the
1989
+ * timer). `active` reflects whether the timer is armed.
1990
+ * - **Outcome lines.** `succeed(message?)` / `fail(message?)` clear the timer, then write + emit a
1991
+ * final line — the theme's success / error status icon + style (`✔` / `✖` by default) + the
2023
1992
  * message — terminated by a newline (the activity is over; the line is committed, not overwritten).
2024
- * `failure` routes to the sink's error stream.
2025
- * - **Lifecycle (§10).** `stop()` clears the timer and LEAVES the current line (no final write);
1993
+ * `fail` routes to the sink's error stream.
1994
+ * - **Lifecycle.** `stop()` clears the timer and leaves the current line (no final write);
2026
1995
  * `destroy()` stops then destroys the emitter. `update(message)` swaps the message (re-rendering
2027
1996
  * immediately when active, so the change shows without waiting for the next tick).
2028
1997
  */
2029
1998
  export declare interface SpinnerInterface {
2030
1999
  readonly emitter: EmitterInterface<SpinnerEventMap>;
2031
- /** Whether the internal timer is currently armed (between `start()` and `stop` / `success` / `failure`). */
2000
+ /** Reports whether the internal timer is armed (between `start()` and `stop` / `succeed` / `fail`). */
2032
2001
  readonly active: boolean;
2033
- /** The current message shown beside the glyph. */
2002
+ /** Holds the current message shown beside the glyph. */
2034
2003
  readonly message: string;
2035
- /** Arm the periodic timer and render the first frame — a no-op when already `active`. */
2004
+ /** Arms the periodic timer and renders the first frame — a no-op when already `active`. */
2036
2005
  start(): void;
2037
- /** Advance one frame: build the line, emit `frame`, and write `\r` + line to the sink. */
2006
+ /** Advances one frame: builds the line, emits `frame`, and writes `\r` + line to the sink. */
2038
2007
  tick(): void;
2039
- /** Change the message; re-renders immediately when `active` so the change shows at once. */
2008
+ /** Changes the message; re-renders immediately when `active` so the change shows at once. */
2040
2009
  update(message: string): void;
2041
- /** Stop with a SUCCESS line — clear the timer, write + emit `✔ message` + newline. */
2042
- success(message?: string): void;
2043
- /** Stop with a FAILURE line — clear the timer, write + emit `✖ message` + newline (error stream). */
2044
- failure(message?: string): void;
2045
- /** Clear the timer and LEAVE the current line (no final write) — a no-op when not `active`. */
2010
+ /** Stops with a success line — clears the timer, writes + emits `✔ message` + newline. */
2011
+ succeed(message?: string): void;
2012
+ /** Stops with an error line — clears the timer, writes + emits `✖ message` + newline (error stream). */
2013
+ fail(message?: string): void;
2014
+ /** Clears the timer and leaves the current line (no final write) — a no-op when not `active`. */
2046
2015
  stop(): void;
2047
- /** Tear down — `stop()` then destroy the emitter. */
2016
+ /** Tears down — `stop()` then destroys the emitter. */
2048
2017
  destroy(): void;
2049
2018
  }
2050
2019
 
2051
2020
  /**
2052
- * Options for `createSpinner` / the {@link SpinnerInterface} constructor.
2021
+ * Configures the {@link import('./Spinner.js').Spinner} constructor.
2053
2022
  *
2054
2023
  * @remarks
2055
- * - `on` — the reserved {@link EmitterHooks} key (§8): initial listeners for the
2024
+ * - `on` — the reserved {@link EmitterHooks} key: initial listeners for the
2056
2025
  * {@link SpinnerEventMap}, wired at construction.
2057
- * - `error` — the emitter's listener-error handler (§13); a listener throw routes here.
2026
+ * - `error` — the emitter's listener-error handler; a listener throw routes here.
2058
2027
  * - `message` — the text shown beside the spinner glyph; defaults to `''` (a bare glyph). Changed
2059
- * live via `update(message)` and overridden by a `success` / `failure` argument.
2028
+ * live through `update(message)` and overridden by a `succeed` / `fail` argument.
2060
2029
  * - `frames` — the cycle of glyph frames the spinner advances through; defaults to
2061
2030
  * {@link SPINNER_FRAMES} (the braille set `⠋⠙⠹…`). Each `tick()` advances to the next, wrapping.
2062
2031
  * - `interval` — the timer period in milliseconds between frames; defaults to
2063
- * {@link DEFAULT_SPINNER_INTERVAL}. The timer is ALWAYS cleared on `success` / `failure` / `stop` /
2064
- * `destroy`, so it never leaks; tests drive frames deterministically via `tick()` (no real clock).
2032
+ * {@link DEFAULT_SPINNER_INTERVAL}. The timer is always cleared on `succeed` / `fail` / `stop` /
2033
+ * `destroy`, so it never leaks; tests drive frames deterministically through `tick()` (no real clock).
2065
2034
  * - `sink` — where each `\r` + frame line is written; defaults to
2066
- * {@link import('./factories.js').createConsoleSink}. A TTY sink (C-g) overwrites on the `\r`.
2035
+ * {@link import('./factories.js').createConsoleSink}. A TTY sink overwrites on the `\r`.
2067
2036
  * - `styler` — the {@link StylerInterface} the glyph is colored through; defaults to
2068
- * {@link import('./factories.js').createStyler} (ANSI). The ONE styler the whole system shares.
2037
+ * {@link import('./factories.js').createStyler} (ANSI). The one styler the whole system shares.
2069
2038
  * - `theme` — the {@link Theme} supplying the accent and outcome roles; defaults to
2070
2039
  * {@link DEFAULT_THEME}.
2071
2040
  */
@@ -2081,34 +2050,34 @@ export declare interface SpinnerOptions {
2081
2050
  }
2082
2051
 
2083
2052
  /**
2084
- * Each {@link StatusLevel}'s {@link Color} — the icon + message color a `status` line renders
2085
- * in (`success` green, `error` red, `warn` yellow, `info` blue). The VISUAL treatment of a
2053
+ * Maps each {@link StatusLevel} to its {@link Color} — the icon + message color a `status` line renders
2054
+ * in (`success` green, `error` red, `warn` yellow, `info` blue). The visual treatment of a
2086
2055
  * narrative outcome, colored through the reporter's styler; orthogonal to leveling, like
2087
2056
  * {@link LEVEL_COLORS}. Excludes `default` so each value indexes a real styler accessor.
2088
2057
  */
2089
2058
  export declare const STATUS_COLORS: Readonly<Record<StatusLevel, Exclude<Color, 'default'>>>;
2090
2059
 
2091
2060
  /**
2092
- * Each {@link StatusLevel}'s icon glyph — the leading mark a {@link
2061
+ * Maps each {@link StatusLevel} to its icon glyph — the leading mark a {@link
2093
2062
  * import('./types.js').ReporterInterface.status} outcome line shows: `success` ✔, `error` ✖,
2094
2063
  * `warn` ⚠, `info` ℹ. The narrative-outcome counterpart to a log level's label; frozen.
2095
2064
  */
2096
2065
  export declare const STATUS_ICONS: Readonly<Record<StatusLevel, string>>;
2097
2066
 
2098
2067
  /**
2099
- * Every {@link StatusLevel}, frozen — the outcomes a `status` line supports (drives exhaustive
2068
+ * Lists every {@link StatusLevel}, frozen — the outcomes a `status` line supports (drives exhaustive
2100
2069
  * tests). The source of truth for the status axis; aligned with {@link STATUS_ICONS} /
2101
2070
  * {@link STATUS_COLORS}.
2102
2071
  */
2103
2072
  export declare const STATUS_LEVELS: readonly StatusLevel[];
2104
2073
 
2105
2074
  /**
2106
- * A narrative outcome level — the four states {@link ReporterInterface.status} reports, each
2075
+ * Names a narrative outcome level — the four states {@link ReporterInterface.status} reports, each
2107
2076
  * with its own icon + color ({@link STATUS_ICONS} / {@link STATUS_COLORS}).
2108
2077
  *
2109
2078
  * @remarks
2110
- * DISTINCT from {@link LogLevel} (`debug` / `info` / `warn` / `error`): a `StatusLevel` is a
2111
- * narrative OUTCOME (did the step success?), not a log SEVERITY threshold — there is no
2079
+ * distinct from {@link LogLevel} (`debug` / `info` / `warn` / `error`): a `StatusLevel` is a
2080
+ * narrative outcome (did the step success?), not a log severity threshold — there is no
2112
2081
  * ordering and no gating. `success` (`✔`, green), `error` (`✖`, red), `warn` (`⚠`, yellow),
2113
2082
  * `info` (`ℹ`, blue). `error` routes to the sink's error stream (the `level` hint passed to
2114
2083
  * {@link SinkInterface.write}); the other three go to the default stream.
@@ -2116,8 +2085,8 @@ export declare const STATUS_LEVELS: readonly StatusLevel[];
2116
2085
  export declare type StatusLevel = 'success' | 'error' | 'warn' | 'info';
2117
2086
 
2118
2087
  /**
2119
- * A step's position in a sequence — the `{ index, total }` a {@link ReporterInterface.step}
2120
- * renders as a `[2/5]` prefix.
2088
+ * Represents where one step sits in a sequence — the `{ index, total }` a
2089
+ * {@link ReporterInterface.step} renders as a `[2/5]` prefix.
2121
2090
  *
2122
2091
  * @remarks
2123
2092
  * Both are 1-based for display (`{ index: 2, total: 5 }` ⇒ `[2/5]`); the reporter formats
@@ -2130,17 +2099,18 @@ export declare interface StepPosition {
2130
2099
  }
2131
2100
 
2132
2101
  /**
2133
- * Stringify ONE captured console argument into a line fragment — the per-argument rule behind
2102
+ * Stringifies one captured console argument into a line fragment — the per-argument rule behind
2134
2103
  * {@link formatArgs}: an `Error` → `name: message`, a plain object / array → circular-safe JSON,
2135
2104
  * anything else (string, number, boolean, `null`, `undefined`, symbol, function) → `String(value)`.
2136
2105
  *
2137
2106
  * @remarks
2138
- * - **Total + never throws.** Like a guard (§14), this never throws on adversarial input — a value
2107
+ * - **Total + never throws.** Like a guard, this never throws on adversarial input — a value
2139
2108
  * carrying a circular reference, a `BigInt`, or a throwing `toJSON` is rendered, not raised. The
2140
2109
  * `JSON.stringify` runs with a circular-guard replacer (a seen-set drops a back-reference as
2141
- * `'[Circular]'`); should `JSON.stringify` still throw (e.g. a `BigInt`), the value falls back to
2142
- * `String(value)`. So a `Capture` can never crash the program whose `console.*` it intercepts.
2143
- * - **`Error` first.** An `Error` renders as `name: message` (e.g. `TypeError: bad`) — the useful
2110
+ * `'[Circular]'`); if `JSON.stringify` still throws (for example on a `BigInt`), the value falls
2111
+ * back to `String(value)`. So a `Capture` can never crash the program whose `console.*` it
2112
+ * intercepts.
2113
+ * - **`Error` first.** An `Error` renders as `name: message` (for example `TypeError: bad`) — the useful
2144
2114
  * one-line form, since `JSON.stringify(error)` is `{}` (its fields are non-enumerable).
2145
2115
  * - **Objects → JSON.** A non-null `object` (including an array) is `JSON.stringify`d; a primitive
2146
2116
  * (or `null` / `undefined` / `function` / `symbol`) goes through `String`.
@@ -2161,11 +2131,11 @@ export declare interface StepPosition {
2161
2131
  export declare function stringifyValue(value: unknown): string;
2162
2132
 
2163
2133
  /**
2164
- * Remove every ANSI escape sequence from `text`, returning the plain visible string.
2134
+ * Removes every ANSI escape sequence from `text`, returning the plain visible string.
2165
2135
  *
2166
2136
  * @remarks
2167
- * Strips SGR color/style codes AND other CSI controls (cursor, erase) plus OSC
2168
- * sequences (titles, hyperlinks) — see {@link ANSI_PATTERN}. A FRESH `RegExp` is built
2137
+ * Strips SGR color/style codes and other CSI controls (cursor, erase) plus OSC
2138
+ * sequences (titles, hyperlinks) — see {@link ANSI_PATTERN}. A fresh `RegExp` is built
2169
2139
  * per call from the canonical pattern's `source` + `flags`, so the shared global
2170
2140
  * pattern's `lastIndex` is never mutated across calls (re-entrant and deterministic).
2171
2141
  *
@@ -2180,14 +2150,14 @@ export declare function stringifyValue(value: unknown): string;
2180
2150
  export declare function strip(text: string): string;
2181
2151
 
2182
2152
  /**
2183
- * Remove every non-printing C0 control character from `text` EXCEPT `\t` / `\n` / `\r`
2153
+ * Removes every non-printing C0 control character from `text` except `\t` / `\n` / `\r`
2184
2154
  * (meaningful whitespace), plus DEL — returning the sanitized string.
2185
2155
  *
2186
2156
  * @remarks
2187
- * Deliberately SEPARATE from {@link strip} (ANSI-escape removal only, so `width` /
2157
+ * Deliberately separate from {@link strip} (ANSI-escape removal only, so `width` /
2188
2158
  * `align` stay untouched) — this is the additional pass a non-TTY output sink applies
2189
2159
  * on top of `strip`, so a captured `\x07` bell or stray `\x00` never reaches a log file
2190
- * / non-terminal target. A FRESH `RegExp` is built per call from {@link CONTROL_PATTERN}'s
2160
+ * / non-terminal target. A fresh `RegExp` is built per call from {@link CONTROL_PATTERN}'s
2191
2161
  * `source` + `flags`, the same re-entrant idiom as `strip`.
2192
2162
  *
2193
2163
  * @param text - Any string, possibly carrying raw control bytes
@@ -2201,7 +2171,7 @@ export declare function strip(text: string): string;
2201
2171
  export declare function stripControls(text: string): string;
2202
2172
 
2203
2173
  /**
2204
- * Text style as DATA — a frozen, readonly record of a foreground color, a background
2174
+ * Represents text style as data — a frozen, readonly record of a foreground color, a background
2205
2175
  * color, and a set of text attributes. The single style value the whole console /
2206
2176
  * terminal system shares; a {@link RendererInterface} renders it for one target.
2207
2177
  *
@@ -2210,7 +2180,7 @@ export declare function stripControls(text: string): string;
2210
2180
  * emits a color code only for a set, non-`default` color.
2211
2181
  * - `attributes` is a de-duplicated, order-stable list (a set modelled as an array so
2212
2182
  * the value stays plain JSON data — no `Set` to clone or serialize). An empty list +
2213
- * no colors is the EMPTY style, which renders text unchanged.
2183
+ * no colors is the empty style, which renders text unchanged.
2214
2184
  * - The value is deeply frozen; compose a new style with the styler rather than mutating.
2215
2185
  */
2216
2186
  export declare interface Style {
@@ -2220,10 +2190,10 @@ export declare interface Style {
2220
2190
  }
2221
2191
 
2222
2192
  /**
2223
- * The fluent, composable styling surface — the consumer-facing API. It is BOTH a
2224
- * function (call it with text to render the accumulated style) AND a record of
2193
+ * Declares the fluent, composable styling surface — the consumer-facing API. It is both a
2194
+ * function (call it with text to render the accumulated style) and a record of
2225
2195
  * chainable accessors: every {@link Color} and {@link Attribute} is a getter returning a
2226
- * NEW styler with that token added, so `styler.red.bold('hi')` and
2196
+ * new styler with that token added, so `styler.red.bold('hi')` and
2227
2197
  * `styler.red(styler.bold('hi'))` both work and nothing is mutated.
2228
2198
  *
2229
2199
  * @remarks
@@ -2231,24 +2201,24 @@ export declare interface Style {
2231
2201
  * styler is reusable and the chains never interfere.
2232
2202
  * - Calling the styler builds the {@link Style} under the hood and renders it through the
2233
2203
  * injected renderer. When `enabled` is `false`, it returns the text verbatim.
2234
- * - `render` is the DATA door beside the accessor chain: it renders a {@link Style} value
2204
+ * - `render` is the data door beside the accessor chain: it renders a {@link Style} value
2235
2205
  * (a {@link Theme} role, say) merged over the accumulated style, so a caller styles by
2236
2206
  * value where the chain styles by name. Both go through the same renderer and the same
2237
2207
  * `enabled` switch.
2238
- * - `style` exposes the accumulated style DATA (the empty style on a base styler), and
2208
+ * - `style` exposes the accumulated style data (the empty style on a base styler), and
2239
2209
  * `enabled` reflects the switch — both inspectable and testable.
2240
2210
  * - A later color of the same channel wins (`styler.red.blue` is blue); a repeated
2241
2211
  * attribute is idempotent (`styler.bold.bold` carries one `bold`).
2242
2212
  */
2243
2213
  export declare interface StylerInterface {
2244
- /** Render the accumulated style around `text` (verbatim when `enabled` is `false`). */
2214
+ /** Renders the accumulated style around `text` (verbatim when `enabled` is `false`). */
2245
2215
  (text: string): string;
2246
- /** The accumulated style DATA — the empty style on a base styler. */
2216
+ /** Holds the accumulated style data — the empty style on a base styler. */
2247
2217
  readonly style: Style;
2248
- /** Whether styling is applied; when `false`, calls return text unchanged. */
2218
+ /** Reports whether styling is applied; when `false`, calls return text unchanged. */
2249
2219
  readonly enabled: boolean;
2250
2220
  /**
2251
- * Render `text` in `style` merged OVER the accumulated style — the by-value counterpart
2221
+ * Renders `text` in `style` merged over the accumulated style — the by-value counterpart
2252
2222
  * of the accessor chain, and the door a {@link Theme} role is applied through.
2253
2223
  *
2254
2224
  * @param style - The style to overlay; its colors win over the accumulated ones and its
@@ -2259,7 +2229,7 @@ export declare interface StylerInterface {
2259
2229
  *
2260
2230
  * @example
2261
2231
  * ```ts
2262
- * import { createStyler, DEFAULT_THEME } from '@src/core'
2232
+ * import { createStyler, DEFAULT_THEME } from '@orkestrel/console'
2263
2233
  *
2264
2234
  * const styler = createStyler()
2265
2235
  * styler.render(DEFAULT_THEME.levels.warn, 'WARN') // yellow
@@ -2292,13 +2262,13 @@ export declare interface StylerInterface {
2292
2262
  }
2293
2263
 
2294
2264
  /**
2295
- * Options for {@link createStyler}.
2265
+ * Configures {@link createStyler}.
2296
2266
  *
2297
2267
  * @remarks
2298
2268
  * - `renderer` — the {@link RendererInterface} every style renders through; defaults to
2299
2269
  * the ANSI renderer (the cross-environment default), so the styler works unchanged in
2300
- * any terminal. Inject a browser `%c` renderer (C-f) to retarget with no other change.
2301
- * - `enabled` — the no-color switch. When `false`, the styler returns text VERBATIM
2270
+ * any terminal. Inject a browser `%c` renderer to retarget with no other change.
2271
+ * - `enabled` — the no-color switch. When `false`, the styler returns text verbatim
2302
2272
  * (for a non-TTY, a `NO_COLOR` environment, or piped output); defaults to `true`.
2303
2273
  */
2304
2274
  export declare interface StylerOptions {
@@ -2307,7 +2277,7 @@ export declare interface StylerOptions {
2307
2277
  }
2308
2278
 
2309
2279
  /**
2310
- * Options for {@link import('./helpers.js').renderTable} — a bordered grid of columns + rows
2280
+ * Configures {@link import('./helpers.js').renderTable} — a bordered grid of columns + rows
2311
2281
  * with per-column alignment and width-aware sizing.
2312
2282
  *
2313
2283
  * @remarks
@@ -2317,7 +2287,7 @@ export declare interface StylerOptions {
2317
2287
  * - `border` — the {@link BorderStyle} the frame + header rule + column separators draw in;
2318
2288
  * defaults to {@link DEFAULT_BORDER} (`single`).
2319
2289
  * - `styler` — colors the border + header labels when supplied; the cells are written as
2320
- * given (already-styled cells are honored — their VISIBLE width drives column sizing, never
2290
+ * given (already-styled cells are honored — their visible width drives column sizing, never
2321
2291
  * their raw `.length`).
2322
2292
  * - `style` — an optional by-value style rendered through `styler` for the frame and headers.
2323
2293
  */
@@ -2330,7 +2300,7 @@ export declare interface TableOptions {
2330
2300
  }
2331
2301
 
2332
2302
  /**
2333
- * The app-wide semantic style vocabulary — every role the console system styles, bound to a
2303
+ * Represents the app-wide semantic style vocabulary — every role the console system styles, bound to a
2334
2304
  * {@link Style} value. Pass one theme to a logger / reporter / spinner / progress and every
2335
2305
  * surface speaks it.
2336
2306
  *
@@ -2342,7 +2312,7 @@ export declare interface TableOptions {
2342
2312
  * step prefix.
2343
2313
  * - `chrome` — the frame role: separators, box / table / tree connectors, and a log line's
2344
2314
  * timestamp / name / data surround.
2345
- * - A theme is the vocabulary the WHOLE application shares; a per-entity option (a
2315
+ * - A theme is the vocabulary the whole application shares; a per-entity option (a
2346
2316
  * `ProgressOptions.fill`, a `BoxOptions.border`) is the presentation of that one instance.
2347
2317
  * - A theme returned by {@link createTheme} is frozen with every {@link Style} leaf deeply
2348
2318
  * frozen, so one theme is safely shared across every entity.
@@ -2355,12 +2325,12 @@ export declare interface Theme {
2355
2325
  }
2356
2326
 
2357
2327
  /**
2358
- * Options for {@link createTheme} — the roles to override on {@link DEFAULT_THEME}.
2328
+ * Holds the options for {@link createTheme} — the roles to override on {@link DEFAULT_THEME}.
2359
2329
  *
2360
2330
  * @remarks
2361
- * Every key is optional and merges per ROLE, never per theme: an omitted role keeps its
2331
+ * Every key is optional and merges per role, never per theme: an omitted role keeps its
2362
2332
  * default, and `levels` / `statuses` merge per entry, so `{ levels: { warn: … } }` restyles
2363
- * the `warn` label and leaves the other three alone. A status override supplies its whole
2333
+ * the `warn` label and leaves `debug`, `info`, and `error` alone. A status override supplies its whole
2364
2334
  * `{ icon, style }` record; {@link createTheme} snapshots and freezes that record and every
2365
2335
  * style leaf it receives.
2366
2336
  */
@@ -2372,12 +2342,12 @@ export declare interface ThemeOptions {
2372
2342
  }
2373
2343
 
2374
2344
  /**
2375
- * One narrative outcome's presentation — the icon glyph a {@link StatusLevel} shows and the
2345
+ * Represents one narrative outcome's presentation — the icon glyph a {@link StatusLevel} shows and the
2376
2346
  * {@link Style} the line renders in.
2377
2347
  *
2378
2348
  * @remarks
2379
2349
  * The themed counterpart of the {@link STATUS_ICONS} / {@link STATUS_COLORS} defaults: those
2380
- * two constants are the SOURCE of {@link DEFAULT_THEME}'s statuses. A status override supplies
2350
+ * two constants are the source of {@link DEFAULT_THEME}'s statuses. A status override supplies
2381
2351
  * the whole record — both `icon` and `style` — through {@link ThemeOptions}.
2382
2352
  */
2383
2353
  export declare interface ThemeStatus {
@@ -2386,7 +2356,7 @@ export declare interface ThemeStatus {
2386
2356
  }
2387
2357
 
2388
2358
  /**
2389
- * One node of a {@link TreeOptions} tree — a label plus optional children, recursively.
2359
+ * Represents one node of a {@link TreeOptions} tree — a label plus optional children, recursively.
2390
2360
  *
2391
2361
  * @remarks
2392
2362
  * - `label` — the node's text (a single visible line; it may already be styled).
@@ -2399,7 +2369,7 @@ export declare interface TreeNode {
2399
2369
  }
2400
2370
 
2401
2371
  /**
2402
- * Options for {@link import('./helpers.js').renderTree} — a nested {@link TreeNode} tree drawn
2372
+ * Configures {@link import('./helpers.js').renderTree} — a nested {@link TreeNode} tree drawn
2403
2373
  * with box-drawing connectors.
2404
2374
  *
2405
2375
  * @remarks
@@ -2419,13 +2389,13 @@ export declare interface TreeOptions {
2419
2389
  }
2420
2390
 
2421
2391
  /**
2422
- * The visible width of `text` — its length after ANSI escapes are stripped, counted in
2392
+ * Measures how many visible columns `text` occupies — its length after ANSI escapes are stripped, counted in
2423
2393
  * Unicode code points (so an astral character such as an emoji counts as one, not the
2424
2394
  * two UTF-16 units `String.length` would report).
2425
2395
  *
2426
2396
  * @remarks
2427
2397
  * The basis for terminal layout (box / table / progress alignment): the column count a
2428
- * styled string occupies, independent of its escape codes. It does NOT account for
2398
+ * styled string occupies, independent of its escape codes. It does not account for
2429
2399
  * wide (CJK / fullwidth) glyphs occupying two cells — a deliberate, documented
2430
2400
  * simplification at this layer; callers needing east-asian width handle it above.
2431
2401
  *
@@ -2439,8 +2409,21 @@ export declare interface TreeOptions {
2439
2409
  */
2440
2410
  export declare function width(text: string): number;
2441
2411
 
2442
- export declare function withCapture<T>(fn: () => Promise<T>, options?: CaptureOptions): Promise<CaptureResult<T>>;
2443
-
2444
- export declare function withCapture<T>(fn: () => T, options?: CaptureOptions): CaptureResult<T>;
2412
+ /**
2413
+ * Groups the three write targets a level-routing sink chooses between — the normal target, the
2414
+ * warning target, and the error target.
2415
+ *
2416
+ * @remarks
2417
+ * The member type is the sink's own: a bound `console` method in core, a browser `%c` console
2418
+ * method, a stream target on the server, or any per-target fact routed the same way. A backend
2419
+ * that sends two levels to one place supplies the same member twice; that is how the server sink
2420
+ * routes `warn` alongside `error` to its error stream.
2421
+ * {@link import('./helpers.js').selectWriter} is the one place the level-to-member decision lives.
2422
+ */
2423
+ export declare interface WriterSet<T> {
2424
+ readonly log: T;
2425
+ readonly warn: T;
2426
+ readonly error: T;
2427
+ }
2445
2428
 
2446
2429
  export { }