Skip to content

Release v6.4.0 β€” adopt engine onIter, fix arrivalPath ordering bug#79

Merged
mellonis merged 3 commits into
masterfrom
v6-4-0
May 19, 2026
Merged

Release v6.4.0 β€” adopt engine onIter, fix arrivalPath ordering bug#79
mellonis merged 3 commits into
masterfrom
v6-4-0

Conversation

@mellonis
Copy link
Copy Markdown
Owner

Summary

Adopts `@turing-machine-js/machine` v6.4.0's new `onIter` hook to fix a pre-existing `arrivalPath` ordering bug that's been latent since v6.1.0. Also surfaces `onIter` as a new `pm.run()` parameter forwarded to the engine.

Version skips 6.2.0 and 6.3.0 β€” both were prepared but neither shipped to npm (see CHANGELOG history note).

The bug

Since v6.1.0 the internal `onStep` wrapper advanced `prev` mid-iter, which races engine v6.0.0+'s per-iter `before β†’ step β†’ after` dispatch order on the same yield. By the time `onPause(after, K)` fired:

  • `prev` had already advanced to iter K's own state (from `onStep`'s wrapper)
  • `m.arrivalPath` resolved to K's next instruction, not K's own
  • The registry-aware `#shouldFireOnPause` filter then saw the wrong path and silently dropped user-registered `{ after: true }` breakpoints β€” they were undocumentedly invisible.

Regression test added in `test/breakpoints.spec.ts` β€” fails on master, passes after the fix.

The fix

Move `advanceTracking` from the internal `onStep` wrapper to a new internal `onIter` wrapper. `onIter` fires at end-of-iter β€” after both `onPause` dispatches on the same yield have already read their iter-correct `prev` β€” so the advance no longer races them. Required the new `onIter` engine hook (turing-machine-js v6.4.0).

Also added

  • `onIter` parameter on `pm.run()`: `onIter?: (m: MachineState) => void | Promise`. Forwards to the engine's `onIter` with PostMachine's wrapped `MachineState` (so `m.arrivalPath` and `m.candidatePaths` are populated). Use for per-iter coordination β€” throttle, animation, yield-to-other-work.

Three-hook contract recap (matches engine v6.4.0)

Hook Sync/Async When Use
`onStep` Sync, not awaited Mid-iter Cheap tracer/logger
`onPause` Awaited On registered breakpoint match (arrival-aware filter) User breakpoints / debugger UI
`onIter` (new) Awaited End of every iter Per-iter coordination

Compatibility

  • Engine peer-dep: `^6.0.0` β†’ `^6.4.0`. Required because v6.4.0 added the `onIter` hook the fix depends on. Consumers on engine v6.0.x – v6.3.x must upgrade the engine alongside this package.
  • Source-level API: purely additive (new `onIter` parameter). No API breaks for consumers that don't opt in.
  • Internal `onStep` wrapper is now conditional (registered only when user provides `onStep`), since it no longer carries the always-on `advanceTracking` side-effect. Engine zero-cost when the consumer provides no callbacks at all.

Release plan after merge

  • `cd packages/machine && npm publish`
  • `gh release create v6.4.0 --target master --title v6.4.0 --notes-file ` (stable, not pre-release per the established pattern)

Test plan

  • `npm test` β€” 266/266 against published engine v6.4.0 (was 265, +1 from the new regression test)
  • `npm run typecheck` β€” clean
  • `npm run lint` β€” clean
  • `npm run build` β€” clean

mellonis added 2 commits May 19, 2026 19:58
Adopts the engine's new `onIter` hook (turing-machine-js v6.4.0,
PR #164) to fix a pre-existing `arrivalPath` ordering bug.

The bug: since v6.1.0 the internal `onStep` wrapper advanced `prev`
mid-iter, which races engine v6.0.0+'s per-iter `before β†’ step β†’
after` dispatch on the same yield. By the time `onPause(after, K)`
fired, `prev` was already iter K β€” so `m.arrivalPath` resolved to
iter K+1's instruction. Worse: the registry-aware
`#shouldFireOnPause` filter then saw the wrong path and silently
dropped user-registered `{ after: true }` breakpoints.

The fix: move `advanceTracking` from the internal `onStep` wrapper
to a new internal `onIter` wrapper. `onIter` fires at end-of-iter,
after both `onPause` dispatches on the same yield have already read
their iter-correct prev. Required engine v6.4.0.

Also:
- New `pm.run({ onIter })` parameter β€” forwards to engine's
  `onIter` with PostMachine's wrapped MachineState. Awaited inline.
- Engine peer-dep widened `^6.0.0` β†’ `^6.4.0` (required for `onIter`).
- Internal `onStep` wrapper now conditional (only registered when
  user provides onStep), since it no longer carries always-on
  advanceTracking side-effect.

Version skips 6.2.0 and 6.3.0 β€” both were prepared but neither
shipped (see CHANGELOG history note).

Regression test added in `test/breakpoints.spec.ts`: an `{ after:
true }` breakpoint must report the firing iter's instructionIndex,
not the next iter's.

NOT YET PUSHED β€” engine v6.4.0 must be published to npm first so CI
can resolve the peer dep range `^6.4.0`.
- `vitest.config.ts`: statements/branches/functions/lines thresholds
  95/90/95/95 β†’ 100/100/100/100. Pin to current actuals (266 tests
  hit every branch). Any new code path must be exercised; future
  regressions surface in CI as the threshold violation they are.
- `CLAUDE.md`: reflect the new floors.
- `test/machine-state.spec.ts`: new test for `onIter` receiving wrapped
  `MachineState` with `arrivalPath` + `candidatePaths`. Closes the
  lines 157-158 gap that previously had no test exercising the
  user-`onIter` forward path.
- `PostMachine.ts`:
  - Rename `anyCallback` β†’ `isAnyCallbackProvided`. Clearer at the
    call site β€” boolean intent reads at a glance.
  - `await super.run({...})` β†’ `return super.run({...})`. Forwards the
    Promise directly, saves one microtask, no behavior change. V8's
    zero-cost async stack traces keep this function in the trace
    regardless, so debugging context is unchanged.

Coverage: 267/267 tests, 100% / 100% / 100% / 100%.
@mellonis mellonis merged commit c5c01b2 into master May 19, 2026
4 checks passed
@mellonis mellonis deleted the v6-4-0 branch May 19, 2026 17:19
@github-project-automation github-project-automation Bot moved this from Todo to Done in @mellonis's machines May 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant