@turing-machine-js/machine 4.0.0 → 5.0.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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,36 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [5.0.0] - 2026-05-09
8
+
9
+ ### Changed (BREAKING)
10
+
11
+ - **Hook renamed: `onDebugBreak` → `onPause`** on `run()` ([#110](https://github.com/mellonis/turing-machine-js/issues/110)). Hard rename, no deprecation alias. The hook signature, payload shape, and dispatch semantics are unchanged — only the option key on `run()` differs. Resolution of the [#109 RFC](https://github.com/mellonis/turing-machine-js/issues/109): the hook now describes the consumer's relationship (this is where you can pause) rather than the engine's event (a debug break fired). The `m.debugBreak` payload field is unchanged.
12
+ - **`haltState.debug.after` now throws on assignment** ([#108](https://github.com/mellonis/turing-machine-js/issues/108) part 2). Halt is terminal — there is no iteration-after-halt for an after-fire to anchor on. Symmetric `{ before: true, after: true }` writes also throw; use `{ before: true }`. Symbol-list filters on `haltState.debug.before` remain silent no-ops as in v4.
13
+
14
+ ### Fixed
15
+
16
+ - **Halting iter's `state.debug.after` now fires** ([#108](https://github.com/mellonis/turing-machine-js/issues/108) part 1). Previously `pendingAfterFromPrev` set after the halting iter's yield was discarded when the `while (!state.isHalt)` loop exited — losing that after-fire. `run()` now drains a final after-fire after the loop when the prior yield armed one. Observable: a debugger UI sees a "we just halted because of state X's after-filter" event that was silent before.
17
+
18
+ ### Added
19
+
20
+ - **`run({ debug: boolean })` flag** ([#106](https://github.com/mellonis/turing-machine-js/issues/106)). Master switch for `onPause` dispatch. When `false`, suppresses all pause-fires (before, after, and the post-loop after-drain) regardless of `state.debug` assignments. `onStep` is unaffected. Defaults to `true`. The `m.debugBreak` field is still populated on yields by the underlying generator (it's a property of the iteration); only `run()`'s hook dispatch is gated. Useful for toggling "debug mode" without editing `state.debug = ...` across the state graph.
21
+
22
+ ### Migration
23
+
24
+ ```diff
25
+ await machine.run({
26
+ initialState,
27
+ - onDebugBreak: (m) => { ... },
28
+ + onPause: (m) => { ... },
29
+ });
30
+ ```
31
+
32
+ ```diff
33
+ - haltState.debug = { before: true, after: true }; // throws in v5
34
+ + haltState.debug = { before: true };
35
+ ```
36
+
7
37
  ## [4.0.0] - 2026-05-07
8
38
 
9
39
  ### Added
package/README.md CHANGED
@@ -256,13 +256,13 @@ myState.debug = null;
256
256
 
257
257
  The `debug` field is mutable — toggle breakpoints at runtime without rebuilding the graph. The internal cell is shared with `state.withOverrodeHaltState(...)` wrappers, so an assignment on the original is visible from every wrapper.
258
258
 
259
- `run()` is async and accepts an `onDebugBreak` hook:
259
+ `run()` is async and accepts an `onPause` hook:
260
260
 
261
261
  ```ts
262
262
  await machine.run({
263
263
  initialState,
264
264
  onStep: (m) => { /* logger sees every step */ },
265
- onDebugBreak: async (m) => {
265
+ onPause: async (m) => {
266
266
  // Awaited at every break — hold execution until you resolve.
267
267
  if (m.debugBreak?.before) console.log('before:', m.state.name);
268
268
  if (m.debugBreak?.after) console.log('after:', m.state.name);
@@ -272,7 +272,7 @@ await machine.run({
272
272
 
273
273
  For `after` calls, `m` is the previous yield's snapshot — `m.state` is the state whose `after` filter fired. For `before` calls, `m` is the current iteration. `onStep` always sees the original (un-substituted) yield.
274
274
 
275
- If `onDebugBreak` is not provided, breaks fire-and-resume invisibly — the trajectory is identical to running without `debug` set.
275
+ If `onPause` is not provided, breaks fire-and-resume invisibly — the trajectory is identical to running without `debug` set.
276
276
 
277
277
  **Filter semantics:** `true` is a wildcard (match any symbol). `[ifOtherSymbol]` is NOT a wildcard — it matches only the catch-all resolution case (same meaning as in transition keys).
278
278
 
@@ -31,10 +31,24 @@ export default class TuringMachine {
31
31
  tapeBlock?: TapeBlock;
32
32
  });
33
33
  get tapeBlock(): TapeBlock;
34
- run({ initialState, stepsLimit, onStep, onDebugBreak, }: RunParameter & {
34
+ run({ initialState, stepsLimit, onStep, onPause, }: RunParameter & {
35
+ /**
36
+ * Sync, ~free hook fired on every iteration. Use for logging/tracing —
37
+ * the hot loop runs this without a microtask boundary, so it must not
38
+ * be async.
39
+ */
35
40
  onStep?: (machineState: MachineState) => void;
36
- onDebugBreak?: (machineState: MachineState) => void | Promise<void>;
41
+ /**
42
+ * Async hook fired only when `state.debug[when]` matches at the current
43
+ * iteration. The promise is awaited inline, so the consumer can suspend
44
+ * execution by deferring its resolution. Use for pause-capable inspection
45
+ * (debugger UIs, conditional breakpoints in tests).
46
+ *
47
+ * Renamed from `onDebugBreak` in v5.0.0. The `m.debugBreak` payload field
48
+ * keeps its name (it describes the engine's reason for pausing).
49
+ */
50
+ onPause?: (machineState: MachineState) => void | Promise<void>;
37
51
  }): Promise<void>;
38
- runStepByStep({ initialState, stepsLimit }: RunParameter): Generator<MachineState>;
52
+ runStepByStep({ initialState, stepsLimit }: RunParameter): Generator<MachineState, MachineState | null>;
39
53
  }
40
54
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@turing-machine-js/machine",
3
- "version": "4.0.0",
3
+ "version": "5.0.0",
4
4
  "description": "A convenient Turing machine",
5
5
  "engines": {
6
6
  "npm": ">=7.0.0"
@@ -34,5 +34,5 @@
34
34
  "default": "./dist/index.mjs"
35
35
  }
36
36
  },
37
- "gitHead": "6641f9e8fd9073771ffd1768a7a5931ff93349a6"
37
+ "gitHead": "ccf9a4743965c2a4ea6340ce1de8f6596e094251"
38
38
  }