jssm 5.157.17 → 5.158.0

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.
@@ -0,0 +1,4084 @@
1
+ import { circular_buffer } from 'circular_buffer_js';
2
+
3
+ /**
4
+ * The descriptor interpreter for the FSL Markdown fence convention: turns a
5
+ * parsed {@link FenceDescriptor} plus FSL source into static HTML, and walks
6
+ * a whole Markdown document replacing every `fsl`/`jssm` fence in place.
7
+ * This is the integration point for the five pieces built ahead of it — the
8
+ * fence-info parser, the viz pipeline, the rasterizer, the SVG fill
9
+ * extractor, and the editor-parity highlighter.
10
+ *
11
+ * @see notes/superpowers/specs/2026-06-23-fsl-markdown-fence-convention-design.md
12
+ */
13
+ /** Options shared by the static fence renderers. */
14
+ interface FenceRenderOptions {
15
+ /** Inline state colors in code spans (default true). @see highlight_fsl_html */
16
+ inline_colors?: boolean;
17
+ }
18
+ /**
19
+ * Render one FSL markdown fence to static HTML per the fence convention:
20
+ * parts stack top-down in the order written, sized by width/height, with
21
+ * editor-parity code highlighting whose state names carry the diagram's own
22
+ * node colors. Invalid FSL renders a visible error box — this function
23
+ * never throws for bad machine source.
24
+ *
25
+ * @param source - The FSL machine source (fence body).
26
+ * @param info - The fence info string (e.g. `'fsl image code width=300'`).
27
+ * @param opts.inline_colors - Whether code spans carry inline diagram colors (default true).
28
+ * @returns The rendered `<div class="fsl-fence">…</div>` markup.
29
+ *
30
+ * @example
31
+ * await render_fence_html('Red => Green => Red;', 'fsl');
32
+ * // '<div class="fsl-fence" …><svg…/svg><pre class="fsl-code">…</pre></div>'
33
+ */
34
+ declare function render_fence_html(source: string, info: string, opts?: FenceRenderOptions): Promise<string>;
35
+ /**
36
+ * Replace every fsl/jssm fenced code block in a Markdown string with its
37
+ * rendered static HTML; all other content passes through byte-identical.
38
+ * Each fence is isolated — a broken machine becomes its own error box and
39
+ * the rest of the document still renders. Backtick fences of length ≥3
40
+ * are recognized; tilde fences are out of scope (v1, spec §9).
41
+ *
42
+ * @param markdown - The full Markdown document source.
43
+ * @param opts.inline_colors - Whether code spans carry inline diagram colors (default true).
44
+ * @returns The document with every `fsl`/`jssm` fence replaced by rendered HTML.
45
+ *
46
+ * @example
47
+ * await transform_markdown('# Doc\n\n```fsl\na -> b;\n```\n');
48
+ * // '# Doc\n\n<div class="fsl-fence">…</div>\n'
49
+ */
50
+ declare function transform_markdown(markdown: string, opts?: FenceRenderOptions): Promise<string>;
51
+ /** Options for {@link render_fence_gif}. */
52
+ interface GifRenderOptions {
53
+ /** Per-frame delay, centiseconds. Default 70 (~0.7s). */
54
+ delay_cs?: number;
55
+ /** Netscape loop count; 0 = forever (default). */
56
+ loop?: number;
57
+ /** Walk-length ceiling; longer walks truncate. Default 64. */
58
+ max_frames?: number;
59
+ /** Raster zoom percentage; 100 = 3× natural (the CLI raster convention). Default 100. */
60
+ scale?: number;
61
+ /** Fill painted on the walked state each frame. Default '#ff9930'. */
62
+ highlight_fill?: string;
63
+ }
64
+ /**
65
+ * Render an FSL machine as a looping animated GIF that walks its states:
66
+ * main-path (`=>`) states in order when a main path exists, else an
67
+ * every-edge tour. Graphviz lays the machine out ONCE; each frame patches
68
+ * one state's fill in the SVG string and rasterizes — identical geometry
69
+ * across frames, no layout jitter.
70
+ *
71
+ * @param source - The FSL machine source.
72
+ * @param opts.delay_cs - Per-frame delay in centiseconds (default 70).
73
+ * @param opts.loop - Netscape loop count, 0 = forever (default 0).
74
+ * @param opts.max_frames - Walk-length ceiling; longer walks truncate (default 64).
75
+ * @param opts.scale - Raster zoom percentage, 100 = 3× natural size (default 100).
76
+ * @param opts.highlight_fill - Fill painted on the walked state (default '#ff9930').
77
+ * @returns The encoded GIF89a bytes.
78
+ *
79
+ * @throws {JssmError} on invalid FSL (programmatic callers want exceptions;
80
+ * the HTML renderers catch and box instead).
81
+ *
82
+ * @example
83
+ * const gif = await render_fence_gif('Red => Green => Yellow => Red;');
84
+ * // Uint8Array starting "GIF89a", three frames, looping forever
85
+ *
86
+ * @see plan_walk
87
+ * @see encode_gif
88
+ */
89
+ declare function render_fence_gif(source: string, opts?: GifRenderOptions): Promise<Uint8Array>;
90
+
91
+ /** Result of {@link quantize}: an RGB palette plus one palette index per input pixel. */
92
+ interface Quantized {
93
+ /** RGB triples, `3 · palette_count` bytes. */
94
+ palette: Uint8Array;
95
+ /** Number of colors actually used (≤ the requested maximum). */
96
+ palette_count: number;
97
+ /** One palette index per input pixel. */
98
+ indices: Uint8Array;
99
+ }
100
+ /**
101
+ * Reduce an RGBA8888 buffer to an indexed-color image with at most
102
+ * `max_colors` colors, for GIF encoding. Alpha is composited over white
103
+ * (GIF v1 output carries no transparency). When the input already has
104
+ * `max_colors` or fewer distinct colors they are preserved exactly;
105
+ * otherwise a median-cut partition supplies the palette and each pixel maps
106
+ * to its box's weighted-average color.
107
+ *
108
+ * @param rgba - Straight RGBA bytes; length must be a multiple of 4.
109
+ * @param max_colors - Palette ceiling, 2..256.
110
+ *
111
+ * @throws {JssmError} when `rgba.length` is not a multiple of 4.
112
+ * @throws {JssmError} when `max_colors` is outside 2..256 — above 256 the
113
+ * palette index no longer fits the `Uint8Array` indices this module packs
114
+ * into GIF codes (silent index corruption instead of a clear failure);
115
+ * below 2 there is no palette to quantize into.
116
+ *
117
+ * @example
118
+ * const q = quantize(new Uint8Array([255,0,0,255, 0,255,0,255]));
119
+ * q.palette_count; // 2
120
+ */
121
+ declare function quantize(rgba: Uint8Array, max_colors?: number): Quantized;
122
+ /**
123
+ * GIF-variant LZW compression: emits a leading clear code, grows code width
124
+ * from `min_code_size + 1` up to the format's 12-bit ceiling, resets the
125
+ * dictionary when full, terminates with EOI, and packs codes LSB-first.
126
+ * Returns raw compressed bytes; the caller wraps them in GIF data sub-blocks.
127
+ *
128
+ * @param indices - Palette indices, each `< 2^min_code_size`.
129
+ * @param min_code_size - Bits needed for the palette (2..8 for GIF).
130
+ *
131
+ * @example
132
+ * lzw_encode(new Uint8Array([0, 0, 1]), 2); // Uint8Array of packed codes
133
+ */
134
+ declare function lzw_encode(indices: Uint8Array, min_code_size: number): Uint8Array;
135
+ /** One animation frame for {@link encode_gif}: straight RGBA8888 pixels. */
136
+ interface GifFrame {
137
+ rgba: Uint8Array;
138
+ width: number;
139
+ height: number;
140
+ }
141
+ /** Options for {@link encode_gif}. */
142
+ interface GifOptions {
143
+ /** Per-frame delay in centiseconds (GIF's native unit). Default 70 (~0.7s). */
144
+ delay_cs?: number;
145
+ /** Netscape loop count; 0 = loop forever (the default). */
146
+ loop?: number;
147
+ }
148
+ /**
149
+ * Encode RGBA frames as a looping animated GIF89a. A single global color
150
+ * table is quantized over the UNION of all frames' pixels (≤256 colors,
151
+ * median-cut when over); each frame then maps nearest-neighbor into that
152
+ * palette, so every frame is pixel-exact while the union stays within 256
153
+ * distinct colors. Frames must share dimensions. No transparency,
154
+ * full-frame disposal — simple and correct first.
155
+ *
156
+ * @param frames - At least one frame; all with identical width/height and
157
+ * `rgba.length === 4 · width · height`.
158
+ *
159
+ * @throws {JssmError} on zero frames, mismatched dimensions, or an rgba
160
+ * buffer whose length contradicts its stated dimensions.
161
+ *
162
+ * @example
163
+ * const red = { rgba: new Uint8Array([255,0,0,255]), width: 1, height: 1 };
164
+ * const gif = encode_gif([red], { delay_cs: 50 });
165
+ * gif.slice(0, 6); // "GIF89a" bytes
166
+ */
167
+ declare function encode_gif(frames: GifFrame[], opts?: GifOptions): Uint8Array;
168
+
169
+ declare type StateType$1 = string;
170
+ /**
171
+ * A color value accepted by jssm-viz for state and arrow styling. Currently
172
+ * any string, validated downstream by Graphviz / the named-colors list.
173
+ * Intended to be narrowed to `#RRGGBB` / `#RRGGBBAA` and CSS named colors
174
+ * in a future release.
175
+ */
176
+ declare type JssmColor = string;
177
+ /**
178
+ * Three-state policy flag: `'required'`, `'disallowed'`, or `'optional'`.
179
+ * Used by machine configuration where a default-permissive middle ground
180
+ * is meaningful (for example, the `actions` config key).
181
+ */
182
+ declare type JssmPermittedOpt = 'required' | 'disallowed' | 'optional';
183
+ /**
184
+ * The set of ASCII arrow tokens recognized by the FSL grammar. Each arrow
185
+ * encodes a direction (one-way left/right, or two-way) and a "kind" for
186
+ * each direction (`-` legal, `=` main path, `~` forced-only). See the
187
+ * Language Reference docs for the full semantic table.
188
+ */
189
+ declare type JssmArrow = '->' | '<-' | '<->' | '<=->' | '<~->' | '=>' | '<=' | '<=>' | '<-=>' | '<~=>' | '~>' | '<~' | '<~>' | '<-~>' | '<=~>';
190
+ /**
191
+ * A type teaching Typescript the various supported shapes for nodes, mostly inherited from GraphViz
192
+ */
193
+ declare type JssmShape = "box" | "polygon" | "ellipse" | "oval" | "circle" | "point" | "egg" | "triangle" | "plaintext" | "plain" | "diamond" | "trapezium" | "parallelogram" | "house" | "pentagon" | "hexagon" | "septagon" | "octagon" | "doublecircle" | "doubleoctagon" | "tripleoctagon" | "invtriangle" | "invtrapezium" | "invhouse" | "Mdiamond" | "Msquare" | "Mcircle" | "rect" | "rectangle" | "square" | "star" | "none" | "underline" | "cylinder" | "note" | "tab" | "folder" | "box3d" | "component" | "promoter" | "cds" | "terminator" | "utr" | "primersite" | "restrictionsite" | "fivepoverhang" | "threepoverhang" | "noverhang" | "assembly" | "signature" | "insulator" | "ribosite" | "rnastab" | "proteasesite" | "proteinstab" | "rpromoter" | "rarrow" | "larrow" | "lpromoter" | "record";
194
+ /**
195
+ * Semantic category of an arrow's transition. `'legal'` is a normal
196
+ * transition, `'main'` is part of the machine's primary path, `'forced'`
197
+ * may only be taken via {@link Machine.force_transition}, and `'none'`
198
+ * means no transition exists in that direction.
199
+ */
200
+ declare type JssmArrowKind = 'none' | 'legal' | 'main' | 'forced';
201
+ /**
202
+ * Graphviz layout engine selector. Controls how jssm-viz lays out the
203
+ * rendered diagram; `'dot'` is the default and most useful for state
204
+ * machines. See the Graphviz documentation for the differences.
205
+ */
206
+ declare type JssmLayout = 'dot' | 'circo' | 'twopi' | 'fdp' | 'neato';
207
+ declare type JssmCorner = 'regular' | 'rounded' | 'lined';
208
+ declare type JssmLineStyle = 'solid' | 'dashed' | 'dotted';
209
+ /**
210
+ * Tristate flag for whether a property may be overridden at runtime.
211
+ * `true` permits overrides, `false` forbids them, and `undefined` defers
212
+ * the decision to the surrounding configuration's default.
213
+ */
214
+ declare type JssmAllowsOverride = true | false | undefined;
215
+ /**
216
+ * Controls whether the state graph may contain disconnected components
217
+ * (islands). `true` permits islands (default), `false` requires a single
218
+ * connected component, and `'with_start'` permits islands only when every
219
+ * component contains at least one start state.
220
+ */
221
+ declare type JssmAllowIslands = true | false | 'with_start';
222
+ /**
223
+ * Structured render-size hint for a machine visualization, set by the FSL
224
+ * `default_size` directive. All three forms are optional in the sense that
225
+ * only one or two fields will be present depending on the form used:
226
+ *
227
+ * - `{ width }` — single-number form (`default_size: 800;`)
228
+ * - `{ width, height }` — bounding-box form (`default_size: 800 600;`)
229
+ * - `{ height }` — height-only form (`default_size: height 600;`)
230
+ *
231
+ * This is a *hint*, not a hard constraint. Renderers may ignore it.
232
+ *
233
+ * @see Machine.default_size
234
+ */
235
+ declare type JssmDefaultSize = {
236
+ width?: number;
237
+ height?: number;
238
+ };
239
+ /**
240
+ * Runtime-iterable list of valid `flow` directions for FSL diagrams.
241
+ * Use this when you need to enumerate directions; for the type itself
242
+ * see {@link FslDirection}.
243
+ */
244
+ declare const FslDirections: readonly ["up", "right", "down", "left"];
245
+ /**
246
+ * String literal type of the four supported FSL flow directions. This is
247
+ * the type of the `flow` config key on a machine.
248
+ */
249
+ declare type FslDirection = typeof FslDirections[number];
250
+ /**
251
+ * Runtime-iterable list of the built-in theme names that ship with jssm-viz.
252
+ * Use this when you need to enumerate themes; for the type itself see
253
+ * {@link FslTheme}.
254
+ */
255
+ declare const FslThemes: readonly ["default", "ocean", "modern", "plain", "bold"];
256
+ /**
257
+ * String literal type of the built-in theme names. This is the element
258
+ * type of the `theme` config key (which accepts an array so that themes
259
+ * can be layered).
260
+ */
261
+ declare type FslTheme = typeof FslThemes[number];
262
+ /**
263
+ * Persistable snapshot of a Machine produced by {@link Machine.serialize}
264
+ * and consumed by {@link deserialize}. Carries the current state, the
265
+ * associated machine data, the recent history (subject to the configured
266
+ * capacity), and metadata to detect version-skew on rehydration.
267
+ *
268
+ * @typeParam DataType - The type of the user-supplied data payload (`mDT`).
269
+ */
270
+ declare type JssmSerialization<DataType> = {
271
+ jssm_version: string;
272
+ timestamp: number;
273
+ comment?: string | undefined;
274
+ state: StateType$1;
275
+ history: [string, DataType][];
276
+ history_capacity: number;
277
+ data: DataType;
278
+ };
279
+ /**
280
+ * One ordered member of a named group's membership list. A `'state'`
281
+ * member is an ordinary state (`a` inside `&g : [a]`). A `'group'` member
282
+ * references another group: `mode: 'nest'` is the `&child` form, which
283
+ * preserves the child group's identity for later precedence/viz, while
284
+ * `mode: 'spread'` is the `...&child` form, which inlines the child's
285
+ * members and erases that identity. Both modes resolve to the same flat
286
+ * set of states via {@link JssmGroupRegistry} resolution; only their
287
+ * structural bookkeeping differs.
288
+ *
289
+ * ```typescript
290
+ * // `&outer : [&inner x];` direct members:
291
+ * // [ { kind: 'group', name: 'inner', mode: 'nest' },
292
+ * // { kind: 'state', name: 'x' } ]
293
+ * ```
294
+ *
295
+ * @see JssmGroupRef
296
+ * @see JssmGroupRegistry
297
+ */
298
+ declare type JssmGroupMemberRef = {
299
+ kind: 'state';
300
+ name: string;
301
+ } | {
302
+ kind: 'group';
303
+ name: string;
304
+ mode: 'nest' | 'spread';
305
+ };
306
+ /**
307
+ * The compiled group table: maps each declared group name to its
308
+ * **ordered, direct** members (a {@link JssmGroupMemberRef} list). Order
309
+ * is meaningful — it carries declaration/iteration/precedence order — so
310
+ * this is always an array-valued `Map`, never a `Set`. Only direct
311
+ * members are stored; transitive (flattened) membership is resolved
312
+ * lazily so the group→group graph survives for viz and precedence.
313
+ *
314
+ * ```typescript
315
+ * // for `&inner : [a b]; &outer : [&inner c];`
316
+ * // registry.get('inner') === [ { kind:'state', name:'a' },
317
+ * // { kind:'state', name:'b' } ]
318
+ * // registry.get('outer') === [ { kind:'group', name:'inner', mode:'nest' },
319
+ * // { kind:'state', name:'c' } ]
320
+ * ```
321
+ *
322
+ * @see JssmGroupMemberRef
323
+ */
324
+ declare type JssmGroupRegistry = Map<string, JssmGroupMemberRef[]>;
325
+ /**
326
+ * The compiled boundary-hook surface for a single subject (a group or a
327
+ * state): the action to run on entry (`onEnter`) and/or on exit (`onExit`).
328
+ * Each is optional so a subject may declare only one direction; the compiler
329
+ * merges an `enter` and an `exit` declaration for the same subject into one
330
+ * of these.
331
+ *
332
+ * @see JssmHookDeclaration
333
+ */
334
+ declare type JssmBoundaryHooks = {
335
+ onEnter?: string;
336
+ onExit?: string;
337
+ };
338
+ /**
339
+ * Maps each group name that has at least one boundary hook to its merged
340
+ * {@link JssmBoundaryHooks}. Carried on {@link JssmGenericConfig} for the
341
+ * runtime to consume; depth-aware firing is a later task.
342
+ *
343
+ * @see JssmHookDeclaration
344
+ */
345
+ declare type JssmGroupHooks = Map<string, JssmBoundaryHooks>;
346
+ /**
347
+ * Maps each plain state name that has at least one boundary hook to its
348
+ * merged {@link JssmBoundaryHooks}. The state-subject analogue of
349
+ * {@link JssmGroupHooks}.
350
+ *
351
+ * @see JssmHookDeclaration
352
+ */
353
+ declare type JssmStateHooks = Map<string, JssmBoundaryHooks>;
354
+ /**
355
+ * Declaration of a named property that a machine's states may carry.
356
+ * Set `required: true` to force every state to define the property, or
357
+ * provide `default_value` to fall back when the state does not specify it.
358
+ *
359
+ * For state-property *bindings* (the `state_property` config list), the
360
+ * compiler also writes `property` and `state` — the unserialized pair behind
361
+ * the serialized `name` — so the Machine constructor can validate bindings
362
+ * without parsing `name` back apart. Both are optional: hand-built configs
363
+ * may carry only the serialized `name`, and global property definitions
364
+ * never set them.
365
+ */
366
+ declare type JssmPropertyDefinition = {
367
+ name: string;
368
+ default_value?: any;
369
+ required?: boolean;
370
+ property?: string;
371
+ state?: string;
372
+ };
373
+ declare type JssmTransitionPermitter<DataType> = (OldState: StateType$1, NewState: StateType$1, OldData: DataType, NewData: DataType) => boolean;
374
+ declare type JssmTransitionPermitterMaybeArray<DataType> = JssmTransitionPermitter<DataType> | Array<JssmTransitionPermitter<DataType>>;
375
+ /**
376
+ * A single directed transition (edge) within a state machine. Captures
377
+ * both the topology (`from` / `to`), the FSL semantics (`kind`,
378
+ * `forced_only`, `main_path`), and any optional metadata such as a
379
+ * per-edge `name`, an action label, a guard `check`, a transition
380
+ * `probability` for stochastic models, and an `after_time` for timed
381
+ * transitions.
382
+ *
383
+ * @typeParam StateType - The state-name type (usually `string`).
384
+ * @typeParam DataType - The machine's data payload type (`mDT`).
385
+ */
386
+ declare type JssmTransition<StateType, DataType> = {
387
+ from: StateType;
388
+ to: StateType;
389
+ after_time?: number;
390
+ se?: JssmCompileSe<StateType, DataType>;
391
+ name?: StateType;
392
+ action?: StateType;
393
+ check?: JssmTransitionPermitterMaybeArray<DataType>;
394
+ probability?: number;
395
+ kind: JssmArrowKind;
396
+ forced_only: boolean;
397
+ main_path: boolean;
398
+ };
399
+ /** A list of {@link JssmTransition}s — the edge set of a machine. */
400
+ declare type JssmTransitions<StateType, DataType> = JssmTransition<StateType, DataType>[];
401
+ /**
402
+ * The set of states that can immediately precede or follow a given state.
403
+ * Returned by jssm helpers that report a state's connectivity in the graph.
404
+ */
405
+ declare type JssmTransitionList = {
406
+ entrances: Array<StateType$1>;
407
+ exits: Array<StateType$1>;
408
+ };
409
+ /**
410
+ * Topology record for one node in a compiled machine: its name, the set of
411
+ * states it can be reached from, the set of states it can transition to,
412
+ * and whether reaching it constitutes "completing" the machine.
413
+ */
414
+ declare type JssmGenericState = {
415
+ from: Array<StateType$1>;
416
+ name: StateType$1;
417
+ to: Array<StateType$1>;
418
+ complete: boolean;
419
+ };
420
+ /**
421
+ * The full internal bookkeeping snapshot of a {@link Machine}, exposed for
422
+ * advanced introspection. Contains the current state, the state map, the
423
+ * edge map and reverse-action map, and the original edge list. The
424
+ * `internal_state_impl_version` field exists so that consumers can detect
425
+ * shape changes if this representation evolves.
426
+ */
427
+ declare type JssmMachineInternalState<DataType> = {
428
+ internal_state_impl_version: 1;
429
+ state: StateType$1;
430
+ states: Map<StateType$1, JssmGenericState>;
431
+ named_transitions: Map<StateType$1, number>;
432
+ edge_map: Map<StateType$1, Map<StateType$1, number>>;
433
+ actions: Map<StateType$1, Map<StateType$1, number>>;
434
+ reverse_actions: Map<StateType$1, Map<StateType$1, number>>;
435
+ edges: Array<JssmTransition<StateType$1, DataType>>;
436
+ };
437
+ declare type JssmStatePermitter<DataType> = (OldState: StateType$1, NewState: StateType$1, OldData: DataType, NewData: DataType) => boolean;
438
+ declare type JssmStatePermitterMaybeArray<DataType> = JssmStatePermitter<DataType> | Array<JssmStatePermitter<DataType>>;
439
+ /**
440
+ * A source span produced by the FSL parser when `parse(input, { locations:
441
+ * true })` is used. Mirrors PEG.js's native `location()` shape: byte
442
+ * `offset`s (0-based, half-open) plus 1-based `line`/`column` for display.
443
+ *
444
+ * ```typescript
445
+ * const [t] = parse('a -> b;', { locations: true });
446
+ * // t.loc === { start: { offset: 0, line: 1, column: 1 },
447
+ * // end: { offset: 7, line: 1, column: 8 } }
448
+ * ```
449
+ */
450
+ declare type FslSourcePoint = {
451
+ offset: number;
452
+ line: number;
453
+ column: number;
454
+ };
455
+ declare type FslSourceLocation = {
456
+ start: FslSourcePoint;
457
+ end: FslSourcePoint;
458
+ };
459
+ /**
460
+ * A single key/value pair from an FSL `state X: { ... };` block, in the
461
+ * raw form produced by the parser before being condensed into a
462
+ * {@link JssmStateDeclaration}.
463
+ */
464
+ declare type JssmStateDeclarationRule = {
465
+ key: string;
466
+ value: any;
467
+ name?: string;
468
+ loc?: FslSourceLocation;
469
+ value_loc?: FslSourceLocation;
470
+ };
471
+ /**
472
+ * The fully-condensed declaration for a single state, including its raw
473
+ * rule list (`declarations`) and the well-known styling fields jssm-viz
474
+ * understands. Returned by {@link Machine.state_declaration}.
475
+ */
476
+ declare type JssmStateDeclaration = {
477
+ declarations: Array<JssmStateDeclarationRule>;
478
+ shape?: JssmShape;
479
+ color?: JssmColor;
480
+ corners?: JssmCorner;
481
+ lineStyle?: JssmLineStyle;
482
+ stateLabel?: string;
483
+ textColor?: JssmColor;
484
+ backgroundColor?: JssmColor;
485
+ borderColor?: JssmColor;
486
+ image?: string;
487
+ url?: string;
488
+ state: StateType$1;
489
+ property?: {
490
+ name: string;
491
+ value: unknown;
492
+ };
493
+ };
494
+ /**
495
+ * A loosened version of {@link JssmStateDeclaration} where every field is
496
+ * optional. Used as the value type for theme entries and for default
497
+ * state configuration where most fields will be inherited or merged.
498
+ */
499
+ declare type JssmStateConfig = Partial<JssmStateDeclaration>;
500
+ declare type JssmStateStyleShape = {
501
+ key: 'shape';
502
+ value: JssmShape;
503
+ };
504
+ declare type JssmStateStyleColor = {
505
+ key: 'color';
506
+ value: JssmColor;
507
+ };
508
+ declare type JssmStateStyleTextColor = {
509
+ key: 'text-color';
510
+ value: JssmColor;
511
+ };
512
+ declare type JssmStateStyleCorners = {
513
+ key: 'corners';
514
+ value: JssmCorner;
515
+ };
516
+ declare type JssmStateStyleLineStyle = {
517
+ key: 'line-style';
518
+ value: JssmLineStyle;
519
+ };
520
+ declare type JssmStateStyleStateLabel = {
521
+ key: 'state-label';
522
+ value: string;
523
+ };
524
+ declare type JssmStateStyleBackgroundColor = {
525
+ key: 'background-color';
526
+ value: JssmColor;
527
+ };
528
+ declare type JssmStateStyleBorderColor = {
529
+ key: 'border-color';
530
+ value: JssmColor;
531
+ };
532
+ declare type JssmStateStyleImage = {
533
+ key: 'image';
534
+ value: string;
535
+ };
536
+ declare type JssmStateStyleUrl = {
537
+ key: 'url';
538
+ value: string;
539
+ };
540
+ /**
541
+ * Tagged union of all individual style key/value pairs that may appear in
542
+ * a state's style configuration. The `key` discriminator selects which
543
+ * member, and the `value` is typed accordingly.
544
+ */
545
+ declare type JssmStateStyleKey = JssmStateStyleShape | JssmStateStyleColor | JssmStateStyleTextColor | JssmStateStyleCorners | JssmStateStyleLineStyle | JssmStateStyleBackgroundColor | JssmStateStyleStateLabel | JssmStateStyleBorderColor | JssmStateStyleImage | JssmStateStyleUrl;
546
+ /**
547
+ * An ordered list of {@link JssmStateStyleKey} entries. Used by the
548
+ * `default_*_state_config` machine config options to provide a fallback
549
+ * style stack.
550
+ */
551
+ declare type JssmStateStyleKeyList = JssmStateStyleKey[];
552
+ /**
553
+ * The graph-wide default edge colour style item, produced by the
554
+ * `edge-color`/`edge_color` line inside a `transition: {}` (or `graph: {}`)
555
+ * config block. Kept distinct from {@link JssmStateStyleColor} because it
556
+ * applies to edges rather than nodes, and because it carries the legacy
557
+ * `graph_default_edge_color` key the grammar emits.
558
+ */
559
+ declare type JssmGraphDefaultEdgeColor = {
560
+ key: 'graph_default_edge_color';
561
+ value: JssmColor;
562
+ };
563
+ /**
564
+ * A single item inside a `transition: {}` default-config block. For v1 this
565
+ * reuses the per-state style items (so `color: red;` works inside a
566
+ * `transition:` block exactly as inside a `state:` block) plus the
567
+ * edge-scoped {@link JssmGraphDefaultEdgeColor} default.
568
+ *
569
+ * @see JssmTransitionConfig
570
+ */
571
+ declare type JssmTransitionStyleKey = JssmStateStyleKey | JssmGraphDefaultEdgeColor;
572
+ /**
573
+ * The compiled value of a `transition: {}` config block: an ordered list of
574
+ * edge-default style items. V1 mirrors the state-style shape used by
575
+ * `default_state_config`; group machinery that consumes it lands in a later
576
+ * task.
577
+ *
578
+ * ```typescript
579
+ * import { compile, parse } from 'jssm';
580
+ * const cfg = compile(parse('a -> b; transition: { color: red; };'));
581
+ * // cfg.default_transition_config === [ { key: 'color', value: '#ff0000ff' } ]
582
+ * ```
583
+ *
584
+ * @see JssmGraphConfig
585
+ */
586
+ declare type JssmTransitionConfig = JssmTransitionStyleKey[];
587
+ /**
588
+ * Graph-scope default-config style items folded from the deprecated
589
+ * top-level graph keywords (`graph_layout`, `graph_bg_color`,
590
+ * `dot_preamble`, `theme`, `flow`, and the `edge-color`/`edge_color`
591
+ * default) into the consolidated `graph: {}` config. Each carries the
592
+ * legacy parse key so downstream consumers can disambiguate.
593
+ */
594
+ declare type JssmGraphAliasKey = {
595
+ key: 'graph_layout';
596
+ value: JssmLayout;
597
+ } | {
598
+ key: 'graph_bg_color';
599
+ value: JssmColor;
600
+ } | {
601
+ key: 'dot_preamble';
602
+ value: string;
603
+ } | {
604
+ key: 'theme';
605
+ value: FslTheme | FslTheme[];
606
+ } | {
607
+ key: 'flow';
608
+ value: FslDirection;
609
+ } | JssmGraphDefaultEdgeColor;
610
+ /**
611
+ * A single item inside a `graph: {}` default-config block. For v1 this
612
+ * reuses the per-state style items plus the graph-scope alias items
613
+ * ({@link JssmGraphAliasKey}) folded in from the deprecated top-level
614
+ * graph keywords.
615
+ *
616
+ * @see JssmGraphConfig
617
+ */
618
+ declare type JssmGraphStyleKey = JssmStateStyleKey | JssmGraphAliasKey;
619
+ /**
620
+ * The compiled value of a `graph: {}` config block: an ordered list of
621
+ * graph-default style items. The compiler folds the deprecated top-level
622
+ * graph keywords into this list first, then lets an explicit `graph: {}`
623
+ * block override on key conflict.
624
+ *
625
+ * ```typescript
626
+ * import { compile, parse } from 'jssm';
627
+ * const cfg = compile(parse('a -> b; graph_bg_color: #ffffff;'));
628
+ * // the compiler canonicalizes the folded `graph_bg_color` alias to a
629
+ * // `background-color` item, so:
630
+ * // cfg.default_graph_config includes { key: 'background-color', value: '#ffffffff' }
631
+ * ```
632
+ *
633
+ * @see JssmTransitionConfig
634
+ */
635
+ declare type JssmGraphConfig = JssmGraphStyleKey[];
636
+ /**
637
+ * Complete shape of a jssm-viz theme. A theme provides a style block for
638
+ * each kind of state (`state`, `hooked`, `start`, `end`, `terminal`) as
639
+ * well as a matching `active_*` variant used while that state is current.
640
+ *
641
+ * The `graph`, `legal`, `main`, `forced`, `action`, and `title` slots are
642
+ * reserved for future use and currently typed as `undefined`.
643
+ *
644
+ * Most user-defined themes should be typed as {@link JssmTheme} (the
645
+ * `Partial` of this) so that omitted fields fall back to the base theme.
646
+ */
647
+ declare type JssmBaseTheme = {
648
+ name: string;
649
+ state: JssmStateConfig;
650
+ hooked: JssmStateConfig;
651
+ start: JssmStateConfig;
652
+ end: JssmStateConfig;
653
+ terminal: JssmStateConfig;
654
+ active: JssmStateConfig;
655
+ active_hooked: JssmStateConfig;
656
+ active_start: JssmStateConfig;
657
+ active_end: JssmStateConfig;
658
+ active_terminal: JssmStateConfig;
659
+ graph: undefined;
660
+ legal: undefined;
661
+ main: undefined;
662
+ forced: undefined;
663
+ action: undefined;
664
+ title: undefined;
665
+ };
666
+ /**
667
+ * Full configuration object accepted by the {@link Machine} constructor and
668
+ * by {@link from}. Carries the transition list and the optional knobs
669
+ * governing layout, theming, history, start/end states, property
670
+ * definitions, machine metadata (author, license, version, ...) and the
671
+ * runtime hook surfaces (`time_source`, `timeout_source`, ...).
672
+ *
673
+ * Most users never construct one of these directly — the `sm` tagged
674
+ * template literal and {@link from} produce one from FSL source.
675
+ *
676
+ * @typeParam StateType - The state-name type (usually `string`).
677
+ * @typeParam DataType - The user-supplied data payload type (`mDT`).
678
+ */
679
+ /**
680
+ * Editor/panel defaults an FSL machine declares in an `editor: {}` block
681
+ * (fsl#1334), read by the all-widgets web control: a stochastic run-count
682
+ * and the panels the machine requests under `request` panel mode.
683
+ */
684
+ declare type JssmEditorConfig = {
685
+ stochastic_run_count?: number;
686
+ panels?: Array<string>;
687
+ };
688
+ /** Which stochastic view a run batch produces. */
689
+ declare type JssmStochasticMode = 'montecarlo' | 'steady_state';
690
+ /** Options for {@link Machine.stochastic_summary} / {@link Machine.stochastic_runs}. */
691
+ declare type JssmStochasticOptions = {
692
+ mode?: JssmStochasticMode;
693
+ runs?: number;
694
+ max_steps?: number;
695
+ seed?: number;
696
+ };
697
+ /** One walk's result, yielded by {@link Machine.stochastic_runs}. */
698
+ declare type JssmStochasticRun = {
699
+ states: Array<string>;
700
+ edges: Array<string>;
701
+ length: number;
702
+ terminated: boolean;
703
+ };
704
+ /** Aggregate statistics over a stochastic run batch. */
705
+ declare type JssmStochasticSummary = {
706
+ mode: JssmStochasticMode;
707
+ runs: number;
708
+ seed: number;
709
+ state_visits: Map<string, number>;
710
+ state_visit_fraction: Map<string, number>;
711
+ edge_traversals: Map<string, number>;
712
+ path_lengths?: Array<number>;
713
+ terminal_reached?: number;
714
+ capped?: number;
715
+ };
716
+ declare type JssmGenericConfig<StateType, DataType> = {
717
+ graph_layout?: JssmLayout;
718
+ complete?: Array<StateType>;
719
+ transitions: JssmTransitions<StateType, DataType>;
720
+ theme?: FslTheme[];
721
+ flow?: FslDirection;
722
+ name?: string;
723
+ data?: DataType;
724
+ nodes?: Array<StateType>;
725
+ check?: JssmStatePermitterMaybeArray<DataType>;
726
+ history?: number;
727
+ /**
728
+ * Maximum depth of the boundary-hook action cascade before the machine
729
+ * throws a {@link JssmError} rather than risking a stack overflow or hang.
730
+ *
731
+ * Each time a boundary action fires a transition that itself crosses a
732
+ * boundary, the depth counter increments. A cascade exceeding this limit is
733
+ * treated as a probable infinite loop and rejected.
734
+ *
735
+ * Defaults to `100`. Raise it for legitimate pipelines that genuinely nest
736
+ * more than 100 transitions via boundary hooks.
737
+ *
738
+ * @see Machine._boundary_depth_limit
739
+ * @see Machine._fire_boundary_actions
740
+ */
741
+ boundary_depth_limit?: number;
742
+ min_exits?: number;
743
+ max_exits?: number;
744
+ allow_islands?: JssmAllowIslands;
745
+ editor_config?: JssmEditorConfig;
746
+ allow_force?: false;
747
+ actions?: JssmPermittedOpt;
748
+ simplify_bidi?: boolean;
749
+ allows_override?: JssmAllowsOverride;
750
+ config_allows_override?: JssmAllowsOverride;
751
+ dot_preamble?: string;
752
+ start_states: Array<StateType>;
753
+ end_states?: Array<StateType>;
754
+ failed_outputs?: Array<StateType>;
755
+ initial_state?: StateType;
756
+ start_states_no_enforce?: boolean;
757
+ state_declaration?: Object[];
758
+ property_definition?: JssmPropertyDefinition[];
759
+ state_property?: JssmPropertyDefinition[];
760
+ arrange_declaration?: Array<Array<StateType>>;
761
+ arrange_start_declaration?: Array<Array<StateType>>;
762
+ arrange_end_declaration?: Array<Array<StateType>>;
763
+ oarrange_declaration?: Array<Array<StateType>>;
764
+ farrange_declaration?: Array<Array<StateType>>;
765
+ machine_author?: string | Array<string>;
766
+ machine_comment?: string;
767
+ machine_contributor?: string | Array<string>;
768
+ machine_definition?: string;
769
+ machine_language?: string;
770
+ machine_license?: string;
771
+ machine_name?: string;
772
+ machine_version?: string;
773
+ npm_name?: string;
774
+ default_size?: JssmDefaultSize;
775
+ fsl_version?: string;
776
+ auto_api?: boolean | string;
777
+ instance_name?: string | undefined;
778
+ default_state_config?: JssmStateStyleKeyList;
779
+ default_start_state_config?: JssmStateStyleKeyList;
780
+ default_end_state_config?: JssmStateStyleKeyList;
781
+ default_hooked_state_config?: JssmStateStyleKeyList;
782
+ default_terminal_state_config?: JssmStateStyleKeyList;
783
+ default_active_state_config?: JssmStateStyleKeyList;
784
+ default_transition_config?: JssmTransitionConfig;
785
+ default_graph_config?: JssmGraphConfig;
786
+ /**
787
+ * Overlapping-state-group tables produced by the compile pass and consumed
788
+ * by the Task-3 runtime cascade.
789
+ *
790
+ * `group_registry` maps each group name to its ordered list of direct
791
+ * members (states and sub-group references) as declared in the FSL source.
792
+ *
793
+ * `group_metadata` maps each group name to its RAW style object
794
+ * `{ declarations: [...] }` — parsed style items from a
795
+ * `state &g : { … };` declaration, **not** condensed `JssmStateConfig`
796
+ * style fields. Condensation is intentionally deferred to the Task-3
797
+ * runtime cascade so that depth-specificity resolution can weight each
798
+ * group's contribution before merging into per-state config.
799
+ *
800
+ * `group_hooks` and `state_hooks` hold boundary-hook payloads keyed by
801
+ * group name and state name respectively; firing is also a Task-3 concern.
802
+ *
803
+ * All four fields are absent (`undefined`) on machines that declare no
804
+ * groups or hooks.
805
+ */
806
+ group_registry?: JssmGroupRegistry;
807
+ group_metadata?: Map<string, JssmStateConfig>;
808
+ group_hooks?: JssmGroupHooks;
809
+ state_hooks?: JssmStateHooks;
810
+ rng_seed?: number | undefined;
811
+ time_source?: () => number;
812
+ timeout_source?: (Function: any, number: any) => number;
813
+ clear_timeout_source?: (number: any) => void;
814
+ };
815
+ /**
816
+ * Internal compiler intermediate: one link in a chained transition
817
+ * expression (an "s-expression" segment). Carries both directions of an
818
+ * arrow with optional per-direction action labels, probabilities, and
819
+ * after-times. The recursive `se` field allows the parser to chain
820
+ * arrows of the form `A -> B -> C`. Not intended for end-user code.
821
+ *
822
+ * @internal
823
+ */
824
+ declare type JssmCompileSe<StateType, mDT> = {
825
+ to: StateType;
826
+ se?: JssmCompileSe<StateType, mDT>;
827
+ kind: JssmArrow;
828
+ l_action?: StateType;
829
+ r_action?: StateType;
830
+ l_probability: number;
831
+ r_probability: number;
832
+ l_after?: number;
833
+ r_after?: number;
834
+ loc?: FslSourceLocation;
835
+ to_loc?: FslSourceLocation;
836
+ l_action_loc?: FslSourceLocation;
837
+ r_action_loc?: FslSourceLocation;
838
+ };
839
+ declare type BasicHookDescription<mDT> = {
840
+ kind: 'hook';
841
+ from: string;
842
+ to: string;
843
+ handler: HookHandler<mDT>;
844
+ };
845
+ declare type HookDescriptionWithAction<mDT> = {
846
+ kind: 'named';
847
+ from: string;
848
+ to: string;
849
+ action: string;
850
+ handler: HookHandler<mDT>;
851
+ };
852
+ declare type StandardTransitionHook<mDT> = {
853
+ kind: 'standard transition';
854
+ handler: HookHandler<mDT>;
855
+ };
856
+ declare type MainTransitionHook<mDT> = {
857
+ kind: 'main transition';
858
+ handler: HookHandler<mDT>;
859
+ };
860
+ declare type ForcedTransitionHook<mDT> = {
861
+ kind: 'forced transition';
862
+ handler: HookHandler<mDT>;
863
+ };
864
+ declare type AnyTransitionHook<mDT> = {
865
+ kind: 'any transition';
866
+ handler: HookHandler<mDT>;
867
+ };
868
+ declare type GlobalActionHook<mDT> = {
869
+ kind: 'global action';
870
+ action: string;
871
+ handler: HookHandler<mDT>;
872
+ };
873
+ declare type AnyActionHook<mDT> = {
874
+ kind: 'any action';
875
+ handler: HookHandler<mDT>;
876
+ };
877
+ declare type EntryHook<mDT> = {
878
+ kind: 'entry';
879
+ to: string;
880
+ handler: HookHandler<mDT>;
881
+ };
882
+ declare type ExitHook<mDT> = {
883
+ kind: 'exit';
884
+ from: string;
885
+ handler: HookHandler<mDT>;
886
+ };
887
+ declare type AfterHook<mDT> = {
888
+ kind: 'after';
889
+ from: string;
890
+ handler: HookHandler<mDT>;
891
+ };
892
+ declare type PostBasicHookDescription<mDT> = {
893
+ kind: 'post hook';
894
+ from: string;
895
+ to: string;
896
+ handler: PostHookHandler<mDT>;
897
+ };
898
+ declare type PostHookDescriptionWithAction<mDT> = {
899
+ kind: 'post named';
900
+ from: string;
901
+ to: string;
902
+ action: string;
903
+ handler: PostHookHandler<mDT>;
904
+ };
905
+ declare type PostStandardTransitionHook<mDT> = {
906
+ kind: 'post standard transition';
907
+ handler: PostHookHandler<mDT>;
908
+ };
909
+ declare type PostMainTransitionHook<mDT> = {
910
+ kind: 'post main transition';
911
+ handler: PostHookHandler<mDT>;
912
+ };
913
+ declare type PostForcedTransitionHook<mDT> = {
914
+ kind: 'post forced transition';
915
+ handler: PostHookHandler<mDT>;
916
+ };
917
+ declare type PostAnyTransitionHook<mDT> = {
918
+ kind: 'post any transition';
919
+ handler: PostHookHandler<mDT>;
920
+ };
921
+ declare type PostGlobalActionHook<mDT> = {
922
+ kind: 'post global action';
923
+ action: string;
924
+ handler: PostHookHandler<mDT>;
925
+ };
926
+ declare type PostAnyActionHook<mDT> = {
927
+ kind: 'post any action';
928
+ handler: PostHookHandler<mDT>;
929
+ };
930
+ declare type PostEntryHook<mDT> = {
931
+ kind: 'post entry';
932
+ to: string;
933
+ handler: PostHookHandler<mDT>;
934
+ };
935
+ declare type PostExitHook<mDT> = {
936
+ kind: 'post exit';
937
+ from: string;
938
+ handler: PostHookHandler<mDT>;
939
+ };
940
+ declare type PreEverythingHook<mDT> = {
941
+ kind: 'pre everything';
942
+ handler: EverythingHookHandler<mDT>;
943
+ };
944
+ declare type EverythingHook<mDT> = {
945
+ kind: 'everything';
946
+ handler: EverythingHookHandler<mDT>;
947
+ };
948
+ declare type PrePostEverythingHook<mDT> = {
949
+ kind: 'pre post everything';
950
+ handler: PostEverythingHookHandler<mDT>;
951
+ };
952
+ declare type PostEverythingHook<mDT> = {
953
+ kind: 'post everything';
954
+ handler: PostEverythingHookHandler<mDT>;
955
+ };
956
+ /**
957
+ * Discriminated union of every kind of hook registration jssm understands,
958
+ * pre-transition and post-transition. The `kind` field selects the
959
+ * variant; remaining fields describe which transitions / states / actions
960
+ * the hook is bound to and supply the {@link HookHandler} or
961
+ * {@link PostHookHandler} to invoke.
962
+ *
963
+ * Pre-transition variants (`'hook'`, `'named'`, `'standard transition'`,
964
+ * `'main transition'`, `'forced transition'`, `'any transition'`,
965
+ * `'global action'`, `'any action'`, `'entry'`, `'exit'`, `'after'`)
966
+ * may return a falsy value to veto a transition. Post-transition
967
+ * variants (`'post *'`) cannot veto and are invoked only after a
968
+ * successful transition.
969
+ */
970
+ declare type HookDescription<mDT> = BasicHookDescription<mDT> | HookDescriptionWithAction<mDT> | GlobalActionHook<mDT> | AnyActionHook<mDT> | StandardTransitionHook<mDT> | MainTransitionHook<mDT> | ForcedTransitionHook<mDT> | AnyTransitionHook<mDT> | EntryHook<mDT> | ExitHook<mDT> | AfterHook<mDT> | PostBasicHookDescription<mDT> | PostHookDescriptionWithAction<mDT> | PostGlobalActionHook<mDT> | PostAnyActionHook<mDT> | PostStandardTransitionHook<mDT> | PostMainTransitionHook<mDT> | PostForcedTransitionHook<mDT> | PostAnyTransitionHook<mDT> | PostEntryHook<mDT> | PostExitHook<mDT> | PreEverythingHook<mDT> | EverythingHook<mDT> | PrePostEverythingHook<mDT> | PostEverythingHook<mDT>;
971
+ /**
972
+ * Whether an observational hook runs in the pre-transition phase (where it
973
+ * may veto/mutate the transition) or the post-transition phase (a pure
974
+ * observer that runs only after a successful transition commits).
975
+ */
976
+ declare type HookPhase = 'pre' | 'post';
977
+ /**
978
+ * Normalized description of the target a registry entry is bound to. Exactly
979
+ * one scope variant applies; the present fields depend on the scope:
980
+ *
981
+ * - `'edge'` carries `from` + `to` (+ optional `action` for named hooks),
982
+ * - `'state'` carries `state`,
983
+ * - `'action'` carries `action`,
984
+ * - `'global'` carries no further keys (it matches everything),
985
+ * - `'group'` carries `group` (a named state group with a boundary hook).
986
+ */
987
+ declare type HookTarget = {
988
+ scope: 'edge';
989
+ from: StateType$1;
990
+ to: StateType$1;
991
+ action?: string;
992
+ } | {
993
+ scope: 'state';
994
+ state: StateType$1;
995
+ } | {
996
+ scope: 'action';
997
+ action: string;
998
+ } | {
999
+ scope: 'global';
1000
+ } | {
1001
+ scope: 'group';
1002
+ group: string;
1003
+ };
1004
+ /**
1005
+ * Kinds for FSL boundary hooks (`on enter/exit &group do 'X'` and the plain-
1006
+ * state analogue). These fire post-commit when a transition crosses the
1007
+ * subject's boundary and are not part of {@link HookDescription} (that union
1008
+ * covers only the programmatically-registered observational hooks), so the
1009
+ * registry widens its `kind` field with them.
1010
+ */
1011
+ declare type HookBoundaryKind = 'group enter' | 'group exit' | 'state enter' | 'state exit';
1012
+ /**
1013
+ * One row of the generated uniform observational-hook registry. `kind` is
1014
+ * either an original {@link HookDescription} discriminator (e.g. `'entry'`,
1015
+ * `'post named'`) or a {@link HookBoundaryKind} for an FSL boundary hook,
1016
+ * `phase` is the {@link HookPhase} the hook runs in, and `target` is the
1017
+ * normalized {@link HookTarget} it is bound to. The triple
1018
+ * `(kind, target, phase)` is the registry key the spec calls for.
1019
+ */
1020
+ declare type HookRegistryEntry = {
1021
+ kind: HookDescription<unknown>['kind'] | HookBoundaryKind;
1022
+ phase: HookPhase;
1023
+ target: HookTarget;
1024
+ };
1025
+ /**
1026
+ * Query for {@link Machine.has_hook} / {@link Machine.hooks_on}. A bare
1027
+ * string is read as a state name; an `{ from, to, action? }` object is read
1028
+ * as an edge (optionally a named edge); an `{ action }` object is read as a
1029
+ * named action; a `{ group }` object is read as a named state group. This
1030
+ * mirrors the spec's `hooks_on(state)` / `hooks_on(from→to)` /
1031
+ * `hooks_on(action)` / `hooks_on(&group)` set with one parameter shape.
1032
+ */
1033
+ declare type HookQuery = StateType$1 | {
1034
+ from: StateType$1;
1035
+ to: StateType$1;
1036
+ action?: string;
1037
+ } | {
1038
+ action: string;
1039
+ } | {
1040
+ group: string;
1041
+ };
1042
+ /**
1043
+ * Richer hook return value used when a hook needs to do more than just
1044
+ * accept or veto a transition. `pass` is the required accept/veto flag
1045
+ * (kept non-optional so that returning a stray object doesn't accidentally
1046
+ * veto everything). The optional `state` overrides the destination state,
1047
+ * `data` overrides the data observed by other hooks in the same chain,
1048
+ * and `next_data` overrides the data committed after the transition.
1049
+ */
1050
+ declare type HookComplexResult<mDT> = {
1051
+ pass: boolean;
1052
+ state?: StateType$1;
1053
+ data?: mDT;
1054
+ next_data?: mDT;
1055
+ };
1056
+ /**
1057
+ * Return value from a {@link HookHandler}. May be a plain boolean to
1058
+ * accept (`true`/`undefined`/`void`) or veto (`false`) the transition, or
1059
+ * a {@link HookComplexResult} that additionally rewrites the next state
1060
+ * and/or the next data payload.
1061
+ */
1062
+ declare type HookResult<mDT> = true | false | undefined | void | HookComplexResult<mDT>;
1063
+ /**
1064
+ * Context object passed to every {@link HookHandler}. `data` is the
1065
+ * data payload as it stands before the transition, and `next_data` is
1066
+ * the payload that will be committed if the transition is accepted —
1067
+ * handlers may inspect or mutate the latter via a
1068
+ * {@link HookComplexResult} return value.
1069
+ */
1070
+ declare type HookContext<mDT> = {
1071
+ data: mDT;
1072
+ next_data: mDT;
1073
+ };
1074
+ /**
1075
+ * Context object passed to "everything" hooks ({@link EverythingHookHandler}
1076
+ * and {@link PostEverythingHookHandler}). Extends the usual
1077
+ * {@link HookContext} with `hook_name`, which identifies which specific
1078
+ * hook fired so a single handler can route on it.
1079
+ */
1080
+ declare type EverythingHookContext<mDT> = HookContext<mDT> & {
1081
+ hook_name: string;
1082
+ };
1083
+ /**
1084
+ * Signature of a pre-transition hook handler. Receives the current and
1085
+ * proposed-next data payloads via a {@link HookContext} and returns a
1086
+ * {@link HookResult}: a falsy result vetoes the transition, a truthy
1087
+ * result allows it, and a {@link HookComplexResult} can additionally
1088
+ * rewrite the next state or next data.
1089
+ */
1090
+ declare type HookHandler<mDT> = (hook_context: HookContext<mDT>) => HookResult<mDT>;
1091
+ /**
1092
+ * Signature of a post-transition hook handler. Invoked after a successful
1093
+ * transition has been committed; the return value is ignored (the
1094
+ * transition cannot be undone).
1095
+ */
1096
+ declare type PostHookHandler<mDT> = (hook_context: HookContext<mDT>) => void;
1097
+ /**
1098
+ * Signature of an "everything" pre-transition hook handler. Like
1099
+ * {@link HookHandler} but receives an {@link EverythingHookContext} so the
1100
+ * handler can dispatch on `hook_name`.
1101
+ */
1102
+ declare type EverythingHookHandler<mDT> = (hook_context: EverythingHookContext<mDT>) => HookResult<mDT>;
1103
+ /**
1104
+ * Signature of an "everything" post-transition hook handler. Like
1105
+ * {@link PostHookHandler} but receives an {@link EverythingHookContext}.
1106
+ * The return value is ignored.
1107
+ */
1108
+ declare type PostEverythingHookHandler<mDT> = (hook_context: EverythingHookContext<mDT>) => void;
1109
+ /**
1110
+ * Bounded history of recently-visited states paired with the data payload
1111
+ * observed in each. Backed by `circular_buffer_js`, so the oldest entry
1112
+ * is dropped silently once the configured capacity is exceeded.
1113
+ */
1114
+ declare type JssmHistory<mDT> = circular_buffer<[StateType$1, mDT]>;
1115
+ /**
1116
+ * Pluggable random-number-generator function shape. Must return a value
1117
+ * in `[0, 1)` exactly as `Math.random` does. Supplied via the
1118
+ * `rng_seed`-aware machine configuration so that stochastic models can be
1119
+ * made reproducible.
1120
+ */
1121
+ declare type JssmRng = () => number;
1122
+ /**
1123
+ * All event names that {@link Machine.on} accepts. These are observation
1124
+ * events fired by the machine in addition to (not in place of) the hook
1125
+ * system. Hooks intercept; events observe.
1126
+ *
1127
+ * @see Machine.on
1128
+ */
1129
+ declare type JssmEventName = 'transition' | 'rejection' | 'action' | 'entry' | 'exit' | 'terminal' | 'complete' | 'error' | 'data-change' | 'override' | 'timeout' | 'hook-registration' | 'hook-removal';
1130
+ /**
1131
+ * Detail payload fired with a `transition` event. Carries the resolved
1132
+ * source and target, the action name (if the transition was driven by an
1133
+ * action), the data observed before and after the change, the edge kind,
1134
+ * and whether the call was a forced transition.
1135
+ */
1136
+ declare type JssmTransitionEventDetail<mDT> = {
1137
+ from: StateType$1;
1138
+ to: StateType$1;
1139
+ action?: StateType$1;
1140
+ data: mDT;
1141
+ next_data?: mDT;
1142
+ trans_type: string | undefined;
1143
+ forced: boolean;
1144
+ };
1145
+ /**
1146
+ * Detail payload fired with a `rejection` event. Carries the resolved
1147
+ * source and target plus an indication of who rejected the transition
1148
+ * and why. `reason` is `'invalid'` when no edge existed, `'hook'` when
1149
+ * a hook handler vetoed; `hook_name` is set when `reason` is `'hook'`.
1150
+ */
1151
+ declare type JssmRejectionEventDetail<mDT> = {
1152
+ from: StateType$1;
1153
+ to: StateType$1;
1154
+ action?: StateType$1;
1155
+ data: mDT;
1156
+ next_data?: mDT;
1157
+ reason: 'invalid' | 'hook';
1158
+ hook_name?: string;
1159
+ forced: boolean;
1160
+ };
1161
+ /**
1162
+ * Detail payload fired with an `action` event. Fires when an action is
1163
+ * attempted, before transition validation runs.
1164
+ */
1165
+ declare type JssmActionEventDetail<mDT> = {
1166
+ action: StateType$1;
1167
+ from: StateType$1;
1168
+ to?: StateType$1;
1169
+ data: mDT;
1170
+ next_data?: mDT;
1171
+ };
1172
+ /**
1173
+ * Detail payload fired with an `entry` event. `state` is the entered
1174
+ * state. `from` is the predecessor state, if any. `action` is the
1175
+ * action that drove the entry, if any.
1176
+ */
1177
+ declare type JssmEntryEventDetail<mDT> = {
1178
+ state: StateType$1;
1179
+ from?: StateType$1;
1180
+ action?: StateType$1;
1181
+ data: mDT;
1182
+ };
1183
+ /**
1184
+ * Detail payload fired with an `exit` event. `state` is the exited
1185
+ * state. `to` is the next state, if any. `action` is the action that
1186
+ * drove the exit, if any.
1187
+ */
1188
+ declare type JssmExitEventDetail<mDT> = {
1189
+ state: StateType$1;
1190
+ to?: StateType$1;
1191
+ action?: StateType$1;
1192
+ data: mDT;
1193
+ };
1194
+ /**
1195
+ * Detail payload fired with a `terminal` event. Indicates that the
1196
+ * machine has reached a state with no outgoing edges.
1197
+ */
1198
+ declare type JssmTerminalEventDetail<mDT> = {
1199
+ state: StateType$1;
1200
+ data: mDT;
1201
+ };
1202
+ /**
1203
+ * Detail payload fired with a `complete` event. Indicates that the
1204
+ * machine has reached a FSL `complete` state.
1205
+ */
1206
+ declare type JssmCompleteEventDetail<mDT> = {
1207
+ state: StateType$1;
1208
+ data: mDT;
1209
+ };
1210
+ /**
1211
+ * Detail payload fired with an `error` event. Wraps an exception caught
1212
+ * while running an event handler; `source_event` and `source_detail`
1213
+ * identify the event whose handler threw, and `handler` is the offending
1214
+ * function so consumers can correlate / blame.
1215
+ */
1216
+ declare type JssmErrorEventDetail = {
1217
+ error: unknown;
1218
+ source_event: JssmEventName;
1219
+ source_detail: unknown;
1220
+ handler: Function;
1221
+ };
1222
+ /**
1223
+ * Detail payload fired with a `data-change` event. Fires whenever the
1224
+ * machine's data payload is replaced. `old_data` is the value before the
1225
+ * change; `new_data` is the value after.
1226
+ */
1227
+ declare type JssmDataChangeEventDetail<mDT> = {
1228
+ from?: StateType$1;
1229
+ to?: StateType$1;
1230
+ action?: StateType$1;
1231
+ old_data: mDT;
1232
+ new_data: mDT;
1233
+ cause: 'transition' | 'override';
1234
+ };
1235
+ /**
1236
+ * Detail payload fired with an `override` event. Distinguishes a forced
1237
+ * state replacement from a normal transition.
1238
+ */
1239
+ declare type JssmOverrideEventDetail<mDT> = {
1240
+ from: StateType$1;
1241
+ to: StateType$1;
1242
+ old_data: mDT;
1243
+ new_data?: mDT;
1244
+ };
1245
+ /**
1246
+ * Detail payload fired with a `timeout` event. Fires when a configured
1247
+ * `after` clause causes an automatic transition.
1248
+ */
1249
+ declare type JssmTimeoutEventDetail = {
1250
+ from: StateType$1;
1251
+ to: StateType$1;
1252
+ after_time: number;
1253
+ };
1254
+ /**
1255
+ * Detail payload fired with `hook-registration` and `hook-removal` events.
1256
+ * Mirrors the {@link HookDescription} so inspector tools can mirror the
1257
+ * current hook set.
1258
+ */
1259
+ declare type JssmHookLifecycleEventDetail<mDT> = {
1260
+ description: HookDescription<mDT>;
1261
+ };
1262
+ /**
1263
+ * Mapped type from {@link JssmEventName} to the corresponding detail
1264
+ * payload. Drives the discriminated-union typing of {@link Machine.on},
1265
+ * so `e.action` and friends only exist where they're meaningful.
1266
+ */
1267
+ declare type JssmEventDetailMap<mDT> = {
1268
+ 'transition': JssmTransitionEventDetail<mDT>;
1269
+ 'rejection': JssmRejectionEventDetail<mDT>;
1270
+ 'action': JssmActionEventDetail<mDT>;
1271
+ 'entry': JssmEntryEventDetail<mDT>;
1272
+ 'exit': JssmExitEventDetail<mDT>;
1273
+ 'terminal': JssmTerminalEventDetail<mDT>;
1274
+ 'complete': JssmCompleteEventDetail<mDT>;
1275
+ 'error': JssmErrorEventDetail;
1276
+ 'data-change': JssmDataChangeEventDetail<mDT>;
1277
+ 'override': JssmOverrideEventDetail<mDT>;
1278
+ 'timeout': JssmTimeoutEventDetail;
1279
+ 'hook-registration': JssmHookLifecycleEventDetail<mDT>;
1280
+ 'hook-removal': JssmHookLifecycleEventDetail<mDT>;
1281
+ };
1282
+ /**
1283
+ * Filter accepted by {@link Machine.on} / {@link Machine.once} for an
1284
+ * individual event name. Only events whose detail key matches every
1285
+ * filter entry fire the handler. Events that don't list a filter key in
1286
+ * v1 take no filter properties.
1287
+ */
1288
+ declare type JssmEventFilterMap<mDT> = {
1289
+ 'transition': {
1290
+ from?: StateType$1;
1291
+ to?: StateType$1;
1292
+ };
1293
+ 'rejection': Record<string, never>;
1294
+ 'action': Record<string, never>;
1295
+ 'entry': {
1296
+ state?: StateType$1;
1297
+ };
1298
+ 'exit': {
1299
+ state?: StateType$1;
1300
+ };
1301
+ 'terminal': Record<string, never>;
1302
+ 'complete': Record<string, never>;
1303
+ 'error': Record<string, never>;
1304
+ 'data-change': Record<string, never>;
1305
+ 'override': Record<string, never>;
1306
+ 'timeout': Record<string, never>;
1307
+ 'hook-registration': Record<string, never>;
1308
+ 'hook-removal': Record<string, never>;
1309
+ };
1310
+ /**
1311
+ * Per-event filter object (as passed to {@link Machine.on}). Use
1312
+ * `JssmEventDetailMap<mDT>[Ev]` to find the matching detail type.
1313
+ * @typeparam mDT The type of the machine data member.
1314
+ * @typeparam Ev The event name.
1315
+ */
1316
+ declare type JssmEventFilter<mDT, Ev extends JssmEventName> = JssmEventFilterMap<mDT>[Ev];
1317
+ /**
1318
+ * Per-event handler signature. Receives a detail object typed by event
1319
+ * name, so `e.action` (etc.) only exist where they're meaningful.
1320
+ * @typeparam mDT The type of the machine data member.
1321
+ * @typeparam Ev The event name.
1322
+ */
1323
+ declare type JssmEventHandler<mDT, Ev extends JssmEventName> = (detail: JssmEventDetailMap<mDT>[Ev]) => void;
1324
+ /**
1325
+ * Function returned by {@link Machine.on} and {@link Machine.once} that
1326
+ * removes the subscription. Calling it more than once is a no-op.
1327
+ */
1328
+ declare type JssmUnsubscribe = () => void;
1329
+
1330
+ /**
1331
+ * String interning support for the jssm machine internals.
1332
+ *
1333
+ * State and action names are interned to dense integer ids at machine
1334
+ * construction so that per-transition dispatch can use numeric map keys
1335
+ * (integer hashing) instead of repeated string-keyed lookups. Internal
1336
+ * machinery only — deliberately not re-exported from the `jssm` public
1337
+ * surface, so the public API is unchanged.
1338
+ *
1339
+ * @internal
1340
+ */
1341
+ /**
1342
+ * A string↔integer bimap. Assigns dense ids (0, 1, 2, …) in first-seen
1343
+ * order; lookups are O(1) both directions. Grows monotonically — there is
1344
+ * no removal, matching machine semantics (states and actions are fixed
1345
+ * after construction; late interning only happens for never-matching
1346
+ * lookups such as hook registrations naming unknown states).
1347
+ *
1348
+ * @example
1349
+ * const i = new Interner();
1350
+ * i.intern('red'); // 0
1351
+ * i.intern('green'); // 1
1352
+ * i.intern('red'); // 0 (idempotent)
1353
+ * i.id_of('green'); // 1
1354
+ * i.name_of(0); // 'red'
1355
+ *
1356
+ * @see pair_key
1357
+ */
1358
+ declare class Interner {
1359
+ private readonly ids;
1360
+ private readonly names;
1361
+ constructor();
1362
+ /**
1363
+ * Return the id for `name`, assigning the next dense id if the name has
1364
+ * not been seen before.
1365
+ *
1366
+ * @param name - The string to intern.
1367
+ * @returns The (possibly newly assigned) integer id.
1368
+ *
1369
+ * @example
1370
+ * interner.intern('red'); // 0 on first call, 0 on every later call
1371
+ */
1372
+ intern(name: string): number;
1373
+ /**
1374
+ * Return the id for `name` without interning, or `undefined` when the
1375
+ * name has never been interned. This is the hot-path probe for
1376
+ * user-supplied names.
1377
+ *
1378
+ * @param name - The string to look up.
1379
+ *
1380
+ * @example
1381
+ * interner.id_of('mauve'); // undefined — never interned
1382
+ */
1383
+ id_of(name: string): number | undefined;
1384
+ /**
1385
+ * Return the name for `id`, or `undefined` for an id never assigned.
1386
+ *
1387
+ * @param id - The integer id to invert.
1388
+ *
1389
+ * @example
1390
+ * interner.name_of(0); // 'red'
1391
+ */
1392
+ name_of(id: number): string | undefined;
1393
+ /** The count of distinct interned names. */
1394
+ get size(): number;
1395
+ }
1396
+
1397
+ declare type StateType = string;
1398
+
1399
+ /**
1400
+ * Internal record holding a single registered event subscription: the
1401
+ * handler, its optional filter, and a flag for `once` semantics. Not
1402
+ * exported.
1403
+ *
1404
+ * @internal
1405
+ */
1406
+ declare type JssmEventEntry<mDT, Ev extends JssmEventName> = {
1407
+ handler: JssmEventHandler<mDT, Ev>;
1408
+ filter?: JssmEventFilter<mDT, Ev>;
1409
+ once: boolean;
1410
+ };
1411
+ declare class Machine<mDT> {
1412
+ _state: StateType;
1413
+ _states: Map<StateType, JssmGenericState>;
1414
+ _edges: Array<JssmTransition<StateType, mDT>>;
1415
+ _edge_map: Map<StateType, Map<StateType, number>>;
1416
+ _outbound_edge_ids: Map<StateType, Array<number>>;
1417
+ _named_transitions: Map<StateType, number>;
1418
+ _actions: Map<StateType, Map<StateType, number>>;
1419
+ _reverse_actions: Map<StateType, Map<StateType, number>>;
1420
+ _reverse_action_targets: Map<StateType, Map<StateType, number>>;
1421
+ _state_interner: Interner;
1422
+ _action_interner: Interner;
1423
+ _state_id: number;
1424
+ _edge_id_by_pair: Map<number, number>;
1425
+ _edge_id_by_action_pair: Map<number, number>;
1426
+ _edge_to_ids: Array<number>;
1427
+ _start_states: Set<StateType>;
1428
+ _end_states: Set<StateType>;
1429
+ _failed_outputs: Set<StateType>;
1430
+ _machine_author?: Array<string>;
1431
+ _machine_comment?: string;
1432
+ _machine_contributor?: Array<string>;
1433
+ _machine_definition?: string;
1434
+ _machine_language?: string;
1435
+ _machine_license?: string;
1436
+ _machine_name?: string;
1437
+ _machine_version?: string;
1438
+ _npm_name?: string;
1439
+ _default_size?: JssmDefaultSize;
1440
+ _fsl_version?: string;
1441
+ _raw_state_declaration?: Array<Object>;
1442
+ _state_declarations: Map<StateType, JssmStateDeclaration>;
1443
+ _data?: mDT;
1444
+ _instance_name: string;
1445
+ _rng_seed: number;
1446
+ _rng: JssmRng;
1447
+ _graph_layout: JssmLayout;
1448
+ _dot_preamble: string;
1449
+ _default_transition_config: JssmTransitionConfig | undefined;
1450
+ _default_graph_config: JssmGraphConfig | undefined;
1451
+ _arrange_declaration: Array<Array<StateType>>;
1452
+ _arrange_start_declaration: Array<Array<StateType>>;
1453
+ _arrange_end_declaration: Array<Array<StateType>>;
1454
+ _oarrange_declaration: Array<Array<StateType>>;
1455
+ _farrange_declaration: Array<Array<StateType>>;
1456
+ _themes: FslTheme[];
1457
+ _flow: FslDirection;
1458
+ _has_hooks: boolean;
1459
+ _has_basic_hooks: boolean;
1460
+ _has_named_hooks: boolean;
1461
+ _has_entry_hooks: boolean;
1462
+ _has_exit_hooks: boolean;
1463
+ _has_after_hooks: boolean;
1464
+ _has_global_action_hooks: boolean;
1465
+ _has_transition_hooks: boolean;
1466
+ _has_forced_transitions: boolean;
1467
+ _hooks: Map<number, HookHandler<mDT>>;
1468
+ _named_hooks: Map<number, Map<number, HookHandler<mDT>>>;
1469
+ _entry_hooks: Map<number, HookHandler<mDT>>;
1470
+ _exit_hooks: Map<number, HookHandler<mDT>>;
1471
+ _after_hooks: Map<string, HookHandler<mDT>>;
1472
+ _global_action_hooks: Map<number, HookHandler<mDT>>;
1473
+ _any_action_hook: HookHandler<mDT> | undefined;
1474
+ _standard_transition_hook: HookHandler<mDT> | undefined;
1475
+ _main_transition_hook: HookHandler<mDT> | undefined;
1476
+ _forced_transition_hook: HookHandler<mDT> | undefined;
1477
+ _any_transition_hook: HookHandler<mDT> | undefined;
1478
+ _has_post_hooks: boolean;
1479
+ _has_post_basic_hooks: boolean;
1480
+ _has_post_named_hooks: boolean;
1481
+ _has_post_entry_hooks: boolean;
1482
+ _has_post_exit_hooks: boolean;
1483
+ _has_post_global_action_hooks: boolean;
1484
+ _has_post_transition_hooks: boolean;
1485
+ _code_allows_override: JssmAllowsOverride;
1486
+ _config_allows_override: JssmAllowsOverride;
1487
+ _allow_islands: JssmAllowIslands;
1488
+ _editor_config?: JssmEditorConfig;
1489
+ _post_hooks: Map<number, HookHandler<mDT>>;
1490
+ _post_named_hooks: Map<number, Map<number, HookHandler<mDT>>>;
1491
+ _post_entry_hooks: Map<number, HookHandler<mDT>>;
1492
+ _post_exit_hooks: Map<number, HookHandler<mDT>>;
1493
+ _post_global_action_hooks: Map<number, HookHandler<mDT>>;
1494
+ _post_any_action_hook: HookHandler<mDT> | undefined;
1495
+ _post_standard_transition_hook: HookHandler<mDT> | undefined;
1496
+ _post_main_transition_hook: HookHandler<mDT> | undefined;
1497
+ _post_forced_transition_hook: HookHandler<mDT> | undefined;
1498
+ _post_any_transition_hook: HookHandler<mDT> | undefined;
1499
+ _pre_everything_hook: EverythingHookHandler<mDT> | undefined;
1500
+ _everything_hook: EverythingHookHandler<mDT> | undefined;
1501
+ _pre_post_everything_hook: PostEverythingHookHandler<mDT> | undefined;
1502
+ _post_everything_hook: PostEverythingHookHandler<mDT> | undefined;
1503
+ _property_keys: Set<string>;
1504
+ _default_properties: Map<string, any>;
1505
+ _state_properties: Map<string, any>;
1506
+ _required_properties: Set<string>;
1507
+ _state_property_first_state: Map<string, StateType>;
1508
+ _history: JssmHistory<mDT>;
1509
+ _history_length: number;
1510
+ _state_style: JssmStateConfig;
1511
+ _active_state_style: JssmStateConfig;
1512
+ _hooked_state_style: JssmStateConfig;
1513
+ _terminal_state_style: JssmStateConfig;
1514
+ _start_state_style: JssmStateConfig;
1515
+ _end_state_style: JssmStateConfig;
1516
+ _group_registry: JssmGroupRegistry;
1517
+ _group_metadata: Map<string, JssmStateConfig>;
1518
+ _group_hooks: JssmGroupHooks;
1519
+ _state_hooks: JssmStateHooks;
1520
+ _state_to_groups: Map<StateType, Set<string>>;
1521
+ _group_order: string[];
1522
+ _static_state_config_cache: Map<StateType, JssmStateConfig>;
1523
+ _state_labels: Map<string, string>;
1524
+ _time_source: () => number;
1525
+ _create_started: number;
1526
+ _created: number;
1527
+ _after_mapping: Map<string, [string, number]>;
1528
+ _timeout_source: (Function: any, number: any) => number;
1529
+ _clear_timeout_source: (h: any) => void;
1530
+ _timeout_handle: number | undefined;
1531
+ _timeout_target: string | undefined;
1532
+ _timeout_target_time: number | undefined;
1533
+ _event_handlers: Map<JssmEventName, Set<JssmEventEntry<any, any>>>;
1534
+ _event_listener_count: number;
1535
+ _firing_error: boolean;
1536
+ _boundary_depth: number;
1537
+ _boundary_depth_limit: number;
1538
+ constructor({ start_states, end_states, failed_outputs, initial_state, start_states_no_enforce, complete, transitions, machine_author, machine_comment, machine_contributor, machine_definition, machine_language, machine_license, machine_name, machine_version, npm_name, default_size, state_declaration, property_definition, state_property, fsl_version, dot_preamble, arrange_declaration, arrange_start_declaration, arrange_end_declaration, oarrange_declaration, farrange_declaration, theme, flow, graph_layout, instance_name, history, boundary_depth_limit, data, default_state_config, default_active_state_config, default_hooked_state_config, default_terminal_state_config, default_start_state_config, default_end_state_config, default_transition_config, default_graph_config, group_registry, group_metadata, group_hooks, state_hooks, allows_override, config_allows_override, allow_islands, editor_config, rng_seed, time_source, timeout_source, clear_timeout_source }: JssmGenericConfig<StateType, mDT>);
1539
+ /********
1540
+ *
1541
+ * Internal method for fabricating states. Not meant for external use.
1542
+ *
1543
+ * @internal
1544
+ *
1545
+ */
1546
+ _new_state(state_config: JssmGenericState): StateType;
1547
+ /*********
1548
+ *
1549
+ * Get the current state of a machine.
1550
+ *
1551
+ * ```typescript
1552
+ * import * as jssm from 'jssm';
1553
+ *
1554
+ * const lswitch = jssm.from('on <=> off;');
1555
+ * console.log( lswitch.state() ); // 'on'
1556
+ *
1557
+ * lswitch.transition('off');
1558
+ * console.log( lswitch.state() ); // 'off'
1559
+ * ```
1560
+ *
1561
+ * @typeparam mDT The type of the machine data member; usually omitted
1562
+ *
1563
+ * @returns The current state name.
1564
+ *
1565
+ */
1566
+ state(): StateType;
1567
+ /*********
1568
+ *
1569
+ * Get the label for a given state, if any; return `undefined` otherwise.
1570
+ *
1571
+ * ```typescript
1572
+ * import * as jssm from 'jssm';
1573
+ *
1574
+ * const lswitch = jssm.from('a -> b; state a: { label: "Foo!"; };');
1575
+ * console.log( lswitch.label_for('a') ); // 'Foo!'
1576
+ * console.log( lswitch.label_for('b') ); // undefined
1577
+ * ```
1578
+ *
1579
+ * See also {@link display_text}.
1580
+ *
1581
+ * @typeparam mDT The type of the machine data member; usually omitted
1582
+ *
1583
+ * @param state The state to get the label for.
1584
+ *
1585
+ * @returns The label string, or `undefined` if no label is set.
1586
+ *
1587
+ */
1588
+ label_for(state: StateType): string;
1589
+ /*********
1590
+ *
1591
+ * Get whatever the node should show as text.
1592
+ *
1593
+ * Currently, this means to get the label for a given state, if any;
1594
+ * otherwise to return the node's name. However, this definition is expected
1595
+ * to grow with time, and it is currently considered ill-advised to manually
1596
+ * parse this text.
1597
+ *
1598
+ * See also {@link label_for}.
1599
+ *
1600
+ * ```typescript
1601
+ * import * as jssm from 'jssm';
1602
+ *
1603
+ * const lswitch = jssm.from('a -> b; state a: { label: "Foo!"; };');
1604
+ * console.log( lswitch.display_text('a') ); // 'Foo!'
1605
+ * console.log( lswitch.display_text('b') ); // 'b'
1606
+ * ```
1607
+ *
1608
+ * @typeparam mDT The type of the machine data member; usually omitted
1609
+ *
1610
+ * @param state The state to get display text for.
1611
+ *
1612
+ * @returns The label if one exists, otherwise the state's name.
1613
+ *
1614
+ */
1615
+ display_text(state: StateType): string;
1616
+ /*********
1617
+ *
1618
+ * Get the current data of a machine.
1619
+ *
1620
+ * ```typescript
1621
+ * import * as jssm from 'jssm';
1622
+ *
1623
+ * const lswitch = jssm.from('on <=> off;', {data: 1});
1624
+ * console.log( lswitch.data() ); // 1
1625
+ * ```
1626
+ *
1627
+ * @typeparam mDT The type of the machine data member; usually omitted
1628
+ *
1629
+ * @returns A deep clone of the machine's current data value.
1630
+ *
1631
+ */
1632
+ data(): mDT;
1633
+ /**
1634
+ * The machine's current data by REFERENCE — no clone. The public
1635
+ * {@link Machine.data} contract is a deep clone per call (a mutation
1636
+ * boundary for external consumers, and deliberately untouched); that clone
1637
+ * is `structuredClone` of the whole data value, which same-package
1638
+ * read-only consumers — the fsl-bind and fsl-data-inspector panels, which
1639
+ * read one dotted path or serialize per transition — should not pay on
1640
+ * every event. Callers MUST NOT mutate the returned value or store it
1641
+ * beyond the current tick; anything crossing a trust boundary must use
1642
+ * {@link Machine.data} instead.
1643
+ *
1644
+ * ```typescript
1645
+ * const m = jssm.from('on <=> off;', { data: { a: { b: 1 } } });
1646
+ * m._data_ref().a.b; // 1, zero-copy
1647
+ * ```
1648
+ *
1649
+ * @returns The live data value; treat as read-only.
1650
+ *
1651
+ * @see Machine.data
1652
+ * @internal
1653
+ */
1654
+ _data_ref(): mDT;
1655
+ /*********
1656
+ *
1657
+ * Get the current value of a given property name. Checks the current
1658
+ * state's properties first, then falls back to the global default.
1659
+ * Returns `undefined` if neither exists. For a throwing variant, see
1660
+ * {@link strict_prop}.
1661
+ *
1662
+ * ```typescript
1663
+ * const m = sm`property color default "grey"; a -> b;
1664
+ * state b: { property color "blue"; };`;
1665
+ *
1666
+ * m.prop('color'); // 'grey' (default, because state is 'a')
1667
+ * m.go('b');
1668
+ * m.prop('color'); // 'blue' (state 'b' overrides the default)
1669
+ * m.prop('size'); // undefined (no such property)
1670
+ * ```
1671
+ *
1672
+ * @param name The relevant property name to look up.
1673
+ *
1674
+ * @returns The value behind the prop name, or `undefined` if not defined.
1675
+ *
1676
+ */
1677
+ prop(name: string): any;
1678
+ /*********
1679
+ *
1680
+ * Get the current value of a given property name. If missing on the state
1681
+ * and without a global default, throws a {@link JssmError}, unlike
1682
+ * {@link prop}, which would return `undefined` instead.
1683
+ *
1684
+ * ```typescript
1685
+ * const m = sm`property color default "grey"; a -> b;`;
1686
+ *
1687
+ * m.strict_prop('color'); // 'grey'
1688
+ * m.strict_prop('size'); // throws JssmError
1689
+ * ```
1690
+ *
1691
+ * @param name The relevant property name to look up.
1692
+ *
1693
+ * @returns The value behind the prop name.
1694
+ *
1695
+ * @throws {JssmError} If the property is not defined on the current state
1696
+ * and has no default.
1697
+ *
1698
+ */
1699
+ strict_prop(name: string): any;
1700
+ /*********
1701
+ *
1702
+ * Get the current value of every prop, as an object. If no current definition
1703
+ * exists for a prop — that is, if the prop was defined without a default and
1704
+ * the current state also doesn't define the prop — then that prop will be listed
1705
+ * in the returned object with a value of `undefined`.
1706
+ *
1707
+ * ```typescript
1708
+ * const traffic_light = sm`
1709
+ *
1710
+ * property can_go default true;
1711
+ * property hesitate default true;
1712
+ * property stop_first default false;
1713
+ *
1714
+ * Off -> Red => Green => Yellow => Red;
1715
+ * [Red Yellow Green] ~> [Off FlashingRed];
1716
+ * FlashingRed -> Red;
1717
+ *
1718
+ * state Red: { property: stop_first true; property: can_go false; };
1719
+ * state Off: { property: stop_first true; };
1720
+ * state FlashingRed: { property: stop_first true; };
1721
+ * state Green: { property: hesitate false; };
1722
+ *
1723
+ * `;
1724
+ *
1725
+ * traffic_light.state(); // Off
1726
+ * traffic_light.props(); // { can_go: true, hesitate: true, stop_first: true }
1727
+ *
1728
+ * traffic_light.go('Red');
1729
+ * traffic_light.props(); // { can_go: false, hesitate: true, stop_first: true }
1730
+ *
1731
+ * traffic_light.go('Green');
1732
+ * traffic_light.props(); // { can_go: true, hesitate: false, stop_first: false }
1733
+ * ```
1734
+ *
1735
+ * @returns An object mapping every known property name to its current value
1736
+ * (or `undefined` if the property has no default and the current state
1737
+ * doesn't define it).
1738
+ *
1739
+ */
1740
+ props(): object;
1741
+ /*********
1742
+ *
1743
+ * Check whether a given string is a known property's name.
1744
+ *
1745
+ * ```typescript
1746
+ * const example = sm`property foo default 1; a->b;`;
1747
+ *
1748
+ * example.known_prop('foo'); // true
1749
+ * example.known_prop('bar'); // false
1750
+ * ```
1751
+ *
1752
+ * @param prop_name The relevant property name to look up
1753
+ *
1754
+ */
1755
+ known_prop(prop_name: string): boolean;
1756
+ /*********
1757
+ *
1758
+ * List all known property names. If you'd also like values, use
1759
+ * {@link props} instead. The order of the properties is not defined, and
1760
+ * the properties generally will not be sorted.
1761
+ *
1762
+ * ```typescript
1763
+ * const m = sm`property color default "grey"; property size default 1; a -> b;`;
1764
+ *
1765
+ * m.known_props(); // ['color', 'size']
1766
+ * ```
1767
+ *
1768
+ * @returns An array of all property name strings defined on this machine.
1769
+ *
1770
+ */
1771
+ known_props(): string[];
1772
+ /********
1773
+ *
1774
+ * Check whether a given state is a valid start state (either because it was
1775
+ * explicitly named as such, or because it was the first mentioned state.)
1776
+ *
1777
+ * ```typescript
1778
+ * import { sm, is_start_state } from 'jssm';
1779
+ *
1780
+ * const example = sm`a -> b;`;
1781
+ *
1782
+ * console.log( final_test.is_start_state('a') ); // true
1783
+ * console.log( final_test.is_start_state('b') ); // false
1784
+ *
1785
+ * const example = sm`start_states: [a b]; a -> b;`;
1786
+ *
1787
+ * console.log( final_test.is_start_state('a') ); // true
1788
+ * console.log( final_test.is_start_state('b') ); // true
1789
+ * ```
1790
+ *
1791
+ * @typeparam mDT The type of the machine data member; usually omitted
1792
+ *
1793
+ * @param whichState The name of the state to check
1794
+ *
1795
+ */
1796
+ is_start_state(whichState: StateType): boolean;
1797
+ /********
1798
+ *
1799
+ * Check whether a given state is a valid start state (either because it was
1800
+ * explicitly named as such, or because it was the first mentioned state.)
1801
+ *
1802
+ * ```typescript
1803
+ * import { sm, is_end_state } from 'jssm';
1804
+ *
1805
+ * const example = sm`a -> b;`;
1806
+ *
1807
+ * console.log( final_test.is_start_state('a') ); // false
1808
+ * console.log( final_test.is_start_state('b') ); // true
1809
+ *
1810
+ * const example = sm`end_states: [a b]; a -> b;`;
1811
+ *
1812
+ * console.log( final_test.is_start_state('a') ); // true
1813
+ * console.log( final_test.is_start_state('b') ); // true
1814
+ * ```
1815
+ *
1816
+ * @typeparam mDT The type of the machine data member; usually omitted
1817
+ *
1818
+ * @param whichState The name of the state to check
1819
+ *
1820
+ */
1821
+ is_end_state(whichState: StateType): boolean;
1822
+ /********
1823
+ *
1824
+ * Get the set of states declared as failure outputs for this machine.
1825
+ * Returns an array of state labels, or an empty array when none were
1826
+ * declared. A state in this list means the machine is in a failure
1827
+ * condition when it occupies that state.
1828
+ *
1829
+ * @see {@link is_failed_output} to test a single state
1830
+ * @see {@link is_failed} to test the current state
1831
+ *
1832
+ */
1833
+ failed_outputs(): Array<StateType>;
1834
+ /********
1835
+ *
1836
+ * Check whether a given state is declared as a failure output.
1837
+ *
1838
+ * @param whichState The name of the state to check
1839
+ *
1840
+ * @see {@link failed_outputs} for the full failure-output set
1841
+ * @see {@link is_failed} to test the current state
1842
+ *
1843
+ */
1844
+ is_failed_output(whichState: StateType): boolean;
1845
+ /********
1846
+ *
1847
+ * Check whether the machine is currently in a failure state — that is,
1848
+ * whether its current state is one of the declared `failed_outputs`.
1849
+ *
1850
+ * @see {@link failed_outputs} for the full failure-output set
1851
+ * @see {@link is_failed_output} to test an arbitrary state
1852
+ *
1853
+ */
1854
+ is_failed(): boolean;
1855
+ /********
1856
+ *
1857
+ * Check whether a given state is final (either has no exits or is marked
1858
+ * `complete`.)
1859
+ *
1860
+ * ```typescript
1861
+ * import { sm, state_is_final } from 'jssm';
1862
+ *
1863
+ * const final_test = sm`first -> second;`;
1864
+ *
1865
+ * console.log( final_test.state_is_final('first') ); // false
1866
+ * console.log( final_test.state_is_final('second') ); // true
1867
+ * ```
1868
+ *
1869
+ * @typeparam mDT The type of the machine data member; usually omitted
1870
+ *
1871
+ * @param whichState The name of the state to check for finality
1872
+ *
1873
+ */
1874
+ state_is_final(whichState: StateType): boolean;
1875
+ /********
1876
+ *
1877
+ * Check whether the current state is final (either has no exits or is marked
1878
+ * `complete`.)
1879
+ *
1880
+ * ```typescript
1881
+ * import { sm, is_final } from 'jssm';
1882
+ *
1883
+ * const final_test = sm`first -> second;`;
1884
+ *
1885
+ * console.log( final_test.is_final() ); // false
1886
+ * state.transition('second');
1887
+ * console.log( final_test.is_final() ); // true
1888
+ * ```
1889
+ *
1890
+ */
1891
+ is_final(): boolean;
1892
+ /********
1893
+ *
1894
+ * Serialize the current machine, including all defining state but not the
1895
+ * machine string, to a structure. This means you will need the machine
1896
+ * string to recreate (to not waste repeated space;) if you want the machine
1897
+ * string embedded, call {@link serialize_with_string} instead.
1898
+ *
1899
+ * @typeparam mDT The type of the machine data member; usually omitted
1900
+ *
1901
+ * @param comment An optional comment string to embed in the serialized
1902
+ * output for identification or debugging.
1903
+ *
1904
+ * @returns A {@link JssmSerialization} object containing the machine's
1905
+ * current state, data, and timestamp.
1906
+ *
1907
+ */
1908
+ serialize(comment?: string | undefined): JssmSerialization<mDT>;
1909
+ /** Get the graph layout direction (e.g. `'LR'`, `'TB'`). Set via the
1910
+ * FSL `graph_layout` directive.
1911
+ * @returns The layout string, or the default if not set.
1912
+ */
1913
+ graph_layout(): string;
1914
+ /** Get the Graphviz DOT preamble string, injected before the graph body
1915
+ * during visualization. Set via the FSL `dot_preamble` directive.
1916
+ * @returns The preamble string.
1917
+ */
1918
+ dot_preamble(): string;
1919
+ /** Get the consolidated `transition: {}` default-config block: the ordered,
1920
+ * de-duplicated `{ key, value }[]` list of edge-default style items compiled
1921
+ * from a `transition: {}` block (e.g. `transition: { color: blue; }`). The
1922
+ * viz layer projects this onto a Graphviz `edge [ … ]` default statement so
1923
+ * every edge inherits it.
1924
+ *
1925
+ * ```typescript
1926
+ * import { sm } from 'jssm';
1927
+ * sm`a -> b; transition: { color: blue; };`.default_transition_config();
1928
+ * // [ { key: 'color', value: '#0000ffff' } ]
1929
+ * ```
1930
+ *
1931
+ * @returns The transition-config item list, or `undefined` if the machine
1932
+ * declared no `transition: {}` block.
1933
+ * @see default_graph_config
1934
+ */
1935
+ default_transition_config(): JssmTransitionConfig | undefined;
1936
+ /** Get the consolidated `graph: {}` default-config block: the ordered,
1937
+ * de-duplicated `{ key, value }[]` list of graph-scope style items. The
1938
+ * compiler folds the deprecated top-level graph keywords
1939
+ * (`graph_bg_color` → `background-color`, plus `graph_layout`, `theme`,
1940
+ * `flow`, `dot_preamble`) into this list first, then lets an explicit
1941
+ * `graph: {}` block win on key conflict. The viz layer projects the
1942
+ * graph-meaningful keys onto graph-scope Graphviz attributes (e.g.
1943
+ * `background-color` → `bgcolor`).
1944
+ *
1945
+ * ```typescript
1946
+ * import { sm } from 'jssm';
1947
+ * sm`a -> b; graph: { background-color: #ffffff; };`.default_graph_config();
1948
+ * // [ { key: 'background-color', value: '#ffffffff' } ]
1949
+ * ```
1950
+ *
1951
+ * @returns The graph-config item list, or `undefined` if the machine has no
1952
+ * graph config (no `graph: {}` block and no deprecated graph keyword).
1953
+ * @see default_transition_config
1954
+ */
1955
+ default_graph_config(): JssmGraphConfig | undefined;
1956
+ /** Get the machine's author list. Set via the FSL `machine_author` directive.
1957
+ * @returns An array of author name strings.
1958
+ */
1959
+ machine_author(): Array<string>;
1960
+ /** Get the machine's comment string. Set via the FSL `machine_comment` directive.
1961
+ * @returns The comment string.
1962
+ */
1963
+ machine_comment(): string;
1964
+ /** Get the machine's contributor list. Set via the FSL `machine_contributor` directive.
1965
+ * @returns An array of contributor name strings.
1966
+ */
1967
+ machine_contributor(): Array<string>;
1968
+ /** Get the machine's definition string. Set via the FSL `machine_definition` directive.
1969
+ * @returns The definition string.
1970
+ */
1971
+ machine_definition(): string;
1972
+ /** Get the machine's natural language as an ISO 639-1 code. Set via the FSL
1973
+ * `machine_language` directive, which accepts a language name or code, or a
1974
+ * BCP-47 tag whose region subtag is dropped (`en-us` -> `en`). Unrecognized
1975
+ * values resolve to `undefined`.
1976
+ * @returns The ISO 639-1 language code (e.g. `'en'`), or `undefined` if the
1977
+ * supplied value did not resolve to a known language.
1978
+ */
1979
+ machine_language(): string;
1980
+ /** Get the machine's license string. Set via the FSL `machine_license` directive.
1981
+ * @returns The license string.
1982
+ */
1983
+ machine_license(): string;
1984
+ /** Get the machine's name. Set via the FSL `machine_name` directive.
1985
+ * @returns The machine name string.
1986
+ */
1987
+ machine_name(): string;
1988
+ /** The editor/panel defaults declared in the FSL `editor: {}` block, or
1989
+ * `undefined` when none was given. Read by the all-widgets web control
1990
+ * (fsl#1334) — `panels` drives `request` panel mode.
1991
+ *
1992
+ * @returns `{ stochastic_run_count?, panels? }`, or `undefined`.
1993
+ *
1994
+ * @example
1995
+ * const m = sm`editor: { panels: [history]; }; a -> b;`;
1996
+ * m.editor_config(); // => { panels: ['history'] }
1997
+ */
1998
+ editor_config(): JssmEditorConfig | undefined;
1999
+ /** Get the npm package name associated with the machine. Set via the FSL `npm_name` directive.
2000
+ * Returns `undefined` when not present.
2001
+ * @returns The npm package name string, or `undefined`.
2002
+ * @see machine_name
2003
+ */
2004
+ npm_name(): string;
2005
+ /** Get the render-size hint for the machine's visualization. Set via the
2006
+ * FSL `default_size` directive. Returns `undefined` when not present.
2007
+ *
2008
+ * The three FSL forms each produce a different subset of fields:
2009
+ *
2010
+ * - `default_size: 800;` → `{ width: 800 }`
2011
+ * - `default_size: 800 600;` → `{ width: 800, height: 600 }`
2012
+ * - `default_size: height 600;` → `{ height: 600 }`
2013
+ *
2014
+ * This is a hint, not a hard constraint. Renderers may ignore it.
2015
+ *
2016
+ * @returns The size-hint object, or `undefined` if not set.
2017
+ * @see npm_name
2018
+ */
2019
+ default_size(): JssmDefaultSize | undefined;
2020
+ /** Get the machine's version string. Set via the FSL `machine_version` directive.
2021
+ * @returns The version string.
2022
+ */
2023
+ machine_version(): string;
2024
+ /** Get the raw state declaration objects as parsed from the FSL source.
2025
+ * @returns An array of raw state declaration objects.
2026
+ */
2027
+ raw_state_declarations(): Array<Object>;
2028
+ /** Get the processed state declaration for a specific state.
2029
+ * @param which - The state to look up.
2030
+ * @returns The {@link JssmStateDeclaration} for the given state.
2031
+ */
2032
+ state_declaration(which: StateType): JssmStateDeclaration;
2033
+ /** Get all processed state declarations as a Map.
2034
+ * @returns A `Map` from state name to {@link JssmStateDeclaration}.
2035
+ */
2036
+ state_declarations(): Map<StateType, JssmStateDeclaration>;
2037
+ /** Get the FSL language version this machine was compiled under.
2038
+ * @returns The FSL version string.
2039
+ */
2040
+ fsl_version(): string;
2041
+ /** Get the complete internal state of the machine as a serializable
2042
+ * structure. Includes actions, edges, edge map, named transitions,
2043
+ * reverse actions, current state, and states map.
2044
+ * @returns A {@link JssmMachineInternalState} snapshot.
2045
+ */
2046
+ machine_state(): JssmMachineInternalState<mDT>;
2047
+ /*********
2048
+ *
2049
+ * List all the states known by the machine. Please note that the order of
2050
+ * these states is not guaranteed.
2051
+ *
2052
+ * ```typescript
2053
+ * import * as jssm from 'jssm';
2054
+ *
2055
+ * const lswitch = jssm.from('on <=> off;');
2056
+ * console.log( lswitch.states() ); // ['on', 'off']
2057
+ * ```
2058
+ *
2059
+ * @typeparam mDT The type of the machine data member; usually omitted
2060
+ *
2061
+ * @returns An array of all state names in the machine.
2062
+ *
2063
+ */
2064
+ states(): Array<StateType>;
2065
+ /** Get the internal state descriptor for a given state name.
2066
+ * @param whichState - The state to look up.
2067
+ * @returns The {@link JssmGenericState} descriptor.
2068
+ * @throws {JssmError} If the state does not exist.
2069
+ */
2070
+ state_for(whichState: StateType): JssmGenericState;
2071
+ /*********
2072
+ *
2073
+ * Check whether the machine knows a given state.
2074
+ *
2075
+ * ```typescript
2076
+ * import * as jssm from 'jssm';
2077
+ *
2078
+ * const lswitch = jssm.from('on <=> off;');
2079
+ *
2080
+ * console.log( lswitch.has_state('off') ); // true
2081
+ * console.log( lswitch.has_state('dance') ); // false
2082
+ * ```
2083
+ *
2084
+ * @typeparam mDT The type of the machine data member; usually omitted
2085
+ *
2086
+ * @param whichState The state to be checked for existence.
2087
+ *
2088
+ * @returns `true` if the state exists, `false` otherwise.
2089
+ *
2090
+ */
2091
+ has_state(whichState: StateType): boolean;
2092
+ /*********
2093
+ *
2094
+ * Lists all edges of a machine.
2095
+ *
2096
+ * ```typescript
2097
+ * import { sm } from 'jssm';
2098
+ *
2099
+ * const lswitch = sm`on 'toggle' <=> 'toggle' off;`;
2100
+ *
2101
+ * lswitch.list_edges();
2102
+ * [
2103
+ * {
2104
+ * from: 'on',
2105
+ * to: 'off',
2106
+ * kind: 'main',
2107
+ * forced_only: false,
2108
+ * main_path: true,
2109
+ * action: 'toggle'
2110
+ * },
2111
+ * {
2112
+ * from: 'off',
2113
+ * to: 'on',
2114
+ * kind: 'main',
2115
+ * forced_only: false,
2116
+ * main_path: true,
2117
+ * action: 'toggle'
2118
+ * }
2119
+ * ]
2120
+ * ```
2121
+ *
2122
+ * @typeparam mDT The type of the machine data member; usually omitted
2123
+ *
2124
+ * @returns An array of all {@link JssmTransition} edge objects.
2125
+ *
2126
+ */
2127
+ list_edges(): Array<JssmTransition<StateType, mDT>>;
2128
+ /** Get the map of named transitions (transitions with explicit names).
2129
+ * @returns A `Map` from transition name to edge index.
2130
+ */
2131
+ list_named_transitions(): Map<StateType, number>;
2132
+ /** List all distinct action names defined anywhere in the machine.
2133
+ * @returns An array of action name strings.
2134
+ */
2135
+ list_actions(): Array<StateType>;
2136
+ /** Whether any actions are defined on this machine.
2137
+ * @returns `true` if the machine has at least one action.
2138
+ */
2139
+ get uses_actions(): boolean;
2140
+ /** Whether any forced (`~>`) transitions exist in this machine.
2141
+ * @returns `true` if at least one forced transition is defined.
2142
+ */
2143
+ get uses_forced_transitions(): boolean;
2144
+ /*********
2145
+ *
2146
+ * Check if the code that built the machine allows overriding state and data.
2147
+ *
2148
+ * @returns The override permission from the FSL source code.
2149
+ *
2150
+ */
2151
+ get code_allows_override(): JssmAllowsOverride;
2152
+ /*********
2153
+ *
2154
+ * Check if the machine config allows overriding state and data.
2155
+ *
2156
+ * @returns The override permission from the runtime config.
2157
+ *
2158
+ */
2159
+ get config_allows_override(): JssmAllowsOverride;
2160
+ /*********
2161
+ *
2162
+ * Check if a machine allows overriding state and data. Resolves the
2163
+ * combined effect of code and config permissions — config may not be
2164
+ * less strict than code.
2165
+ *
2166
+ * @returns The effective override permission.
2167
+ *
2168
+ */
2169
+ get allows_override(): JssmAllowsOverride;
2170
+ /*********
2171
+ *
2172
+ * Return the effective island policy for this machine. `true` means
2173
+ * disconnected components are allowed (the default), `false` requires a
2174
+ * single connected component, and `'with_start'` allows islands only when
2175
+ * every component contains at least one start state.
2176
+ *
2177
+ * @returns The island policy stored in the machine.
2178
+ *
2179
+ */
2180
+ get allow_islands(): JssmAllowIslands;
2181
+ /** List all available theme names.
2182
+ * @returns An array of theme name strings.
2183
+ */
2184
+ all_themes(): FslTheme[];
2185
+ /** List the character ranges accepted by the FSL grammar in any but the
2186
+ * first position of a state name (atom). Each entry is an inclusive
2187
+ * `{from, to}` range of single Unicode characters.
2188
+ *
2189
+ * @returns An array of `{from, to}` inclusive character ranges.
2190
+ *
2191
+ * @example
2192
+ * import { sm } from 'jssm';
2193
+ * const m = sm`a -> b;`;
2194
+ * m.all_state_name_chars().some(r => '+' >= r.from && '+' <= r.to); // => true
2195
+ */
2196
+ all_state_name_chars(): ReadonlyArray<{
2197
+ from: string;
2198
+ to: string;
2199
+ }>;
2200
+ /** List the character ranges accepted by the FSL grammar in the first
2201
+ * position of a state name (atom). Narrower than
2202
+ * {@link all_state_name_chars}: notably omits `+`, `(`, `)`, `&`, `#`, `@`.
2203
+ *
2204
+ * @returns An array of `{from, to}` inclusive character ranges.
2205
+ *
2206
+ * @example
2207
+ * import { sm } from 'jssm';
2208
+ * const m = sm`a -> b;`;
2209
+ * m.all_state_name_first_chars().some(r => '+' >= r.from && '+' <= r.to); // => false
2210
+ */
2211
+ all_state_name_first_chars(): ReadonlyArray<{
2212
+ from: string;
2213
+ to: string;
2214
+ }>;
2215
+ /** List the character ranges accepted inside a single-quoted FSL action
2216
+ * label without escaping. Space is allowed; the apostrophe `'` is
2217
+ * explicitly excluded since it terminates the label.
2218
+ *
2219
+ * @returns An array of `{from, to}` inclusive character ranges.
2220
+ *
2221
+ * @example
2222
+ * import { sm } from 'jssm';
2223
+ * const m = sm`a -> b;`;
2224
+ * m.all_action_label_chars().some(r => ' ' >= r.from && ' ' <= r.to); // => true
2225
+ * m.all_action_label_chars().some(r => "'" >= r.from && "'" <= r.to); // => false
2226
+ */
2227
+ all_action_label_chars(): ReadonlyArray<{
2228
+ from: string;
2229
+ to: string;
2230
+ }>;
2231
+ /** Get the active theme(s) for this machine. Always stored as an array
2232
+ * internally; the union return type exists for setter compatibility.
2233
+ * @returns The current theme or array of themes.
2234
+ */
2235
+ get themes(): FslTheme | FslTheme[];
2236
+ /** Set the active theme(s). Accepts a single theme name or an array.
2237
+ * @param to - A theme name or array of theme names to apply.
2238
+ */
2239
+ set themes(to: FslTheme | FslTheme[]);
2240
+ /** Get the flow direction for graph layout (e.g. `'right'`, `'down'`).
2241
+ * Set via the FSL `flow` directive.
2242
+ * @returns The current flow direction.
2243
+ */
2244
+ flow(): FslDirection;
2245
+ /** Look up a transition's edge index by source and target state names.
2246
+ * @param from - Source state name.
2247
+ * @param to - Target state name.
2248
+ * @returns The edge index in the edges array, or `undefined` if no
2249
+ * such transition exists.
2250
+ */
2251
+ get_transition_by_state_names(from: StateType, to: StateType): number;
2252
+ /** Look up the full transition object for a given source→target pair.
2253
+ * @param from - Source state name.
2254
+ * @param to - Target state name.
2255
+ * @returns The {@link JssmTransition} object, or `undefined` if none exists.
2256
+ */
2257
+ lookup_transition_for(from: StateType, to: StateType): JssmTransition<StateType, mDT>;
2258
+ /********
2259
+ *
2260
+ * List all transitions attached to the current state, sorted by entrance and
2261
+ * exit. The order of each sublist is not defined. A node could appear in
2262
+ * both lists.
2263
+ *
2264
+ * ```typescript
2265
+ * import { sm } from 'jssm';
2266
+ *
2267
+ * const light = sm`red 'next' -> green 'next' -> yellow 'next' -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
2268
+ *
2269
+ * light.state(); // 'red'
2270
+ * light.list_transitions(); // { entrances: [ 'yellow', 'off' ], exits: [ 'green', 'off' ] }
2271
+ * ```
2272
+ *
2273
+ * @typeparam mDT The type of the machine data member; usually omitted
2274
+ *
2275
+ * @param whichState The state whose transitions to have listed
2276
+ *
2277
+ */
2278
+ list_transitions(whichState?: StateType): JssmTransitionList;
2279
+ /********
2280
+ *
2281
+ * List all entrances attached to the current state. Please note that the
2282
+ * order of the list is not defined. This list includes both unforced and
2283
+ * forced entrances; if this isn't desired, consider
2284
+ * {@link list_unforced_entrances} or {@link list_forced_entrances} as
2285
+ * appropriate.
2286
+ *
2287
+ * ```typescript
2288
+ * import { sm } from 'jssm';
2289
+ *
2290
+ * const light = sm`red 'next' -> green 'next' -> yellow 'next' -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
2291
+ *
2292
+ * light.state(); // 'red'
2293
+ * light.list_entrances(); // [ 'yellow', 'off' ]
2294
+ * ```
2295
+ *
2296
+ * @typeparam mDT The type of the machine data member; usually omitted
2297
+ *
2298
+ * @param whichState The state whose entrances to have listed
2299
+ *
2300
+ */
2301
+ list_entrances(whichState?: StateType): Array<StateType>;
2302
+ /********
2303
+ *
2304
+ * List all exits attached to the current state. Please note that the order
2305
+ * of the list is not defined. This list includes both unforced and forced
2306
+ * exits; if this isn't desired, consider {@link list_unforced_exits} or
2307
+ * {@link list_forced_exits} as appropriate.
2308
+ *
2309
+ * ```typescript
2310
+ * import { sm } from 'jssm';
2311
+ *
2312
+ * const light = sm`red 'next' -> green 'next' -> yellow 'next' -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
2313
+ *
2314
+ * light.state(); // 'red'
2315
+ * light.list_exits(); // [ 'green', 'off' ]
2316
+ * ```
2317
+ *
2318
+ * @typeparam mDT The type of the machine data member; usually omitted
2319
+ *
2320
+ * @param whichState The state whose exits to have listed
2321
+ *
2322
+ */
2323
+ list_exits(whichState?: StateType): Array<StateType>;
2324
+ /** Get the transitions available from a state for use by the probabilistic
2325
+ * walk system.
2326
+ *
2327
+ * If any exit declares a `probability`, only those probability-bearing
2328
+ * exits are returned, so that non-probability peers cannot dilute the
2329
+ * declared distribution. If no exit declares a `probability`, every
2330
+ * legal (non-forced) exit is returned, which `weighted_rand_select`
2331
+ * treats as equal weight. Forced-only exits (`~>`) are always excluded,
2332
+ * since they cannot be taken by an ordinary `transition()` call.
2333
+ *
2334
+ * Fixes StoneCypher/fsl#1325, in which the function previously returned
2335
+ * every exit unconditionally — including forced-only exits and exits
2336
+ * with no `probability`, which distorted the weighted distribution.
2337
+ *
2338
+ * @param whichState - The state to inspect.
2339
+ * @returns An array of {@link JssmTransition} edges exiting the state,
2340
+ * filtered as described above. May be empty.
2341
+ * @throws {JssmError} If the state does not exist.
2342
+ */
2343
+ probable_exits_for(whichState: StateType): Array<JssmTransition<StateType, mDT>>;
2344
+ /** Take a single random transition from the current state, weighted by
2345
+ * edge probabilities.
2346
+ * @returns `true` if a transition was taken, `false` otherwise.
2347
+ */
2348
+ probabilistic_transition(): boolean;
2349
+ /** Take `n` consecutive probabilistic transitions and return the sequence
2350
+ * of states visited (before each transition).
2351
+ * @param n - Number of steps to walk.
2352
+ * @returns An array of state names visited during the walk.
2353
+ */
2354
+ probabilistic_walk(n: number): Array<StateType>;
2355
+ /** Take `n` probabilistic steps and return a histograph of how many times
2356
+ * each state was visited.
2357
+ * @param n - Number of steps to walk.
2358
+ * @returns A `Map` from state name to visit count.
2359
+ */
2360
+ probabilistic_histo_walk(n: number): Map<StateType, number>;
2361
+ /** One non-destructive weighted-random walk over the graph from `start`.
2362
+ *
2363
+ * Reads the graph and advances the PRNG only — it never calls
2364
+ * {@link Machine.transition}, so it fires no hooks, mutates no machine
2365
+ * state, and touches no `data`. A state with no probabilistic exits
2366
+ * (a terminal, or a forced-only `~>` state) ends the walk.
2367
+ *
2368
+ * @param start - State to begin the walk from.
2369
+ * @param max_steps - Maximum transitions before the walk is step-capped.
2370
+ * @param exit_memo - Per-run-set cache of {@link Machine.probable_exits_for}
2371
+ * results. The graph is immutable after construction, so a state's
2372
+ * probable exits never change; sharing one memo across a generator's
2373
+ * runs collapses runs×steps re-derivations (two array allocations and an
2374
+ * exit rescan per step) to one per distinct state. The memo only reuses
2375
+ * the derived arrays — RNG draw order is untouched, so seeded walks
2376
+ * reproduce exactly.
2377
+ * @returns The {@link JssmStochasticRun} for this walk.
2378
+ */
2379
+ private _stochastic_one_walk;
2380
+ /** Lazily yield one {@link JssmStochasticRun} at a time.
2381
+ *
2382
+ * In `montecarlo` mode (default) yields `runs` independent walks from the
2383
+ * current state, each ending at a terminal or after `max_steps`. In
2384
+ * `steady_state` mode yields exactly one walk of `max_steps` steps. This
2385
+ * is the lazy engine behind {@link Machine.stochastic_summary}; the
2386
+ * fsl-stochastic panel drives it across animation frames.
2387
+ *
2388
+ * Passing `seed` reseeds the machine for reproducible runs. Unlike
2389
+ * {@link Machine.stochastic_summary}, the generator does NOT restore the
2390
+ * prior seed afterward — a direct caller's machine is left reseeded.
2391
+ *
2392
+ * @param opts - {@link JssmStochasticOptions}.
2393
+ * @returns A generator of per-run results.
2394
+ *
2395
+ * @example
2396
+ * const m = sm`a 'go' -> b 'go' -> c;`;
2397
+ * [...m.stochastic_runs({ runs: 2, seed: 1 })].length; // => 2
2398
+ */
2399
+ stochastic_runs(opts?: JssmStochasticOptions): Generator<JssmStochasticRun>;
2400
+ /** Run many weighted-random walks and return aggregate statistics.
2401
+ *
2402
+ * Honors `%` transition probabilities (via the existing probabilistic
2403
+ * machinery). Non-destructive: the machine's current state and
2404
+ * {@link Machine.rng_seed} are restored before returning, so calling this
2405
+ * never perturbs the live machine. `montecarlo` mode (default) reports
2406
+ * per-run `path_lengths`, `terminal_reached`, and `capped`; `steady_state`
2407
+ * mode runs one long walk and omits those fields.
2408
+ *
2409
+ * Timing (`after`) decorations and data-guard conditions are not modeled
2410
+ * by this sampler; it walks the probabilistic graph topology.
2411
+ *
2412
+ * @param opts - {@link JssmStochasticOptions}. `runs` defaults to the
2413
+ * machine's declared `editor: { stochastic_run_count }` (fsl#1334) when
2414
+ * present, otherwise {@link STOCHASTIC_DEFAULT_RUNS}.
2415
+ * @returns A {@link JssmStochasticSummary}.
2416
+ *
2417
+ * @see Machine.stochastic_runs
2418
+ * @see Machine.probabilistic_walk
2419
+ * @see Machine.editor_config
2420
+ *
2421
+ * @example
2422
+ * const m = sm`a 'go' -> b 'go' -> c;`;
2423
+ * const s = m.stochastic_summary({ runs: 100, seed: 1 });
2424
+ * s.terminal_reached; // => 100
2425
+ */
2426
+ stochastic_summary(opts?: JssmStochasticOptions): JssmStochasticSummary;
2427
+ /********
2428
+ *
2429
+ * List all actions available from this state. Please note that the order of
2430
+ * the actions is not guaranteed.
2431
+ *
2432
+ * ```typescript
2433
+ * import { sm } from 'jssm';
2434
+ *
2435
+ * const machine = sm`
2436
+ * red 'next' -> green 'next' -> yellow 'next' -> red;
2437
+ * [red yellow green] 'shutdown' ~> off 'start' -> red;
2438
+ * `;
2439
+ *
2440
+ * console.log( machine.state() ); // logs 'red'
2441
+ * console.log( machine.actions() ); // logs ['next', 'shutdown']
2442
+ *
2443
+ * machine.action('next'); // true
2444
+ * console.log( machine.state() ); // logs 'green'
2445
+ * console.log( machine.actions() ); // logs ['next', 'shutdown']
2446
+ *
2447
+ * machine.action('shutdown'); // true
2448
+ * console.log( machine.state() ); // logs 'off'
2449
+ * console.log( machine.actions() ); // logs ['start']
2450
+ *
2451
+ * machine.action('start'); // true
2452
+ * console.log( machine.state() ); // logs 'red'
2453
+ * console.log( machine.actions() ); // logs ['next', 'shutdown']
2454
+ * ```
2455
+ *
2456
+ * @typeparam mDT The type of the machine data member; usually omitted
2457
+ *
2458
+ * @param whichState The state whose actions to list. Defaults to the
2459
+ * current state.
2460
+ *
2461
+ * @returns An array of action names available from the given state.
2462
+ *
2463
+ */
2464
+ actions(whichState?: StateType): Array<StateType>;
2465
+ /********
2466
+ *
2467
+ * List all states that have a specific action attached. Please note that
2468
+ * the order of the states is not guaranteed.
2469
+ *
2470
+ * ```typescript
2471
+ * import { sm } from 'jssm';
2472
+ *
2473
+ * const machine = sm`
2474
+ * red 'next' -> green 'next' -> yellow 'next' -> red;
2475
+ * [red yellow green] 'shutdown' ~> off 'start' -> red;
2476
+ * `;
2477
+ *
2478
+ * console.log( machine.list_states_having_action('next') ); // ['red', 'green', 'yellow']
2479
+ * console.log( machine.list_states_having_action('start') ); // ['off']
2480
+ * ```
2481
+ *
2482
+ * @typeparam mDT The type of the machine data member; usually omitted
2483
+ *
2484
+ * @param whichState The action to be checked for associated states
2485
+ *
2486
+ */
2487
+ list_states_having_action(whichState: StateType): Array<StateType>;
2488
+ /** List all action names available as exits from a given state.
2489
+ *
2490
+ * Returns the empty array (does not throw) when `whichState` exists but has
2491
+ * no action-named exits — including terminal states, states whose only
2492
+ * exits are plain `->` transitions, and states in machines that use no
2493
+ * actions at all. Only nonexistent states cause a throw.
2494
+ *
2495
+ * @param whichState - The state to inspect. Defaults to the current state.
2496
+ * @returns An array of action name strings, possibly empty.
2497
+ * @throws {JssmError} If the state does not exist.
2498
+ *
2499
+ * @example
2500
+ * const m = sm`a 'go' -> b; b -> c;`;
2501
+ * m.list_exit_actions('a'); // => ['go']
2502
+ * m.list_exit_actions('b'); // => []
2503
+ * m.list_exit_actions('c'); // => []
2504
+ * expect(() => m.list_exit_actions('z')).toThrow();
2505
+ */
2506
+ list_exit_actions(whichState?: StateType): Array<StateType>;
2507
+ /** List all action exits from a state with their probabilities.
2508
+ * @param whichState - The state to inspect. Defaults to the current state.
2509
+ * @returns An array of `{ action, probability }` objects.
2510
+ * @throws {JssmError} If the state does not exist.
2511
+ */
2512
+ probable_action_exits(whichState?: StateType): Array<any>;
2513
+ /** Check whether a state has no incoming transitions (unreachable after start).
2514
+ * @param whichState - The state to check.
2515
+ * @returns `true` if the state has zero entrances.
2516
+ * @throws {JssmError} If the state does not exist.
2517
+ */
2518
+ is_unenterable(whichState: StateType): boolean;
2519
+ /** Check whether any state in the machine is unenterable.
2520
+ * @returns `true` if at least one state has no incoming transitions.
2521
+ */
2522
+ has_unenterables(): boolean;
2523
+ /** Check whether the current state is terminal (has no exits).
2524
+ * @returns `true` if the current state has zero exits.
2525
+ */
2526
+ is_terminal(): boolean;
2527
+ /** Check whether a specific state is terminal (has no exits).
2528
+ * @param whichState - The state to check.
2529
+ * @returns `true` if the state has zero exits.
2530
+ * @throws {JssmError} If the state does not exist.
2531
+ */
2532
+ state_is_terminal(whichState: StateType): boolean;
2533
+ /** Check whether any state in the machine is terminal.
2534
+ * @returns `true` if at least one state has no exits.
2535
+ */
2536
+ has_terminals(): boolean;
2537
+ /********
2538
+ *
2539
+ * Reports whether the machine's CURRENT state is a transitive member of a
2540
+ * named group. Membership is deep: a state counts as in `groupName` if it
2541
+ * belongs to that group directly, or via any nested (`&child`) or spread
2542
+ * (`...&child`) sub-group, at any depth. An undeclared group simply has no
2543
+ * members, so this returns `false` rather than throwing.
2544
+ *
2545
+ * ```typescript
2546
+ * import { sm } from 'jssm';
2547
+ *
2548
+ * const m = sm`&busy : [working]; idle 'go' -> working;`;
2549
+ * m.isIn('busy'); // false — current state is 'idle'
2550
+ * m.action('go');
2551
+ * m.isIn('busy'); // true — current state is now 'working'
2552
+ * m.isIn('nonesuch'); // false — undeclared group has no members
2553
+ * ```
2554
+ *
2555
+ * @typeparam mDT The type of the machine data member; usually omitted
2556
+ *
2557
+ * @param groupName The group to test the current state against.
2558
+ *
2559
+ * @returns `true` if the current state is a transitive member of `groupName`.
2560
+ *
2561
+ * @see groupsOf
2562
+ * @see statesIn
2563
+ *
2564
+ */
2565
+ isIn(groupName: string): boolean;
2566
+ /********
2567
+ *
2568
+ * Lists every group that transitively contains a given state. Membership is
2569
+ * deep — direct, nested, and spread sub-group containment all count — and the
2570
+ * result is the precomputed inverse-index entry for the state, so the lookup
2571
+ * is constant-time. A state that belongs to no group (or a state name that
2572
+ * appears in no group) yields an empty `Set`.
2573
+ *
2574
+ * ```typescript
2575
+ * import { sm } from 'jssm';
2576
+ *
2577
+ * const m = sm`&inner : [a]; &outer : [&inner b]; a -> b;`;
2578
+ * m.groupsOf('a'); // Set { 'inner', 'outer' } — deep through &inner
2579
+ * m.groupsOf('b'); // Set { 'outer' }
2580
+ * m.groupsOf('z'); // Set {} — not in any group
2581
+ * ```
2582
+ *
2583
+ * @typeparam mDT The type of the machine data member; usually omitted
2584
+ *
2585
+ * @param state The state whose containing groups are wanted.
2586
+ *
2587
+ * @returns A `Set` of every group name transitively containing `state`;
2588
+ * empty when `state` belongs to no group.
2589
+ *
2590
+ * @see isIn
2591
+ * @see groups
2592
+ *
2593
+ */
2594
+ groupsOf(state: StateType): Set<string>;
2595
+ /********
2596
+ *
2597
+ * Lists all declared group names, in source declaration order. The order
2598
+ * matches the order the `&group : [ … ];` declarations appear in the FSL, and
2599
+ * is the same order used to break depth-specificity ties in the config
2600
+ * cascade. Machines that declare no groups return an empty array.
2601
+ *
2602
+ * ```typescript
2603
+ * import { sm } from 'jssm';
2604
+ *
2605
+ * const m = sm`&first : [a]; &second : [b]; a -> b;`;
2606
+ * m.groups(); // [ 'first', 'second' ]
2607
+ * ```
2608
+ *
2609
+ * @typeparam mDT The type of the machine data member; usually omitted
2610
+ *
2611
+ * @returns The declared group names, in declaration order.
2612
+ *
2613
+ * @see groupsOf
2614
+ * @see statesIn
2615
+ *
2616
+ */
2617
+ groups(): string[];
2618
+ /********
2619
+ *
2620
+ * Lists every state that is a transitive member of a named group — the
2621
+ * flattened membership of the group, descending through nested and spread
2622
+ * sub-groups, in member-declaration order.
2623
+ *
2624
+ * ```typescript
2625
+ * import { sm } from 'jssm';
2626
+ *
2627
+ * const m = sm`&inner : [a b]; &outer : [&inner c]; a -> b -> c;`;
2628
+ * m.statesIn('outer'); // [ 'a', 'b', 'c' ]
2629
+ * m.statesIn('inner'); // [ 'a', 'b' ]
2630
+ * ```
2631
+ *
2632
+ * @typeparam mDT The type of the machine data member; usually omitted
2633
+ *
2634
+ * @param groupName The group whose transitive member states are wanted.
2635
+ *
2636
+ * @returns The transitive member states of `groupName`, in declaration order.
2637
+ *
2638
+ * @throws {JssmError} If `groupName` is not a declared group.
2639
+ *
2640
+ * @see groups
2641
+ * @see groupsOf
2642
+ *
2643
+ */
2644
+ statesIn(groupName: string): Array<StateType>;
2645
+ /** Check whether the current state is complete (every exit has an action).
2646
+ * @returns `true` if the current state is complete.
2647
+ */
2648
+ is_complete(): boolean;
2649
+ /** Check whether a specific state is complete (every exit has an action).
2650
+ * @param whichState - The state to check.
2651
+ * @returns `true` if the state is complete.
2652
+ * @throws {JssmError} If the state does not exist.
2653
+ */
2654
+ state_is_complete(whichState: StateType): boolean;
2655
+ /** Check whether any state in the machine is complete.
2656
+ * @returns `true` if at least one state is complete.
2657
+ */
2658
+ has_completes(): boolean;
2659
+ /**
2660
+ * Subscribe to a typed observation event. Hooks (`set_hook` and friends)
2661
+ * intercept and may cancel a transition; events fire alongside the same
2662
+ * state-machine moments but cannot influence the outcome. This is the
2663
+ * surface most users actually want for "tell me when state changes".
2664
+ *
2665
+ * Handlers run synchronously, in registration order. A throwing handler
2666
+ * does not block subsequent handlers — its exception is caught and
2667
+ * re-emitted as an `error` event whose detail names the original event
2668
+ * and the offending handler.
2669
+ *
2670
+ * ```typescript
2671
+ * const m = sm`a -> b -> c;`;
2672
+ *
2673
+ * m.on('transition', e => console.log(`${e.from} -> ${e.to}`));
2674
+ * m.on('entry', { state: 'b' }, e => console.log(`entered ${e.state}`));
2675
+ *
2676
+ * const off = m.on('transition', () => {});
2677
+ * off(); // unsubscribe
2678
+ * ```
2679
+ *
2680
+ * @typeparam Ev The event name (drives the detail type).
2681
+ * @param name The event name to subscribe to.
2682
+ * @param filterOrFn Either a filter object or, when calling the no-filter
2683
+ * form, the handler itself.
2684
+ * @param maybeFn The handler, when a filter object was supplied.
2685
+ * @returns A function that unsubscribes when called.
2686
+ *
2687
+ * @see Machine.off
2688
+ * @see Machine.once
2689
+ */
2690
+ on<Ev extends JssmEventName>(name: Ev, handler: JssmEventHandler<mDT, Ev>): JssmUnsubscribe;
2691
+ on<Ev extends JssmEventName>(name: Ev, filter: JssmEventFilter<mDT, Ev>, handler: JssmEventHandler<mDT, Ev>): JssmUnsubscribe;
2692
+ /**
2693
+ * Subscribe to a typed observation event for one matching delivery, then
2694
+ * auto-remove. Accepts the same `(name, handler)` and `(name, filter,
2695
+ * handler)` shapes as {@link Machine.on}.
2696
+ *
2697
+ * ```typescript
2698
+ * m.once('terminal', e => console.log(`done at ${e.state}`));
2699
+ * ```
2700
+ *
2701
+ * @typeparam Ev The event name.
2702
+ * @param name The event name.
2703
+ * @param filterOrFn A filter object or the handler (no-filter form).
2704
+ * @param maybeFn The handler, when a filter was supplied.
2705
+ * @returns A function that unsubscribes early if called before the
2706
+ * handler has fired.
2707
+ *
2708
+ * @see Machine.on
2709
+ * @see Machine.off
2710
+ */
2711
+ once<Ev extends JssmEventName>(name: Ev, handler: JssmEventHandler<mDT, Ev>): JssmUnsubscribe;
2712
+ once<Ev extends JssmEventName>(name: Ev, filter: JssmEventFilter<mDT, Ev>, handler: JssmEventHandler<mDT, Ev>): JssmUnsubscribe;
2713
+ /**
2714
+ * Remove a previously-registered event handler. Match is by reference —
2715
+ * the same function value passed to {@link Machine.on} or
2716
+ * {@link Machine.once}. Returns `true` if a subscription was found and
2717
+ * removed, `false` otherwise.
2718
+ *
2719
+ * ```typescript
2720
+ * const fn = (e: any) => console.log(e);
2721
+ * m.on('transition', fn);
2722
+ * m.off('transition', fn); // true
2723
+ * m.off('transition', fn); // false
2724
+ * ```
2725
+ *
2726
+ * @param name The event name.
2727
+ * @param handler The handler reference to remove.
2728
+ * @returns `true` if removed, `false` if no match was registered.
2729
+ */
2730
+ off<Ev extends JssmEventName>(name: Ev, handler: JssmEventHandler<mDT, Ev>): boolean;
2731
+ /**
2732
+ * Remove one event-subscription entry from its set and keep
2733
+ * {@link Machine._event_listener_count} in sync. The count is decremented
2734
+ * only when the entry was actually present, so calling a stale unsubscribe
2735
+ * closure (or removing an already-fired `once` entry) is idempotent and
2736
+ * cannot drive the count negative.
2737
+ *
2738
+ * @param set The per-event-name subscription set.
2739
+ * @param entry The entry to remove.
2740
+ * @internal
2741
+ */
2742
+ _unsubscribe_entry(set: Set<JssmEventEntry<any, any>>, entry: JssmEventEntry<any, any>): void;
2743
+ /**
2744
+ * Shared registration core used by {@link Machine.on} and
2745
+ * {@link Machine.once}. Normalizes the optional filter argument and
2746
+ * installs the entry into the per-event subscription set.
2747
+ *
2748
+ * @internal
2749
+ */
2750
+ _subscribe<Ev extends JssmEventName>(name: Ev, filterOrFn: JssmEventFilter<mDT, Ev> | JssmEventHandler<mDT, Ev>, maybeFn: JssmEventHandler<mDT, Ev> | undefined, once: boolean): JssmUnsubscribe;
2751
+ /**
2752
+ * Invoke a single event-handler entry, respecting its filter, once-removal
2753
+ * semantics, and the error re-fire / recursion-guard logic. Extracted so
2754
+ * {@link _fire} can share identical behavior between the size-1 fast-path
2755
+ * and the general snapshotted loop.
2756
+ *
2757
+ * @param entry - The subscriber descriptor to invoke.
2758
+ * @param set - The live Set that owns `entry`; needed for once-removal.
2759
+ * @param name - The event name being dispatched (used in error re-fires).
2760
+ * @param detail - The event payload forwarded to the handler.
2761
+ *
2762
+ * @internal
2763
+ */
2764
+ _fire_one<Ev extends JssmEventName>(entry: JssmEventEntry<mDT, Ev>, set: Set<JssmEventEntry<any, any>>, name: Ev, detail: JssmEventDetailMap<mDT>[Ev]): void;
2765
+ /**
2766
+ * Dispatch an event to every registered subscriber in registration
2767
+ * order. Filters are checked first; non-matching handlers are skipped
2768
+ * without invoking the handler. Exceptions thrown by a handler are
2769
+ * caught and re-emitted as an `error` event so subsequent handlers
2770
+ * still run.
2771
+ *
2772
+ * Re-entry into the `error` event itself is guarded — if an `error`
2773
+ * handler throws, the new exception is swallowed rather than rebroadcast
2774
+ * to avoid an infinite loop.
2775
+ *
2776
+ * When exactly one subscriber is registered the common case avoids the
2777
+ * `Array.from(set)` snapshot allocation by capturing the lone entry into a
2778
+ * local first — equivalent to a 1-element snapshot but allocation-free.
2779
+ * The general path still snapshots for re-entrancy safety.
2780
+ *
2781
+ * @internal
2782
+ */
2783
+ /**
2784
+ * Whether at least one live subscriber is registered for `name`. Used by
2785
+ * the transition-commit observation block to skip building a detail
2786
+ * literal that {@link Machine._fire} would immediately discard — a panel
2787
+ * listening only to `'transition'` (fsl-bind, fsl-viz, fsl-info-panel)
2788
+ * previously paid for the exit/entry/data-change detail allocations on
2789
+ * every transition. Read at fire time, so a listener installed by a
2790
+ * pre-hook is still seen (#671).
2791
+ *
2792
+ * @param name The event name to probe.
2793
+ * @returns `true` when a subsequent `_fire(name, ...)` would reach at
2794
+ * least one handler.
2795
+ *
2796
+ * ```typescript
2797
+ * machine.on('transition', () => {});
2798
+ * machine._has_subscribers('transition'); // true
2799
+ * machine._has_subscribers('exit'); // false
2800
+ * ```
2801
+ *
2802
+ * @see Machine._fire
2803
+ * @internal
2804
+ */
2805
+ _has_subscribers(name: JssmEventName): boolean;
2806
+ _fire<Ev extends JssmEventName>(name: Ev, detail: JssmEventDetailMap<mDT>[Ev]): void;
2807
+ /** Low-level hook registration. Installs a handler described by a
2808
+ * {@link HookDescription} into the appropriate internal map. Prefer the
2809
+ * convenience wrappers ({@link hook}, {@link hook_entry}, etc.) over
2810
+ * calling this directly.
2811
+ * @param HookDesc - A hook descriptor specifying kind, states, and handler.
2812
+ */
2813
+ /**
2814
+ * Validate a {@link HookDescription} before registration. Every hook needs
2815
+ * a `handler` function, and each kind's identifying spatial fields
2816
+ * (`from`/`to`/`action`) must be exactly those `set_hook` reads for that
2817
+ * kind — present when required, absent otherwise. This turns a mis-shaped
2818
+ * descriptor into a thrown error instead of a silently dead hook keyed on
2819
+ * `undefined` (e.g. an `exit` hook handed `to` instead of `from`, #734).
2820
+ *
2821
+ * @param HookDesc - The descriptor about to be registered.
2822
+ * @throws JssmError if the kind is unknown, the handler is not a function, a
2823
+ * required field is missing, or an inapplicable field is present.
2824
+ *
2825
+ * @example
2826
+ * const m = sm`a -> b;`;
2827
+ * // an exit hook is keyed by `from`, so supplying `to` is rejected:
2828
+ * expect(() => m.set_hook({ kind: 'exit', to: 'a', handler: () => true })).toThrow();
2829
+ */
2830
+ _validate_hook_description(HookDesc: HookDescription<mDT>): void;
2831
+ set_hook(HookDesc: HookDescription<mDT>): void;
2832
+ /**
2833
+ * Remove a previously-registered hook described by a
2834
+ * {@link HookDescription}. Match is by `kind` + identifying keys
2835
+ * (`from`/`to`/`action`/etc.), not by handler reference — there is one
2836
+ * hook per slot in the registry, so the description uniquely identifies
2837
+ * which one to clear. Fires a `hook-removal` event for inspector tools.
2838
+ *
2839
+ * This is the symmetric counterpart of {@link Machine.set_hook} for the
2840
+ * event-bridging use case (#638). Reasoning about hooks via observation
2841
+ * events requires being able to observe their disappearance too.
2842
+ *
2843
+ * ```typescript
2844
+ * const m = sm`a -> b;`;
2845
+ * const fn = () => true;
2846
+ * m.set_hook({ kind: 'hook', from: 'a', to: 'b', handler: fn });
2847
+ * m.remove_hook({ kind: 'hook', from: 'a', to: 'b', handler: fn });
2848
+ * ```
2849
+ *
2850
+ * @param HookDesc - A hook descriptor identifying the hook to remove.
2851
+ * @returns `true` if a hook was removed, `false` otherwise.
2852
+ */
2853
+ remove_hook(HookDesc: HookDescription<mDT>): boolean;
2854
+ /** Register a pre-transition hook on a specific edge. Fires before
2855
+ * transitioning from `from` to `to`. If the handler returns `false`, the
2856
+ * transition is blocked.
2857
+ *
2858
+ * ```typescript
2859
+ * const m = sm`a -> b -> c;`;
2860
+ * m.hook('a', 'b', () => console.log('a->b'));
2861
+ * ```
2862
+ *
2863
+ * @param from - Source state name.
2864
+ * @param to - Target state name.
2865
+ * @param handler - Callback invoked before the transition.
2866
+ * @returns `this` for chaining.
2867
+ */
2868
+ hook(from: string, to: string, handler: HookHandler<mDT>): Machine<mDT>;
2869
+ /** Register a pre-transition hook on a specific action-labeled edge.
2870
+ * @param from - Source state name.
2871
+ * @param to - Target state name.
2872
+ * @param action - The action label that triggers this hook.
2873
+ * @param handler - Callback invoked before the transition.
2874
+ * @returns `this` for chaining.
2875
+ */
2876
+ hook_action(from: string, to: string, action: string, handler: HookHandler<mDT>): Machine<mDT>;
2877
+ /** Register a pre-transition hook on any edge triggered by a specific action.
2878
+ * @param action - The action name to hook.
2879
+ * @param handler - Callback invoked before any transition with this action.
2880
+ * @returns `this` for chaining.
2881
+ */
2882
+ hook_global_action(action: string, handler: HookHandler<mDT>): Machine<mDT>;
2883
+ /** Register a pre-transition hook on any action-driven transition.
2884
+ * @param handler - Callback invoked before any action transition.
2885
+ * @returns `this` for chaining.
2886
+ */
2887
+ hook_any_action(handler: HookHandler<mDT>): Machine<mDT>;
2888
+ /** Register a pre-transition hook on any standard (`->`) transition.
2889
+ * @param handler - Callback invoked before any legal transition.
2890
+ * @returns `this` for chaining.
2891
+ */
2892
+ hook_standard_transition(handler: HookHandler<mDT>): Machine<mDT>;
2893
+ /** Register a pre-transition hook on any main-path (`=>`) transition.
2894
+ * @param handler - Callback invoked before any main transition.
2895
+ * @returns `this` for chaining.
2896
+ */
2897
+ hook_main_transition(handler: HookHandler<mDT>): Machine<mDT>;
2898
+ /** Register a pre-transition hook on any forced (`~>`) transition.
2899
+ * @param handler - Callback invoked before any forced transition.
2900
+ * @returns `this` for chaining.
2901
+ */
2902
+ hook_forced_transition(handler: HookHandler<mDT>): Machine<mDT>;
2903
+ /** Register a pre-transition hook on any transition regardless of kind.
2904
+ * @param handler - Callback invoked before every transition.
2905
+ * @returns `this` for chaining.
2906
+ */
2907
+ hook_any_transition(handler: HookHandler<mDT>): Machine<mDT>;
2908
+ /** Register a hook that fires when entering a specific state.
2909
+ * @param to - The state being entered.
2910
+ * @param handler - Callback invoked on entry.
2911
+ * @returns `this` for chaining.
2912
+ */
2913
+ hook_entry(to: string, handler: HookHandler<mDT>): Machine<mDT>;
2914
+ /** Register a hook that fires when leaving a specific state.
2915
+ * @param from - The state being exited.
2916
+ * @param handler - Callback invoked on exit.
2917
+ * @returns `this` for chaining.
2918
+ */
2919
+ hook_exit(from: string, handler: HookHandler<mDT>): Machine<mDT>;
2920
+ /** Register a hook that fires when a state's `after` timer elapses — the
2921
+ * delay-over companion to `a after 5s -> b;` style time transitions. It
2922
+ * does NOT fire when the state is entered or left by ordinary dispatch;
2923
+ * use {@link hook_entry} / {@link hook_exit} for those. (Versions through
2924
+ * 5.143.28 also spuriously fired it on entering the state, the jssm side
2925
+ * of StoneCypher/fsl#1327.)
2926
+ * @param from - The state whose `after` timer is being watched.
2927
+ * @param handler - Callback invoked when the timer fires, just before the
2928
+ * timed transition is taken; informational — its outcome
2929
+ * cannot reject the transition.
2930
+ * @returns `this` for chaining.
2931
+ *
2932
+ * @example
2933
+ * const m = sm`a after 1000 -> b; a -> c; c -> a;`;
2934
+ * let calls = 0;
2935
+ * m.hook_after('a', () => { calls += 1; });
2936
+ * m.go('c');
2937
+ * m.go('a');
2938
+ * // ordinary dispatch never fires it; only the timer elapsing does:
2939
+ * calls; // => 0
2940
+ * m.clear_state_timeout();
2941
+ *
2942
+ * @see hook_entry
2943
+ * @see hook_exit
2944
+ * @see set_state_timeout
2945
+ */
2946
+ hook_after(from: string, handler: HookHandler<mDT>): Machine<mDT>;
2947
+ /** Post-transition hook on a specific edge. Fires after the transition
2948
+ * from `from` to `to` has completed. Cannot block the transition.
2949
+ * @param from - Source state name.
2950
+ * @param to - Target state name.
2951
+ * @param handler - Callback invoked after the transition.
2952
+ * @returns `this` for chaining.
2953
+ */
2954
+ post_hook(from: string, to: string, handler: HookHandler<mDT>): Machine<mDT>;
2955
+ /** Post-transition hook on a specific action-labeled edge.
2956
+ * @param from - Source state name.
2957
+ * @param to - Target state name.
2958
+ * @param action - The action label.
2959
+ * @param handler - Callback invoked after the transition.
2960
+ * @returns `this` for chaining.
2961
+ */
2962
+ post_hook_action(from: string, to: string, action: string, handler: HookHandler<mDT>): Machine<mDT>;
2963
+ /** Post-transition hook on any edge triggered by a specific action.
2964
+ * @param action - The action name.
2965
+ * @param handler - Callback invoked after any transition with this action.
2966
+ * @returns `this` for chaining.
2967
+ */
2968
+ post_hook_global_action(action: string, handler: HookHandler<mDT>): Machine<mDT>;
2969
+ /** Post-transition hook on any action-driven transition.
2970
+ * @param handler - Callback invoked after any action transition.
2971
+ * @returns `this` for chaining.
2972
+ */
2973
+ post_hook_any_action(handler: HookHandler<mDT>): Machine<mDT>;
2974
+ /** Post-transition hook on any standard (`->`) transition.
2975
+ * @param handler - Callback invoked after any legal transition.
2976
+ * @returns `this` for chaining.
2977
+ */
2978
+ post_hook_standard_transition(handler: HookHandler<mDT>): Machine<mDT>;
2979
+ /** Post-transition hook on any main-path (`=>`) transition.
2980
+ * @param handler - Callback invoked after any main transition.
2981
+ * @returns `this` for chaining.
2982
+ */
2983
+ post_hook_main_transition(handler: HookHandler<mDT>): Machine<mDT>;
2984
+ /** Post-transition hook on any forced (`~>`) transition.
2985
+ * @param handler - Callback invoked after any forced transition.
2986
+ * @returns `this` for chaining.
2987
+ */
2988
+ post_hook_forced_transition(handler: HookHandler<mDT>): Machine<mDT>;
2989
+ /** Post-transition hook on any transition regardless of kind.
2990
+ * @param handler - Callback invoked after every transition.
2991
+ * @returns `this` for chaining.
2992
+ */
2993
+ post_hook_any_transition(handler: HookHandler<mDT>): Machine<mDT>;
2994
+ /** Post-transition hook that fires after entering a specific state.
2995
+ * @param to - The state that was entered.
2996
+ * @param handler - Callback invoked after entry.
2997
+ * @returns `this` for chaining.
2998
+ */
2999
+ post_hook_entry(to: string, handler: HookHandler<mDT>): Machine<mDT>;
3000
+ /** Post-transition hook that fires after leaving a specific state.
3001
+ * @param from - The state that was exited.
3002
+ * @param handler - Callback invoked after exit.
3003
+ * @returns `this` for chaining.
3004
+ */
3005
+ post_hook_exit(from: string, handler: HookHandler<mDT>): Machine<mDT>;
3006
+ /** Register a pre-transition hook that fires **before** all other pre-hooks
3007
+ * on every transition. If the handler returns `false`, the transition is
3008
+ * blocked. The handler receives an {@link EverythingHookContext} whose
3009
+ * `hook_name` is `'pre everything'`.
3010
+ *
3011
+ * ```typescript
3012
+ * const m = sm`a -> b -> c;`;
3013
+ * m.hook_pre_everything(({ hook_name }) => {
3014
+ * console.log(`${hook_name} fired`);
3015
+ * return true;
3016
+ * });
3017
+ * ```
3018
+ *
3019
+ * @param handler - Callback invoked before all other pre-hooks.
3020
+ * @returns `this` for chaining.
3021
+ */
3022
+ hook_pre_everything(handler: EverythingHookHandler<mDT>): Machine<mDT>;
3023
+ /** Register a pre-transition hook that fires **after** all other pre-hooks
3024
+ * on every transition. If the handler returns `false`, the transition is
3025
+ * blocked. The handler receives an {@link EverythingHookContext} whose
3026
+ * `hook_name` is `'everything'`.
3027
+ *
3028
+ * ```typescript
3029
+ * const m = sm`a -> b -> c;`;
3030
+ * m.hook_everything(({ hook_name }) => {
3031
+ * console.log(`${hook_name} fired`);
3032
+ * return true;
3033
+ * });
3034
+ * ```
3035
+ *
3036
+ * @param handler - Callback invoked after all other pre-hooks.
3037
+ * @returns `this` for chaining.
3038
+ */
3039
+ hook_everything(handler: EverythingHookHandler<mDT>): Machine<mDT>;
3040
+ /** Register a post-transition hook that fires **after** all other
3041
+ * post-hooks on every transition. Cannot block the transition. The
3042
+ * handler receives an {@link EverythingHookContext} whose `hook_name` is
3043
+ * `'post everything'`.
3044
+ *
3045
+ * ```typescript
3046
+ * const m = sm`a -> b -> c;`;
3047
+ * m.hook_post_everything(({ hook_name }) => {
3048
+ * console.log(`${hook_name} fired`);
3049
+ * });
3050
+ * ```
3051
+ *
3052
+ * @param handler - Callback invoked after all other post-hooks.
3053
+ * @returns `this` for chaining.
3054
+ */
3055
+ hook_post_everything(handler: PostEverythingHookHandler<mDT>): Machine<mDT>;
3056
+ /** Register a post-transition hook that fires **before** all other
3057
+ * post-hooks on every transition. Cannot block the transition. The
3058
+ * handler receives an {@link EverythingHookContext} whose `hook_name` is
3059
+ * `'pre post everything'`.
3060
+ *
3061
+ * ```typescript
3062
+ * const m = sm`a -> b -> c;`;
3063
+ * m.hook_pre_post_everything(({ hook_name }) => {
3064
+ * console.log(`${hook_name} fired`);
3065
+ * });
3066
+ * ```
3067
+ *
3068
+ * @param handler - Callback invoked before all other post-hooks.
3069
+ * @returns `this` for chaining.
3070
+ */
3071
+ hook_pre_post_everything(handler: PostEverythingHookHandler<mDT>): Machine<mDT>;
3072
+ /** Get the current RNG seed used for probabilistic transitions.
3073
+ * @returns The numeric seed value.
3074
+ */
3075
+ get rng_seed(): number;
3076
+ /** Set the RNG seed. Pass `undefined` to reseed from the current time.
3077
+ * Resets the internal PRNG so subsequent probabilistic operations use the
3078
+ * new seed.
3079
+ * @param to - The seed value, or `undefined` for time-based seeding.
3080
+ */
3081
+ set rng_seed(to: number | undefined);
3082
+ /** Get all edges between two states (there can be multiple with
3083
+ * different actions).
3084
+ * @param from - Source state name.
3085
+ * @param to - Target state name.
3086
+ * @returns An array of matching {@link JssmTransition} objects.
3087
+ */
3088
+ edges_between(from: string, to: string): JssmTransition<StateType, mDT>[];
3089
+ /*********
3090
+ *
3091
+ * Replace the current state and data with no regard to the graph.
3092
+ *
3093
+ * ```typescript
3094
+ * import { sm } from 'jssm';
3095
+ *
3096
+ * const machine = sm`a -> b -> c;`;
3097
+ * console.log( machine.state() ); // 'a'
3098
+ *
3099
+ * machine.go('b');
3100
+ * machine.go('c');
3101
+ * console.log( machine.state() ); // 'c'
3102
+ *
3103
+ * machine.override('a');
3104
+ * console.log( machine.state() ); // 'a'
3105
+ * ```
3106
+ *
3107
+ */
3108
+ override(newState: StateType, newData?: mDT | undefined): void;
3109
+ /*********
3110
+ *
3111
+ * Fire a `'rejection'` event caused by a hook vetoing a pending transition.
3112
+ * Extracted from the per-call closures inside {@link transition_impl} so
3113
+ * that it is allocated once at class-definition time rather than on every
3114
+ * hooked transition.
3115
+ *
3116
+ * @param hook_name Name of the hook that rejected (e.g. `'exit'`).
3117
+ * @param fromState State the machine was in when the transition was
3118
+ * attempted; used as the `from` field of the rejection event.
3119
+ * @param newState State that would have been entered had the hook
3120
+ * passed; used as the `to` field of the rejection event.
3121
+ * @param fromAction Action name when the transition was initiated by an
3122
+ * action call; `undefined` for plain state transitions.
3123
+ * @param oldData Machine data at the moment the transition was
3124
+ * attempted, before any hook mutations.
3125
+ * @param newData The `next_data` value passed to the transition call.
3126
+ * @param wasForced Whether the transition was attempted via
3127
+ * `force_transition`.
3128
+ *
3129
+ * @see transition_impl
3130
+ * @see _fire
3131
+ *
3132
+ * @internal
3133
+ *
3134
+ */
3135
+ _fire_hook_rejection(hook_name: string, fromState: StateType, newState: StateType, fromAction: StateType | undefined, oldData: mDT, newData: mDT | undefined, wasForced: boolean): void;
3136
+ /*********
3137
+ *
3138
+ * Fire the FSL boundary-hook actions for a single, already-committed state
3139
+ * change. In FSL, `do` is a synonym for `action`, so `on enter &g do 'X';`
3140
+ * means "when the machine crosses INTO group `g`, dispatch machine action
3141
+ * `X`" — and likewise `on exit` / plain-state subjects. This is the runtime
3142
+ * that fires those parked hooks.
3143
+ *
3144
+ * Crossing semantics (statechart convention — exits before enters):
3145
+ *
3146
+ * 1. `prev_groups` / `next_groups` are the deep (transitive) group sets of
3147
+ * the old and new states, from `_state_to_groups`.
3148
+ * 2. **Exits** fire first: every group in `prev_groups \ next_groups` with an
3149
+ * `onExit`, plus the plain `prev_state`'s `onExit` (when the state name
3150
+ * actually changed).
3151
+ * 3. **Enters** fire next: every group in `next_groups \ prev_groups` with an
3152
+ * `onEnter`, plus the plain `next_state`'s `onEnter` (when the state name
3153
+ * changed).
3154
+ * 4. A group present in BOTH sets is a transition *within* that group and
3155
+ * fires neither of its boundary hooks. `prev_state === next_state` fires
3156
+ * nothing at all.
3157
+ * 5. "Fire its action" is `this.action(label)`. If that action is not valid
3158
+ * from the current state, `action` is a safe no-op (returns `false`) — an
3159
+ * inapplicable boundary action never throws.
3160
+ * 6. Multi-membership and nesting both fan out naturally: a state in groups
3161
+ * A and B fires both; crossing an inner and an outer boundary fires both
3162
+ * levels.
3163
+ *
3164
+ * Because firing an action can drive a further transition (which crosses
3165
+ * more boundaries, which fires more actions), this is a bounded
3166
+ * run-to-completion: `_boundary_depth` tracks the live cascade depth and a
3167
+ * cascade deeper than `_boundary_depth_limit` throws a {@link JssmError}
3168
+ * rather than overflowing the stack or hanging. The limit defaults to 100
3169
+ * and is configurable via the `boundary_depth_limit` constructor option.
3170
+ *
3171
+ * @param prev_state The state the machine was in before this commit.
3172
+ * @param next_state The state the machine is in now (already committed).
3173
+ *
3174
+ * @throws {JssmError} If cascaded boundary firing exceeds `_boundary_depth_limit`
3175
+ * (a probable infinite loop).
3176
+ *
3177
+ * @see action
3178
+ * @see transition_impl
3179
+ *
3180
+ * @internal
3181
+ *
3182
+ */
3183
+ _fire_boundary_actions(prev_state: StateType, next_state: StateType): void;
3184
+ /*********
3185
+ *
3186
+ * Shared transition core used by {@link transition}, {@link force_transition},
3187
+ * and {@link action}. Runs validation, fires the full hook pipeline (pre-
3188
+ * everything, any-action, after, any-transition, exit, named, basic,
3189
+ * edge-type, entry, everything), commits the new state if nothing
3190
+ * rejected, and returns whether the transition succeeded.
3191
+ *
3192
+ * Not meant for external use. Call one of the public wrappers instead:
3193
+ * - `transition` for an ordinary legal transition
3194
+ * - `force_transition` to bypass the legality check
3195
+ * - `action` to dispatch by action name rather than target state
3196
+ *
3197
+ * @remarks
3198
+ * Known sharp edges, carried over from the original `// TODO` comments:
3199
+ * - The forced-ness behavior needs to be cleaned up a lot here.
3200
+ * - The callbacks are not fully correct across the forced / action / plain
3201
+ * cases and should be revisited.
3202
+ * - When multiple edges exist between two states with different `kind`
3203
+ * values, only the first edge's kind is used to pick the edge-type hook.
3204
+ *
3205
+ * @typeparam mDT The type of the machine data member; usually omitted.
3206
+ *
3207
+ * @param newStateOrAction The target state name (for a plain or forced
3208
+ * transition) or the action name (when `wasAction` is true).
3209
+ *
3210
+ * @param newData Optional replacement machine data to install alongside
3211
+ * the transition. Hooks may further override this via complex results.
3212
+ *
3213
+ * @param wasForced `true` if the caller invoked `force_transition`, in
3214
+ * which case legality is checked against `valid_force_transition` rather
3215
+ * than `valid_transition`.
3216
+ *
3217
+ * @param wasAction `true` if the caller invoked `action`, in which case
3218
+ * `newStateOrAction` is an action name and the target state is looked up
3219
+ * via the current action edge.
3220
+ *
3221
+ * @returns `true` if the transition was valid and every hook passed;
3222
+ * `false` if the transition was invalid or any hook rejected.
3223
+ *
3224
+ * @internal
3225
+ *
3226
+ */
3227
+ transition_impl(newStateOrAction: StateType, newData: mDT | undefined, wasForced: boolean, wasAction: boolean): boolean;
3228
+ /** If the current state has an `after` timeout configured, schedule it.
3229
+ * Called internally after each transition.
3230
+ */
3231
+ auto_set_state_timeout(): void;
3232
+ /*********
3233
+ *
3234
+ * Get a truncated history of the recent states and data of the machine.
3235
+ * Turned off by default; configure with `.from('...', {data: 5})` by length,
3236
+ * or set `.history_length` at runtime.
3237
+ *
3238
+ * History *does not contain the current state*. If you want that, call
3239
+ * `.history_inclusive` instead.
3240
+ *
3241
+ * ```typescript
3242
+ * const foo = jssm.from(
3243
+ * "a 'next' -> b 'next' -> c 'next' -> d 'next' -> e;",
3244
+ * { history: 3 }
3245
+ * );
3246
+ *
3247
+ * foo.action('next');
3248
+ * foo.action('next');
3249
+ * foo.action('next');
3250
+ * foo.action('next');
3251
+ *
3252
+ * foo.history; // [ ['b',undefined], ['c',undefined], ['d',undefined] ]
3253
+ * ```
3254
+ *
3255
+ * Notice that the machine's current state, `e`, is not in the returned list.
3256
+ *
3257
+ * @typeparam mDT The type of the machine data member; usually omitted
3258
+ *
3259
+ */
3260
+ get history(): [string, mDT][];
3261
+ /*********
3262
+ *
3263
+ * Get a truncated history of the recent states and data of the machine,
3264
+ * including the current state. Turned off by default; configure with
3265
+ * `.from('...', {data: 5})` by length, or set `.history_length` at runtime.
3266
+ *
3267
+ * History inclusive contains the current state. If you only want past
3268
+ * states, call `.history` instead.
3269
+ *
3270
+ * The list returned will be one longer than the history buffer kept, as the
3271
+ * history buffer kept gets the current state added to it to produce this
3272
+ * list.
3273
+ *
3274
+ * ```typescript
3275
+ * const foo = jssm.from(
3276
+ * "a 'next' -> b 'next' -> c 'next' -> d 'next' -> e;",
3277
+ * { history: 3 }
3278
+ * );
3279
+ *
3280
+ * foo.action('next');
3281
+ * foo.action('next');
3282
+ * foo.action('next');
3283
+ * foo.action('next');
3284
+ *
3285
+ * foo.history_inclusive; // [ ['b',undefined], ['c',undefined], ['d',undefined], ['e',undefined] ]
3286
+ * ```
3287
+ *
3288
+ * Notice that the machine's current state, `e`, is in the returned list.
3289
+ *
3290
+ * @typeparam mDT The type of the machine data member; usually omitted
3291
+ *
3292
+ */
3293
+ get history_inclusive(): [string, mDT][];
3294
+ /*********
3295
+ *
3296
+ * Find out how long a history this machine is keeping. Defaults to zero.
3297
+ * Settable directly.
3298
+ *
3299
+ * ```typescript
3300
+ * const foo = jssm.from("a -> b;");
3301
+ * foo.history_length; // 0
3302
+ *
3303
+ * const bar = jssm.from("a -> b;", { history: 3 });
3304
+ * foo.history_length; // 3
3305
+ * foo.history_length = 5;
3306
+ * foo.history_length; // 5
3307
+ * ```
3308
+ *
3309
+ * @typeparam mDT The type of the machine data member; usually omitted
3310
+ *
3311
+ */
3312
+ get history_length(): number;
3313
+ set history_length(to: number);
3314
+ /********
3315
+ *
3316
+ * Instruct the machine to complete an action. Synonym for {@link do}.
3317
+ *
3318
+ * ```typescript
3319
+ * const light = sm`red 'next' -> green 'next' -> yellow 'next' -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
3320
+ *
3321
+ * light.state(); // 'red'
3322
+ * light.action('next'); // true
3323
+ * light.state(); // 'green'
3324
+ * ```
3325
+ *
3326
+ * @typeparam mDT The type of the machine data member; usually omitted
3327
+ *
3328
+ * @param actionName The action to engage
3329
+ *
3330
+ * @param newData The data change to insert during the action
3331
+ *
3332
+ * @returns `true` if the action was valid and the transition occurred,
3333
+ * `false` otherwise.
3334
+ *
3335
+ */
3336
+ action(actionName: StateType, newData?: mDT): boolean;
3337
+ /********
3338
+ *
3339
+ * Get the standard style for a single state. ***Does not*** include
3340
+ * composition from an applied theme, or things from the underlying base
3341
+ * stylesheet; only the modifications applied by this machine.
3342
+ *
3343
+ * ```typescript
3344
+ * const light = sm`a -> b;`;
3345
+ * console.log(light.standard_state_style);
3346
+ * // {}
3347
+ *
3348
+ * const light = sm`a -> b; state: { shape: circle; };`;
3349
+ * console.log(light.standard_state_style);
3350
+ * // { shape: 'circle' }
3351
+ * ```
3352
+ *
3353
+ * @typeparam mDT The type of the machine data member; usually omitted
3354
+ *
3355
+ * @returns The {@link JssmStateConfig} for standard states.
3356
+ *
3357
+ */
3358
+ get standard_state_style(): JssmStateConfig;
3359
+ /********
3360
+ *
3361
+ * Get the hooked state style. ***Does not*** include
3362
+ * composition from an applied theme, or things from the underlying base
3363
+ * stylesheet; only the modifications applied by this machine.
3364
+ *
3365
+ * The hooked style is only applied to nodes which have a named hook in the
3366
+ * graph. Open hooks set through the external API aren't graphed, because
3367
+ * that would be literally every node.
3368
+ *
3369
+ * ```typescript
3370
+ * const light = sm`a -> b;`;
3371
+ * console.log(light.hooked_state_style);
3372
+ * // {}
3373
+ *
3374
+ * const light = sm`a -> b; hooked_state: { shape: circle; };`;
3375
+ * console.log(light.hooked_state_style);
3376
+ * // { shape: 'circle' }
3377
+ * ```
3378
+ *
3379
+ * @typeparam mDT The type of the machine data member; usually omitted
3380
+ *
3381
+ * @returns The {@link JssmStateConfig} for hooked states.
3382
+ *
3383
+ */
3384
+ get hooked_state_style(): JssmStateConfig;
3385
+ /********
3386
+ *
3387
+ * Get the start state style. ***Does not*** include composition from an
3388
+ * applied theme, or things from the underlying base stylesheet; only the
3389
+ * modifications applied by this machine.
3390
+ *
3391
+ * Start states are defined by the directive `start_states`, or in absentia,
3392
+ * are the first mentioned state.
3393
+ *
3394
+ * ```typescript
3395
+ * const light = sm`a -> b;`;
3396
+ * console.log(light.start_state_style);
3397
+ * // {}
3398
+ *
3399
+ * const light = sm`a -> b; start_state: { shape: circle; };`;
3400
+ * console.log(light.start_state_style);
3401
+ * // { shape: 'circle' }
3402
+ * ```
3403
+ *
3404
+ * @typeparam mDT The type of the machine data member; usually omitted
3405
+ *
3406
+ * @returns The {@link JssmStateConfig} for start states.
3407
+ *
3408
+ */
3409
+ get start_state_style(): JssmStateConfig;
3410
+ /********
3411
+ *
3412
+ * Get the end state style. ***Does not*** include
3413
+ * composition from an applied theme, or things from the underlying base
3414
+ * stylesheet; only the modifications applied by this machine.
3415
+ *
3416
+ * End states are defined in the directive `end_states`, and are distinct
3417
+ * from terminal states. End states are voluntary successful endpoints for a
3418
+ * process. Terminal states are states that cannot be exited. By example,
3419
+ * most error states are terminal states, but not end states. Also, since
3420
+ * some end states can be exited and are determined by hooks, such as
3421
+ * recursive or iterative nodes, there is such a thing as an end state that
3422
+ * is not a terminal state.
3423
+ *
3424
+ * ```typescript
3425
+ * const light = sm`a -> b;`;
3426
+ * console.log(light.standard_state_style);
3427
+ * // {}
3428
+ *
3429
+ * const light = sm`a -> b; end_state: { shape: circle; };`;
3430
+ * console.log(light.standard_state_style);
3431
+ * // { shape: 'circle' }
3432
+ * ```
3433
+ *
3434
+ * @typeparam mDT The type of the machine data member; usually omitted
3435
+ *
3436
+ * @returns The {@link JssmStateConfig} for end states.
3437
+ *
3438
+ */
3439
+ get end_state_style(): JssmStateConfig;
3440
+ /********
3441
+ *
3442
+ * Get the terminal state style. ***Does not*** include
3443
+ * composition from an applied theme, or things from the underlying base
3444
+ * stylesheet; only the modifications applied by this machine.
3445
+ *
3446
+ * Terminal state styles are automatically determined by the machine. Any
3447
+ * state without a valid exit transition is terminal.
3448
+ *
3449
+ * ```typescript
3450
+ * const light = sm`a -> b;`;
3451
+ * console.log(light.terminal_state_style);
3452
+ * // {}
3453
+ *
3454
+ * const light = sm`a -> b; terminal_state: { shape: circle; };`;
3455
+ * console.log(light.terminal_state_style);
3456
+ * // { shape: 'circle' }
3457
+ * ```
3458
+ *
3459
+ * @typeparam mDT The type of the machine data member; usually omitted
3460
+ *
3461
+ * @returns The {@link JssmStateConfig} for terminal states.
3462
+ *
3463
+ */
3464
+ get terminal_state_style(): JssmStateConfig;
3465
+ /********
3466
+ *
3467
+ * Get the style for the active state. ***Does not*** include
3468
+ * composition from an applied theme, or things from the underlying base
3469
+ * stylesheet; only the modifications applied by this machine.
3470
+ *
3471
+ * ```typescript
3472
+ * const light = sm`a -> b;`;
3473
+ * console.log(light.active_state_style);
3474
+ * // {}
3475
+ *
3476
+ * const light = sm`a -> b; active_state: { shape: circle; };`;
3477
+ * console.log(light.active_state_style);
3478
+ * // { shape: 'circle' }
3479
+ * ```
3480
+ *
3481
+ * @typeparam mDT The type of the machine data member; usually omitted
3482
+ *
3483
+ * @returns The {@link JssmStateConfig} for the active state.
3484
+ *
3485
+ */
3486
+ get active_state_style(): JssmStateConfig;
3487
+ /********
3488
+ *
3489
+ * Generate the uniform observational-hook registry — every currently
3490
+ * registered hook projected onto a normalized `(kind, target, phase)` row
3491
+ * (megaspec §12, → #1357). The registry is *generated* on demand by
3492
+ * walking the concrete per-kind storage tables rather than maintained as a
3493
+ * second copy, so it can never drift from the tables {@link Machine.set_hook}
3494
+ * actually dispatches into. It is the single source of truth behind the
3495
+ * introspection accessors ({@link Machine.has_hook}, {@link Machine.hooks_on})
3496
+ * and the `hooked_state` viz styling.
3497
+ *
3498
+ * Targets are normalized: edge hooks become `{ scope: 'edge', from, to }`
3499
+ * (named hooks add `action`), entry/exit/after become `{ scope: 'state' }`,
3500
+ * global-action hooks become `{ scope: 'action' }`, and the `any-*`,
3501
+ * transition-class, and `everything` observers become `{ scope: 'global' }`.
3502
+ *
3503
+ * ```typescript
3504
+ * const m = sm`a 'go' -> b;`;
3505
+ * m.hook_entry('b', () => true);
3506
+ * m.hook_registry();
3507
+ * // => [ { kind: 'entry', phase: 'pre', target: { scope: 'state', state: 'b' } } ]
3508
+ * ```
3509
+ *
3510
+ * @returns Every registered hook as a {@link HookRegistryEntry}, in a stable
3511
+ * table-walk order (pre-phase tables first, then post-phase).
3512
+ *
3513
+ */
3514
+ hook_registry(): HookRegistryEntry[];
3515
+ /********
3516
+ *
3517
+ * Does a single registry entry reference the state `state`? An entry
3518
+ * references a state when it is a `'state'`-scoped hook on that state, or an
3519
+ * `'edge'`-scoped hook whose `from` or `to` is that state. `'action'`- and
3520
+ * `'global'`-scoped entries reference no particular state. This is the
3521
+ * predicate behind both per-state introspection and the `hooked_state`
3522
+ * styling layer.
3523
+ *
3524
+ * @param entry The registry entry to test.
3525
+ * @param state The state name to test membership of.
3526
+ * @returns `true` when the entry observes that state.
3527
+ *
3528
+ */
3529
+ private static _entry_touches_state;
3530
+ /********
3531
+ *
3532
+ * Does a single registry entry match a `{ from, to, action? }` edge query?
3533
+ * Only `'edge'`-scoped entries can match. When the query omits `action`
3534
+ * the entry's action (if any) is ignored; when the query supplies `action`
3535
+ * it must match exactly.
3536
+ *
3537
+ * @param entry The registry entry to test.
3538
+ * @param from The edge origin to match.
3539
+ * @param to The edge destination to match.
3540
+ * @param action Optional named action to match exactly.
3541
+ * @returns `true` when the entry observes that edge.
3542
+ *
3543
+ */
3544
+ private static _entry_matches_edge;
3545
+ /********
3546
+ *
3547
+ * Does a single registry entry match an action name? Both `'action'`-scoped
3548
+ * hooks (global-action hooks) and named-edge hooks carrying that action
3549
+ * count as matches.
3550
+ *
3551
+ * @param entry The registry entry to test.
3552
+ * @param action The action name to match.
3553
+ * @returns `true` when the entry observes that action.
3554
+ *
3555
+ */
3556
+ private static _entry_matches_action;
3557
+ /********
3558
+ *
3559
+ * Does a single registry entry match a named state group? Only
3560
+ * `'group'`-scoped entries (FSL group-boundary hooks) match. Group hooks
3561
+ * are matched by group name only — they deliberately do not propagate to
3562
+ * member states, so a member-state query never returns them.
3563
+ *
3564
+ * @param entry The registry entry to test.
3565
+ * @param group The group name to match.
3566
+ * @returns `true` when the entry observes that group's boundary.
3567
+ *
3568
+ */
3569
+ private static _entry_matches_group;
3570
+ /********
3571
+ *
3572
+ * Return every registry entry observing the given target (megaspec §12).
3573
+ * The `query` selects the target shape:
3574
+ *
3575
+ * - a bare **state name** matches entry/exit/after hooks on that state, its
3576
+ * state-boundary hooks, and every edge hook touching it (`from` or `to`),
3577
+ * - a `{ from, to, action? }` **edge** matches edge hooks on that
3578
+ * transition (optionally narrowed to the named action),
3579
+ * - a `{ action }` **action** matches global-action and named-edge hooks
3580
+ * carrying that action,
3581
+ * - a `{ group }` **group** matches that group's boundary hooks (group hooks
3582
+ * are matched by name only and do not propagate to member states).
3583
+ *
3584
+ * ```typescript
3585
+ * const m = sm`a 'go' -> b;`;
3586
+ * m.hook_entry('b', () => true);
3587
+ * m.hooks_on('b').length; // 1
3588
+ * m.hooks_on({ from: 'a', to: 'b' }); // [] (no edge hook registered)
3589
+ * ```
3590
+ *
3591
+ * @param query The {@link HookQuery} naming the target to inspect.
3592
+ * @returns The matching {@link HookRegistryEntry} rows (possibly empty).
3593
+ *
3594
+ */
3595
+ hooks_on(query: HookQuery): HookRegistryEntry[];
3596
+ /********
3597
+ *
3598
+ * Is at least one observational hook bound to the given target (megaspec
3599
+ * §12)? The `query` is read exactly as in {@link Machine.hooks_on}. An
3600
+ * optional `phase` narrows the test to pre- or post-transition hooks only;
3601
+ * omitted, either phase satisfies it.
3602
+ *
3603
+ * ```typescript
3604
+ * const m = sm`a -> b;`;
3605
+ * m.has_hook('b'); // false
3606
+ * m.hook_entry('b', () => true);
3607
+ * m.has_hook('b'); // true
3608
+ * m.has_hook('b', 'post'); // false (the entry hook is pre-phase)
3609
+ * ```
3610
+ *
3611
+ * @param query The {@link HookQuery} naming the target to inspect.
3612
+ * @param phase Optional {@link HookPhase} to restrict the test to.
3613
+ * @returns `true` when a matching hook exists.
3614
+ *
3615
+ */
3616
+ has_hook(query: HookQuery, phase?: HookPhase): boolean;
3617
+ /********
3618
+ *
3619
+ * Does the given state carry any observational hook — i.e. should it receive
3620
+ * the `hooked_state` viz styling? True when an entry/exit/after hook is
3621
+ * bound to the state, any edge hook touches it, or the state has its own
3622
+ * boundary hook. Group-boundary hooks do *not* count here — they are
3623
+ * matched by group only and never propagate to member states. Powers the
3624
+ * `hooked` styling layer in {@link Machine.resolve_state_config}; replaces
3625
+ * the long-stubbed `has_hooks` placeholder (megaspec §12).
3626
+ *
3627
+ * ```typescript
3628
+ * const m = sm`a -> b;`;
3629
+ * m.state_has_hooks('a'); // false
3630
+ * m.hook_exit('a', () => true);
3631
+ * m.state_has_hooks('a'); // true
3632
+ * ```
3633
+ *
3634
+ * @param state The state to test.
3635
+ * @returns `true` when the state is observed by at least one hook.
3636
+ *
3637
+ */
3638
+ state_has_hooks(state: StateType): boolean;
3639
+ /********
3640
+ *
3641
+ * Returns the list of resolved theme implementations for this machine, in
3642
+ * the order they should layer (outer/base-most first). Each declared theme
3643
+ * name is mapped through {@link theme_mapping}; unknown names are skipped.
3644
+ *
3645
+ * The list is reversed relative to declaration order to match the historical
3646
+ * layering of {@link style_for}: a later-declared theme layers under an
3647
+ * earlier-declared one.
3648
+ *
3649
+ * @returns The resolved {@link JssmBaseTheme} stack, base-most first.
3650
+ *
3651
+ * @internal
3652
+ *
3653
+ */
3654
+ _resolved_themes(): JssmBaseTheme[];
3655
+ /********
3656
+ *
3657
+ * Reads the condensed per-state style fields (`color`, `shape`, …) out of a
3658
+ * state's declaration into a fresh {@link JssmStateConfig} — the tier-5
3659
+ * "`state foo : { … }`" contribution of the config cascade. A state with no
3660
+ * declaration yields an all-`undefined` config (which contributes nothing
3661
+ * once folded with {@link merge_state_config}).
3662
+ *
3663
+ * @param state The state whose per-state declared style is wanted.
3664
+ *
3665
+ * @returns The per-state style config (fields may be `undefined`).
3666
+ *
3667
+ * @internal
3668
+ *
3669
+ */
3670
+ _individual_state_config(state: StateType): JssmStateConfig;
3671
+ /********
3672
+ *
3673
+ * Orders the groups a state belongs to by nesting depth for the config
3674
+ * cascade — outermost first, innermost last — so that, folded in order,
3675
+ * the innermost (nearest / smallest {@link membership_distance}) group's
3676
+ * metadata wins. Equal-distance groups are ordered by group declaration
3677
+ * order, so a later-declared group of the same depth wins the tie.
3678
+ *
3679
+ * Concretely: groups are sorted by descending membership distance (largest
3680
+ * distance applied first / wins least), and for equal distances by
3681
+ * ascending declaration index (later index applied last / wins most).
3682
+ *
3683
+ * @param state The state whose containing groups are being ordered.
3684
+ *
3685
+ * @returns The containing group names, ordered for outer→inner folding
3686
+ * (the last entry wins).
3687
+ *
3688
+ * @internal
3689
+ *
3690
+ */
3691
+ _groups_by_depth(state: StateType): string[];
3692
+ /********
3693
+ *
3694
+ * Folds the static tiers 1–5 of the unified config cascade for a state, plus
3695
+ * — when `active` is set — the active-state THEME layers, which historically
3696
+ * sit just below the per-state config so that a `state foo : { … }` block
3697
+ * still overrides a theme's `active` styling. The user `active_state : { … }`
3698
+ * overlay (tier 6) is NOT applied here; it is layered on top by
3699
+ * {@link resolve_state_config} so it wins over per-state config.
3700
+ *
3701
+ * Tiers, folded least-specific → most-specific with {@link merge_state_config}
3702
+ * (later wins, never throwing on a cross-tier key collision):
3703
+ *
3704
+ * 1. theme defaults — `base_theme.state`, then each selected theme's
3705
+ * `.state` block.
3706
+ * 2. `default_state_config` (the implicit `state : { … }` root over every
3707
+ * state).
3708
+ * 3. static per-kind defaults selected by structural kind — terminal,
3709
+ * then start, then end — each contributing its `base_theme.<kind>`,
3710
+ * selected themes' `.<kind>`, and the machine's `default_<kind>_state_config`.
3711
+ * When `active`, the active-state theme layers (`base_theme.active` and
3712
+ * each selected theme's `.active`) are folded here too.
3713
+ * 4. group metadata, depth-ordered outer→inner (see {@link _groups_by_depth}),
3714
+ * each group's RAW `{ declarations }` already condensed at construction.
3715
+ * 5. the per-state `state foo : { … }` config.
3716
+ *
3717
+ * @param state The state to resolve config for.
3718
+ * @param active Whether to include the active-state theme layers (true only
3719
+ * for the machine's currently-occupied state).
3720
+ *
3721
+ * @returns The composited tiers-1–5 {@link JssmStateConfig} for the state.
3722
+ *
3723
+ * @internal
3724
+ *
3725
+ */
3726
+ _compose_state_config(state: StateType, active: boolean): JssmStateConfig;
3727
+ /********
3728
+ *
3729
+ * Resolves the full unified style/config cascade for a state — the runtime
3730
+ * successor to the ad-hoc layer merge {@link style_for} used to perform.
3731
+ *
3732
+ * For any state OTHER than the current one, this returns the memoized static
3733
+ * resolution (tiers 1–5; see {@link _compose_state_config}) — theme →
3734
+ * `default_state_config` → per-kind defaults → depth-ordered group metadata →
3735
+ * per-state config. The cache is keyed by state and never invalidated, since
3736
+ * those tiers do not depend on which state is current.
3737
+ *
3738
+ * For the machine's CURRENTLY-occupied state the result is recomputed each
3739
+ * call (never cached) and additionally carries the dynamic `active_state`
3740
+ * layers: the active-state THEME layers fold in just below the per-state
3741
+ * config (tier 3-active), and the user `active_state : { … }` overlay folds
3742
+ * in LAST (tier 6), on top of everything, so it wins over per-state config.
3743
+ * Every fold uses {@link merge_state_config}, so a key set at a lower tier is
3744
+ * overridden — never rejected — by a higher one.
3745
+ *
3746
+ * ```typescript
3747
+ * import { sm } from 'jssm';
3748
+ *
3749
+ * const m = sm`&busy : [working]; idle 'go' -> working; state &busy : { color: orange; };`;
3750
+ * m.resolve_state_config('working').color; // '#ffa500ff' — from group &busy
3751
+ * ```
3752
+ *
3753
+ * @typeparam mDT The type of the machine data member; usually omitted
3754
+ *
3755
+ * @param state The state to compute the composite config for.
3756
+ *
3757
+ * @returns The fully composited {@link JssmStateConfig} for the state,
3758
+ * including the active overlay when the state is current.
3759
+ *
3760
+ * @see style_for
3761
+ *
3762
+ */
3763
+ resolve_state_config(state: StateType): JssmStateConfig;
3764
+ /********
3765
+ *
3766
+ * Gets the composite style for a specific node — the public viz entry point,
3767
+ * now a thin wrapper over the unified config cascade in
3768
+ * {@link resolve_state_config}.
3769
+ *
3770
+ * The order of composition runs least-specific to most-specific: theme
3771
+ * defaults, then the `default_state_config` root, then per-kind defaults
3772
+ * (terminal, start, end), then depth-ordered group metadata (inner groups
3773
+ * winning over outer), then the per-state config, and finally — for the
3774
+ * current state only — the active overlay. Last wins at every tier.
3775
+ *
3776
+ * @typeparam mDT The type of the machine data member; usually omitted
3777
+ *
3778
+ * @param state The state to compute the composite style for.
3779
+ *
3780
+ * @returns The fully composited {@link JssmStateConfig} for the given state.
3781
+ *
3782
+ * @see resolve_state_config
3783
+ *
3784
+ */
3785
+ style_for(state: StateType): JssmStateConfig;
3786
+ /********
3787
+ *
3788
+ * Instruct the machine to complete an action. Synonym for {@link action}.
3789
+ *
3790
+ * ```typescript
3791
+ * const light = sm`
3792
+ * off 'start' -> red;
3793
+ * red 'next' -> green 'next' -> yellow 'next' -> red;
3794
+ * [red yellow green] 'shutdown' ~> off;
3795
+ * `;
3796
+ *
3797
+ * light.state(); // 'off'
3798
+ * light.do('start'); // true
3799
+ * light.state(); // 'red'
3800
+ * light.do('next'); // true
3801
+ * light.state(); // 'green'
3802
+ * light.do('next'); // true
3803
+ * light.state(); // 'yellow'
3804
+ * light.do('dance'); // !! false - no such action
3805
+ * light.state(); // 'yellow'
3806
+ * light.do('start'); // !! false - yellow does not have the action start
3807
+ * light.state(); // 'yellow'
3808
+ * ```
3809
+ *
3810
+ * @typeparam mDT The type of the machine data member; usually omitted
3811
+ *
3812
+ * @param actionName The action to engage
3813
+ *
3814
+ * @param newData The data change to insert during the action
3815
+ *
3816
+ * @returns `true` if the action was valid and the transition occurred,
3817
+ * `false` otherwise.
3818
+ *
3819
+ */
3820
+ do(actionName: StateType, newData?: mDT): boolean;
3821
+ /********
3822
+ *
3823
+ * Instruct the machine to complete a transition. Synonym for {@link go}.
3824
+ *
3825
+ * ```typescript
3826
+ * const light = sm`
3827
+ * off 'start' -> red;
3828
+ * red 'next' -> green 'next' -> yellow 'next' -> red;
3829
+ * [red yellow green] 'shutdown' ~> off;
3830
+ * `;
3831
+ *
3832
+ * light.state(); // 'off'
3833
+ * light.go('red'); // true
3834
+ * light.state(); // 'red'
3835
+ * light.go('green'); // true
3836
+ * light.state(); // 'green'
3837
+ * light.go('blue'); // !! false - no such state
3838
+ * light.state(); // 'green'
3839
+ * light.go('red'); // !! false - green may not go directly to red, only to yellow
3840
+ * light.state(); // 'green'
3841
+ * ```
3842
+ *
3843
+ * @typeparam mDT The type of the machine data member; usually omitted
3844
+ *
3845
+ * @param newState The state to switch to
3846
+ *
3847
+ * @param newData The data change to insert during the transition
3848
+ *
3849
+ * @returns `true` if the transition was legal and occurred, `false` otherwise.
3850
+ *
3851
+ */
3852
+ transition(newState: StateType, newData?: mDT): boolean;
3853
+ /********
3854
+ *
3855
+ * Instruct the machine to complete a transition. Synonym for {@link transition}.
3856
+ *
3857
+ * ```typescript
3858
+ * const light = sm`red -> green -> yellow -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
3859
+ *
3860
+ * light.state(); // 'red'
3861
+ * light.go('green'); // true
3862
+ * light.state(); // 'green'
3863
+ * ```
3864
+ *
3865
+ * @typeparam mDT The type of the machine data member; usually omitted
3866
+ *
3867
+ * @param newState The state to switch to
3868
+ *
3869
+ * @param newData The data change to insert during the transition
3870
+ *
3871
+ * @returns `true` if the transition was legal and occurred, `false` otherwise.
3872
+ *
3873
+ */
3874
+ go(newState: StateType, newData?: mDT): boolean;
3875
+ /********
3876
+ *
3877
+ * Instruct the machine to complete a forced transition (which will reject if
3878
+ * called with a normal {@link transition} call.)
3879
+ *
3880
+ * ```typescript
3881
+ * const light = sm`red -> green -> yellow -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
3882
+ *
3883
+ * light.state(); // 'red'
3884
+ * light.transition('off'); // false
3885
+ * light.state(); // 'red'
3886
+ * light.force_transition('off'); // true
3887
+ * light.state(); // 'off'
3888
+ * ```
3889
+ *
3890
+ * @typeparam mDT The type of the machine data member; usually omitted
3891
+ *
3892
+ * @param newState The state to switch to
3893
+ *
3894
+ * @param newData The data change to insert during the transition
3895
+ *
3896
+ * @returns `true` if a transition (forced or otherwise) existed and occurred,
3897
+ * `false` otherwise.
3898
+ *
3899
+ */
3900
+ force_transition(newState: StateType, newData?: mDT): boolean;
3901
+ /** Get the edge index for an action from the current state.
3902
+ * Interned dispatch: resolves via the numeric (action, from) index —
3903
+ * unknown action names miss without throwing.
3904
+ * @param action - The action name.
3905
+ * @returns The edge index, or `undefined` if the action is not available.
3906
+ */
3907
+ current_action_for(action: StateType): number;
3908
+ /** Get the full transition object for an action from the current state.
3909
+ * @param action - The action name.
3910
+ * @returns The {@link JssmTransition} object.
3911
+ * @throws {JssmError} If the action is not available from the current state.
3912
+ */
3913
+ current_action_edge_for(action: StateType): JssmTransition<StateType, mDT>;
3914
+ /** Check whether an action is available from the current state.
3915
+ * @param action - The action name to check.
3916
+ * @param _newData - Reserved for future data validation.
3917
+ * @returns `true` if the action can be taken.
3918
+ */
3919
+ valid_action(action: StateType, _newData?: mDT): boolean;
3920
+ /** Check whether a transition to a given state is legal (non-forced) from
3921
+ * the current state.
3922
+ * @param newState - The target state.
3923
+ * @param _newData - Reserved for future data validation.
3924
+ * @returns `true` if the transition is legal.
3925
+ */
3926
+ valid_transition(newState: StateType, _newData?: mDT): boolean;
3927
+ /** Check whether a forced transition to a given state exists from the
3928
+ * current state.
3929
+ * @param newState - The target state.
3930
+ * @param _newData - Reserved for future data validation.
3931
+ * @returns `true` if a forced (or any) transition exists.
3932
+ */
3933
+ valid_force_transition(newState: StateType, _newData?: mDT): boolean;
3934
+ /** Get the instance name of this machine, if one was assigned at creation.
3935
+ * @returns The instance name string, or `undefined`.
3936
+ */
3937
+ instance_name(): string | undefined;
3938
+ /** Get the creation date of this machine as a `Date` object.
3939
+ * @returns A `Date` representing when the machine was created.
3940
+ */
3941
+ get creation_date(): Date;
3942
+ /** Get the creation timestamp (milliseconds since epoch).
3943
+ * @returns The timestamp as a number.
3944
+ */
3945
+ get creation_timestamp(): number;
3946
+ /** Get the timestamp when construction began (before parsing).
3947
+ * @returns The start-of-construction timestamp as a number.
3948
+ */
3949
+ get create_start_time(): number;
3950
+ /** Schedule an automatic transition to `next_state` after `after_time`
3951
+ * milliseconds. Only one timeout may be active at a time.
3952
+ * @param next_state - The state to transition to when the timer fires.
3953
+ * @param after_time - Delay in milliseconds.
3954
+ * @throws {JssmError} If a timeout is already pending.
3955
+ */
3956
+ set_state_timeout(next_state: StateType, after_time: number): void;
3957
+ /** Cancel any pending state timeout. Safe to call when no timeout is active.
3958
+ */
3959
+ clear_state_timeout(): void;
3960
+ /** Get the configured `after` timeout for a given state, if any.
3961
+ * @param which_state - The state to look up.
3962
+ * @returns A `[targetState, delayMs]` tuple, or `undefined` if no timeout
3963
+ * is configured for that state.
3964
+ */
3965
+ state_timeout_for(which_state: StateType): [StateType, number] | undefined;
3966
+ /** Get the configured `after` timeout for the current state, if any.
3967
+ * @returns A `[targetState, delayMs]` tuple, or `undefined`.
3968
+ */
3969
+ current_state_timeout(): [StateType, number] | undefined;
3970
+ /** Convenience method to create a new machine from a tagged template literal.
3971
+ * Equivalent to calling the top-level `sm` function.
3972
+ * @param template_strings - The template string array.
3973
+ * @param remainder - Interpolated values.
3974
+ * @returns A new {@link Machine} instance.
3975
+ */
3976
+ sm(template_strings: TemplateStringsArray, ...remainder: any[]): Machine<mDT>;
3977
+ }
3978
+
3979
+ /**
3980
+ * Plan the frame sequence for an animated machine walk, as state names.
3981
+ *
3982
+ * With main-path edges (FSL `=>`, `main_path === true`): start at the
3983
+ * machine's current state — the start state for a freshly-constructed
3984
+ * machine, which is what the fence pipeline always passes — and follow
3985
+ * main-path edges in declaration order, stopping at the first revisited
3986
+ * state (the animation loops, so the cycle closes visually). Without any:
3987
+ * tour every edge in declaration order, emitting each edge's endpoints and
3988
+ * collapsing consecutive duplicates.
3989
+ *
3990
+ * This is presentation, not simulation — a tour's consecutive entries need
3991
+ * not be legal transitions, and no machine state is mutated.
3992
+ *
3993
+ * @example
3994
+ * plan_walk(sm`Red => Green => Yellow => Red;`); // ['Red', 'Green', 'Yellow']
3995
+ *
3996
+ * @see encode_gif
3997
+ */
3998
+ declare function plan_walk(machine: Machine<unknown>): string[];
3999
+
4000
+ /**
4001
+ * Two-layer static FSL highlighter: the SAME `fslLanguage` stream grammar and
4002
+ * `fslSemanticSpans` parser overlay the CodeMirror editor uses, merged into
4003
+ * flat runs and (optionally) serialized to HTML. There is no third
4004
+ * tokenizer — this is the parity guarantee between the editor and any
4005
+ * static render (markdown fences, the cookbook, docs).
4006
+ */
4007
+ /** One classified slice of highlighted FSL source. */
4008
+ interface HighlightRun {
4009
+ text: string;
4010
+ /** Space-separated classes: `fsl-tok-*` token layer, `fsl-sem-*` semantic layer. */
4011
+ classes: string;
4012
+ /** The state name, present exactly on semantic state-name runs. */
4013
+ state?: string;
4014
+ }
4015
+ /**
4016
+ * Tokenize FSL source through the SAME two layers the editor uses — the
4017
+ * `fslLanguage` stream grammar for token classes and `fslSemanticSpans` for
4018
+ * parser-derived roles — merged into flat runs whose concatenated text
4019
+ * reproduces the source byte-for-byte. Semantic classes overlay token
4020
+ * classes (both are kept).
4021
+ *
4022
+ * This is the parity guarantee: there is no third tokenizer, so static
4023
+ * output can never disagree with the editor.
4024
+ *
4025
+ * @param source FSL source text to classify.
4026
+ * @returns Flat, gap-free, order-preserving runs; `runs.map(r => r.text).join('')` is `source`.
4027
+ *
4028
+ * @example
4029
+ * highlight_fsl_runs('Red -> Green;').find(r => r.state === 'Red');
4030
+ * // { text: 'Red', classes: 'fsl-tok-variableName fsl-sem-state', state: 'Red' }
4031
+ */
4032
+ declare function highlight_fsl_runs(source: string): HighlightRun[];
4033
+ /**
4034
+ * Render FSL source as highlighted HTML (`<pre class="fsl-code">` inner
4035
+ * content) using {@link highlight_fsl_runs}. Semantic state-name spans get
4036
+ * `data-state`; when `inline_colors` (default true) and the state appears in
4037
+ * `state_colors`, an inline `style="color:…"` ties the code block's state
4038
+ * names to the diagram's node colors with zero host CSS.
4039
+ *
4040
+ * @param source FSL source text to render.
4041
+ * @param opts.state_colors Maps a state name to its diagram fill color (e.g. from `extract_state_fills`).
4042
+ * @param opts.inline_colors Whether to emit inline `style="color:…"` for matched states. Defaults to `true`.
4043
+ * @returns HTML markup for the highlighted source; unclassed runs are emitted as escaped text with no wrapping span.
4044
+ *
4045
+ * @example
4046
+ * highlight_fsl_html('Red -> Green;', { state_colors: new Map([['Red', '#a00']]) });
4047
+ * // '…<span class="… fsl-sem-state" data-state="Red" style="color:#a00">Red</span>…'
4048
+ */
4049
+ declare function highlight_fsl_html(source: string, opts?: {
4050
+ state_colors?: ReadonlyMap<string, string>;
4051
+ inline_colors?: boolean;
4052
+ }): string;
4053
+
4054
+ /**
4055
+ * Read each state's current fill color out of a graphviz-rendered machine
4056
+ * SVG, keyed by state name. States whose shape carries no `fill` attribute
4057
+ * are omitted.
4058
+ *
4059
+ * @param svg - SVG markup from the jssm viz pipeline (`fsl_to_svg_string`).
4060
+ *
4061
+ * @example
4062
+ * extract_state_fills(await fsl_to_svg_string('A -> B;')); // Map { 'A' => '#…', 'B' => '#…' }
4063
+ *
4064
+ * @see patch_state_fill
4065
+ */
4066
+ declare function extract_state_fills(svg: string): Map<string, string>;
4067
+ /**
4068
+ * Return a copy of the SVG with the named state's first shape fill replaced.
4069
+ * The unmatched-state case returns the input unchanged (walk truncation and
4070
+ * render races surface as a missing highlight, never a throw).
4071
+ *
4072
+ * @param svg - SVG markup from the jssm viz pipeline.
4073
+ * @param state - State name as written in FSL (unescaped).
4074
+ * @param fill - Any SVG paint value, e.g. `'#ff9930'`.
4075
+ *
4076
+ * @example
4077
+ * patch_state_fill(svg, 'Red', '#ff9930'); // Red's node now renders orange
4078
+ *
4079
+ * @see extract_state_fills
4080
+ */
4081
+ declare function patch_state_fill(svg: string, state: string, fill: string): string;
4082
+
4083
+ export { encode_gif, extract_state_fills, highlight_fsl_html, highlight_fsl_runs, lzw_encode, patch_state_fill, plan_walk, quantize, render_fence_gif, render_fence_html, transform_markdown };
4084
+ export type { FenceRenderOptions, GifFrame, GifOptions, GifRenderOptions, HighlightRun, Quantized };