jssm 5.162.9 → 5.162.11

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.
@@ -18,10 +18,10 @@ Please edit the file it's derived from, instead: `./src/md/readme_base.md`
18
18
 
19
19
 
20
20
 
21
- * Generated for version 5.162.9 at 7/12/2026, 3:21:43 AM
21
+ * Generated for version 5.162.11 at 7/12/2026, 8:54:54 AM
22
22
 
23
23
  -->
24
- # jssm 5.162.9
24
+ # jssm 5.162.11
25
25
 
26
26
  [**Try the live editor**](https://stonecypher.github.io/jssm-viz-demo/graph_explorer.html) ·
27
27
  [Documentation](https://stonecypher.github.io/jssm/docs/) ·
@@ -333,7 +333,7 @@ That decision shows up everywhere downstream:
333
333
  or run `npm run benny` against your own machine.
334
334
 
335
335
  - **More thoroughly tested than any other JavaScript state-machine
336
- library.** 8,151 tests at 100.0% line coverage
336
+ library.** 8,623 tests at 100.0% line coverage
337
337
  ([report](https://coveralls.io/github/StoneCypher/jssm)), plus
338
338
  fuzz testing via `fast-check`, with parser test data across ten natural
339
339
  languages and Emoji.
@@ -346,6 +346,7 @@ That decision shows up everywhere downstream:
346
346
 
347
347
  - [What are state machines?](https://github.com/StoneCypher/jssm/blob/main/src/doc_md/WhatAreStateMachines.md) - conceptual intro for newcomers
348
348
  - [Getting started](https://github.com/StoneCypher/jssm/blob/main/src/doc_md/GettingStarted.md) - install and use the library across Node, browser, Deno, ES5/ES6, CDN, and TypeScript
349
+ - [Using jssm in the browser](https://github.com/StoneCypher/jssm/blob/main/src/doc_md/Environments_Browser.md) - script tags, CDN, native ES modules, bundlers, and web components
349
350
  - [Tutorial: a four-state traffic light](https://github.com/StoneCypher/jssm/blob/main/src/doc_md/Tutorial_TrafficLight.md) - short walkthrough that introduces the three arrow types
350
351
  - [Tutorial: building an ATM state machine](https://github.com/StoneCypher/jssm/blob/main/src/doc_md/Tutorial_ATM.md) - longer walkthrough that builds a real-world machine in nine incremental steps
351
352
  - [Language reference](https://github.com/StoneCypher/jssm/blob/main/src/doc_md/LanguageReference.md) - DSL reference for people already comfortable with state machines
@@ -466,11 +467,11 @@ If your contribution is missing here, please open an issue.
466
467
 
467
468
  <br/>
468
469
 
469
- ***8,151 tests***, run 83,589 times.
470
+ ***8,623 tests***, run 97,921 times.
470
471
 
471
- - 7,389 specs with 100.0% coverage
472
- - 762 fuzz tests with 47.9% coverage
473
- - 10,882 TypeScript lines - 0.7 tests per line, 7.7 generated tests per line
472
+ - 7,721 specs with 100.0% coverage
473
+ - 902 fuzz tests with 56.6% coverage
474
+ - 10,907 TypeScript lines - 0.8 tests per line, 9.0 generated tests per line
474
475
 
475
476
  [![Actions Status](https://github.com/StoneCypher/jssm/workflows/Node%20CI/badge.svg)](https://github.com/StoneCypher/jssm/actions)
476
477
  [![NPM version](https://img.shields.io/npm/v/jssm.svg)](https://www.npmjs.com/package/jssm)
@@ -1,6 +1,6 @@
1
1
  type StateType = string;
2
2
  import { JssmGenericState, JssmGenericConfig, JssmStateConfig, JssmTransition, JssmTransitionList, // JssmTransitionRule,
3
- JssmMachineInternalState, JssmAllowsOverride, JssmAllowIslands, JssmEditorConfig, JssmStochasticOptions, JssmStochasticRun, JssmStochasticSummary, JssmDefaultSize, JssmStateDeclaration, JssmStateStyleKeyList, JssmTransitionConfig, JssmGraphConfig, JssmLayout, JssmHistory, JssmSerialization, FslDirection, FslTheme, HookDescription, HookHandler, HookContext, HookResult, HookComplexResult, EverythingHookContext, EverythingHookHandler, PostEverythingHookHandler, HookPhase, HookRegistryEntry, HookQuery, JssmEventName, JssmEventFilter, JssmEventHandler, JssmUnsubscribe, JssmGroupRegistry, JssmGroupHooks, JssmStateHooks, JssmRng } from './jssm_types.js';
3
+ JssmMachineInternalState, JssmAllowsOverride, JssmAllowIslands, JssmEditorConfig, JssmStochasticOptions, JssmStochasticRun, JssmStochasticSummary, JssmDefaultSize, JssmParsedSemver, JssmStateDeclaration, JssmStateStyleKeyList, JssmTransitionConfig, JssmGraphConfig, JssmLayout, JssmHistory, JssmSerialization, FslDirection, FslTheme, HookDescription, HookHandler, HookContext, HookResult, HookComplexResult, EverythingHookContext, EverythingHookHandler, PostEverythingHookHandler, HookPhase, HookRegistryEntry, HookQuery, JssmEventName, JssmEventFilter, JssmEventHandler, JssmUnsubscribe, JssmGroupRegistry, JssmGroupHooks, JssmStateHooks, JssmRng } from './jssm_types.js';
4
4
  import { Interner } from './jssm_intern.js';
5
5
  declare const shapes: string[], gviz_shapes: string[], named_colors: string[], state_name_chars: readonly {
6
6
  from: string;
@@ -58,10 +58,10 @@ declare class Machine<mDT> {
58
58
  _machine_language?: string;
59
59
  _machine_license?: string;
60
60
  _machine_name?: string;
61
- _machine_version?: string;
61
+ _machine_version?: JssmParsedSemver;
62
62
  _npm_name?: string;
63
63
  _default_size?: JssmDefaultSize;
64
- _fsl_version?: string;
64
+ _fsl_version?: JssmParsedSemver;
65
65
  _raw_state_declaration?: Array<object>;
66
66
  _state_declarations: Map<StateType, JssmStateDeclaration>;
67
67
  _data?: mDT;
@@ -684,10 +684,18 @@ declare class Machine<mDT> {
684
684
  */
685
685
  default_size(): JssmDefaultSize | undefined;
686
686
  /**
687
- * Get the machine's version string. Set via the FSL `machine_version` directive.
688
- * @returns The version string.
687
+ * Get the machine's declared version, parsed. Set via the FSL
688
+ * `machine_version` directive, which takes a semver triple; the parser
689
+ * breaks it into numeric `major`/`minor`/`patch` fields and keeps the
690
+ * exact source text in `full`. Returns `undefined` when the directive
691
+ * was not given.
692
+ * @returns The parsed {@link JssmParsedSemver}, or `undefined` if unset.
693
+ * @example
694
+ * const m = sm`machine_version: 1.2.3; a -> b;`;
695
+ * m.machine_version(); // => { major: 1, minor: 2, patch: 3, full: '1.2.3' }
696
+ * @see fsl_version
689
697
  */
690
- machine_version(): string;
698
+ machine_version(): JssmParsedSemver | undefined;
691
699
  /**
692
700
  * Get the raw state declaration objects as parsed from the FSL source.
693
701
  * @returns An array of raw state declaration objects.
@@ -705,10 +713,18 @@ declare class Machine<mDT> {
705
713
  */
706
714
  state_declarations(): Map<StateType, JssmStateDeclaration>;
707
715
  /**
708
- * Get the FSL language version this machine was compiled under.
709
- * @returns The FSL version string.
716
+ * Get the FSL language version this machine declares, parsed. Set via
717
+ * the FSL `fsl_version` directive, which takes a semver triple; the
718
+ * parser breaks it into numeric `major`/`minor`/`patch` fields and keeps
719
+ * the exact source text in `full`. Returns `undefined` when the
720
+ * directive was not given.
721
+ * @returns The parsed {@link JssmParsedSemver}, or `undefined` if unset.
722
+ * @example
723
+ * const m = sm`fsl_version: 1.0.0; a -> b;`;
724
+ * m.fsl_version(); // => { major: 1, minor: 0, patch: 0, full: '1.0.0' }
725
+ * @see machine_version
710
726
  */
711
- fsl_version(): string;
727
+ fsl_version(): JssmParsedSemver | undefined;
712
728
  /**
713
729
  * Get the complete internal state of the machine as a serializable
714
730
  * structure. Includes actions, edges, edge map, named transitions,
@@ -911,7 +927,19 @@ declare class Machine<mDT> {
911
927
  get themes(): FslTheme | FslTheme[];
912
928
  /**
913
929
  * Set the active theme(s). Accepts a single theme name or an array.
930
+ * Also drops every memoized static state config, so styles resolved
931
+ * before the change re-resolve under the new theme stack.
932
+ *
933
+ * ```typescript
934
+ * const m = sm`a -> b;`;
935
+ * m.style_for('b'); // resolved under the default theme
936
+ * m.themes = 'ocean';
937
+ * m.style_for('b').backgroundColor; // 'cadetblue1' — ocean, not a stale default
938
+ * ```
939
+ *
914
940
  * @param to - A theme name or array of theme names to apply.
941
+ *
942
+ * @see resolve_state_config
915
943
  */
916
944
  set themes(to: FslTheme | FslTheme[]);
917
945
  /**
@@ -1021,10 +1049,34 @@ declare class Machine<mDT> {
1021
1049
  * @throws {JssmError} If the state does not exist.
1022
1050
  */
1023
1051
  probable_exits_for(whichState: StateType): Array<JssmTransition<StateType, mDT>>;
1052
+ /**
1053
+ * Guard for the random-selection paths ({@link Machine.probabilistic_transition},
1054
+ * {@link Machine.stochastic_runs}): rejects a candidate pool whose total
1055
+ * selectable weight is zero, because weighted selection over an all-zero
1056
+ * pool has no meaningful answer (StoneCypher/fsl#1248). Undeclared
1057
+ * probabilities count as weight 1, matching {@link weighted_rand_select}.
1058
+ * An empty pool is not this guard's concern (terminality is handled by the
1059
+ * callers) and passes through untouched.
1060
+ *
1061
+ * ```typescript
1062
+ * const m = sm`a 0% -> b; a 0% -> c;`;
1063
+ * m.probabilistic_transition(); // throws JssmError — every exit is 0%
1064
+ * ```
1065
+ * @param whichState - The state the pool exits from, named in the error.
1066
+ * @param exits - The candidate pool, as built by {@link Machine.probable_exits_for}.
1067
+ * @throws {JssmError} If the pool is non-empty and every candidate edge
1068
+ * has probability 0 — including the case where explicit `0%` edges
1069
+ * excluded their unweighted sibling edges from the candidate pool.
1070
+ * @see probable_exits_for
1071
+ */
1072
+ private _assert_selectable_exit_pool;
1024
1073
  /**
1025
1074
  * Take a single random transition from the current state, weighted by
1026
1075
  * edge probabilities.
1027
1076
  * @returns `true` if a transition was taken, `false` otherwise.
1077
+ * @throws {JssmError} If the candidate exit pool is non-empty but its
1078
+ * total weight is zero — every candidate declares `0%` — per
1079
+ * StoneCypher/fsl#1248.
1028
1080
  */
1029
1081
  probabilistic_transition(): boolean;
1030
1082
  /**
@@ -1032,6 +1084,8 @@ declare class Machine<mDT> {
1032
1084
  * of states visited (before each transition).
1033
1085
  * @param n - Number of steps to walk.
1034
1086
  * @returns An array of state names visited during the walk.
1087
+ * @throws {JssmError} If a visited state's candidate exit pool is
1088
+ * non-empty but all-zero-weight (StoneCypher/fsl#1248).
1035
1089
  */
1036
1090
  probabilistic_walk(n: number): Array<StateType>;
1037
1091
  /**
@@ -1039,6 +1093,8 @@ declare class Machine<mDT> {
1039
1093
  * each state was visited.
1040
1094
  * @param n - Number of steps to walk.
1041
1095
  * @returns A `Map` from state name to visit count.
1096
+ * @throws {JssmError} If a visited state's candidate exit pool is
1097
+ * non-empty but all-zero-weight (StoneCypher/fsl#1248).
1042
1098
  */
1043
1099
  probabilistic_histo_walk(n: number): Map<StateType, number>;
1044
1100
  /**
@@ -1058,6 +1114,9 @@ declare class Machine<mDT> {
1058
1114
  * the derived arrays — RNG draw order is untouched, so seeded walks
1059
1115
  * reproduce exactly.
1060
1116
  * @returns The {@link JssmStochasticRun} for this walk.
1117
+ * @throws {JssmError} If a visited state's candidate exit pool is
1118
+ * non-empty but all-zero-weight — see
1119
+ * {@link Machine._assert_selectable_exit_pool} (StoneCypher/fsl#1248).
1061
1120
  */
1062
1121
  private _stochastic_one_walk;
1063
1122
  /**
@@ -2224,8 +2283,12 @@ declare class Machine<mDT> {
2224
2283
  * For any state OTHER than the current one, this returns the memoized static
2225
2284
  * resolution (tiers 1–5; see `_compose_state_config`) — theme →
2226
2285
  * `default_state_config` → per-kind defaults → depth-ordered group metadata →
2227
- * per-state config. The cache is keyed by state and never invalidated, since
2228
- * those tiers do not depend on which state is current.
2286
+ * per-state config. The cache is keyed by state; those tiers do not depend
2287
+ * on which state is current, so it survives transitions, but the mutable
2288
+ * cascade inputs each clear it when they change — hook registration and
2289
+ * removal ({@link Machine.set_hook}, {@link Machine.remove_hook}; the
2290
+ * hooked layer) and theme assignment (the `themes` setter; tier 1 and the
2291
+ * per-kind theme layers).
2229
2292
  *
2230
2293
  * For the machine's CURRENTLY-occupied state the result is recomputed each
2231
2294
  * call (never cached) and additionally carries the dynamic `active_state`