Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ This is an npm-workspaces + Lerna monorepo (`packages/*`). Versioning is **locks
- **`@turing-machine-js/builder`** — declarative state-table → machine builder; depends on `machine`. Soft-deprecated; see its README.
- **`@turing-machine-js/library-binary-numbers`** — prebuilt states for `^…$`-delimited binary arithmetic on a 5-symbol alphabet; depends on `machine`.
- **`@turing-machine-js/library-binary-numbers-bare`** — same operations on a 3-symbol alphabet (no markers, single number per tape, much smaller state graphs); depends on `machine`. Side-by-side with the marker-based library to make the alphabet-vs-graph-size trade-off visible.
- **`@turing-machine-js/visuals`** (v7-only, [#204](https://github.com/mellonis/turing-machine-js/issues/204)) — pure highlight + graph-indexing logic for the engine `Graph`. Peer dep on `machine`, no runtime deps. Exposes `applyHighlight` / `applyIndicator` / `indexGraph` / `bareIdOf` / `highlightExpand` / `equivalentIds` / `recordingOps` (renderer-agnostic ops contract via `HighlightOps` / `IndicatorOps`), plus the `recordSnippet` artifact recorder (`Snippet` / `Frame` / `StepCommand` / `TapeSnapshot`) and the engine-edge-label formatter primitives (`formatStepNotation` / `tokenizeStep` / `formatTape`, the latter shipped in alpha.6.1). 16-rule contract for `applyHighlight` lives at `packages/visuals/docs/graph-highlight-and-breakpoints.md` (moved there from machines-demo). Used by machines-demo for graph highlight + step-log rendering; designed to be reusable by article embeds and any future Graph consumer that wants byte-identical edge-label notation to `toMermaid`. **Engine + libraries are at `7.0.0-alpha.6`; visuals at `7.0.0-alpha.6.1`** (visuals-only patch added formatter primitives + tokens).
- **`@turing-machine-js/visuals`** (v7-only, [#204](https://github.com/mellonis/turing-machine-js/issues/204)) — pure highlight + graph-indexing logic for the engine `Graph`. Peer dep on `machine`, no runtime deps. Exposes `applyHighlight` / `applyIndicator` / `indexGraph` / `bareIdOf` / `highlightExpand` / `equivalentIds` / `recordingOps` (renderer-agnostic ops contract via `HighlightOps` / `IndicatorOps`), the `recordSnippet` artifact recorder + `SnippetPlayer` class (`Snippet` / `Frame` / `StepCommand`), and the engine-edge-label formatter primitives (`formatStepNotation` / `tokenizeStep` / `formatTape`, shipped in alpha.6.1). **`TapeSnapshot` + `tapeViewport` are re-exported from `@turing-machine-js/machine`** ([#227](https://github.com/mellonis/turing-machine-js/issues/227), v7.0.0-alpha.8 onward) — they live next to the `Tape` class in the engine; visuals re-exports for consumer-import stability. 16-rule contract for `applyHighlight` lives at `packages/visuals/docs/graph-highlight-and-breakpoints.md` (moved there from machines-demo). Used by machines-demo for graph highlight + step-log rendering; designed to be reusable by article embeds and any future Graph consumer that wants byte-identical edge-label notation to `toMermaid`. **Engine + libraries are at `7.0.0-alpha.8`; visuals at `7.0.0-alpha.8`** (re-aligned to lockstep after alpha.7.1 visuals-only patch).

### Versioning convention

Expand Down
22 changes: 21 additions & 1 deletion packages/machine/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,18 @@ tape.viewportWidth; // 7 (the constructor bumps even values to the next odd)

`viewportWidth` defaults to `1` and must be ≥ 1; `tape.viewport` always has exactly `viewportWidth` cells regardless of how many symbols the tape actually holds. Useful for rendering a sliding window in a UI; ignore if you only need `tape.symbols` / `tape.position`.

For wire-data tape transmission (worker boundaries, snippet recording, snapshot tests), the package exports the **`TapeSnapshot`** type (`{ symbols: string[]; position: number }`) and a pure-function equivalent of `Tape.viewport`:

```javascript
import { tapeViewport } from '@turing-machine-js/machine';

const snapshot = { symbols: ['a', 'b', 'c'], position: 1 };
const { cells, headIndex } = tapeViewport(snapshot, 7, ' ');
// cells: [' ',' ','a','b','c',' ',' '], headIndex: 3
```

`tapeViewport(snapshot, width, blank)` returns `{ cells, headIndex }` with `cells.length === width` (out-of-bounds positions padded with `blank`) and `headIndex === Math.floor(width / 2)`. Throws `RangeError` on non-positive or non-integer width. `Tape.viewport` and `tapeViewport` share an internal centering core, so the two routes produce identical results when given equivalent inputs. (`TapeSnapshot` + `tapeViewport` are also re-exported from `@turing-machine-js/visuals` for backwards-compatible imports from earlier alphas; canonical home is `@turing-machine-js/machine` as of v7.0.0-alpha.8, [#227](https://github.com/mellonis/turing-machine-js/issues/227).)

### TapeBlock

A bundle of one or more `Tape`s that the machine reads/writes together in lock-step. Construct via either factory:
Expand Down Expand Up @@ -840,7 +852,15 @@ API surface changes since v3, in past tense so the timing of each piece is expli
- **v6.2** *(superseded by v6.3.0)* — widened `onStep`'s signature to `(m) => void | Promise<void>` and added an inline `await onStep(...)` in the run loop, enabling throttle-in-`onStep` patterns. This overturned the docstring-stated contract that `onStep` is sync (microtask-free); the right place for per-iter throttling is `onPause` with self-rearm (see [Throttle pattern](#throttle-pattern)). Restored in v6.3.0.
- **v6.3** — `onStep` reverted to its v6.0–v6.1 sync contract — `(m) => void`, called synchronously inside the run loop. The Throttle pattern section documents the engine-native shape for per-iter throttle / "wait between iters" UIs. No other API changes.
- **v6.4** — New **`onIter`** hook on `run()`: awaited, fires once at the end of every iter (after both `onPause` dispatches on the same yield), unaffected by the `debug` master switch. Use for per-iter throttle / animation / coordination needing a suspend point; complements the existing sync `onStep` (tracing) and conditional `onPause` (user breakpoints). Three-hook contract is now `onStep` (sync, mid-iter) / `onPause` (awaited, on `state.debug` match) / `onIter` (awaited, end-of-iter). Additive — peer-deps unchanged. The v6.3.0 README's `onPause`-rearm throttle workaround is superseded.
- **v7** *(latest alpha: alpha.4, 2026-05-23)* — Composition-representation overhaul + first-class state tags + id-keyed `State.collectStates` lookup. **Pre-release on the `next` dist-tag:** `npm install @turing-machine-js/machine@next` (or pin `@7.0.0-alpha.4`). Stable v7.0.0 still pending [#102](https://github.com/mellonis/turing-machine-js/issues/102) (debugger step-in/over/out primitives). Highlights across alphas:
- **v7** *(latest alpha: alpha.8, 2026-06-02)* — Composition-representation overhaul + first-class state tags + id-keyed `State.collectStates` lookup + `DebugSession` step controls + `CallFrame` + `tapeViewport`/`TapeSnapshot`. **Pre-release on the `next` dist-tag:** `npm install @turing-machine-js/machine@next` (or pin `@7.0.0-alpha.8`). **v7 milestone is feature-complete with #102**; the stable v7.0.0 cut is the only remaining step. Highlights across alphas:

**alpha.8** — **`TapeSnapshot` type + `tapeViewport` helper** ([#227](https://github.com/mellonis/turing-machine-js/issues/227)) moved into the engine from `@turing-machine-js/visuals`, next to the live `Tape` class (visuals re-exports for consumer-import stability). `Tape.viewport` getter refactored to share its centering loop with `tapeViewport` via an internal core — the centering math now lives once; the two public surfaces supply their own data-shape-appropriate `cellAt` lambdas. See [§Tape](#tape).

**alpha.7** — **`CallFrame` extraction** ([#213](https://github.com/mellonis/turing-machine-js/issues/213)) — `withOverriddenHaltState`'s wrapper is now a first-class `CallFrame extends State` subclass that delegates transition lookups + `debug` to its bare; `instanceof State` preserved (additive), `instanceof CallFrame` discriminates wrappers. Plus **`toMermaid` framed-wrapper emit fix** ([#223](https://github.com/mellonis/turing-machine-js/issues/223)) — `toGraph`'s reach-set now tunnels through wrappers AND captures the wrappers themselves, so framed-wrapper-continuations (e.g. `library-binary-numbers/minusOne`'s `goToNumberStart(invertNumberGoToNumberWithInversion)` inside `invertNumber`'s callable subtree) render inside the owner subgraph rather than escaping to the top level. `library-binary-numbers/states.md` regenerated under the new emit.

**alpha.6** — **Debugger step controls** ([#102](https://github.com/mellonis/turing-machine-js/issues/102)) — full reshape of the debug surface. `run()` is now **sync + callback-free**; `runStepByStep` is the **pure-iteration primitive** (no `state.debug` filter evaluation); a new **`DebugSession`** class (`new DebugSession(machine, {initialState})`) owns all interactive debugging via `pause` / `step` / `iter` / `halt` events, depth-based `stepIn` / `stepOver` / `stepOut`, external `pause()` / `stop()` / `setRunInterval(ms)`. Per-yield `m.debugBreak: {before?, after?, cause}` **replaced by one-sided `m.pause: {side, cause}`** on `pause` events only. See [§Debugging](#debugging).

**alpha.5** — Per-iter **`matchedTransition`** ([#205](https://github.com/mellonis/turing-machine-js/issues/205)) on every `MachineState` yield (`{id, matchKinds}`, `id` is `${stateId}.${ix}` resolvable in `toGraph`). **`haltState.debug` collapsed to a `boolean`** ([#207](https://github.com/mellonis/turing-machine-js/issues/207)) — object-shaped writes throw; halt pause fires on the AFTER side of the halt-triggering iter with `m.state` = the triggering state. `HaltState` typed alias narrows `debug` to `boolean` at the canonical access path.

**alpha.4** — **`State.collectStates(initial, tapeBlock)`** ([#195](https://github.com/mellonis/turing-machine-js/issues/195)) returns a `Map<number, {state, transitionSymbols}>` keyed by `GraphNode.id` so downstream tooling can mutate `state.debug` by numeric id and set per-pattern breakpoints by `GraphTransition.id`. Graph serialization extracted to `utilities/stateGraph.ts` with a Symbol-keyed `@internal` accessor on `State` ([#180](https://github.com/mellonis/turing-machine-js/issues/180); no public-API change — the `State.toGraph` / `.fromGraph` statics remain as thin delegates). Two upstream fixes: `toMermaid` HTML-entity-escapes user content in labels so alphabets containing `"`, `<`, etc. parse correctly ([#194](https://github.com/mellonis/turing-machine-js/issues/194)); `runStepByStep`'s halt stack is now run-scoped, fixing a memory leak / ghost-iteration when the same `TuringMachine` instance is reused across calls ([#196](https://github.com/mellonis/turing-machine-js/issues/196)). See [§Setting breakpoints by graph id](#setting-breakpoints-by-graph-id).

Expand Down
2 changes: 1 addition & 1 deletion packages/visuals/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ type GraphHighlight = {
type GraphIndexes = { /* node→frame, frame→wrappers, frame→label, etc. */ };

// Recording artifact
type TapeSnapshot = { symbols: string[]; position: number };
type TapeSnapshot = { symbols: string[]; position: number }; // re-exported from @turing-machine-js/machine (alpha.8+); canonical home is the engine package, next to the Tape class
type StepCommand = { movement: 'L' | 'R' | 'S'; symbol: string | null };
type Frame = {
step: number;
Expand Down