<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Articles — Ruslan Gilmullin</title>
    <link>https://mellonis.ru/en/articles/</link>
    <description>Articles by Ruslan Gilmullin.</description>
    <language>en</language>
    <atom:link href="https://mellonis.ru/en/articles/rss.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>DebugSession: a companion class for coordination</title>
      <link>https://mellonis.ru/en/articles/klass-kompanion-debugsession/</link>
      <guid isPermaLink="false">https://mellonis.ru/en/articles/klass-kompanion-debugsession/</guid>
      <pubDate>Sun, 07 Jun 2026 00:00:00 GMT</pubDate>
      <description>The worker in the previous article built coordination on top of the engine’s hooks. v7 lifted that coordination into a companion class next to the engine.</description>
      <content:encoded><![CDATA[<p><a href="https://github.com/mellonis/turing-machine-js"><code>turing-machine-js</code></a> is a Turing-machine interpreter. Over the last two majors, a two-part debugging API took shape: some hooks observe execution, others coordinate it. The first part is the subject of “<a href="https://mellonis.ru/en/articles/three-majors-two-mistakes/">Three majors, two mistakes: designing a pause API for a Turing-machine interpreter</a>” (1). The second is the subject of “<a href="https://mellonis.ru/en/articles/pauza-dvojstvennaya-po-prirode/">A pause with two sides: the hook contract and the worker protocol</a>” (2). <a href="https://mellonis.ru/en/articles/pauza-dvojstvennaya-po-prirode/">Article (2)</a> ended on a working protocol between the main thread and the <a href="https://demo.machines.mellonis.ru"><code>machines-demo</code></a> worker: an <code>idle</code>/<code>busy</code> message pair, a <code>stepRequested</code> flag, a synthetic <code>paused</code> event on click, an <code>intervalMs</code> field on <code>resume</code>. Four mechanisms, each closing one concrete problem. This article is about the next step.</p>
<p>Suppose a second consumer comes to the engine. Not the demo’s worker — say, an IDE extension, or an in-process educational debugger without a Web Worker. What from <a href="https://mellonis.ru/en/articles/pauza-dvojstvennaya-po-prirode/">article (2)</a>’s protocol does it carry over? It doesn’t need the watchdog timer — there’s no thread boundary. It doesn’t need a message queue — the handlers live in the same thread. But the “step flag”, the “pause coordination”, the “<code>paused</code> event with multiple causes” — <em>all of that</em>, it does need. And it, without having read article (2), will reinvent the whole thing.</p>
<p>This article is about why coordination keeps getting reinvented. Not because the worker is “special”, but because in v6 coordination had no home of its own in the library. v7 gave it one: a companion class, <code>DebugSession</code>, sitting next to <code>TuringMachine</code> in the same package.</p>
<h2 id="what-the-worker-reinvented"><a class="heading-anchor" href="#what-the-worker-reinvented">What the worker reinvented</a></h2>
<p>Re-read <a href="https://mellonis.ru/en/articles/pauza-dvojstvennaya-po-prirode/">article (2)</a>’s protocol through the new lens. Four mechanisms:</p>
<ol>
<li><code>idle</code>/<code>busy</code> around the async throttle in <code>onIter</code> — wrapping for the watchdog timer.</li>
<li><code>stepRequested</code> flag inside the worker — the “step” modeled as a one-shot request.</li>
<li>Synthetic <code>paused</code> event on click-Pause — handling an external pause command.</li>
<li><code>intervalMs</code> field on <code>resume</code> — reading the speed “at click time”, not “at run start”.</li>
</ol>
<p>Sort them by ownership. The first and the fourth are about the worker: the watchdog timer lives on the main thread because there’s a boundary between threads; <code>intervalMs</code> arrives with every <code>resume</code> because the interval input and the engine sit on different threads. The second and third are about <em>coordination</em>: the step modeled as a one-shot event, the translation of an external pause command into a standard event. Web Workers have nothing to do with any of that — the same mechanisms would be needed in any debugger that switches the engine between paused and running.</p>
<p>Two out of four mechanisms — candidates for lifting out of the consumer and into the library. The worker would be left with two: the watchdog wrapping and the speed parameter on resume. That isn’t “reinvention of coordination” anymore — it’s an adapter between two interfaces: between the worker’s message protocol and the session’s API.</p>
<h2 id="where-coordination-can-live"><a class="heading-anchor" href="#where-coordination-can-live">Where coordination can live</a></h2>
<p>In v6, there were two places to put coordination:</p>
<ul>
<li>On the consumer side. Every new debugger builds it from scratch. With only one consumer, its choice of where to put coordination looks principled: there’s nothing to compare it against. Two consumers would highlight the duplication; three would confirm the pattern.</li>
<li>In the engine’s hooks. This temptation is laid out in <a href="https://mellonis.ru/en/articles/pauza-dvojstvennaya-po-prirode/">article (2)</a>: widening <code>onStep</code> to an async signature (v6.2.0) conflated observation with coordination. The appearance of a dedicated <code>onIter</code> hook (v6.4.0) solved the “where does the throttle live” question, but didn’t lift the underlying constraint: a hook is a notification point, not a state machine. A hook has no internal state of its own, no lifecycle, no control methods — it hands the listener the current moment and awaits the listener’s Promise. Coordination, however, is exactly a state machine: “pause on breakpoint → continue / step-in / step-over / step-out / stop”. For step-over and step-out, where the next pause lands is determined by stack depth.</li>
</ul>
<p>The third option didn’t appear in v6 because the question wasn’t <em>forced</em> yet. With two consumers (or three, or N) the answer becomes obvious: coordination lives in a <em>sibling</em> class next to the engine. Not down the dependency graph (in the consumer), not inside the engine class itself (as yet another hook), but sideways — in a companion class on the same level of the library.</p>
<p>A side effect that’s also evidence: in v7, <code>TuringMachine.run()</code> is sync-and-<code>void</code> again — no callbacks. In v4 the same method became async to host the async pause hook (<code>onDebugBreak</code>, renamed to <code>onPause</code> in v5). Lifting coordination out erased that reason, and the signature reverted to its earlier shape. If async had been intrinsic to the engine, removing <code>onPause</code> wouldn’t have restored <code>run()</code> to its pre-v4 shape — but it did. So the async in <code>run()</code> was carried for that hook, not for the engine’s own execution logic.</p>
<figure><img src="https://mellonis.ru/articles/klass-kompanion-debugsession/architecture-en.svg?v=c08ac75a" alt="Architecture: DebugSession as a sibling of TuringMachine in the engine package; a consumer composes both." width="880" height="560"><figcaption>Architecture: DebugSession as a sibling of TuringMachine in the engine package; a consumer composes both.</figcaption></figure>
<h2 id="what-debugsession-owns"><a class="heading-anchor" href="#what-debugsession-owns">What <code>DebugSession</code> owns</a></h2>
<p>The class sits in <code>packages/machine/src/classes/DebugSession.ts</code>, alongside <code>TuringMachine</code>. Constructed directly — <code>new DebugSession(machine, {initialState})</code>. The engine knows nothing about the session; the session knows about the engine only through its public sync generator <code>runStepByStep</code>, plus one package-private accessor keyed by the symbol <code>MACHINE_STATE_INTERNAL</code>, which sibling modules can read and the public <code>index.ts</code> doesn’t re-export. Same package-private-via-Symbol pattern as <code>STATE_INTERNAL</code> (<a href="https://github.com/mellonis/turing-machine-js/issues/180"><code>turing-machine-js#180</code></a>) — it lets the session reach the per-iter halt-stack snapshot without exposing it through the public API.</p>
<p>The session listens for four events, each with its own dispatch contract:</p>
<ul>
<li><code>step</code> — fire-and-forget. Sync, hot-loop observation; the listener’s Promise (if any) is not awaited. One-to-one with the v6 <code>onStep</code> contract.</li>
<li><code>iter</code> — <em>awaited</em>. Per-iter coordination: a throttle between iterations, step-boundary synthesis, anywhere the engine genuinely needs to wait on the listener. One-to-one with the v6 <code>onIter</code> contract from <a href="https://mellonis.ru/en/articles/pauza-dvojstvennaya-po-prirode/">article (2)</a>.</li>
<li><code>pause</code> — listeners are called fire-and-forget (just like for <code>step</code> and <code>halt</code>: the Promise that an async listener would return isn’t awaited). But after dispatching them, the session itself blocks on its own internal Promise — and until that Promise resolves, the <code>#drive</code> loop doesn’t pull the next step out of the generator. The Promise is resolved by one of the session’s control methods: <code>continue()</code> / <code>stepIn()</code> / <code>stepOver()</code> / <code>stepOut()</code> / <code>stop()</code>. All of them, by design, are called from outside — a UI click, a message from the main thread (when the session lives in a worker), or a timer.</li>
<li><code>halt</code> — fire-and-forget. Terminal session event.</li>
</ul>
<p>Session controls mirror DevTools conventions where that makes sense. <code>pause()</code> is an external pause request; it fires on the before-side of the next iter with <code>cause: 'manual'</code>. <code>stepIn()</code> — pause on the next iter. <code>stepOver()</code> — pause on the next iter where <code>depth &#x3C;= clickTimeDepth</code>: frames the current iter pushes onto the stack are played through to return without stopping. <code>stepOut()</code> — pause when the halt-stack depth drops below the click-time depth (<code>depth &#x3C; clickTimeDepth</code>): the current wrapper has finished, control has passed to its override. <code>stepOut()</code> from depth 0 throws an exception: “step out of nothing” is a programming error in the consumer’s code, not a silent no-op. <code>setRunInterval(ms)</code> sets a per-iter delay (in ms) between iterations. <code>stop()</code> is terminal — the session resolves. The session is single-use: <code>start()</code> is called once; to re-run, construct a fresh session.</p>
<p>Breakpoint detection <em>also moved here</em>. In v6 the <code>runStepByStep</code> generator itself decided which iteration should “fire” by <code>state.debug</code>. In v7 the generator yields a minimal <code>MachineState</code>, and the session reads the current tape symbol via <code>MACHINE_STATE_INTERNAL</code>, checks it against the <code>before</code>/<code>after</code> filters in <code>state.debug</code> with <code>matchFilter</code>, and dispatches <code>pause</code> itself with <code>cause: 'breakpoint'</code>. The engine’s generator has no “debug” logic left — it’s pure execution. The session, in turn, carries all three pause causes (<code>breakpoint</code>, <code>step</code>, <code>manual</code>) in one descriptor <code>PauseInfo { side, cause }</code> with the precedence order <code>breakpoint > step > manual</code> for when several causes coincide on one iter.</p>
<p>This is exactly the “coordination as a state machine” that didn’t fit into a hook: internal state (the pause-Promise that holds the engine, the currently active step-in/over/out mode, the halt-stack depth captured at click time), control methods, a lifecycle — all in one object with its own constructor and its own <code>start()</code> method.</p>
<h2 id="what-stays-in-the-worker"><a class="heading-anchor" href="#what-stays-in-the-worker">What stays in the worker</a></h2>
<p>After the coordination lift, the worker isn’t empty. What it’s now responsible for:</p>
<ul>
<li>The Web Worker boundary itself — the message protocol, the user-code sandbox, the lifecycle of build / run / step requests. The worker is the natural home for that layer.</li>
<li>A per-iter delay wrapped with <code>idle</code>/<code>busy</code> messages for the <code>WORKER_TIMEOUT_MS</code> watchdog. The session has its own simple throttle — <code>setRunInterval(ms)</code>. But it doesn’t fit the worker: that wait runs inside the session’s <code>#drive</code> loop, and there’s no way to bracket it with <code>idle</code>/<code>busy</code> from the outside — and without the bracketing, the main-thread watchdog trips on a legitimate delay as if the worker were hung. So the worker implements the wait in its own listener for the <code>iter</code> event (which the session awaits asynchronously): inside the listener, an <code>idle</code> / <code>busy</code> pair brackets <code>await setTimeout(intervalMs)</code> exactly where it needs to be.</li>
<li>Holding and updating <code>intervalMs</code>. The “<code>withPause</code> is read at click time” semantics from <a href="https://mellonis.ru/en/articles/pauza-dvojstvennaya-po-prirode/">article (2)</a> didn’t go anywhere — the interval input in the UI is a consumer-level concern. The worker keeps the current value in its own local variable and updates it on every <code>resume</code> message from the main thread.</li>
<li>Translating UI clicks to session methods: Pause click → <code>activeSession.pause()</code>, Step click → <code>activeSession.stepIn()</code>, Continue click → <code>activeSession.continue()</code>. The worker no longer synthesizes <code>paused</code> from <code>onIter</code> — all pauses (breakpoint, step, manual) come back through the single <code>pause</code> event on the session, with a <code>cause</code> discriminant.</li>
</ul>
<p>The line is clean. What stayed is what the session can’t own without stepping onto the consumer’s territory. What left was never worker-specific to begin with — it was <em>coordination</em>, disguised as worker-specifics. A different consumer — an in-process debugger built into an IDE, a DAP server, an educational demo without a Worker — will compose <code>DebugSession</code> differently (no <code>postMessage</code>, no watchdog), but consume <em>the same session API</em>.</p>
<h2 id="the-lift-generalizes"><a class="heading-anchor" href="#the-lift-generalizes">The lift generalizes</a></h2>
<p><code>PostMachine.debugRun()</code> returns a <code>PostDebugSession</code>, which wraps the engine’s <code>DebugSession</code>. Same four events, same step methods, same lifecycle. On top: wrapping <code>MachineState</code> in post-specific <code>arrivalPath</code> / <code>candidatePaths</code>, and filtering by the <code>PostMachine</code> breakpoint registry before forwarding <code>pause</code> events outward. The demo’s worker handles both sessions through a structural <code>SessionLike</code> type — both look the same from the outside.</p>
<p>This is <em>companion-of-companion</em>: the pattern generalizes one library level up. The engine library lifts coordination once into its own companion class; the next library on top of it lifts its own specifics into its own companion class wrapping the engine’s. Evidence that “companion class” isn’t a one-off trick under one library — it’s a reproducible shape.</p>
<h2 id="what-follows-from-this"><a class="heading-anchor" href="#what-follows-from-this">What follows from this</a></h2>
<p>In the lineage of articles about the engine’s API, three lessons appear in a row:</p>
<ul>
<li>From <a href="https://mellonis.ru/en/articles/three-majors-two-mistakes/">article (1)</a>: naming the lifecycle pins decisions about the shape of the API — name the states correctly, and the surface lands in the right shape on its own.</li>
<li>From <a href="https://mellonis.ru/en/articles/pauza-dvojstvennaya-po-prirode/">article (2)</a>: observation and coordination are different jobs, and each one needs its own hook contract with its own dispatch semantics.</li>
<li>From this one: when N consumers reinvent the same coordination scaffolding on top of your hooks, your hook contract isn’t <em>incomplete</em> — it’s at the wrong <em>granularity</em>. A coordination state machine is a <em>neighbor</em> to hooks, not an extension of them.</li>
</ul>
<p>The diagnostic for a library author: if you find yourself widening a hook’s signature so the consumer can do work the consumer already has to do (v6.2.0’s major from <a href="https://mellonis.ru/en/articles/pauza-dvojstvennaya-po-prirode/">article (2)</a>) — or if the same handler shape repeats from consumer to consumer without meaningful differences (the case that triggered this refactor) — then the hook is being asked to do something a hook fundamentally can’t.</p>
<p>For this engine, that landed as a clean boundary: a public sync <code>runStepByStep</code>, its coordination companion <code>DebugSession</code>, and any consumer — the demo’s worker, a DAP server, an in-process debug panel — writes an adapter between its own entry point and the session API, not a reinvented coordination layer.</p>
<hr>
<p><em>Code: <a href="https://github.com/mellonis/turing-machine-js"><code>turing-machine-js</code></a> (engine, v7 — <code>DebugSession</code>), <a href="https://github.com/mellonis/post-machine-js"><code>post-machine-js</code></a> (<code>PostDebugSession</code>), and <a href="https://demo.machines.mellonis.ru"><code>machines-demo</code></a> (the demo worker, rewritten around the session in <a href="https://github.com/mellonis/machines-demo/pull/80">PR #80</a>).</em></p>]]></content:encoded>
    </item>
    <item>
      <title>Three guises of a Turing machine: object, graph, behaviour</title>
      <link>https://mellonis.ru/en/articles/tri-ipostasi-mashini/</link>
      <guid isPermaLink="false">https://mellonis.ru/en/articles/tri-ipostasi-mashini/</guid>
      <pubDate>Tue, 02 Jun 2026 00:00:00 GMT</pubDate>
      <description>I serialized a machine to a Mermaid diagram and rebuilt it. Proving it’s the same machine turned “the same” into three questions: object, graph, behaviour</description>
      <content:encoded><![CDATA[<p>In <a href="https://github.com/mellonis/turing-machine-js"><code>@turing-machine-js/machine</code></a> I built something I’d wanted for a long time: a state machine can be serialized to a <a href="https://mermaid.js.org/syntax/flowchart.html">Mermaid</a> diagram and rebuilt. <code>toGraph</code> turns a machine into a graph, <code>toMermaid</code> into diagram text; <code>fromMermaid</code> and <code>fromGraph</code> walk the path back. Diagram and machine became interchangeable: you can draw one, edit it, save it — and restore a working machine.</p>
<p>And right away I wanted a regression test: run a machine through the round-trip and check that what comes out is the same machine. That word “same” is where it all started.</p>
<p>Byte-for-byte? No: node ids are runtime instance ids, and <code>fromGraph</code> assigns them fresh. The same structure? Sometimes yes, sometimes no — depending on how the composition is built. Behaves the same? That’s a different check entirely, one that never touches the graph.</p>
<p>It turned out “the same” isn’t one question but three, and each has its own API to answer it. These three answers I added to the library over years, one at a time, and for a long time never spelled out to myself that they’re three separate boundaries, not one stretchy “equals”. Object, graph, behaviour — three guises of one machine, and on a flat machine they all give the same answer. Composition is where the answers diverge. What follows: what the engine ships for this, where the boundaries run, and how v7 packed two guises of the three into graph form, leaving the third to a separate function, <code>equivalentOn</code>.</p>
<h2 id="what-does-the-engine-actually-ship"><a class="heading-anchor" href="#what-does-the-engine-actually-ship">What does the engine actually ship?</a></h2>
<p>Before pulling the three guises apart, an inventory.</p>
<p>There are three layers in the engine that the question “is it the same machine?” lands on:</p>
<p><strong>Runtime objects.</strong> <code>State</code> is a node in the machine’s graph. It has a name, transitions (for each possible tape symbol — the next state, what to write, where to move), and identity: two different <code>State</code>s are two different objects, no matter how similar their transition tables look.</p>
<p><strong>The graph as serialization.</strong> <code>State.toGraph(state, tapeBlock)</code> walks the reachable states and returns a <code>Graph</code> — plain data: nodes with names and transitions, indexed by numeric ids. <code>State.fromGraph(graph)</code> takes that data back and returns <code>{start, tapeBlock, states}</code>. On top of the graph there’s <code>toMermaid(graph)</code> and <code>fromMermaid(text)</code>, a mapping into <a href="https://mermaid.js.org/syntax/flowchart.html">Mermaid flowchart</a> syntax and back. The parser is strict: it accepts only what the emitter produces.</p>
<p><strong>Behavioural equivalence.</strong> <code>equivalentOn(reference, candidate, cases)</code> in <code>utilities/equivalence.ts</code> — runs both machines on a set of test inputs, compares outputs and per-step snapshots. A separate module, knows nothing about the graph.</p>
<p>Three layers, three “is it the same?” questions. The rest of this post is about how they diverge.</p>
<h2 id="flat-machine-the-boring-case"><a class="heading-anchor" href="#flat-machine-the-boring-case">Flat machine: the boring case</a></h2>
<p>On a flat machine — no composition — all three guises coincide.</p>
<p><strong>Object-wise:</strong> one <code>State</code> equals another only if it’s the same instance (<code>===</code>). That’s the basic JavaScript semantics; the engine doesn’t add anything.</p>
<p><strong>Graph-wise:</strong> take <code>toGraph</code>, run it through JSON and back, rebuild via <code>fromGraph</code> — you get a twin with the same names and transitions. The match isn’t byte-for-byte but up to node-id renaming: node ids are runtime <code>State</code> ids, reassigned on every <code>fromGraph</code> rebuild. There’s a regression test for this in the repo (<a href="https://github.com/mellonis/turing-machine-js/issues/139"><code>turing-machine-js#139</code></a>). It’s not “looks the same” — it’s the same structure.</p>
<p><strong>Behaviour-wise:</strong> <code>equivalentOn</code> runs both machines on the test inputs and confirms “yes, the same”.</p>
<p>The boring case. All three guises coincide because there’s no place where they could diverge. Composition is that place.</p>
<h2 id="composition-where-it-gets-interesting"><a class="heading-anchor" href="#composition-where-it-gets-interesting">Composition: where it gets interesting</a></h2>
<p>Composition in this engine looks like this:</p>
<pre class="shiki shiki-themes github-light github-dark language-javascript" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">const</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> wrapper</span><span style="color:#D73A49;--shiki-dark:#F97583"> =</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> bareState.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">withOverriddenHaltState</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(overrideState);</span></span></code></pre>
<p><code>wrapper</code> is a new <code>State</code>. It <em>delegates</em> transition lookup to its <code>bareState</code>, but <em>substitutes</em> the halt-exit: instead of the machine halting, it transitions into <code>overrideState</code>.</p>
<p>Conceptually a wrapper is “run the bare as a subroutine, on exit jump to <code>overrideState</code>”. The composition’s name follows a rule: for a bare named <code>A</code> and an override named <code>B</code>, the wrapper gets the name <code>A(B)</code>. The how and why of that exact name is its own article, <a href="https://mellonis.ru/en/articles/seven-arrows-429-trees/">“Seven arrows, 429 trees”</a> (1).</p>
<p>Here is where the three guises start to diverge.</p>
<p><strong>Object-wise:</strong> wrapper and bare are two different <code>State</code>s. <code>wrapper !== bareState</code>. That’s the consequence of <code>withOverriddenHaltState</code> returning a new instance.</p>
<p><strong>Graph-wise:</strong> the wrapper has <em>no transitions of its own</em>. They live on the bare. If you visualise the graph, the wrapper is a delegation node, not a transition node.</p>
<p><strong>Behaviour-wise:</strong> wrapper and bare are <em>not</em> equivalent. They have different halt-exits. On any input the trace matches step for step up to the bare’s halt-exit — and diverges exactly at that moment.</p>
<p>A wrapper exists as a separate object precisely so it can hold that substitution. Next question: how does the graph encode it, so that <code>fromGraph</code> can rebuild it?</p>
<h2 id="how-composition-lands-in-the-graph"><a class="heading-anchor" href="#how-composition-lands-in-the-graph">How composition lands in the graph</a></h2>
<p>I wanted the graph to carry the composition itself — that kills two birds. First, <code>fromGraph</code> rebuilds the machine straight from the structure instead of guessing the composition from a runtime hint. Second, the graph stays readable: the composition shows up on the diagram itself rather than dissolving into a flat list of transitions. In v7 (<a href="https://github.com/mellonis/turing-machine-js/issues/180"><code>turing-machine-js#180</code></a>) a wrapper emits two nodes:</p>
<ul>
<li><strong>Wrapper node</strong> — a call-site with no transitions, shape <code>[[wrapper-name]]</code>, its <code>bareStateId</code> field pointing at the bare.</li>
<li><strong>Bare node</strong> — a regular node with transitions, shape <code>[bareState-name]</code>, placed inside a Mermaid subgraph “callable subtree of NAME”.</li>
</ul>
<p>In full, for <code>scanToX(eraseHere)</code>:</p>
<svg xmlns="http://www.w3.org/2000/svg" id="mermaid-0" width="100%" aria-roledescription="flowchart-v2" class="flowchart" style="font-family:arial,sans-serif;font-size:16px;fill:#333;max-width:427.20782470703125px" viewBox="0 0 427.208 549.897"><style>@keyframes edge-animation-frame{0%{stroke-dashoffset:0}}@keyframes dash{to{stroke-dashoffset:0}}#mermaid-0 .edge-thickness-normal{stroke-width:1px}#mermaid-0 .edge-pattern-solid{stroke-dasharray:0}#mermaid-0 .edge-pattern-dotted{stroke-dasharray:2}#mermaid-0 .marker{fill:#333;stroke:#333}#mermaid-0 .marker.cross{stroke:#333}#mermaid-0 svg{font-family:arial,sans-serif;font-size:16px}#mermaid-0 p{margin:0}#mermaid-0 .label{font-family:arial,sans-serif;color:#333}#mermaid-0 span{fill:#333;color:#333}#mermaid-0 .node circle,#mermaid-0 .node path,#mermaid-0 .node rect{fill:#ececff;stroke:#9370db;stroke-width:1px}#mermaid-0 .flowchart-link{stroke:#333;fill:none}#mermaid-0 .edgeLabel,#mermaid-0 .node .label{text-align:center}#mermaid-0 .edgeLabel,#mermaid-0 .edgeLabel p,#mermaid-0 .edgeLabel rect{background-color:rgba(232,232,232,.8)}#mermaid-0 .edgeLabel rect{opacity:.5;fill:rgba(232,232,232,.8)}#mermaid-0 .labelBkg{background-color:rgba(232,232,232,.5)}#mermaid-0 [data-look=neo].cluster rect,#mermaid-0 [data-look=neo].node circle,#mermaid-0 [data-look=neo].node rect{stroke:#9370db;filter:drop-shadow(1px 2px 2px #b9b9b9)}#mermaid-0 [data-look=neo].node path{stroke:#9370db;stroke-width:1px}#mermaid-0 [data-look=neo].node .outer-path{filter:drop-shadow(1px 2px 2px #b9b9b9)}#mermaid-0 :root{--mermaid-font-family:arial,sans-serif}</style><marker id="mermaid-0_flowchart-v2-pointEnd" class="marker flowchart-v2" markerHeight="8" markerUnits="userSpaceOnUse" markerWidth="8" orient="auto" refX="5" refY="5" viewBox="0 0 10 10"><path d="m0 0 10 5-10 5z" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></path></marker><marker id="mermaid-0_flowchart-v2-pointStart" class="marker flowchart-v2" markerHeight="8" markerUnits="userSpaceOnUse" markerWidth="8" orient="auto" refX="4.5" refY="5" viewBox="0 0 10 10"><path d="m0 5 10 5V0z" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></path></marker><marker id="mermaid-0_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="10.5" orient="auto" refX="11.5" refY="7" viewBox="0 0 11.5 14"><path d="m0 0 11.5 7L0 14z" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></path></marker><marker id="mermaid-0_flowchart-v2-pointStart-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="11.5" orient="auto" refX="1" refY="7" viewBox="0 0 11.5 14"><path d="m0 7 11.5 7V0z" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></path></marker><marker id="mermaid-0_flowchart-v2-circleEnd" class="marker flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="11" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-0_flowchart-v2-circleStart" class="marker flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="-1" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-0_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="14" orient="auto" refX="12.25" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-0_flowchart-v2-circleStart-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="14" orient="auto" refX="-2" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-0_flowchart-v2-crossEnd" class="marker cross flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="12" refY="5.2" viewBox="0 0 11 11"><path d="m1 1 9 9m0-9-9 9" class="arrowMarkerPath" style="stroke-width:2;stroke-dasharray:1,0"></path></marker><marker id="mermaid-0_flowchart-v2-crossStart" class="marker cross flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="-1" refY="5.2" viewBox="0 0 11 11"><path d="m1 1 9 9m0-9-9 9" class="arrowMarkerPath" style="stroke-width:2;stroke-dasharray:1,0"></path></marker><marker id="mermaid-0_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" markerHeight="12" markerUnits="userSpaceOnUse" markerWidth="12" orient="auto" refX="17.7" refY="7.5" viewBox="0 0 15 15"><path d="m1 1 13 13M1 14 14 1" class="arrowMarkerPath" style="stroke-width:2.5"></path></marker><marker id="mermaid-0_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" markerHeight="12" markerUnits="userSpaceOnUse" markerWidth="12" orient="auto" refX="-3.5" refY="7.5" viewBox="0 0 15 15"><path d="m1 1 13 13M1 14 14 1" class="arrowMarkerPath" style="stroke-width:2.5;stroke-dasharray:1,0"></path></marker><g class="root"><g class="clusters"><g id="mermaid-0-w_1" class="cluster" data-look="classic"><path d="M8 234h241.505v307.897H8z" style="fill:#ffffde;stroke:#aa3;stroke-width:1px"></path><foreignObject width="195.672" height="24" class="cluster-label" transform="translate(30.916 234)"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5"><span class="nodeLabel" style="color:#333"><p style="background-color:transparent">callable subtree of scanToX</p></span></div></foreignObject></g></g><g class="edgePaths"><path id="mermaid-0-L_idle_s3_0" marker-end="url(#mermaid-0_flowchart-v2-pointEnd)" d="m191.363 47.5-.084 6.083c-.083 6.084-.25 18.25-.259 29.917s.14 22.834.215 28.417l.074 5.583" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_idle_s3_0" data-look="classic" data-points="W3sieCI6MTkxLjM2MjUwMDAwMDc0NTA2LCJ5Ijo0Ny41fSx7IngiOjE5MC44NjI1MDAwMDA3NDUwNiwieSI6ODR9LHsieCI6MTkxLjM2MjUwMDAwMDc0NTA2LCJ5IjoxMjEuNX1d"></path><path id="mermaid-0-L_s3_s1_0" marker-end="url(#mermaid-0_flowchart-v2-pointEnd)" d="m151.666 160.5-12.637 6.083c-12.637 6.084-37.911 18.25-50.548 30.5s-12.637 24.584-7.006 34.544c5.631 9.961 16.893 17.55 22.524 21.344l5.631 3.794" class="edge-pattern-solid edge-thickness-normal flowchart-link" data-edge="true" data-et="edge" data-id="L_s3_s1_0" data-look="classic" data-points="W3sieCI6MTUxLjY2NTc2MzI3NDgyNDIsInkiOjE2MC41fSx7IngiOjc1Ljg0Mzc1LCJ5IjoxOTd9LHsieCI6NzUuODQzNzUsInkiOjIzNH0seyJ4IjoxMTIuOTQ3MTE1Mzg0OTczNTksInkiOjI1OX1d" style="stroke-width:3.5px"></path><path id="mermaid-0-L_s3_s2_0" marker-end="url(#mermaid-0_flowchart-v2-pointEnd)" d="m246.927 160.5 17.488 6.083c17.488 6.084 52.465 18.25 69.953 30.5s17.488 24.584 17.488 34.25V255" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_s3_s2_0" data-look="classic" data-points="W3sieCI6MjQ2LjkyNjcxNDYwMjY0MzU2LCJ5IjoxNjAuNX0seyJ4IjozNTEuODU2MjUwMDAxMTE3NiwieSI6MTk3fSx7IngiOjM1MS44NTYyNTAwMDExMTc2LCJ5IjoyMzR9LHsieCI6MzUxLjg1NjI1MDAwMTExNzYsInkiOjI1OX1d"></path><path id="mermaid-0-L_s1_c1_0" marker-end="url(#mermaid-0_flowchart-v2-pointEnd)" d="m120.134 313-7.51 6.167c-7.511 6.166-22.532 18.5-30.043 30.166S75.07 372 75.07 377.5v5.5" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_s1_c1_0" data-look="classic" data-points="W3sieCI6MTIwLjEzNDI1MjkzMDExODI0LCJ5IjozMTN9LHsieCI6NzUuMDcwMzEyNSwieSI6MzUwfSx7IngiOjc1LjA3MDMxMjUsInkiOjM4N31d"></path><path id="mermaid-0-s1-cyclic-special-1" d="M153.019 313v101.848" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="s1-cyclic-special-1" data-look="classic" data-points="W3sieCI6MTUzLjAxODc1MDAwMDc0NTA2LCJ5IjozMTN9LHsieCI6MTUzLjAxODc1MDAwMDc0NTA2LCJ5IjozNTB9LHsieCI6MTUzLjAxODc1MDAwMDc0NTA2LCJ5Ijo0MTQuODQ4NDM3NDk5MjU0OTR9XQ=="></path><path id="mermaid-0-s1-cyclic-special-mid" d="M153.019 414.948v10.809c0 10.808 0 32.424 2.514 49.398 2.515 16.975 7.544 29.309 10.058 35.475l2.514 6.167" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="s1-cyclic-special-mid" data-look="classic" data-points="W3sieCI6MTUzLjAxODc1MDAwMDc0NTA2LCJ5Ijo0MTQuOTQ4NDM3NTAwNzQ1MDZ9LHsieCI6MTUzLjAxODc1MDAwMDc0NTA2LCJ5Ijo0NzkuNzk2ODc1fSx7IngiOjE2OC4xMDUzOTM4OTQyMDEsInkiOjUxNi43OTY4NzV9XQ=="></path><path id="mermaid-0-s1-cyclic-special-2" marker-end="url(#mermaid-0_flowchart-v2-pointEnd)" d="m168.176 516.812 8.967-6.169c8.967-6.169 26.902-18.508 35.869-35.493 8.968-16.986 8.968-38.619 8.968-60.252 0-21.632 0-43.265-6.156-59.795-6.156-16.529-18.468-27.956-24.624-33.669l-6.156-5.713" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="s1-cyclic-special-2" data-look="classic" data-points="W3sieCI6MTY4LjE3NTc4MTI1MTg2MjY1LCJ5Ijo1MTYuODEyNDc2MzgxMjgyN30seyJ4IjoyMjEuOTc5Njg3NTAwNzQ1MDYsInkiOjQ3OS43OTY4NzV9LHsieCI6MjIxLjk3OTY4NzUwMDc0NTA2LCJ5Ijo0MTQuODk4NDM3NX0seyJ4IjoyMjEuOTc5Njg3NTAwNzQ1MDYsInkiOjM1MH0seyJ4IjoxODIuMTExNjQ1NTA4NTU3NTYsInkiOjMxM31d"></path><path id="mermaid-0-L_s2_s0_0" marker-end="url(#mermaid-0_flowchart-v2-pointEnd)" d="M351.856 313v70" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_s2_s0_0" data-look="classic" data-points="W3sieCI6MzUxLjg1NjI1MDAwMTExNzYsInkiOjMxM30seyJ4IjozNTEuODU2MjUwMDAxMTE3NiwieSI6MzUwfSx7IngiOjM1MS44NTYyNTAwMDExMTc2LCJ5IjozODd9XQ=="></path><path id="mermaid-0-L_w_1_s3_0" marker-end="url(#mermaid-0_flowchart-v2-pointEnd)" d="m191.661 197-.02-32.5" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_w_1_s3_0" data-look="classic" data-points="W3sieCI6MTczLjA4Mjk2Mjc0MTMyMzEyLCJ5IjoyNTl9LHsieCI6MTkxLjY2MDkzNzUwMTExNzYsInkiOjIzNH0seyJ4IjoxOTEuNjYwOTM3NTAxMTE3NiwieSI6MTk3fSx7IngiOjE5MS42MzgwNjY5MjU2NTI0LCJ5IjoxNjAuNX1d"></path></g><g class="edgeLabels"><g class="edgeLabel"><foreignObject width="36.469" height="24" class="label" data-id="L_idle_s3_0" transform="translate(172.628 72)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>enter</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="24.016" height="24" class="label" data-id="L_s3_s1_0" transform="translate(63.836 185)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>call</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="0" height="0" class="label" data-id="L_s3_s2_0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="94.141" height="24" class="label" data-id="L_s1_c1_0" transform="translate(28 338)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>['X'] → [K]/[S]</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="0" height="0" class="label" data-id="s1-cyclic-special-1"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="84.469" height="24" class="label" data-id="s1-cyclic-special-mid" transform="translate(110.784 467.797)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>[*] → [K]/[R]</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="0" height="0" class="label" data-id="s1-cyclic-special-2"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="83.578" height="24" class="label" data-id="L_s2_s0_0" transform="translate(310.067 338)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>[*] → [E]/[S]</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="41.797" height="24" class="label" data-id="L_w_1_s3_0" transform="translate(170.751 166.75)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>return</p></span></div></foreignObject></g></g><g class="nodes"><g id="mermaid-0-flowchart-s0-0" class="node default" data-look="classic"><g class="basic label-container" transform="translate(351.856 414.898)"><circle r="27.898" class="outer-circle"></circle><circle r="22.898" class="inner-circle"></circle></g><g class="label" transform="translate(338.958 402.898)"><rect></rect><foreignObject width="25.797" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>halt</p></span></div></foreignObject></g></g><g id="mermaid-0-flowchart-s2-1" class="node default" data-look="classic"><path d="M284.504 259h134.703v54H284.504z" class="basic label-container"></path><g class="label" transform="translate(314.505 274)"><rect></rect><foreignObject width="74.703" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>eraseHere</p></span></div></foreignObject></g></g><g id="mermaid-0-flowchart-s3-2" class="node default" data-look="classic"><path d="M0 0h161.734v-39H0V0h-8 177.734v-39H-8V0z" class="label-container" style="fill:#ececff;stroke:#9370db;stroke-width:1px" transform="translate(109.995 160)"></path><g class="label" transform="translate(117.495 128.5)"><rect></rect><foreignObject width="146.734" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>scanToX(eraseHere)</p></span></div></foreignObject></g></g><g id="mermaid-0-flowchart-idle-3" class="node default" data-look="classic"><g class="basic label-container outer-path"><path fill="#ececff" stroke-width="0" d="M185.534 8h10.657l1.249.04 1.244.12 1.234.2 1.219.278 1.198.355 1.173.432 1.143.506 1.109.578 1.069.648 1.025.715.977.78.925.84.87.898.81.952.748 1.002.682 1.047.613 1.09.543 1.126.469 1.158.394 1.187.317 1.209.239 1.227.16 1.24.08 1.247v1.25l-.08 1.247-.16 1.24c-.08.412-.16.824-.24 1.227l-.316 1.21-.394 1.186-.47 1.158-.542 1.126-.613 1.09-.682 1.047-.748 1.002-.81.952-.87.898-.925.84-.977.78-1.025.715-1.07.648-1.108.578-1.143.506-1.173.432-1.198.355-1.219.278-1.234.2-1.244.12-1.25.04h-10.656l-1.249-.04-1.244-.12c-.467-.076-.933-.15-1.234-.2l-1.219-.278-1.198-.355-1.173-.432-1.143-.506-1.109-.578-1.069-.648-1.025-.715-.977-.78-.925-.84-.87-.898-.81-.952-.748-1.002-.682-1.047-.613-1.09-.543-1.126-.469-1.158-.394-1.187-.317-1.209-.239-1.227-.16-1.24-.08-1.247v-1.25l.08-1.247.16-1.24.24-1.227.316-1.21.394-1.186.47-1.158c.11-.231.222-.462.542-1.126l.613-1.09.682-1.047.748-1.002.81-.952.87-.898.925-.84.977-.78 1.025-.715 1.07-.648 1.108-.578 1.143-.506 1.173-.432 1.198-.355 1.219-.278 1.234-.2 1.244-.12 1.25-.04"></path><path fill="none" stroke="#9370db" stroke-dasharray="0 0" stroke-width="1.3" d="M185.534 8h10.657m-10.657 0h10.657m0 0 1.249.04M196.19 8l1.25.04m0 0 1.244.12m-1.244-.12 1.244.12m0 0 1.234.2m-1.234-.2 1.234.2m0 0 1.219.278m-1.219-.278 1.219.278m0 0 1.198.355m-1.198-.355 1.198.355m0 0 1.173.432m-1.173-.432 1.173.432m0 0 1.143.506m-1.143-.506 1.143.506m0 0 1.109.578m-1.109-.578 1.109.578m0 0 1.069.648m-1.07-.648 1.07.648m0 0 1.025.715m-1.025-.715 1.025.715m0 0 .977.78m-.977-.78.977.78m0 0 .925.84m-.925-.84.925.84m0 0 .87.898m-.87-.898.87.898m0 0 .81.952m-.81-.952.81.952m0 0 .748 1.002m-.748-1.002.748 1.002m0 0 .682 1.047m-.682-1.047.682 1.047m0 0 .613 1.09m-.613-1.09.613 1.09m0 0 .543 1.126m-.543-1.126.543 1.126m0 0 .469 1.158m-.47-1.158.47 1.158m0 0 .394 1.187m-.394-1.187.394 1.187m0 0 .317 1.209m-.317-1.21.317 1.21m0 0 .239 1.227m-.24-1.227.24 1.227m0 0c.06.47.12.94.16 1.24m-.16-1.24.16 1.24m0 0 .08 1.247m-.08-1.247.08 1.247m0 0v1.25m0-1.25v1.25m0 0-.08 1.247m.08-1.247-.08 1.247m0 0-.16 1.24m.16-1.24-.16 1.24m0 0-.24 1.227m.24-1.227-.24 1.227m0 0-.316 1.21m.317-1.21-.317 1.21m0 0c-.13.389-.26.779-.394 1.186m.394-1.187-.394 1.187m0 0-.47 1.158m.47-1.158-.47 1.158m0 0-.542 1.126m.543-1.126-.543 1.126m0 0-.613 1.09m.613-1.09-.613 1.09m0 0-.682 1.047m.682-1.047-.682 1.047m0 0-.748 1.002m.748-1.002-.748 1.002m0 0-.81.952m.81-.952-.81.952m0 0c-.18.185-.36.37-.87.898m.87-.898-.87.898m0 0-.925.84m.925-.84-.925.84m0 0-.977.78m.977-.78-.977.78m0 0-1.025.715m1.025-.715-1.025.715m0 0-1.07.648m1.07-.648-1.07.648m0 0-1.108.578m1.109-.578-1.109.578m0 0-1.143.506m1.143-.506-1.143.506m0 0-1.173.432m1.173-.432-1.173.432m0 0-1.198.355m1.198-.355-1.198.355m0 0-1.219.278m1.219-.278-1.219.278m0 0-1.234.2m1.234-.2-1.234.2m0 0-1.244.12m1.244-.12-1.244.12m0 0-1.25.04m1.25-.04-1.25.04m0 0h-10.656m10.657 0h-10.657m0 0-1.249-.04m1.25.04-1.25-.04m0 0-1.244-.12m1.244.12-1.244-.12m0 0-1.234-.2m1.234.2-1.234-.2m0 0-1.219-.278m1.219.278-1.219-.278m0 0-1.198-.355m1.198.355-1.198-.355m0 0-1.173-.432m1.173.432-1.173-.432m0 0-1.143-.506m1.143.506-1.143-.506m0 0-1.109-.578m1.109.578-1.109-.578m0 0-1.069-.648m1.07.648-1.07-.648m0 0c-.3-.21-.6-.42-1.025-.715m1.025.715-1.025-.715m0 0-.977-.78m.977.78-.977-.78m0 0-.925-.84m.925.84-.925-.84m0 0-.87-.898m.87.898-.87-.898m0 0-.81-.952m.81.952-.81-.952m0 0-.748-1.002m.748 1.002-.748-1.002m0 0-.682-1.047m.682 1.047-.682-1.047m0 0-.613-1.09m.613 1.09-.613-1.09m0 0-.543-1.126m.543 1.126-.543-1.126m0 0-.469-1.158m.47 1.158-.47-1.158m0 0-.394-1.187m.394 1.187-.394-1.187m0 0-.317-1.209m.317 1.21-.317-1.21m0 0-.239-1.227m.24 1.227-.24-1.227m0 0-.16-1.24m.16 1.24-.16-1.24m0 0-.08-1.247m.08 1.247-.08-1.247m0 0v-1.25m0 1.25v-1.25m0 0c.03-.45.058-.898.08-1.247m-.08 1.247c.03-.45.058-.9.08-1.247m0 0 .16-1.24m-.16 1.24.16-1.24m0 0 .24-1.227m-.24 1.227.24-1.227m0 0 .316-1.21m-.317 1.21.317-1.21m0 0 .394-1.186m-.394 1.187.394-1.187m0 0 .47-1.158m-.47 1.158.47-1.158m0 0c.214-.447.43-.894.542-1.126m-.543 1.126.543-1.126m0 0 .613-1.09m-.613 1.09.613-1.09m0 0 .682-1.047m-.682 1.047.682-1.047m0 0 .748-1.002m-.748 1.002.748-1.002m0 0q.406-.479.81-.952m-.81.952.81-.952m0 0 .87-.898m-.87.898.87-.898m0 0 .925-.84m-.925.84.925-.84m0 0 .977-.78m-.977.78.977-.78m0 0c.295-.205.59-.41 1.025-.715m-1.025.715 1.025-.715m0 0 1.07-.648m-1.07.648 1.07-.648m0 0 1.108-.578m-1.109.578 1.109-.578m0 0 1.143-.506m-1.143.506 1.143-.506m0 0 1.173-.432m-1.173.432 1.173-.432m0 0 1.198-.355m-1.198.355 1.198-.355m0 0 1.219-.278m-1.219.278 1.219-.278m0 0c.301-.05.603-.098 1.234-.2m-1.234.2 1.234-.2m0 0 1.244-.12m-1.244.12 1.244-.12m0 0 1.25-.04m-1.25.04 1.25-.04m0 0"></path></g><g class="label" transform="translate(178.41 15.5)"><rect></rect><foreignObject width="24.906" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>idle</p></span></div></foreignObject></g></g><g id="mermaid-0-flowchart-s1-4" class="node default" data-look="classic"><path d="M92.33 259h121.376v54H92.33z" class="basic label-container"></path><g class="label" transform="translate(122.331 274)"><rect></rect><foreignObject width="61.375" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>scanToX</p></span></div></foreignObject></g></g><g id="mermaid-0-flowchart-c1-5" class="node default" data-look="classic"><g class="basic label-container" transform="translate(75.07 414.898)"><circle r="27.898" class="outer-circle"></circle><circle r="22.898" class="inner-circle"></circle></g><g class="label" transform="translate(62.172 402.898)"><rect></rect><foreignObject width="25.797" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>halt</p></span></div></foreignObject></g></g><g id="s1---s1---1" class="label edgeLabel"><path d="M153.019 414.898h.1v.1h-.1z"></path><g class="label" transform="translate(153.019 414.898)"><rect></rect><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:10px;text-align:center"><span class="nodeLabel"></span></div></foreignObject></g></g><g id="s1---s1---2" class="label edgeLabel"><path d="M168.126 516.847h.1v.1h-.1z"></path><g class="label" transform="translate(168.126 516.847)"><rect></rect><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:10px;text-align:center"><span class="nodeLabel"></span></div></foreignObject></g></g></g></g><defs><filter id="mermaid-0-drop-shadow" width="130%" height="130%"><feDropShadow dx="4" dy="4" flood-color="#000" flood-opacity=".06" stdDeviation="0"></feDropShadow></filter></defs><defs><filter id="mermaid-0-drop-shadow-small" width="150%" height="150%"><feDropShadow dx="2" dy="2" flood-color="#000" flood-opacity=".06" stdDeviation="0"></feDropShadow></filter></defs></svg>
<p>That’s enough for <code>fromGraph</code> to rebuild the wrapper from the structure: here’s the call-site, here’s the bare it points to. The graph <em>encodes</em> the composition rather than hinting at it.</p>
<blockquote>
<p><strong>Under the hood</strong> (skippable). The halt-exit of each frame is a separate <code>isHaltMarker</code> node with id <code>= -frameId</code>; at runtime it collapses into the singleton <code>haltState</code>, but on the graph it lives separately, otherwise the whole machine “absorbs” into one halt node. When a single bare is reachable from several wrappers, frames are computed by union-find over bare-reachability (the subgraph is labelled “callable subtree of A” or “callable scope: A ∪ B”). The start of the machine is marked by a sentinel <code>idle([idle])</code> with a dotted <code>enter</code> arrow — an anchor the parser reads to find the start state. Transition labels follow a small format <code>[reads] → [writes]/[moves]</code> — one cell per tape.</p>
</blockquote>
<h2 id="is-it-the-same-machine-after-a-round-trip"><a class="heading-anchor" href="#is-it-the-same-machine-after-a-round-trip">Is it the same machine after a round-trip?</a></h2>
<p>For a simple composition — one wrapper, one bare, a tree that doesn’t overlap with others — the round-trip is reproducible up to id renaming. The graph keeps nodes, names, transitions; <code>fromGraph</code> reassembles the same machine. The composite name <code>scanToX(eraseHere)</code> does ride along in the graph — it’s the wrapper node’s label — but <code>fromGraph</code> doesn’t read it: it recomputes the composite from the bare and the override, through the single place where mutating a name is permitted, the Symbol accessor <code>STATE_INTERNAL</code> (<a href="https://github.com/mellonis/turing-machine-js/issues/180"><code>turing-machine-js#180</code></a>). So names never accumulate: on every rebuild the name is computed from the structure, not stacked on top of the previous one. That’s exactly what the regression test on simple wrappers checks.</p>
<p>Reproducibility breaks on a shared bare — when one and the same <code>State</code> serves as the bare of several wrappers. Not a contrivance: in <code>library-binary-numbers</code> the <code>minusOne</code> algorithm is built so that <code>invertNumber</code> ends up as the bare of two wrappers, an outer and an inner one (<a href="https://github.com/mellonis/turing-machine-js/blob/master/packages/library-binary-numbers/states.md#minusone">the full graph</a>). One object, two call-sites.</p>
<p>This doesn’t break the structure: <code>toGraph</code> walks the reachable states exactly once, keyed by instance id, so a shared bare is <strong>one</strong> node, and the two wrappers just point at it with two arrows; <code>fromGraph</code> rebuilds exactly one shared instance for both wrappers. The shared bare itself survives the round-trip. What doesn’t is the <em>reproducibility of the serialization</em>: a second rebuild can give a graph that won’t line up with the original even if you ignore the ids.</p>
<p>The same shape in miniature, on <code>scanToX</code> — one bare under two wrappers:</p>
<svg xmlns="http://www.w3.org/2000/svg" id="mermaid-1" width="100%" aria-roledescription="flowchart-v2" class="flowchart" style="font-family:arial,sans-serif;font-size:16px;fill:#333;max-width:219.671875px" viewBox="-6.148 0 219.672 346"><style>@keyframes edge-animation-frame{0%{stroke-dashoffset:0}}@keyframes dash{to{stroke-dashoffset:0}}#mermaid-1 .edge-thickness-normal{stroke-width:1px}#mermaid-1 .edge-thickness-thick{stroke-width:3.5px}#mermaid-1 .edge-pattern-solid{stroke-dasharray:0}#mermaid-1 .edge-pattern-dotted{stroke-dasharray:2}#mermaid-1 .marker{fill:#333;stroke:#333}#mermaid-1 .marker.cross{stroke:#333}#mermaid-1 svg{font-family:arial,sans-serif;font-size:16px}#mermaid-1 p{margin:0}#mermaid-1 .label{font-family:arial,sans-serif;color:#333}#mermaid-1 span{fill:#333;color:#333}#mermaid-1 .node circle,#mermaid-1 .node path,#mermaid-1 .node rect{fill:#ececff;stroke:#9370db;stroke-width:1px}#mermaid-1 .flowchart-link{stroke:#333;fill:none}#mermaid-1 .edgeLabel,#mermaid-1 .node .label{text-align:center}#mermaid-1 .edgeLabel,#mermaid-1 .edgeLabel p,#mermaid-1 .edgeLabel rect{background-color:rgba(232,232,232,.8)}#mermaid-1 .edgeLabel rect{opacity:.5;fill:rgba(232,232,232,.8)}#mermaid-1 .labelBkg{background-color:rgba(232,232,232,.5)}#mermaid-1 [data-look=neo].cluster rect,#mermaid-1 [data-look=neo].node circle,#mermaid-1 [data-look=neo].node rect{stroke:#9370db;filter:drop-shadow(1px 2px 2px #b9b9b9)}#mermaid-1 [data-look=neo].node path{stroke:#9370db;stroke-width:1px}#mermaid-1 :root{--mermaid-font-family:arial,sans-serif}</style><marker id="mermaid-1_flowchart-v2-pointEnd" class="marker flowchart-v2" markerHeight="8" markerUnits="userSpaceOnUse" markerWidth="8" orient="auto" refX="5" refY="5" viewBox="0 0 10 10"><path d="m0 0 10 5-10 5z" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></path></marker><marker id="mermaid-1_flowchart-v2-pointStart" class="marker flowchart-v2" markerHeight="8" markerUnits="userSpaceOnUse" markerWidth="8" orient="auto" refX="4.5" refY="5" viewBox="0 0 10 10"><path d="m0 5 10 5V0z" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></path></marker><marker id="mermaid-1_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="10.5" orient="auto" refX="11.5" refY="7" viewBox="0 0 11.5 14"><path d="m0 0 11.5 7L0 14z" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></path></marker><marker id="mermaid-1_flowchart-v2-pointStart-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="11.5" orient="auto" refX="1" refY="7" viewBox="0 0 11.5 14"><path d="m0 7 11.5 7V0z" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></path></marker><marker id="mermaid-1_flowchart-v2-circleEnd" class="marker flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="11" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-1_flowchart-v2-circleStart" class="marker flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="-1" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-1_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="14" orient="auto" refX="12.25" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-1_flowchart-v2-circleStart-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="14" orient="auto" refX="-2" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-1_flowchart-v2-crossEnd" class="marker cross flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="12" refY="5.2" viewBox="0 0 11 11"><path d="m1 1 9 9m0-9-9 9" class="arrowMarkerPath" style="stroke-width:2;stroke-dasharray:1,0"></path></marker><marker id="mermaid-1_flowchart-v2-crossStart" class="marker cross flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="-1" refY="5.2" viewBox="0 0 11 11"><path d="m1 1 9 9m0-9-9 9" class="arrowMarkerPath" style="stroke-width:2;stroke-dasharray:1,0"></path></marker><marker id="mermaid-1_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" markerHeight="12" markerUnits="userSpaceOnUse" markerWidth="12" orient="auto" refX="17.7" refY="7.5" viewBox="0 0 15 15"><path d="m1 1 13 13M1 14 14 1" class="arrowMarkerPath" style="stroke-width:2.5"></path></marker><marker id="mermaid-1_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" markerHeight="12" markerUnits="userSpaceOnUse" markerWidth="12" orient="auto" refX="-3.5" refY="7.5" viewBox="0 0 15 15"><path d="m1 1 13 13M1 14 14 1" class="arrowMarkerPath" style="stroke-width:2.5;stroke-dasharray:1,0"></path></marker><g class="root"><g class="clusters"><g id="mermaid-1-w_1" class="cluster" data-look="classic"><path d="M1.852 121h203.672v104H1.852z" style="fill:#ffffde;stroke:#aa3;stroke-width:1px"></path><foreignObject width="195.672" height="24" class="cluster-label" transform="translate(5.852 121)"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5"><span class="nodeLabel" style="color:#333"><p style="background-color:transparent">callable subtree of scanToX</p></span></div></foreignObject></g></g><g class="edgePaths"><path id="mermaid-1-L_s3_s1_0" marker-end="url(#mermaid-1_flowchart-v2-pointEnd)" d="m94.578 47.5-3.123 6.083c-3.122 6.084-9.367 18.25-12.489 30.5s-3.122 24.584-1.206 34.329 5.749 16.904 7.666 20.483l1.916 3.579" class="edge-thickness-thick edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_s3_s1_0" data-look="classic" data-points="W3sieCI6OTQuNTc3NzEwMTc2OTkxMTUsInkiOjQ3LjV9LHsieCI6NzUuODQzNzUsInkiOjg0fSx7IngiOjc1Ljg0Mzc1LCJ5IjoxMjF9LHsieCI6ODkuMjMwMTY4MjY5MjMwNzcsInkiOjE0Nn1d"></path><path id="mermaid-1-L_s8_s1_0" marker-end="url(#mermaid-1_flowchart-v2-pointEnd)" d="m117.249 299.5 4.047-6.25c4.047-6.25 12.141-18.75 16.188-31.167 4.047-12.416 4.047-24.75 1.407-34.544s-7.92-17.05-10.56-20.677l-2.64-3.628" class="edge-thickness-thick edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_s8_s1_0" data-look="classic" data-points="W3sieCI6MTE3LjI0ODYxNzI1NjYzNzE3LCJ5IjoyOTkuNX0seyJ4IjoxNDEuNTMxMjUsInkiOjI2Mn0seyJ4IjoxNDEuNTMxMjUsInkiOjIyNX0seyJ4IjoxMjMuMzM3MTM5NDIzMDc2OTIsInkiOjIwMH1d"></path><path id="mermaid-1-L_w_1_s3_0" marker-end="url(#mermaid-1_flowchart-v2-pointEnd)" d="M141.531 121v-6.167c0-6.166 0-18.5-3.678-30.195s-11.033-22.751-14.711-28.279l-3.678-5.529" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_w_1_s3_0" data-look="classic" data-points="W3sieCI6MTIzLjMzNzEzOTQyMzA3NjkyLCJ5IjoxNDZ9LHsieCI6MTQxLjUzMTI1LCJ5IjoxMjF9LHsieCI6MTQxLjUzMTI1LCJ5Ijo4NH0seyJ4IjoxMTcuMjQ4NjE3MjU2NjM3MTcsInkiOjQ3LjV9XQ=="></path><path id="mermaid-1-L_w_1_s8_0" marker-end="url(#mermaid-1_flowchart-v2-pointEnd)" d="M75.844 225v6.167c0 6.166 0 18.5 2.824 30.32 2.825 11.82 8.473 23.127 11.298 28.781l2.824 5.654" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_w_1_s8_0" data-look="classic" data-points="W3sieCI6ODkuMjMwMTY4MjY5MjMwNzcsInkiOjIwMH0seyJ4Ijo3NS44NDM3NSwieSI6MjI1fSx7IngiOjc1Ljg0Mzc1LCJ5IjoyNjJ9LHsieCI6OTQuNTc3NzEwMTc2OTkxMTUsInkiOjI5OS41fV0="></path></g><g class="edgeLabels"><g class="edgeLabel"><foreignObject width="24.016" height="24" class="label" data-id="L_s3_s1_0" transform="translate(63.836 72)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>call</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="24.016" height="24" class="label" data-id="L_s8_s1_0" transform="translate(129.523 250)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>call</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="41.797" height="24" class="label" data-id="L_w_1_s3_0" transform="translate(118.739 69.153)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>return</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="41.797" height="24" class="label" data-id="L_w_1_s8_0" transform="translate(56.045 252.2)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>return</p></span></div></foreignObject></g></g><g class="nodes"><g id="mermaid-1-flowchart-s3-0" class="node default" data-look="classic"><path d="M22.82 47h161.735V8H22.82v39h-8 177.735V8H14.82v39z" class="label-container"></path><g class="label" transform="translate(30.32 15.5)"><rect></rect><foreignObject width="146.734" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>scanToX(eraseHere)</p></span></div></foreignObject></g></g><g id="mermaid-1-flowchart-s8-1" class="node default" data-look="classic"><path d="M37.93 338h131.515v-39H37.93v39h-8 147.515v-39H29.93v39z" class="label-container"></path><g class="label" transform="translate(45.43 306.5)"><rect></rect><foreignObject width="116.516" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>scanToX(goLeft)</p></span></div></foreignObject></g></g><g id="mermaid-1-flowchart-s1-2" class="node default" data-look="classic"><path d="M43 146h121.375v54H43z" class="basic label-container"></path><g class="label" transform="translate(73 161)"><rect></rect><foreignObject width="61.375" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>scanToX</p></span></div></foreignObject></g></g></g></g><defs><filter id="mermaid-1-drop-shadow" width="130%" height="130%"><feDropShadow dx="4" dy="4" flood-color="#000" flood-opacity=".06" stdDeviation="0"></feDropShadow></filter></defs><defs><filter id="mermaid-1-drop-shadow-small" width="150%" height="150%"><feDropShadow dx="2" dy="2" flood-color="#000" flood-opacity=".06" stdDeviation="0"></feDropShadow></filter></defs></svg>
<blockquote>
<p><strong>Under the hood</strong> (skippable). Node ids are runtime instance ids; <code>fromGraph</code> assigns them fresh. “Reproducible” here means: serialize, rebuild, serialize again, and compare the two graphs, ignoring the id values themselves. For a simple wrapper a second <code>toGraph</code> gives the same layout up to renaming. For a shared bare, say one shared by two wrappers, the ids can come out in a different order after the rebuild, and nodes are emitted sorted by id — the layout shifts, and ignoring the ids no longer helps.</p>
</blockquote>
<p>And here the graph stops being the answer to lean on. <code>equivalentOn</code>, though, gives <code>allAgree: true</code> on both machines: by behaviour — the same. The boundary is simple: reproducibility of the serialization only for simple wrappers, behavioural equivalence always.</p>
<h2 id="where-equivalenton-lives"><a class="heading-anchor" href="#where-equivalenton-lives">Where <code>equivalentOn</code> lives</a></h2>
<p><code>equivalentOn(reference, candidate, cases)</code> lives in <code>utilities/equivalence.ts</code>. <code>reference</code> and <code>candidate</code> are <code>Runnable</code>s (<code>{ state, getTapeBlock }</code>), <code>cases</code> is an array of test inputs; it runs both machines, compares outputs and per-step snapshots, and returns a report <code>{ results, allAgree }</code>: the per-step results plus an overall yes/no in <code>allAgree</code>.</p>
<p>What matters is that it <em>doesn’t</em> live in <code>utilities/stateGraph.ts</code>, where <code>toGraph</code>/<code>fromGraph</code> are. These are different modules, different layers of the library. <code>equivalentOn</code> knows nothing about the graph; it doesn’t care whether a wrapper is emitted as a call-site or as a single node, what frames its transitions live in. It only looks at observable behaviour.</p>
<p>That’s its role. When the reproducibility of <code>toGraph</code>/<code>fromGraph</code> is shaky (a bare shared by two wrappers), <code>equivalentOn</code> answers the question the consumer actually has: “after the rebuild — is this the same machine <em>by behaviour</em>?”. The graph is a serialization tool; behaviour is the contract.</p>
<p>The trap is easy to fall into: checking sameness with <code>===</code> on <code>State</code> instances. After a rebuild that gives <code>false</code> — <code>fromGraph</code> always makes fresh instances — even though the behaviour is identical. A false regression out of nowhere. <code>equivalentOn</code> exists precisely so that doesn’t happen — but only if you know it’s there.</p>
<h2 id="tags-data-rides-with-the-graph-identity-stays-local"><a class="heading-anchor" href="#tags-data-rides-with-the-graph-identity-stays-local">Tags: data rides with the graph, identity stays local</a></h2>
<p>A small but symptomatic v7 addition — tags (<a href="https://github.com/mellonis/turing-machine-js/issues/186"><code>turing-machine-js#186</code></a>). <code>State</code> got an API: <code>state.tag('hot', 'subroutine-entry')</code>, <code>state.tags</code>, <code>state.untag(...)</code>. Tags are string labels on an instance. They’re for tooling on top of the machine: <code>toMermaid</code> colours and groups nodes by them via <code>classDef</code>, and consumers like post-machine-js use them to mark subroutine entry points. They don’t affect the machine’s semantics.</p>
<p>What’s important about them for the three guises:</p>
<ul>
<li><strong>Behaviourally — they don’t count.</strong> <code>equivalentOn</code> doesn’t look at tags. A machine with tags and a machine without them, on the same transitions, are behaviourally the same.</li>
<li><strong>Graph-wise — they survive round-trip.</strong> <code>GraphNode.tags</code> is serialised; <code>toMermaid</code> emits tags in the node label via <code>&#x3C;br></code> <em>and</em> as <code>classDef</code> for hash-based colour grouping in the rendering; <code>fromMermaid</code> reads from the label (<code>&#x3C;br></code> is the source of truth, <code>classDef</code> is decorative).</li>
<li><strong>Object-wise — they’re local to the instance.</strong> Tags live on a specific <code>State</code>, not on the bare. Two wrappers share one bare, but each has its own set of tags. Tag one, and both the other wrapper and the bare itself stay untagged.</li>
</ul>
<p>A clean boundary: data describing a graph node rides with the graph; instance identity stays local to a specific construction. Tags land in the middle: behaviour doesn’t see them (<code>equivalentOn</code> is blind to them), but they outlast <code>===</code> identity — that resets on every rebuild, while tags ride with the graph and survive the round-trip.</p>
<h2 id="what-i-came-away-with"><a class="heading-anchor" href="#what-i-came-away-with">What I came away with</a></h2>
<p>I didn’t design the three guises all at once — they accumulated one at a time, and only in hindsight did it become clear that they’re different <em>projections</em> of a single entity, not one stretchy “equals”.</p>
<p>The object guise JavaScript gives for free: <code>===</code> and <code>instanceof</code> just work. The behavioural one I got almost for free — <code>equivalentOn</code> is just running two machines on tests. The graph guise I had to design: without it <code>fromGraph</code> couldn’t restore anything from a serialized machine, and it’s precisely for its sake that v7 packed composition into the graph data.</p>
<p>Two things dawned on me late. Bijective naming of compositions isn’t decoration but a precondition: while names are ambiguous, the graph loses one of the ways of checking for “same” before <code>fromGraph</code> even runs. <a href="https://mellonis.ru/en/articles/seven-arrows-429-trees/">The article (1)</a> is about this same ambiguity. And behavioural equivalence has to live apart from the graph: <code>equivalentOn</code> knows nothing about <code>toGraph</code>, and that’s right — a consumer more often needs the behavioural answer than a byte-for-byte round-trip.</p>
<p>Tags, too, suggested a simple check: what survives the round-trip describes a graph node, what doesn’t describes a specific instance. When I add a field, I look at which guise it lands in — that’s what decides in what sense it makes two machines “the same.”</p>
<hr>
<p><em>Code:</em> <a href="https://github.com/mellonis/turing-machine-js"><code>turing-machine-js</code></a> <em>(engine with v7 graph utilities). The interactive demo at</em> <a href="https://demo.machines.mellonis.ru">demo.machines.mellonis.ru</a> <em>draws machines via</em> <code>toMermaid</code> <em>and highlights the current transition.</em></p>]]></content:encoded>
    </item>
    <item>
      <title>Seven arrows, 429 trees: a Mermaid cleanup uncovered a 7-year naming bug</title>
      <link>https://mellonis.ru/en/articles/seven-arrows-429-trees/</link>
      <guid isPermaLink="false">https://mellonis.ru/en/articles/seven-arrows-429-trees/</guid>
      <pubDate>Tue, 26 May 2026 00:00:00 GMT</pubDate>
      <description>Composed-state naming in a Turing-machine engine was non-injective since 2019: one name, up to C_7 = 429 distinct machines. v7 fixes it with parens.</description>
      <content:encoded><![CDATA[<p>Two Turing machines walked into a diagram. They had the same name.</p>
<p>What I really mean is: two distinct wrapper states in <a href="https://github.com/mellonis/turing-machine-js"><code>@turing-machine-js/machine</code></a>, constructed differently, with different runtime behavior, and with byte-identical <code>state.name</code>. I’ve been developing the library as a hobby since 2019, and I’d missed this for seven years.</p>
<p>I caught it sideways, starting from what looked like a Mermaid cleanup ticket. It ended in a redesign of how state composition is <em>encoded in the name</em>. And along the way I learned that tucked inside that redesign is the number <math><mrow><msub><mi>C</mi><mn>7</mn></msub><mo>=</mo><mn>429</mn></mrow></math>.</p>
<figure><img src="https://mellonis.ru/articles/seven-arrows-429-trees/forest.svg?v=29b1a432" alt="Archer with bow drawn, contemplating which tree of a forest his arrow will hit" width="800" height="400"><figcaption>Archer with bow drawn, contemplating which tree of a forest his arrow will hit</figcaption></figure>
<h2 id="where-it-started"><a class="heading-anchor" href="#where-it-started">Where it started</a></h2>
<p>Composition in the engine is one primitive: <code>bareState.withOverrodeHaltState(overrideState)</code>. It returns a copy of <code>bareState</code> whose would-be halt transitions fall through to <code>overrideState</code>. From here on I’ll call <code>bareState</code> the <em>bare state</em> and the returned copy a <em>wrapper</em> over it. Composition via wrapping is the only way to build a bigger machine out of smaller halt-on-completion subroutines.</p>
<p>The wrapper’s name, in the old API, was formed like this:</p>
<pre class="shiki shiki-themes github-light github-dark language-javascript" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">state.#name </span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> `${</span><span style="color:#005CC5;--shiki-dark:#79B8FF">this</span><span style="color:#032F62;--shiki-dark:#9ECBFF">.</span><span style="color:#24292E;--shiki-dark:#E1E4E8">name</span><span style="color:#032F62;--shiki-dark:#9ECBFF">}>${</span><span style="color:#24292E;--shiki-dark:#E1E4E8">override</span><span style="color:#032F62;--shiki-dark:#9ECBFF">.</span><span style="color:#24292E;--shiki-dark:#E1E4E8">name</span><span style="color:#032F62;--shiki-dark:#9ECBFF">}`</span><span style="color:#24292E;--shiki-dark:#E1E4E8">;</span></span></code></pre>
<p>So <code>A.withOverrodeHaltState(B)</code> is named <code>A>B</code>. Simple, readable: “A, then B.”</p>
<p>That line shipped in 2019 and hadn’t been touched since. It’s the name logs use, the name error messages use, the name tests compare against, and the name any user-facing diagnostic surfaces.</p>
<p>The investigation began with the Mermaid output. <a href="https://github.com/mellonis/turing-machine-js/issues/138"><code>turing-machine-js#138</code></a> asked for a cleaner emit. Before v7, <code>toMermaid</code> rendered a wrapper as a separate node whose transitions were <em>duplicated</em> from the bare — visually it looked like the wrapper had a life of its own. But the wrapper’s transitions are the bare’s — even <code>#symbolToDataMap</code> is the same reference, not a copy. What it does own is call-frame semantics: push the override onto the halt-stack on entry, pop on the bare’s halt. Behaviorally, the wrapper adds one thing on top of the bare: where halt goes.</p>
<p>Roughly, this is what it looked like:</p>
<svg xmlns="http://www.w3.org/2000/svg" id="mermaid-0" width="100%" aria-roledescription="flowchart-v2" class="flowchart" style="font-family:arial,sans-serif;font-size:16px;fill:#333;max-width:426.546875px" viewBox="0 0 426.547 195.5"><style>@keyframes edge-animation-frame{0%{stroke-dashoffset:0}}@keyframes dash{to{stroke-dashoffset:0}}#mermaid-0 .edge-thickness-normal{stroke-width:1px}#mermaid-0 .edge-pattern-solid{stroke-dasharray:0}#mermaid-0 .marker{fill:#333;stroke:#333}#mermaid-0 .marker.cross{stroke:#333}#mermaid-0 svg{font-family:arial,sans-serif;font-size:16px}#mermaid-0 p{margin:0}#mermaid-0 .label{font-family:arial,sans-serif;color:#333}#mermaid-0 span{fill:#333;color:#333}#mermaid-0 .node circle,#mermaid-0 .node path,#mermaid-0 .node rect{fill:#ececff;stroke:#9370db;stroke-width:1px}#mermaid-0 .flowchart-link{stroke:#333;fill:none}#mermaid-0 .edgeLabel,#mermaid-0 .node .label{text-align:center}#mermaid-0 .edgeLabel,#mermaid-0 .edgeLabel p,#mermaid-0 .edgeLabel rect{background-color:rgba(232,232,232,.8)}#mermaid-0 .edgeLabel rect{opacity:.5;fill:rgba(232,232,232,.8)}#mermaid-0 .labelBkg{background-color:rgba(232,232,232,.5)}#mermaid-0 [data-look=neo].node circle,#mermaid-0 [data-look=neo].node rect{stroke:#9370db;filter:drop-shadow(1px 2px 2px #b9b9b9)}#mermaid-0 [data-look=neo].node path{stroke:#9370db;stroke-width:1px}#mermaid-0 [data-look=neo].node .outer-path{filter:drop-shadow(1px 2px 2px #b9b9b9)}#mermaid-0 :root{--mermaid-font-family:arial,sans-serif}</style><marker id="mermaid-0_flowchart-v2-pointEnd" class="marker flowchart-v2" markerHeight="8" markerUnits="userSpaceOnUse" markerWidth="8" orient="auto" refX="5" refY="5" viewBox="0 0 10 10"><path d="m0 0 10 5-10 5z" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></path></marker><marker id="mermaid-0_flowchart-v2-pointStart" class="marker flowchart-v2" markerHeight="8" markerUnits="userSpaceOnUse" markerWidth="8" orient="auto" refX="4.5" refY="5" viewBox="0 0 10 10"><path d="m0 5 10 5V0z" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></path></marker><marker id="mermaid-0_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="10.5" orient="auto" refX="11.5" refY="7" viewBox="0 0 11.5 14"><path d="m0 0 11.5 7L0 14z" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></path></marker><marker id="mermaid-0_flowchart-v2-pointStart-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="11.5" orient="auto" refX="1" refY="7" viewBox="0 0 11.5 14"><path d="m0 7 11.5 7V0z" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></path></marker><marker id="mermaid-0_flowchart-v2-circleEnd" class="marker flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="11" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-0_flowchart-v2-circleStart" class="marker flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="-1" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-0_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="14" orient="auto" refX="12.25" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-0_flowchart-v2-circleStart-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="14" orient="auto" refX="-2" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-0_flowchart-v2-crossEnd" class="marker cross flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="12" refY="5.2" viewBox="0 0 11 11"><path d="m1 1 9 9m0-9-9 9" class="arrowMarkerPath" style="stroke-width:2;stroke-dasharray:1,0"></path></marker><marker id="mermaid-0_flowchart-v2-crossStart" class="marker cross flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="-1" refY="5.2" viewBox="0 0 11 11"><path d="m1 1 9 9m0-9-9 9" class="arrowMarkerPath" style="stroke-width:2;stroke-dasharray:1,0"></path></marker><marker id="mermaid-0_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" markerHeight="12" markerUnits="userSpaceOnUse" markerWidth="12" orient="auto" refX="17.7" refY="7.5" viewBox="0 0 15 15"><path d="m1 1 13 13M1 14 14 1" class="arrowMarkerPath" style="stroke-width:2.5"></path></marker><marker id="mermaid-0_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" markerHeight="12" markerUnits="userSpaceOnUse" markerWidth="12" orient="auto" refX="-3.5" refY="7.5" viewBox="0 0 15 15"><path d="m1 1 13 13M1 14 14 1" class="arrowMarkerPath" style="stroke-width:2.5;stroke-dasharray:1,0"></path></marker><g class="root"><g class="edgePaths"><path id="mermaid-0-L_A_A1_0" marker-end="url(#mermaid-0_flowchart-v2-pointEnd)" d="m71.545 28 12.544-.083c12.545-.084 37.634-.25 57.553 1.512s34.667 5.452 42.041 7.298l7.374 1.845" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_A_A1_0" data-look="classic" data-points="W3sieCI6NzEuNTQ0NjY5MjM0MTk0ODgsInkiOjI4fSx7IngiOjE0Ni44MTI1LCJ5IjoyNy41fSx7IngiOjE5NC45Mzc1LCJ5IjozOS41NDMwMTA3NTI2ODgxNzZ9XQ=="></path><path id="mermaid-0-L_A1_haltA_0" marker-end="url(#mermaid-0_flowchart-v2-pointEnd)" d="M274.516 49.5h84.234" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_A1_haltA_0" data-look="classic" data-points="W3sieCI6Mjc0LjUxNTYyNSwieSI6NDkuNX0seyJ4IjozMTguNjMyODEyNSwieSI6NDkuNX0seyJ4IjozNjIuNzUsInkiOjQ5LjV9XQ=="></path><path id="mermaid-0-L_W_A1_0" marker-end="url(#mermaid-0_flowchart-v2-pointEnd)" d="m98.688 122.593 8.02-4.141c8.021-4.14 24.063-12.421 39.52-20.643s30.33-16.384 37.767-20.466l7.436-4.081" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_W_A1_0" data-look="classic" data-points="W3sieCI6OTguNjg3NSwieSI6MTIyLjU5Mjg2MTkxOTA5MDYxfSx7IngiOjE0Ni44MTI1LCJ5Ijo5Ny43NX0seyJ4IjoxOTQuOTM3NSwieSI6NzEuMzM3NDg3NzgxMDM2MTd9XQ=="></path><path id="mermaid-0-L_W_B_0" marker-end="url(#mermaid-0_flowchart-v2-pointEnd)" d="m98.688 156.673 8.02 1.888c8.021 1.887 24.063 5.663 43.203 7.63 19.139 1.966 41.377 2.123 52.496 2.202l11.119.079" class="edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_W_B_0" data-look="classic" data-points="W3sieCI6OTguNjg3NSwieSI6MTU2LjY3MjY4NDcyMDgyOTE1fSx7IngiOjE0Ni44MTI1LCJ5IjoxNjh9LHsieCI6MjE3LjUyNTY0NDMwMjM2Mzg0LCJ5IjoxNjguNTAwMDAwMDAwMDAwMDN9XQ==" style="stroke-dasharray:2"></path></g><g class="edgeLabels"><g class="edgeLabel"><foreignObject width="40.891" height="24" class="label" data-id="L_A_A1_0" transform="translate(126.367 15.5)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>x: y/R</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="38.234" height="24" class="label" data-id="L_A1_haltA_0" transform="translate(299.516 37.5)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>y: y/L</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="40.891" height="24" class="label" data-id="L_W_A1_0" transform="translate(126.367 85.75)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>x: y/R</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="46.25" height="24" class="label" data-id="L_W_B_0" transform="translate(123.688 156)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>onHalt</p></span></div></foreignObject></g></g><g class="nodes"><g id="mermaid-0-flowchart-A-0" class="node default" data-look="classic"><g class="basic label-container outer-path"><path fill="#ececff" stroke-width="0" d="M55.133 8h-3.578l1.25.04 1.243.12 1.234.2c.375.085.75.17 1.219.278l1.198.355 1.173.432 1.143.506 1.109.578 1.069.648 1.025.715.977.78.925.84.87.898.81.952.748 1.002.682 1.047.613 1.09.543 1.126.469 1.158.394 1.187.317 1.209.239 1.227.16 1.24c.02.328.042.656.08 1.247v1.25l-.08 1.247-.16 1.24-.24 1.227-.316 1.21-.394 1.186-.47 1.158c-.2.418-.401.835-.542 1.126l-.613 1.09-.682 1.047-.748 1.002-.81.952-.87.898-.925.84-.977.78-1.025.715-1.07.648-1.108.578-1.143.506-1.173.432-1.198.355-1.219.278-1.234.2-1.244.12-1.25.04h3.579l-1.25-.04-1.244-.12-1.234-.2-1.218-.278-1.199-.355-1.173-.432-1.143-.506-1.108-.578-1.07-.648-1.024-.715-.978-.78-.925-.84-.87-.898-.81-.952-.748-1.002-.681-1.047-.614-1.09-.542-1.126-.47-1.158-.393-1.187-.317-1.209-.24-1.227-.16-1.24-.08-1.247v-1.25c.03-.45.059-.9.08-1.247.044-.333.087-.665.16-1.24l.24-1.227.317-1.21.394-1.186.469-1.158.542-1.126.614-1.09.681-1.047.748-1.002.81-.952.87-.898.925-.84.978-.78 1.025-.715 1.069-.648 1.108-.578 1.143-.506 1.173-.432 1.199-.355 1.218-.278 1.234-.2 1.244-.12 1.25-.04"></path><path fill="none" stroke="#9370db" stroke-dasharray="0 0" stroke-width="1.3" d="M55.133 8h-3.578m3.578 0h-3.578m0 0 1.25.04M51.554 8l1.25.04m0 0 1.243.12m-1.244-.12 1.244.12m0 0 1.234.2m-1.234-.2 1.234.2m0 0 1.219.278m-1.219-.278 1.219.278m0 0 1.198.355M56.5 8.638l1.198.355m0 0 1.173.432M57.7 8.993l1.173.432m0 0 1.143.506m-1.143-.506 1.143.506m0 0 1.109.578m-1.109-.578 1.109.578m0 0 1.069.648m-1.07-.648 1.07.648m0 0 1.025.715m-1.025-.715 1.025.715m0 0 .977.78m-.977-.78.977.78m0 0 .925.84m-.925-.84.925.84m0 0 .87.898m-.87-.898.87.898m0 0 .81.952m-.81-.952.81.952m0 0 .748 1.002m-.748-1.002.748 1.002m0 0 .682 1.047m-.682-1.047.682 1.047m0 0 .613 1.09m-.613-1.09.613 1.09m0 0 .543 1.126m-.543-1.126.543 1.126m0 0 .469 1.158m-.47-1.158.47 1.158m0 0 .394 1.187m-.394-1.187.394 1.187m0 0 .317 1.209m-.317-1.21.317 1.21m0 0 .239 1.227m-.24-1.227.24 1.227m0 0 .16 1.24m-.16-1.24.16 1.24m0 0 .08 1.247m-.08-1.247.08 1.247m0 0v1.25m0-1.25v1.25m0 0-.08 1.247m.08-1.247-.08 1.247m0 0-.16 1.24m.16-1.24-.16 1.24m0 0-.24 1.227m.24-1.227-.24 1.227m0 0-.316 1.21m.317-1.21-.317 1.21m0 0-.394 1.186m.394-1.187-.394 1.187m0 0-.47 1.158m.47-1.158-.47 1.158m0 0-.542 1.126m.543-1.126-.543 1.126m0 0-.613 1.09m.613-1.09-.613 1.09m0 0-.682 1.047m.682-1.047-.682 1.047m0 0-.748 1.002m.748-1.002-.748 1.002m0 0-.81.952m.81-.952-.81.952m0 0-.87.898m.87-.898-.87.898m0 0-.925.84m.925-.84-.925.84m0 0-.977.78m.977-.78-.977.78m0 0-1.025.715m1.025-.715c-.246.17-.49.342-1.025.715m0 0-1.07.648m1.07-.648-1.07.648m0 0-1.108.578m1.109-.578-1.109.578m0 0-1.143.506m1.143-.506-1.143.506m0 0-1.173.432m1.173-.432-1.173.432m0 0-1.198.355m1.198-.355-1.198.355m0 0-1.219.278m1.219-.278-1.219.278m0 0-1.234.2m1.234-.2-1.234.2m0 0-1.244.12m1.244-.12-1.244.12m0 0-1.25.04m1.25-.04-1.25.04m0 0h3.579m-3.578 0h3.578m0 0-1.25-.04m1.25.04-1.25-.04m0 0-1.244-.12m1.244.12-1.244-.12m0 0-1.234-.2m1.234.2-1.234-.2m0 0-1.218-.278m1.218.278-1.218-.278m0 0-1.199-.355m1.199.355-1.199-.355m0 0-1.173-.432m1.173.432-1.173-.432m0 0-1.143-.506m1.143.506-1.143-.506m0 0-1.108-.578m1.108.578-1.108-.578m0 0-1.07-.648m1.07.648-1.07-.648m0 0-1.024-.715m1.025.715-1.025-.715m0 0-.978-.78m.978.78-.978-.78m0 0-.925-.84m.925.84-.925-.84m0 0-.87-.898m.87.898-.87-.898m0 0-.81-.952m.81.952-.81-.952m0 0-.748-1.002m.748 1.002-.748-1.002m0 0-.681-1.047m.681 1.047-.681-1.047m0 0-.614-1.09m.614 1.09-.614-1.09m0 0-.542-1.126m.542 1.126-.542-1.126m0 0-.47-1.158m.47 1.158-.47-1.158m0 0c-.12-.366-.242-.732-.393-1.187m.394 1.187-.394-1.187m0 0-.317-1.209m.317 1.21-.317-1.21m0 0-.24-1.227m.24 1.227-.24-1.227m0 0c-.045-.353-.09-.706-.16-1.24m.16 1.24-.16-1.24m0 0-.08-1.247m.08 1.247c-.016-.258-.032-.517-.08-1.247m0 0v-1.25m0 1.25v-1.25m0 0 .08-1.247m-.08 1.247c.03-.454.06-.908.08-1.247m0 0c.057-.434.113-.867.16-1.24m-.16 1.24c.034-.253.066-.506.16-1.24m0 0 .24-1.227m-.24 1.227.24-1.227m0 0 .317-1.21m-.317 1.21.317-1.21m0 0 .394-1.186m-.394 1.187.394-1.187m0 0 .469-1.158m-.47 1.158.47-1.158m0 0 .542-1.126m-.542 1.126.542-1.126m0 0 .614-1.09m-.614 1.09.614-1.09m0 0 .681-1.047m-.681 1.047.681-1.047m0 0 .748-1.002m-.748 1.002.748-1.002m0 0 .81-.952m-.81.952.81-.952m0 0 .87-.898m-.87.898.87-.898m0 0 .925-.84m-.925.84.925-.84m0 0 .978-.78m-.978.78.978-.78m0 0 1.025-.715m-1.025.715 1.025-.715m0 0 1.069-.648m-1.07.648 1.07-.648m0 0 1.108-.578m-1.108.578 1.108-.578m0 0 1.143-.506m-1.143.506 1.143-.506m0 0c.436-.16.872-.32 1.173-.432m-1.173.432 1.173-.432m0 0 1.199-.355m-1.199.355 1.199-.355m0 0c.345-.08.69-.158 1.218-.278m-1.218.278 1.218-.278m0 0 1.234-.2m-1.234.2 1.234-.2m0 0 1.244-.12m-1.244.12 1.244-.12m0 0 1.25-.04m-1.25.04 1.25-.04m0 0"></path></g><g class="label" transform="translate(48.008 15.5)"><rect></rect><foreignObject width="10.672" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>A</p></span></div></foreignObject></g></g><g id="mermaid-0-flowchart-A1-1" class="node default" data-look="classic"><path d="M194.938 22.5h79.578v54h-79.578z" class="basic label-container"></path><g class="label" transform="translate(224.938 37.5)"><rect></rect><foreignObject width="19.578" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>A1</p></span></div></foreignObject></g></g><g id="mermaid-0-flowchart-haltA-3" class="node default" data-look="classic"><g class="basic label-container" transform="translate(390.648 49.5)"><circle r="27.898" class="outer-circle"></circle><circle r="22.898" class="inner-circle"></circle></g><g class="label" transform="translate(377.75 37.5)"><rect></rect><foreignObject width="25.797" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>halt</p></span></div></foreignObject></g></g><g id="mermaid-0-flowchart-W-4" class="node default" data-look="classic"><path d="M8 119h90.688v54H8z" class="basic label-container"></path><g class="label" transform="translate(38 134)"><rect></rect><foreignObject width="30.688" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>A>B</p></span></div></foreignObject></g></g><g id="mermaid-0-flowchart-B-7" class="node default" data-look="classic"><g class="basic label-container outer-path"><path fill="#ececff" stroke-width="0" d="M236.516 148.5h-3.578l1.249.04 1.244.12 1.234.2 1.219.278 1.198.355 1.173.432 1.143.506 1.108.578c.37.225.74.45 1.07.648l1.025.715.977.78.925.84.87.898.81.952.748 1.002.682 1.047.613 1.09.543 1.126.469 1.158.394 1.187.317 1.209.239 1.227.16 1.24.08 1.247v1.25l-.08 1.247-.16 1.24-.24 1.227-.316 1.21-.394 1.186-.47 1.158-.542 1.126-.613 1.09c-.17.26-.34.52-.682 1.047l-.748 1.002-.81.952-.87.898-.925.84-.977.78-1.026.715-1.069.648-1.108.578-1.143.506-1.173.432-1.198.355-1.219.278-1.234.2-1.244.12-1.25.04h3.579l-1.25-.04-1.244-.12-1.234-.2-1.219-.278-1.198-.355-1.173-.432-1.143-.506-1.108-.578-1.07-.648-1.025-.715-.977-.78-.925-.84-.87-.898-.81-.952-.748-1.002-.682-1.047-.613-1.09-.542-1.126-.47-1.158-.393-1.187-.317-1.209-.24-1.227-.16-1.24-.08-1.247v-1.25l.08-1.247.16-1.24.24-1.227.317-1.21.393-1.186.47-1.158.542-1.126.613-1.09.682-1.047.748-1.002.81-.952.87-.898.925-.84.977-.78 1.026-.715 1.069-.648 1.108-.578 1.143-.506 1.173-.432 1.198-.355 1.219-.278 1.234-.2 1.244-.12 1.25-.04"></path><path fill="none" stroke="#9370db" stroke-dasharray="0 0" stroke-width="1.3" d="M236.516 148.5h-3.578m3.578 0h-3.578m0 0 1.249.04m-1.25-.04 1.25.04m0 0 1.244.12m-1.244-.12 1.244.12m0 0 1.234.2m-1.234-.2 1.234.2m0 0 1.219.278m-1.219-.278 1.219.278m0 0 1.198.355m-1.198-.355 1.198.355m0 0 1.173.432m-1.173-.432 1.173.432m0 0 1.143.506m-1.143-.506 1.143.506m0 0 1.108.578m-1.108-.578 1.108.578m0 0 1.07.648m-1.07-.648 1.07.648m0 0 1.025.715m-1.026-.715 1.026.715m0 0 .977.78m-.977-.78.977.78m0 0 .925.84m-.925-.84.925.84m0 0 .87.898m-.87-.898.87.898m0 0 .81.952m-.81-.952.81.952m0 0 .748 1.002m-.748-1.002c.27.36.539.722.748 1.002m0 0 .682 1.047m-.682-1.047.682 1.047m0 0 .613 1.09m-.613-1.09.613 1.09m0 0 .543 1.126m-.543-1.126.543 1.126m0 0 .469 1.158m-.47-1.158.47 1.158m0 0 .394 1.187m-.394-1.187.394 1.187m0 0 .317 1.209m-.317-1.21.317 1.21m0 0 .239 1.227m-.24-1.227.24 1.227m0 0 .16 1.24m-.16-1.24c.04.314.08.629.16 1.24m0 0 .08 1.247m-.08-1.247.08 1.247m0 0v1.25m0-1.25v1.25m0 0c-.02.3-.04.6-.08 1.247m.08-1.247-.08 1.247m0 0-.16 1.24m.16-1.24-.16 1.24m0 0-.24 1.227m.24-1.227-.24 1.227m0 0-.316 1.21m.317-1.21-.317 1.21m0 0-.394 1.186m.394-1.187-.394 1.187m0 0-.47 1.158m.47-1.158-.47 1.158m0 0-.542 1.126m.543-1.126-.543 1.126m0 0-.613 1.09m.613-1.09-.613 1.09m0 0-.682 1.047m.682-1.047-.682 1.047m0 0-.748 1.002m.748-1.002-.748 1.002m0 0-.81.952m.81-.952-.81.952m0 0-.87.898m.87-.898-.87.898m0 0-.925.84m.925-.84-.925.84m0 0-.977.78m.977-.78-.977.78m0 0-1.026.715m1.026-.715-1.026.715m0 0-1.069.648m1.07-.648-1.07.648m0 0-1.108.578m1.108-.578-1.108.578m0 0-1.143.506m1.143-.506-1.143.506m0 0-1.173.432m1.173-.432-1.173.432m0 0-1.198.355m1.198-.355-1.198.355m0 0-1.219.278m1.219-.278-1.219.278m0 0-1.234.2m1.234-.2-1.234.2m0 0-1.244.12m1.244-.12-1.244.12m0 0-1.25.04m1.25-.04-1.25.04m0 0h3.579m-3.578 0h3.578m0 0-1.25-.04m1.25.04-1.25-.04m0 0-1.244-.12m1.244.12-1.244-.12m0 0-1.234-.2m1.234.2-1.234-.2m0 0-1.219-.278m1.219.278-1.219-.278m0 0-1.198-.355m1.198.355-1.198-.355m0 0-1.173-.432m1.173.432-1.173-.432m0 0-1.143-.506m1.143.506-1.143-.506m0 0-1.108-.578m1.108.578-1.108-.578m0 0-1.07-.648m1.07.648-1.07-.648m0 0c-.275-.192-.55-.385-1.025-.715m1.026.715-1.026-.715m0 0-.977-.78m.977.78-.977-.78m0 0-.925-.84m.925.84-.925-.84m0 0-.87-.898m.87.898-.87-.898m0 0-.81-.952m.81.952-.81-.952m0 0-.748-1.002m.748 1.002-.748-1.002m0 0-.682-1.047m.682 1.047-.682-1.047m0 0-.613-1.09m.613 1.09-.613-1.09m0 0c-.215-.445-.43-.891-.542-1.126m.542 1.126-.542-1.126m0 0-.47-1.158m.47 1.158-.47-1.158m0 0-.393-1.187m.393 1.187-.393-1.187m0 0-.317-1.209m.317 1.21-.317-1.21m0 0-.24-1.227m.24 1.227-.24-1.227m0 0-.16-1.24m.16 1.24-.16-1.24m0 0-.08-1.247m.08 1.247-.08-1.247m0 0v-1.25m0 1.25v-1.25m0 0c.024-.357.047-.715.08-1.247m-.08 1.247c.03-.45.058-.9.08-1.247m0 0 .16-1.24m-.16 1.24.16-1.24m0 0 .24-1.227m-.24 1.227.24-1.227m0 0 .317-1.21m-.317 1.21.317-1.21m0 0 .393-1.186m-.393 1.187.393-1.187m0 0 .47-1.158m-.47 1.158.47-1.158m0 0 .542-1.126m-.542 1.126.542-1.126m0 0 .613-1.09m-.613 1.09.613-1.09m0 0 .682-1.047m-.682 1.047.682-1.047m0 0 .748-1.002m-.748 1.002.748-1.002m0 0 .81-.952m-.81.952.81-.952m0 0 .87-.898m-.87.898.87-.898m0 0 .925-.84m-.925.84.925-.84m0 0 .977-.78m-.977.78.977-.78m0 0 1.026-.715m-1.026.715 1.026-.715m0 0 1.069-.648m-1.07.648 1.07-.648m0 0 1.108-.578m-1.108.578 1.108-.578m0 0 1.143-.506m-1.143.506 1.143-.506m0 0 1.173-.432m-1.173.432 1.173-.432m0 0 1.198-.355m-1.198.355 1.198-.355m0 0 1.219-.278m-1.219.278 1.219-.278m0 0 1.234-.2m-1.234.2 1.234-.2m0 0 1.244-.12m-1.244.12 1.244-.12m0 0 1.25-.04m-1.25.04 1.25-.04m0 0"></path></g><g class="label" transform="translate(229.39 156)"><rect></rect><foreignObject width="10.672" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>B</p></span></div></foreignObject></g></g></g></g><defs><filter id="mermaid-0-drop-shadow" width="130%" height="130%"><feDropShadow dx="4" dy="4" flood-color="#000" flood-opacity=".06" stdDeviation="0"></feDropShadow></filter></defs><defs><filter id="mermaid-0-drop-shadow-small" width="150%" height="150%"><feDropShadow dx="2" dy="2" flood-color="#000" flood-opacity=".06" stdDeviation="0"></feDropShadow></filter></defs></svg>
<p><code>A</code> and <code>A>B</code> are two nodes with literally the same outgoing transition to <code>A1</code>, plus the wrapper gets a dashed <code>onHalt</code> arrow to <code>B</code>. The reader sees “two distinct machines,” when behaviorally it’s one machine with a single point of divergence — where halt goes.</p>
<p>The first fix attempt looked reasonable: render the wrapper as a single node that reuses the bare’s transitions, with the override-halt as a separate arrow:</p>
<svg xmlns="http://www.w3.org/2000/svg" id="mermaid-1" width="100%" aria-roledescription="flowchart-v2" class="flowchart" style="font-family:arial,sans-serif;font-size:16px;fill:#333;max-width:564.40185546875px" viewBox="0 0 564.402 71.797"><style>@keyframes edge-animation-frame{0%{stroke-dashoffset:0}}@keyframes dash{to{stroke-dashoffset:0}}#mermaid-1 .edge-thickness-normal{stroke-width:1px}#mermaid-1 .edge-pattern-solid{stroke-dasharray:0}#mermaid-1 .marker{fill:#333;stroke:#333}#mermaid-1 .marker.cross{stroke:#333}#mermaid-1 svg{font-family:arial,sans-serif;font-size:16px}#mermaid-1 p{margin:0}#mermaid-1 .label{font-family:arial,sans-serif;color:#333}#mermaid-1 span{fill:#333;color:#333}#mermaid-1 .node circle,#mermaid-1 .node path,#mermaid-1 .node rect{fill:#ececff;stroke:#9370db;stroke-width:1px}#mermaid-1 .flowchart-link{stroke:#333;fill:none}#mermaid-1 .edgeLabel,#mermaid-1 .node .label{text-align:center}#mermaid-1 .edgeLabel,#mermaid-1 .edgeLabel p,#mermaid-1 .edgeLabel rect{background-color:rgba(232,232,232,.8)}#mermaid-1 .edgeLabel rect{opacity:.5;fill:rgba(232,232,232,.8)}#mermaid-1 .labelBkg{background-color:rgba(232,232,232,.5)}#mermaid-1 [data-look=neo].node circle,#mermaid-1 [data-look=neo].node rect{stroke:#9370db;filter:drop-shadow(1px 2px 2px #b9b9b9)}#mermaid-1 [data-look=neo].node path{stroke:#9370db;stroke-width:1px}#mermaid-1 [data-look=neo].node .outer-path{filter:drop-shadow(1px 2px 2px #b9b9b9)}#mermaid-1 :root{--mermaid-font-family:arial,sans-serif}</style><marker id="mermaid-1_flowchart-v2-pointEnd" class="marker flowchart-v2" markerHeight="8" markerUnits="userSpaceOnUse" markerWidth="8" orient="auto" refX="5" refY="5" viewBox="0 0 10 10"><path d="m0 0 10 5-10 5z" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></path></marker><marker id="mermaid-1_flowchart-v2-pointStart" class="marker flowchart-v2" markerHeight="8" markerUnits="userSpaceOnUse" markerWidth="8" orient="auto" refX="4.5" refY="5" viewBox="0 0 10 10"><path d="m0 5 10 5V0z" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></path></marker><marker id="mermaid-1_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="10.5" orient="auto" refX="11.5" refY="7" viewBox="0 0 11.5 14"><path d="m0 0 11.5 7L0 14z" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></path></marker><marker id="mermaid-1_flowchart-v2-pointStart-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="11.5" orient="auto" refX="1" refY="7" viewBox="0 0 11.5 14"><path d="m0 7 11.5 7V0z" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></path></marker><marker id="mermaid-1_flowchart-v2-circleEnd" class="marker flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="11" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-1_flowchart-v2-circleStart" class="marker flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="-1" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-1_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="14" orient="auto" refX="12.25" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-1_flowchart-v2-circleStart-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="14" orient="auto" refX="-2" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-1_flowchart-v2-crossEnd" class="marker cross flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="12" refY="5.2" viewBox="0 0 11 11"><path d="m1 1 9 9m0-9-9 9" class="arrowMarkerPath" style="stroke-width:2;stroke-dasharray:1,0"></path></marker><marker id="mermaid-1_flowchart-v2-crossStart" class="marker cross flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="-1" refY="5.2" viewBox="0 0 11 11"><path d="m1 1 9 9m0-9-9 9" class="arrowMarkerPath" style="stroke-width:2;stroke-dasharray:1,0"></path></marker><marker id="mermaid-1_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" markerHeight="12" markerUnits="userSpaceOnUse" markerWidth="12" orient="auto" refX="17.7" refY="7.5" viewBox="0 0 15 15"><path d="m1 1 13 13M1 14 14 1" class="arrowMarkerPath" style="stroke-width:2.5"></path></marker><marker id="mermaid-1_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" markerHeight="12" markerUnits="userSpaceOnUse" markerWidth="12" orient="auto" refX="-3.5" refY="7.5" viewBox="0 0 15 15"><path d="m1 1 13 13M1 14 14 1" class="arrowMarkerPath" style="stroke-width:2.5;stroke-dasharray:1,0"></path></marker><g class="root"><g class="edgePaths"><path id="mermaid-1-L_W_A1_0" marker-end="url(#mermaid-1_flowchart-v2-pointEnd)" d="M98.688 35.898h86.89" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_W_A1_0" data-look="classic" data-points="W3sieCI6OTguNjg3NSwieSI6MzUuODk4NDM3NX0seyJ4IjoxNDQuMTMyODEyNSwieSI6MzUuODk4NDM3NX0seyJ4IjoxODkuNTc4MTI1LCJ5IjozNS44OTg0Mzc1fV0="></path><path id="mermaid-1-L_A1_haltA_0" marker-end="url(#mermaid-1_flowchart-v2-pointEnd)" d="M269.156 35.898h84.235" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_A1_haltA_0" data-look="classic" data-points="W3sieCI6MjY5LjE1NjI1LCJ5IjozNS44OTg0Mzc1fSx7IngiOjMxMy4yNzM0Mzc1LCJ5IjozNS44OTg0Mzc1fSx7IngiOjM1Ny4zOTA2MjUsInkiOjM1Ljg5ODQzNzV9XQ=="></path><path id="mermaid-1-L_haltA_B_0" marker-end="url(#mermaid-1_flowchart-v2-pointEnd)" d="M413.188 35.898h8.984c8.984 0 26.953 0 44.338.078 17.386.077 34.188.231 42.589.308l8.401.078" class="edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_haltA_B_0" data-look="classic" data-points="W3sieCI6NDEzLjE4NzUsInkiOjM1Ljg5ODQzNzV9LHsieCI6NDY3LjA5Mzc1LCJ5IjozNS44OTg0Mzc1fSx7IngiOjUyMS41MDAwMDAwMDAwMDEzLCJ5IjozNi4zOTg0Mzc1fV0=" style="stroke-dasharray:2"></path></g><g class="edgeLabels"><g class="edgeLabel"><foreignObject width="40.891" height="24" class="label" data-id="L_W_A1_0" transform="translate(123.688 23.898)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>x: y/R</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="38.234" height="24" class="label" data-id="L_A1_haltA_0" transform="translate(294.156 23.898)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>y: y/L</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="57.813" height="24" class="label" data-id="L_haltA_B_0" transform="translate(438.188 23.898)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>override</p></span></div></foreignObject></g></g><g class="nodes"><g id="mermaid-1-flowchart-W-0" class="node default" data-look="classic"><path d="M8 8.898h90.688v54H8z" class="basic label-container"></path><g class="label" transform="translate(38 23.898)"><rect></rect><foreignObject width="30.688" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>A>B</p></span></div></foreignObject></g></g><g id="mermaid-1-flowchart-A1-1" class="node default" data-look="classic"><path d="M189.578 8.898h79.578v54h-79.578z" class="basic label-container"></path><g class="label" transform="translate(219.578 23.898)"><rect></rect><foreignObject width="19.578" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>A1</p></span></div></foreignObject></g></g><g id="mermaid-1-flowchart-haltA-3" class="node default" data-look="classic"><g class="basic label-container" transform="translate(385.29 35.898)"><circle r="27.898" class="outer-circle"></circle><circle r="22.898" class="inner-circle"></circle></g><g class="label" transform="translate(372.39 23.898)"><rect></rect><foreignObject width="25.797" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>halt</p></span></div></foreignObject></g></g><g id="mermaid-1-flowchart-B-5" class="node default" data-look="classic"><g class="basic label-container outer-path"><path fill="#ececff" stroke-width="0" d="M540.49 16.398h-3.578l1.25.04 1.243.12 1.234.2 1.22.278 1.197.356 1.174.432 1.143.506 1.108.578 1.069.648 1.025.715.977.78.926.84.87.898.81.951.747 1.002.682 1.048.614 1.089.542 1.126.469 1.159.394 1.186.317 1.21.239 1.226.16 1.24.08 1.247v1.25l-.08 1.248c-.04.302-.078.603-.16 1.24l-.24 1.227-.316 1.209-.394 1.186-.47 1.159-.541 1.126-.614 1.09-.682 1.047-.747 1.001-.81.952-.87.898-.926.84-.977.78-1.025.715-1.07.648-1.107.578-1.143.506-1.174.432-1.198.356-1.219.278-1.234.2-1.244.12-1.25.04h3.579l-1.25-.04-1.244-.12-1.234-.2-1.218-.278-1.199-.356-1.173-.432-1.143-.506-1.108-.578-1.069-.648-1.025-.715-.977-.78-.926-.84-.87-.898-.81-.952-.747-1.001-.682-1.048c-.24-.424-.479-.849-.614-1.09l-.542-1.125-.47-1.159-.393-1.186-.317-1.21-.24-1.226-.159-1.24-.08-1.248v-1.25l.08-1.247.16-1.24.239-1.227.317-1.209.394-1.186.469-1.159.542-1.126.614-1.09.682-1.047.747-1.002.81-.951.87-.898c.225-.205.45-.41.926-.84l.977-.78 1.025-.715 1.069-.648 1.108-.578 1.143-.506 1.173-.432 1.199-.356 1.218-.278 1.234-.2 1.245-.12 1.249-.04"></path><path fill="none" stroke="#9370db" stroke-dasharray="0 0" stroke-width="1.3" d="M540.49 16.398h-3.578m3.578 0h-3.578m0 0 1.25.04m-1.25-.04 1.25.04m0 0 1.243.12m-1.244-.12 1.244.12m0 0 1.234.2m-1.234-.2 1.234.2m0 0 1.22.278m-1.22-.278 1.22.278m0 0 1.197.356m-1.198-.356 1.198.356m0 0 1.174.432m-1.174-.432 1.174.432m0 0 1.143.506m-1.143-.506 1.143.506m0 0 1.108.578m-1.108-.578 1.108.578m0 0 1.069.648m-1.07-.648 1.07.648m0 0 1.025.715m-1.025-.715 1.025.715m0 0 .977.78m-.977-.78.977.78m0 0 .926.84m-.926-.84.926.84m0 0 .87.898m-.87-.898.87.898m0 0 .81.951m-.81-.951.81.951m0 0 .747 1.002m-.747-1.002.747 1.002m0 0 .682 1.048m-.682-1.048.682 1.048m0 0 .614 1.089m-.614-1.09.614 1.09m0 0 .542 1.126m-.542-1.126.542 1.126m0 0 .469 1.159m-.47-1.159.47 1.159m0 0 .394 1.186m-.394-1.186.394 1.186m0 0 .317 1.21m-.317-1.21.317 1.21m0 0 .239 1.226m-.24-1.227.24 1.227m0 0 .16 1.24m-.16-1.24.16 1.24m0 0 .08 1.247m-.08-1.247.08 1.247m0 0v1.25m0-1.25v1.25m0 0-.08 1.248m.08-1.248-.08 1.248m0 0-.16 1.24m.16-1.24-.16 1.24m0 0-.24 1.227m.24-1.227c-.09.463-.18.926-.24 1.227m0 0-.316 1.209m.317-1.21-.317 1.21m0 0-.394 1.186m.394-1.186-.394 1.186m0 0-.47 1.159m.47-1.159-.47 1.159m0 0-.541 1.126m.542-1.126-.542 1.126m0 0-.614 1.09m.614-1.09-.614 1.09m0 0-.682 1.047m.682-1.048-.682 1.048m0 0-.747 1.001m.747-1.001-.747 1.001m0 0-.81.952m.81-.952-.81.952m0 0-.87.898m.87-.898-.87.898m0 0-.926.84m.926-.84-.926.84m0 0-.977.78m.977-.78-.977.78m0 0-1.025.715m1.025-.715-1.025.715m0 0-1.07.648m1.07-.648-1.07.648m0 0-1.107.578m1.108-.578-1.108.578m0 0-1.143.506m1.143-.506-1.143.506m0 0-1.174.432m1.174-.432-1.174.432m0 0-1.198.356m1.198-.356-1.198.356m0 0-1.219.278m1.22-.278-1.22.278m0 0-1.234.2m1.234-.2-1.234.2m0 0-1.244.12m1.244-.12-1.244.12m0 0c-.335.01-.67.02-1.25.04m1.25-.04-1.25.04m0 0h3.579m-3.578 0h3.578m0 0-1.25-.04m1.25.04-1.25-.04m0 0-1.244-.12m1.245.12-1.245-.12m0 0-1.234-.2m1.234.2-1.234-.2m0 0-1.218-.278m1.218.278-1.218-.278m0 0-1.199-.356m1.199.356-1.199-.356m0 0-1.173-.432m1.173.432-1.173-.432m0 0-1.143-.506m1.143.506-1.143-.506m0 0-1.108-.578m1.108.578-1.108-.578m0 0-1.069-.648m1.069.648-1.069-.648m0 0-1.025-.715m1.025.715c-.25-.174-.5-.35-1.025-.715m0 0-.977-.78m.977.78-.977-.78m0 0-.926-.84m.926.84-.926-.84m0 0-.87-.898m.87.898-.87-.898m0 0-.81-.952m.81.952-.81-.952m0 0-.747-1.001m.747 1.001-.747-1.001m0 0-.682-1.048m.682 1.048-.682-1.048m0 0-.614-1.09m.614 1.09-.614-1.09m0 0-.542-1.125m.542 1.126-.542-1.126m0 0-.47-1.159m.47 1.159-.47-1.159m0 0-.393-1.186m.394 1.186-.394-1.186m0 0-.317-1.21m.317 1.21-.317-1.21m0 0c-.07-.36-.14-.721-.24-1.226m.24 1.227-.24-1.227m0 0-.159-1.24m.16 1.24-.16-1.24m0 0-.08-1.248m.08 1.248-.08-1.248m0 0v-1.25m0 1.25v-1.25m0 0 .08-1.247m-.08 1.247.08-1.247m0 0 .16-1.24m-.16 1.24.16-1.24m0 0 .239-1.227m-.24 1.227.24-1.227m0 0 .317-1.209m-.317 1.21.317-1.21m0 0 .394-1.186m-.394 1.186.394-1.186m0 0 .469-1.159m-.47 1.159.47-1.159m0 0 .542-1.126m-.542 1.126.542-1.126m0 0 .614-1.09m-.614 1.09.614-1.09m0 0 .682-1.047m-.682 1.048.682-1.048m0 0 .747-1.002m-.747 1.002.747-1.002m0 0 .81-.951m-.81.951.81-.951m0 0 .87-.898m-.87.898.87-.898m0 0 .926-.84m-.926.84.926-.84m0 0 .977-.78m-.977.78.977-.78m0 0c.25-.175.5-.35 1.025-.715m-1.025.715 1.025-.715m0 0 1.069-.648m-1.069.648 1.069-.648m0 0 1.108-.578m-1.108.578 1.108-.578m0 0 1.143-.506m-1.143.506 1.143-.506m0 0 1.173-.432m-1.173.432 1.173-.432m0 0 1.199-.356m-1.199.356 1.199-.356m0 0 1.218-.278m-1.218.278 1.218-.278m0 0 1.234-.2m-1.234.2 1.234-.2m0 0 1.245-.12m-1.245.12c.428-.04.855-.082 1.245-.12m0 0 1.249-.04m-1.25.04 1.25-.04m0 0"></path></g><g class="label" transform="translate(533.365 23.898)"><rect></rect><foreignObject width="10.672" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>B</p></span></div></foreignObject></g></g></g></g><defs><filter id="mermaid-1-drop-shadow" width="130%" height="130%"><feDropShadow dx="4" dy="4" flood-color="#000" flood-opacity=".06" stdDeviation="0"></feDropShadow></filter></defs><defs><filter id="mermaid-1-drop-shadow-small" width="150%" height="150%"><feDropShadow dx="2" dy="2" flood-color="#000" flood-opacity=".06" stdDeviation="0"></feDropShadow></filter></defs></svg>
<p>One <code>A>B</code> node, transitions reused from the bare’s graph, override-halt as a separate dashed arrow from halt to <code>B</code>. Clean, compact, no visual noise. Almost worked.</p>
<h2 id="almost-worked-then-broke"><a class="heading-anchor" href="#almost-worked-then-broke">Almost worked — then broke</a></h2>
<p>Take <code>minusOne</code> from <a href="https://github.com/mellonis/turing-machine-js/tree/master/packages/library-binary-numbers"><code>library-binary-numbers</code></a> — it’s built by nested wrapping:</p>
<pre class="shiki shiki-themes github-light github-dark language-javascript" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">const</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> minusOne</span><span style="color:#D73A49;--shiki-dark:#F97583"> =</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> invertNumber</span></span>
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">  .</span><span style="color:#6F42C1;--shiki-dark:#B392F0">withOverrodeHaltState</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span></span>
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">    plusOne</span></span>
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">      .</span><span style="color:#6F42C1;--shiki-dark:#B392F0">withOverrodeHaltState</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span></span>
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">        invertNumber</span></span>
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">          .</span><span style="color:#6F42C1;--shiki-dark:#B392F0">withOverrodeHaltState</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(normalizeNumber),</span></span>
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">      ),</span></span>
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">  );</span></span></code></pre>
<p>Composite name: <code>invertNumber>plusOne>invertNumber>normalizeNumber</code> — three <code>></code> separators in real code, and already one base (<code>invertNumber</code>) appears twice. When a name gets longer, it’s tempting to read it as a <em>walking instruction</em>. Take <code>A>B>B>A>A>B>B>A</code> (seven separators): each letter is a bare state you land in after the previous one halts. The sequence of bases visited should equal the name.</p>
<p>Except that’s wishful reading. The name doesn’t formally determine the traversal. It <em>resembles</em> it. And only if the chain was constructed the one specific way I happened to picture when I wrote the naming rule in 2019.</p>
<h2 id="the-catch"><a class="heading-anchor" href="#the-catch">The catch</a></h2>
<p>Take a smaller example: <code>A>B>A</code>. How many ways to build it?</p>
<p>At least two:</p>
<pre class="shiki shiki-themes github-light github-dark language-javascript" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Construction 1</span></span>
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">const</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> c1</span><span style="color:#D73A49;--shiki-dark:#F97583"> =</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> A</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">withOverrodeHaltState</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">B</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">withOverrodeHaltState</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">A</span><span style="color:#24292E;--shiki-dark:#E1E4E8">));</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Construction 2</span></span>
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">const</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> c2</span><span style="color:#D73A49;--shiki-dark:#F97583"> =</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> A</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">withOverrodeHaltState</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">B</span><span style="color:#24292E;--shiki-dark:#E1E4E8">).</span><span style="color:#6F42C1;--shiki-dark:#B392F0">withOverrodeHaltState</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">A</span><span style="color:#24292E;--shiki-dark:#E1E4E8">);</span></span></code></pre>
<p>Both flatten to the string <code>A>B>A</code> under <code>${this.name}>${override.name}</code>. But the wrapper topologies differ — each construction builds its own binary tree (internal <code>•</code> nodes are <code>withOverrodeHaltState</code> applications, leaves are plain <code>State</code> instances):</p>
<svg xmlns="http://www.w3.org/2000/svg" id="mermaid-2" width="100%" aria-roledescription="flowchart-v2" class="flowchart" style="font-family:arial,sans-serif;font-size:16px;fill:#333;max-width:183.31369018554688px" viewBox="0 -1.695 183.314 264.305"><style>@keyframes edge-animation-frame{0%{stroke-dashoffset:0}}@keyframes dash{to{stroke-dashoffset:0}}#mermaid-2 .edge-thickness-normal{stroke-width:1px}#mermaid-2 .edge-pattern-solid{stroke-dasharray:0}#mermaid-2 .marker{fill:#333;stroke:#333}#mermaid-2 .marker.cross{stroke:#333}#mermaid-2 svg{font-family:arial,sans-serif;font-size:16px}#mermaid-2 p{margin:0}#mermaid-2 .label{font-family:arial,sans-serif;color:#333}#mermaid-2 span{fill:#333;color:#333}#mermaid-2 .node circle,#mermaid-2 .node path,#mermaid-2 .node rect{fill:#ececff;stroke:#9370db;stroke-width:1px}#mermaid-2 .flowchart-link{stroke:#333;fill:none}#mermaid-2 .edgeLabel,#mermaid-2 .node .label{text-align:center}#mermaid-2 .edgeLabel,#mermaid-2 .edgeLabel p,#mermaid-2 .edgeLabel rect{background-color:rgba(232,232,232,.8)}#mermaid-2 .edgeLabel rect{opacity:.5;fill:rgba(232,232,232,.8)}#mermaid-2 .labelBkg{background-color:rgba(232,232,232,.5)}#mermaid-2 [data-look=neo].node circle,#mermaid-2 [data-look=neo].node rect{stroke:#9370db;filter:drop-shadow(1px 2px 2px #b9b9b9)}#mermaid-2 [data-look=neo].node path{stroke:#9370db;stroke-width:1px}#mermaid-2 [data-look=neo].node .outer-path{filter:drop-shadow(1px 2px 2px #b9b9b9)}#mermaid-2 :root{--mermaid-font-family:arial,sans-serif}</style><marker id="mermaid-2_flowchart-v2-pointEnd" class="marker flowchart-v2" markerHeight="8" markerUnits="userSpaceOnUse" markerWidth="8" orient="auto" refX="5" refY="5" viewBox="0 0 10 10"><path d="m0 0 10 5-10 5z" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></path></marker><marker id="mermaid-2_flowchart-v2-pointStart" class="marker flowchart-v2" markerHeight="8" markerUnits="userSpaceOnUse" markerWidth="8" orient="auto" refX="4.5" refY="5" viewBox="0 0 10 10"><path d="m0 5 10 5V0z" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></path></marker><marker id="mermaid-2_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="10.5" orient="auto" refX="11.5" refY="7" viewBox="0 0 11.5 14"><path d="m0 0 11.5 7L0 14z" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></path></marker><marker id="mermaid-2_flowchart-v2-pointStart-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="11.5" orient="auto" refX="1" refY="7" viewBox="0 0 11.5 14"><path d="m0 7 11.5 7V0z" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></path></marker><marker id="mermaid-2_flowchart-v2-circleEnd" class="marker flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="11" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-2_flowchart-v2-circleStart" class="marker flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="-1" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-2_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="14" orient="auto" refX="12.25" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-2_flowchart-v2-circleStart-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="14" orient="auto" refX="-2" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-2_flowchart-v2-crossEnd" class="marker cross flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="12" refY="5.2" viewBox="0 0 11 11"><path d="m1 1 9 9m0-9-9 9" class="arrowMarkerPath" style="stroke-width:2;stroke-dasharray:1,0"></path></marker><marker id="mermaid-2_flowchart-v2-crossStart" class="marker cross flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="-1" refY="5.2" viewBox="0 0 11 11"><path d="m1 1 9 9m0-9-9 9" class="arrowMarkerPath" style="stroke-width:2;stroke-dasharray:1,0"></path></marker><marker id="mermaid-2_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" markerHeight="12" markerUnits="userSpaceOnUse" markerWidth="12" orient="auto" refX="17.7" refY="7.5" viewBox="0 0 15 15"><path d="m1 1 13 13M1 14 14 1" class="arrowMarkerPath" style="stroke-width:2.5"></path></marker><marker id="mermaid-2_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" markerHeight="12" markerUnits="userSpaceOnUse" markerWidth="12" orient="auto" refX="-3.5" refY="7.5" viewBox="0 0 15 15"><path d="m1 1 13 13M1 14 14 1" class="arrowMarkerPath" style="stroke-width:2.5;stroke-dasharray:1,0"></path></marker><g class="root"><g class="edgePaths"><path id="mermaid-2-L_o1_a1_0" marker-end="url(#mermaid-2_flowchart-v2-pointEnd)" d="m58.148 26.255-5.408 6.559c-5.407 6.559-16.223 19.677-21.557 31.82-5.333 12.142-5.184 23.309-5.11 28.892l.075 5.584" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_o1_a1_0" data-look="classic" data-points="W3sieCI6NTguMTQ4MzUwNDU1MTIxMzQ2LCJ5IjoyNi4yNTUzOTE5MjY4NDM1Mn0seyJ4IjoyNS43MDA5MTgxOTc2MzE4MzYsInkiOjY1LjYwOTM3NX0seyJ4IjoyNi4yMDA5MTgxOTc2MzE4MzYsInkiOjEwMy4xMDkzNzV9XQ=="></path><path id="mermaid-2-L_o1_i1_0" marker-end="url(#mermaid-2_flowchart-v2-pointEnd)" d="m71.259 26.255 5.408 6.559c5.408 6.559 16.224 19.677 21.632 33.269s5.408 27.657 5.408 34.689v7.033" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_o1_i1_0" data-look="classic" data-points="W3sieCI6NzEuMjU5MDkxNjM3Nzc0MTYsInkiOjI2LjI1NTM5MTkyNjg0MzUyfSx7IngiOjEwMy43MDY1MjM4OTUyNjM2NywieSI6NjUuNjA5Mzc1fSx7IngiOjEwMy43MDY1MjM4OTUyNjM2NywieSI6MTExLjgwNDY4NzV9XQ=="></path><path id="mermaid-2-L_i1_b1_0" marker-end="url(#mermaid-2_flowchart-v2-pointEnd)" d="m97.493 130.33-6.081 8.047c-6.081 8.046-18.244 24.139-24.251 37.769s-5.858 24.797-5.783 30.38l.074 5.584" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_i1_b1_0" data-look="classic" data-points="W3sieCI6OTcuNDkzNDAzMTI0MTk1MjgsInkiOjEzMC4zMzAzMDY1MDE3Njg4fSx7IngiOjYxLjAwNTYwNTY5NzYzMTgzNiwieSI6MTc4LjYwOTM3NX0seyJ4Ijo2MS41MDU2MDU2OTc2MzE4MzYsInkiOjIxNi4xMDkzNzV9XQ=="></path><path id="mermaid-2-L_i1_a2_0" marker-end="url(#mermaid-2_flowchart-v2-pointEnd)" d="m109.92 130.33 6.081 8.047c6.081 8.046 18.244 24.139 24.4 37.769s6.304 24.797 6.379 30.38l.074 5.584" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_i1_a2_0" data-look="classic" data-points="W3sieCI6MTA5LjkxOTY0NDY2NjMzMjA2LCJ5IjoxMzAuMzMwMzA2NTAxNzY4OH0seyJ4IjoxNDYuNDA3NDQyMDkyODk1NSwieSI6MTc4LjYwOTM3NX0seyJ4IjoxNDYuOTA3NDQyMDkyODk1NSwieSI6MjE2LjEwOTM3NX1d"></path></g><g class="edgeLabels"><g class="edgeLabel"><foreignObject width="32.031" height="24" class="label" data-id="L_o1_a1_0" transform="translate(9.685 53.61)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>bare</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="57.813" height="24" class="label" data-id="L_o1_i1_0" transform="translate(74.8 53.61)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>override</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="32.031" height="24" class="label" data-id="L_i1_b1_0" transform="translate(44.99 166.61)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>bare</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="57.813" height="24" class="label" data-id="L_i1_a2_0" transform="translate(117.501 166.61)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>override</p></span></div></foreignObject></g></g><g class="nodes"><g id="mermaid-2-flowchart-o1-0" class="node default" data-look="classic" transform="translate(64.704 18.305)"><circle r="10.305" class="basic label-container"></circle><g class="label" transform="translate(-2.805 -12)"><rect></rect><foreignObject width="5.609" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>•</p></span></div></foreignObject></g></g><g id="mermaid-2-flowchart-a1-1" class="node default" data-look="classic"><g class="basic label-container outer-path"><path fill="#ececff" stroke-width="0" d="M27.49 102.61h-3.578l1.25.04 1.243.12 1.234.199 1.22.278 1.197.356 1.174.431 1.143.506 1.108.579 1.069.648 1.025.715.977.78.926.84.87.898.81.951.747 1.002.682 1.048.614 1.089.542 1.126.469 1.159.394 1.186.317 1.21.239 1.226.16 1.24.08 1.247v1.25l-.08 1.248-.16 1.24-.24 1.227-.316 1.209-.394 1.186-.47 1.159-.541 1.126-.614 1.089-.682 1.048-.747 1.001-.81.952-.87.898-.926.84-.977.78-1.025.715-1.07.648-1.107.578-1.143.506-1.174.432-1.198.356-1.219.278-1.234.2-1.244.12c-.337.01-.674.02-1.25.04h3.579c-.495-.017-.99-.032-1.25-.04l-1.244-.12-1.234-.2-1.218-.278-1.199-.356-1.173-.432-1.143-.506-1.108-.578-1.069-.648-1.025-.715-.977-.78-.926-.84-.87-.898-.81-.952-.747-1.001-.682-1.048-.614-1.09-.542-1.125-.47-1.159-.393-1.186-.317-1.21-.24-1.226-.159-1.24-.08-1.248v-1.25l.08-1.247.16-1.24.239-1.227.317-1.209.394-1.186.469-1.159.542-1.126.614-1.09.682-1.047.747-1.002.81-.951.87-.898.926-.84.977-.78 1.025-.715 1.069-.648 1.108-.579 1.143-.506 1.173-.431 1.199-.356 1.218-.278 1.234-.2c.427-.04.853-.082 1.245-.12l1.249-.04"></path><path fill="none" stroke="#9370db" stroke-dasharray="0 0" stroke-width="1.3" d="M27.49 102.61h-3.578m3.578 0h-3.578m0 0 1.25.04m-1.25-.04 1.25.04m0 0 1.243.12m-1.244-.12 1.244.12m0 0 1.234.199m-1.234-.2c.367.06.734.12 1.234.2m0 0 1.22.278m-1.22-.278 1.22.278m0 0 1.197.356m-1.198-.356 1.198.356m0 0 1.174.431m-1.174-.431 1.174.431m0 0c.232.104.465.207 1.143.506m-1.143-.506c.233.104.467.208 1.143.506m0 0 1.108.579m-1.108-.579 1.108.579m0 0 1.069.648m-1.07-.648 1.07.648m0 0 1.025.715m-1.025-.715 1.025.715m0 0 .977.78m-.977-.78.977.78m0 0 .926.84m-.926-.84.926.84m0 0 .87.898m-.87-.898.87.898m0 0 .81.951m-.81-.951.81.951m0 0 .747 1.002m-.747-1.002.747 1.002m0 0 .682 1.048m-.682-1.048.682 1.048m0 0 .614 1.089m-.614-1.09.614 1.09m0 0 .542 1.126m-.542-1.126.542 1.126m0 0 .469 1.159m-.47-1.159.47 1.159m0 0 .394 1.186m-.394-1.186.394 1.186m0 0 .317 1.21m-.317-1.21.317 1.21m0 0 .239 1.226m-.24-1.227.24 1.227m0 0 .16 1.24m-.16-1.24c.05.392.1.783.16 1.24m0 0 .08 1.247m-.08-1.247.08 1.247m0 0v1.25m0-1.25v1.25m0 0-.08 1.248m.08-1.248-.08 1.248m0 0-.16 1.24m.16-1.24-.16 1.24m0 0-.24 1.227m.24-1.227-.24 1.227m0 0-.316 1.209m.317-1.21-.317 1.21m0 0-.394 1.186m.394-1.186-.394 1.186m0 0-.47 1.159m.47-1.159-.47 1.159m0 0-.541 1.126m.542-1.126-.542 1.126m0 0-.614 1.089m.614-1.09-.614 1.09m0 0-.682 1.048m.682-1.048-.682 1.048m0 0-.747 1.001m.747-1.001-.747 1.001m0 0-.81.952m.81-.952-.81.952m0 0-.87.898m.87-.898-.87.898m0 0-.926.84m.926-.84-.926.84m0 0-.977.78m.977-.78-.977.78m0 0-1.025.715m1.025-.715-1.025.715m0 0-1.07.648m1.07-.648-1.07.648m0 0-1.107.578m1.108-.578-1.108.578m0 0-1.143.506m1.143-.506-1.143.506m0 0-1.174.432m1.174-.432-1.174.432m0 0-1.198.356m1.198-.356-1.198.356m0 0-1.219.278m1.22-.278-1.22.278m0 0-1.234.2m1.234-.2-1.234.2m0 0-1.244.12m1.244-.12-1.244.12m0 0c-.492.015-.984.03-1.25.04m1.25-.04-1.25.04m0 0h3.579m-3.578 0h3.578m0 0-1.25-.04m1.25.04-1.25-.04m0 0-1.244-.12m1.245.12c-.404-.04-.807-.078-1.245-.12m0 0-1.234-.2m1.234.2-1.234-.2m0 0-1.218-.278m1.218.278-1.218-.278m0 0-1.199-.356m1.199.356-1.199-.356m0 0-1.173-.432m1.173.432-1.173-.432m0 0-1.143-.506m1.143.506-1.143-.506m0 0-1.108-.578m1.108.578-1.108-.578m0 0-1.069-.648m1.069.648-1.069-.648m0 0-1.025-.715m1.025.715-1.025-.715m0 0-.977-.78m.977.78-.977-.78m0 0-.926-.84m.926.84-.926-.84m0 0-.87-.898m.87.898-.87-.898m0 0-.81-.952m.81.952-.81-.952m0 0-.747-1.001m.747 1.001-.747-1.001m0 0-.682-1.048m.682 1.048-.682-1.048m0 0-.614-1.09m.614 1.09-.614-1.09m0 0-.542-1.125m.542 1.126-.542-1.126m0 0-.47-1.159m.47 1.159c-.154-.38-.307-.76-.47-1.159m0 0-.393-1.186m.394 1.186-.394-1.186m0 0-.317-1.21m.317 1.21-.317-1.21m0 0-.24-1.226m.24 1.227c-.055-.284-.11-.568-.24-1.227m0 0c-.038-.305-.078-.61-.159-1.24m.16 1.24-.16-1.24m0 0L8 122.734m.08 1.248L8 122.734m0 0v-1.25m0 1.25v-1.25m0 0 .08-1.247M8 121.484l.08-1.247m0 0 .16-1.24m-.16 1.24.16-1.24m0 0 .239-1.227m-.24 1.227.24-1.227m0 0 .317-1.209m-.317 1.21.317-1.21m0 0 .394-1.186m-.394 1.186.394-1.186m0 0 .469-1.159m-.47 1.159.47-1.159m0 0 .542-1.126m-.542 1.126.542-1.126m0 0 .614-1.09m-.614 1.09.614-1.09m0 0 .682-1.047m-.682 1.048.682-1.048m0 0 .747-1.002m-.747 1.002.747-1.002m0 0 .81-.951m-.81.951.81-.951m0 0 .87-.898m-.87.898.87-.898m0 0c.369-.335.737-.67.926-.84m-.926.84.926-.84m0 0 .977-.78m-.977.78.977-.78m0 0 1.025-.715m-1.025.715 1.025-.715m0 0 1.069-.648m-1.069.648 1.069-.648m0 0 1.108-.579m-1.108.579 1.108-.579m0 0 1.143-.506m-1.143.506 1.143-.506m0 0 1.173-.431m-1.173.431 1.173-.431m0 0 1.199-.356m-1.199.356 1.199-.356m0 0 1.218-.278m-1.218.278 1.218-.278m0 0 1.234-.2m-1.234.2 1.234-.2m0 0 1.245-.12m-1.245.12 1.245-.12m0 0 1.249-.04m-1.25.04 1.25-.04m0 0"></path></g><g class="label" transform="translate(20.365 110.11)"><rect></rect><foreignObject width="10.672" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>A</p></span></div></foreignObject></g></g><g id="mermaid-2-flowchart-i1-3" class="node default" data-look="classic" transform="translate(103.707 122.11)"><circle r="10.305" class="basic label-container"></circle><g class="label" transform="translate(-2.805 -12)"><rect></rect><foreignObject width="5.609" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>•</p></span></div></foreignObject></g></g><g id="mermaid-2-flowchart-b1-5" class="node default" data-look="classic"><g class="basic label-container outer-path"><path fill="#ececff" stroke-width="0" d="M62.795 215.61h-3.578l1.249.04 1.244.12 1.234.199 1.219.278 1.198.356 1.173.431 1.143.506 1.109.579 1.068.648 1.026.715.977.78.925.84.87.898.81.951.748 1.002.682 1.048.613 1.089.543 1.126.469 1.159.394 1.186c.12.462.242.924.317 1.21l.239 1.226.16 1.24.08 1.247v1.25l-.08 1.248-.16 1.24-.24 1.227-.316 1.209-.394 1.186-.47 1.159-.542 1.126-.613 1.089-.682 1.048-.748 1.001-.81.952c-.23.239-.462.477-.87.898l-.925.84-.977.78-1.026.715-1.068.648-1.109.578c-.417.185-.833.37-1.143.506l-1.173.432-1.198.356-1.219.278-1.234.2c-.41.039-.82.078-1.244.12-.391.012-.783.024-1.25.04h3.579c-.434-.015-.868-.028-1.25-.04l-1.244-.12-1.234-.2-1.219-.278-1.198-.356-1.173-.432-1.143-.506-1.108-.578-1.07-.648-1.024-.715-.978-.78-.925-.84-.87-.898-.81-.952-.748-1.001-.682-1.048-.613-1.09-.542-1.125-.47-1.159-.393-1.186-.317-1.21-.24-1.226-.16-1.24c-.02-.321-.04-.642-.08-1.248v-1.25c.03-.452.059-.904.08-1.247l.16-1.24.24-1.227.317-1.209.394-1.186c.128-.319.257-.637.469-1.159l.542-1.126.613-1.09.682-1.047.748-1.002.81-.951.87-.898.925-.84.978-.78 1.025-.715 1.069-.648 1.108-.579 1.143-.506 1.173-.431 1.198-.356c.4-.09.798-.182 1.22-.278l1.233-.2 1.244-.12c.347-.01.694-.022 1.25-.04"></path><path fill="none" stroke="#9370db" stroke-dasharray="0 0" stroke-width="1.3" d="M62.795 215.61h-3.578m3.578 0h-3.578m0 0 1.249.04m-1.25-.04c.471.014.942.03 1.25.04m0 0 1.244.12m-1.244-.12c.429.04.857.082 1.244.12m0 0 1.234.199m-1.234-.2 1.234.2m0 0 1.219.278m-1.219-.278 1.219.278m0 0 1.198.356m-1.198-.356 1.198.356m0 0 1.173.431m-1.173-.431 1.173.431m0 0c.44.195.878.39 1.143.506m-1.143-.506 1.143.506m0 0 1.109.579m-1.109-.579 1.109.579m0 0c.414.25.829.502 1.068.648m-1.068-.648 1.068.648m0 0 1.026.715m-1.026-.715 1.026.715m0 0 .977.78m-.977-.78.977.78m0 0 .925.84m-.925-.84.925.84m0 0 .87.898m-.87-.898q.439.45.87.898m0 0 .81.951m-.81-.951c.24.28.479.562.81.951m0 0 .748 1.002m-.748-1.002.748 1.002m0 0 .682 1.048m-.682-1.048.682 1.048m0 0 .613 1.089m-.613-1.09.613 1.09m0 0 .543 1.126m-.543-1.126.543 1.126m0 0 .469 1.159m-.47-1.159.47 1.159m0 0 .394 1.186m-.394-1.186.394 1.186m0 0 .317 1.21m-.317-1.21.317 1.21m0 0 .239 1.226m-.24-1.227.24 1.227m0 0 .16 1.24m-.16-1.24.16 1.24m0 0 .08 1.247m-.08-1.247c.015.25.032.5.08 1.247m0 0v1.25m0-1.25v1.25m0 0-.08 1.248m.08-1.248-.08 1.248m0 0-.16 1.24m.16-1.24-.16 1.24m0 0-.24 1.227m.24-1.227-.24 1.227m0 0-.316 1.209m.317-1.21-.317 1.21m0 0-.394 1.186m.394-1.186-.394 1.186m0 0-.47 1.159m.47-1.159-.47 1.159m0 0-.542 1.126m.543-1.126-.543 1.126m0 0-.613 1.089m.613-1.09-.613 1.09m0 0-.682 1.048m.682-1.048-.682 1.048m0 0-.748 1.001m.748-1.001-.748 1.001m0 0-.81.952m.81-.952-.81.952m0 0-.87.898m.87-.898c-.32.33-.638.66-.87.898m0 0-.925.84m.925-.84-.925.84m0 0-.977.78m.977-.78-.977.78m0 0-1.026.715m1.026-.715-1.026.715m0 0-1.068.648m1.068-.648-1.068.648m0 0-1.109.578m1.109-.578-1.109.578m0 0-1.143.506m1.143-.506-1.143.506m0 0-1.173.432m1.173-.432-1.173.432m0 0-1.198.356m1.198-.356-1.198.356m0 0-1.219.278m1.219-.278-1.219.278m0 0-1.234.2m1.234-.2-1.234.2m0 0c-.41.039-.82.078-1.244.12m1.244-.12c-.431.04-.863.083-1.244.12m0 0-1.25.04m1.25-.04c-.469.014-.938.03-1.25.04m0 0h3.579m-3.578 0h3.578m0 0c-.468-.016-.935-.03-1.25-.04m1.25.04-1.25-.04m0 0-1.244-.12m1.244.12-1.244-.12m0 0-1.234-.2m1.234.2-1.234-.2m0 0-1.219-.278m1.22.278c-.478-.11-.955-.218-1.22-.278m0 0-1.198-.356m1.198.356-1.198-.356m0 0-1.173-.432m1.173.432-1.173-.432m0 0-1.143-.506m1.143.506-1.143-.506m0 0-1.108-.578m1.108.578-1.108-.578m0 0-1.07-.648m1.07.648-1.07-.648m0 0-1.024-.715m1.025.715-1.025-.715m0 0-.978-.78m.978.78c-.29-.23-.578-.46-.978-.78m0 0-.925-.84m.925.84c-.21-.19-.42-.38-.925-.84m0 0-.87-.898m.87.898-.87-.898m0 0-.81-.952m.81.952-.81-.952m0 0-.748-1.001m.748 1.001-.748-1.001m0 0-.682-1.048m.682 1.048-.682-1.048m0 0-.613-1.09m.613 1.09-.613-1.09m0 0-.542-1.125m.542 1.126-.542-1.126m0 0-.47-1.159m.47 1.159-.47-1.159m0 0-.393-1.186m.394 1.186-.394-1.186m0 0-.317-1.21m.317 1.21-.317-1.21m0 0-.24-1.226m.24 1.227-.24-1.227m0 0c-.055-.43-.11-.861-.16-1.24m.16 1.24-.16-1.24m0 0-.08-1.248m.08 1.248-.08-1.248m0 0v-1.25m0 1.25v-1.25m0 0c.02-.293.038-.585.08-1.247m-.08 1.247c.021-.318.042-.637.08-1.247m0 0c.045-.34.089-.68.16-1.24m-.16 1.24.16-1.24m0 0 .24-1.227m-.24 1.227.24-1.227m0 0 .317-1.209m-.317 1.21.317-1.21m0 0 .394-1.186m-.394 1.186.394-1.186m0 0 .469-1.159m-.47 1.159.47-1.159m0 0 .542-1.126m-.542 1.126.542-1.126m0 0 .613-1.09m-.613 1.09.613-1.09m0 0 .682-1.047m-.682 1.048.682-1.048m0 0 .748-1.002m-.748 1.002.748-1.002m0 0 .81-.951m-.81.951.81-.951m0 0 .87-.898m-.87.898.87-.898m0 0 .925-.84m-.925.84.925-.84m0 0 .978-.78m-.978.78.978-.78m0 0 1.025-.715m-1.025.715 1.025-.715m0 0 1.069-.648m-1.07.648 1.07-.648m0 0 1.108-.579m-1.108.579 1.108-.579m0 0c.408-.18.816-.36 1.143-.506m-1.143.506 1.143-.506m0 0 1.173-.431m-1.173.431 1.173-.431m0 0 1.198-.356m-1.198.356 1.198-.356m0 0 1.22-.278m-1.22.278 1.22-.278m0 0 1.233-.2m-1.234.2 1.234-.2m0 0 1.244-.12m-1.244.12 1.244-.12m0 0 1.25-.04m-1.25.04 1.25-.04m0 0"></path></g><g class="label" transform="translate(55.67 223.11)"><rect></rect><foreignObject width="10.672" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>B</p></span></div></foreignObject></g></g><g id="mermaid-2-flowchart-a2-7" class="node default" data-look="classic"><g class="basic label-container outer-path"><path fill="#ececff" stroke-width="0" d="M148.197 215.61h-3.579l1.25.04 1.244.12 1.234.199 1.219.278 1.198.356 1.173.431c.291.13.582.258 1.143.506l1.108.579 1.07.648 1.025.715.977.78.925.84.87.898.81.951.748 1.002.682 1.048.613 1.089.542 1.126.47 1.159.393 1.186.317 1.21.24 1.226c.044.345.088.69.16 1.24l.08 1.247v1.25l-.08 1.248-.16 1.24-.24 1.227-.317 1.209-.393 1.186-.47 1.159-.542 1.126-.613 1.089c-.255.39-.509.781-.682 1.048l-.748 1.001-.81.952-.87.898-.925.84-.977.78-1.026.715-1.069.648-1.108.578-1.143.506-1.173.432-1.198.356-1.219.278-1.234.2c-.43.04-.862.082-1.244.12l-1.25.04h3.579l-1.25-.04c-.264-.026-.528-.052-1.244-.12-.36-.06-.722-.117-1.234-.2l-1.219-.278-1.198-.356-1.173-.432-1.143-.506-1.108-.578-1.07-.648-1.025-.715-.977-.78c-.33-.298-.658-.597-.925-.84l-.87-.898-.81-.952-.748-1.001c-.22-.34-.442-.68-.682-1.048l-.613-1.09-.543-1.125-.469-1.159-.394-1.186-.317-1.21-.239-1.226-.16-1.24c-.03-.487-.062-.973-.08-1.248v-1.25l.08-1.247.16-1.24.24-1.227.316-1.209.394-1.186.47-1.159.542-1.126.613-1.09.682-1.047.748-1.002.81-.951.87-.898.925-.84.977-.78 1.026-.715 1.069-.648 1.108-.579 1.143-.506 1.173-.431 1.198-.356 1.219-.278 1.234-.2 1.244-.12 1.25-.04"></path><path fill="none" stroke="#9370db" stroke-dasharray="0 0" stroke-width="1.3" d="M148.197 215.61h-3.579m3.579 0h-3.579m0 0c.35.01.7.022 1.25.04m-1.25-.04c.282.008.564.017 1.25.04m0 0 1.244.12m-1.244-.12 1.244.12m0 0 1.234.199m-1.234-.2 1.234.2m0 0 1.219.278m-1.219-.278 1.219.278m0 0 1.198.356m-1.198-.356 1.198.356m0 0 1.173.431m-1.173-.431 1.173.431m0 0 1.143.506m-1.143-.506 1.143.506m0 0 1.108.579m-1.108-.579 1.108.579m0 0 1.07.648m-1.07-.648 1.07.648m0 0 1.025.715m-1.026-.715 1.026.715m0 0 .977.78m-.977-.78.977.78m0 0 .925.84m-.925-.84.925.84m0 0 .87.898m-.87-.898.87.898m0 0 .81.951m-.81-.951.81.951m0 0 .748 1.002m-.748-1.002.748 1.002m0 0 .682 1.048m-.682-1.048.682 1.048m0 0 .613 1.089m-.613-1.09c.2.358.402.715.613 1.09m0 0 .542 1.126m-.542-1.126.542 1.126m0 0 .47 1.159m-.47-1.159.47 1.159m0 0 .393 1.186m-.393-1.186.393 1.186m0 0 .317 1.21m-.317-1.21.317 1.21m0 0 .24 1.226m-.24-1.227.24 1.227m0 0 .16 1.24m-.16-1.24c.049.384.098.768.16 1.24m0 0c.027.439.056.877.08 1.247m-.08-1.247c.028.454.058.908.08 1.247m0 0v1.25m0-1.25v1.25m0 0c-.023.341-.044.682-.08 1.248m.08-1.248-.08 1.248m0 0-.16 1.24m.16-1.24-.16 1.24m0 0-.24 1.227m.24-1.227-.24 1.227m0 0-.317 1.209m.317-1.21-.317 1.21m0 0-.393 1.186m.393-1.186-.393 1.186m0 0-.47 1.159m.47-1.159-.47 1.159m0 0-.542 1.126m.542-1.126-.542 1.126m0 0-.613 1.089m.613-1.09-.613 1.09m0 0-.682 1.048m.682-1.048-.682 1.048m0 0-.748 1.001m.748-1.001-.748 1.001m0 0-.81.952m.81-.952-.81.952m0 0-.87.898m.87-.898-.87.898m0 0-.925.84m.925-.84-.925.84m0 0-.977.78m.977-.78-.977.78m0 0c-.25.173-.498.347-1.026.715m1.026-.715-1.026.715m0 0-1.069.648m1.07-.648-1.07.648m0 0-1.108.578m1.108-.578-1.108.578m0 0-1.143.506m1.143-.506-1.143.506m0 0-1.173.432m1.173-.432-1.173.432m0 0-1.198.356m1.198-.356-1.198.356m0 0-1.219.278m1.219-.278-1.219.278m0 0-1.234.2m1.234-.2-1.234.2m0 0-1.244.12m1.244-.12c-.43.04-.859.082-1.244.12m0 0-1.25.04m1.25-.04c-.329.01-.657.02-1.25.04m0 0h3.579m-3.579 0h3.579m0 0-1.25-.04m1.25.04-1.25-.04m0 0c-.305-.03-.61-.06-1.244-.12m1.244.12-1.244-.12m0 0-1.234-.2m1.234.2-1.234-.2m0 0-1.219-.278m1.219.278-1.219-.278m0 0-1.198-.356m1.198.356-1.198-.356m0 0-1.173-.432m1.173.432-1.173-.432m0 0-1.143-.506m1.143.506-1.143-.506m0 0-1.108-.578m1.108.578-1.108-.578m0 0-1.07-.648m1.07.648-1.07-.648m0 0-1.025-.715m1.026.715-1.026-.715m0 0-.977-.78m.977.78-.977-.78m0 0-.925-.84m.925.84c-.189-.17-.377-.342-.925-.84m0 0-.87-.898m.87.898-.87-.898m0 0c-.213-.25-.427-.5-.81-.952m.81.952-.81-.952m0 0-.748-1.001m.748 1.001-.748-1.001m0 0-.682-1.048m.682 1.048-.682-1.048m0 0-.613-1.09m.613 1.09-.613-1.09m0 0-.543-1.125m.543 1.126c-.13-.272-.262-.543-.543-1.126m0 0-.469-1.159m.47 1.159-.47-1.159m0 0-.394-1.186m.394 1.186-.394-1.186m0 0-.317-1.21m.317 1.21-.317-1.21m0 0-.239-1.226m.24 1.227-.24-1.227m0 0-.16-1.24m.16 1.24-.16-1.24m0 0-.08-1.248m.08 1.248-.08-1.248m0 0v-1.25m0 1.25v-1.25m0 0c.017-.257.034-.514.08-1.247m-.08 1.247.08-1.247m0 0 .16-1.24m-.16 1.24.16-1.24m0 0 .24-1.227m-.24 1.227.24-1.227m0 0 .316-1.209m-.317 1.21.317-1.21m0 0 .394-1.186m-.394 1.186.394-1.186m0 0 .47-1.159m-.47 1.159.47-1.159m0 0 .542-1.126m-.543 1.126.543-1.126m0 0 .613-1.09m-.613 1.09.613-1.09m0 0 .682-1.047m-.682 1.048.682-1.048m0 0 .748-1.002m-.748 1.002.748-1.002m0 0 .81-.951m-.81.951.81-.951m0 0c.334-.345.667-.69.87-.898m-.87.898.87-.898m0 0 .925-.84m-.925.84.925-.84m0 0 .977-.78m-.977.78.977-.78m0 0 1.026-.715m-1.026.715 1.026-.715m0 0c.386-.235.773-.47 1.069-.648m-1.07.648 1.07-.648m0 0 1.108-.579m-1.108.579 1.108-.579m0 0 1.143-.506m-1.143.506 1.143-.506m0 0 1.173-.431m-1.173.431 1.173-.431m0 0 1.198-.356m-1.198.356 1.198-.356m0 0 1.219-.278m-1.219.278 1.219-.278m0 0 1.234-.2m-1.234.2 1.234-.2m0 0 1.244-.12m-1.244.12 1.244-.12m0 0c.347-.01.693-.022 1.25-.04m-1.25.04 1.25-.04m0 0"></path></g><g class="label" transform="translate(141.072 223.11)"><rect></rect><foreignObject width="10.672" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>A</p></span></div></foreignObject></g></g></g></g><defs><filter id="mermaid-2-drop-shadow" width="130%" height="130%"><feDropShadow dx="4" dy="4" flood-color="#000" flood-opacity=".06" stdDeviation="0"></feDropShadow></filter></defs><defs><filter id="mermaid-2-drop-shadow-small" width="150%" height="150%"><feDropShadow dx="2" dy="2" flood-color="#000" flood-opacity=".06" stdDeviation="0"></feDropShadow></filter></defs></svg>
<svg xmlns="http://www.w3.org/2000/svg" id="mermaid-3" width="100%" aria-roledescription="flowchart-v2" class="flowchart" style="font-family:arial,sans-serif;font-size:16px;fill:#333;max-width:179.01893615722656px" viewBox="0 -1.695 179.019 264.305"><style>@keyframes edge-animation-frame{0%{stroke-dashoffset:0}}@keyframes dash{to{stroke-dashoffset:0}}#mermaid-3 .edge-thickness-normal{stroke-width:1px}#mermaid-3 .edge-pattern-solid{stroke-dasharray:0}#mermaid-3 .marker{fill:#333;stroke:#333}#mermaid-3 .marker.cross{stroke:#333}#mermaid-3 svg{font-family:arial,sans-serif;font-size:16px}#mermaid-3 p{margin:0}#mermaid-3 .label{font-family:arial,sans-serif;color:#333}#mermaid-3 span{fill:#333;color:#333}#mermaid-3 .node circle,#mermaid-3 .node path,#mermaid-3 .node rect{fill:#ececff;stroke:#9370db;stroke-width:1px}#mermaid-3 .flowchart-link{stroke:#333;fill:none}#mermaid-3 .edgeLabel,#mermaid-3 .node .label{text-align:center}#mermaid-3 .edgeLabel,#mermaid-3 .edgeLabel p,#mermaid-3 .edgeLabel rect{background-color:rgba(232,232,232,.8)}#mermaid-3 .edgeLabel rect{opacity:.5;fill:rgba(232,232,232,.8)}#mermaid-3 .labelBkg{background-color:rgba(232,232,232,.5)}#mermaid-3 [data-look=neo].node circle,#mermaid-3 [data-look=neo].node rect{stroke:#9370db;filter:drop-shadow(1px 2px 2px #b9b9b9)}#mermaid-3 [data-look=neo].node path{stroke:#9370db;stroke-width:1px}#mermaid-3 [data-look=neo].node .outer-path{filter:drop-shadow(1px 2px 2px #b9b9b9)}#mermaid-3 :root{--mermaid-font-family:arial,sans-serif}</style><marker id="mermaid-3_flowchart-v2-pointEnd" class="marker flowchart-v2" markerHeight="8" markerUnits="userSpaceOnUse" markerWidth="8" orient="auto" refX="5" refY="5" viewBox="0 0 10 10"><path d="m0 0 10 5-10 5z" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></path></marker><marker id="mermaid-3_flowchart-v2-pointStart" class="marker flowchart-v2" markerHeight="8" markerUnits="userSpaceOnUse" markerWidth="8" orient="auto" refX="4.5" refY="5" viewBox="0 0 10 10"><path d="m0 5 10 5V0z" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></path></marker><marker id="mermaid-3_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="10.5" orient="auto" refX="11.5" refY="7" viewBox="0 0 11.5 14"><path d="m0 0 11.5 7L0 14z" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></path></marker><marker id="mermaid-3_flowchart-v2-pointStart-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="11.5" orient="auto" refX="1" refY="7" viewBox="0 0 11.5 14"><path d="m0 7 11.5 7V0z" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></path></marker><marker id="mermaid-3_flowchart-v2-circleEnd" class="marker flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="11" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-3_flowchart-v2-circleStart" class="marker flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="-1" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-3_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="14" orient="auto" refX="12.25" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-3_flowchart-v2-circleStart-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="14" orient="auto" refX="-2" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-3_flowchart-v2-crossEnd" class="marker cross flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="12" refY="5.2" viewBox="0 0 11 11"><path d="m1 1 9 9m0-9-9 9" class="arrowMarkerPath" style="stroke-width:2;stroke-dasharray:1,0"></path></marker><marker id="mermaid-3_flowchart-v2-crossStart" class="marker cross flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="-1" refY="5.2" viewBox="0 0 11 11"><path d="m1 1 9 9m0-9-9 9" class="arrowMarkerPath" style="stroke-width:2;stroke-dasharray:1,0"></path></marker><marker id="mermaid-3_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" markerHeight="12" markerUnits="userSpaceOnUse" markerWidth="12" orient="auto" refX="17.7" refY="7.5" viewBox="0 0 15 15"><path d="m1 1 13 13M1 14 14 1" class="arrowMarkerPath" style="stroke-width:2.5"></path></marker><marker id="mermaid-3_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" markerHeight="12" markerUnits="userSpaceOnUse" markerWidth="12" orient="auto" refX="-3.5" refY="7.5" viewBox="0 0 15 15"><path d="m1 1 13 13M1 14 14 1" class="arrowMarkerPath" style="stroke-width:2.5;stroke-dasharray:1,0"></path></marker><g class="root"><g class="edgePaths"><path id="mermaid-3-L_o2_i2_0" marker-end="url(#mermaid-3_flowchart-v2-pointEnd)" d="m100.849 26.255-5.408 6.559c-5.408 6.559-16.223 19.677-21.631 33.269s-5.408 27.657-5.408 34.689v7.033" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_o2_i2_0" data-look="classic" data-points="W3sieCI6MTAwLjg0OTI2ODY1Mjc1MzE4LCJ5IjoyNi4yNTUzOTE5MjY4NDM1Mn0seyJ4Ijo2OC40MDE4MzYzOTUyNjM2NywieSI6NjUuNjA5Mzc1fSx7IngiOjY4LjQwMTgzNjM5NTI2MzY3LCJ5IjoxMTEuODA0Njg3NX1d"></path><path id="mermaid-3-L_o2_a3_0" marker-end="url(#mermaid-3_flowchart-v2-pointEnd)" d="m113.96 26.255 5.408 6.559c5.408 6.559 16.224 19.677 21.706 31.82 5.482 12.142 5.631 23.309 5.706 28.892l.074 5.584" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_o2_a3_0" data-look="classic" data-points="W3sieCI6MTEzLjk2MDAwOTgzNTQwNiwieSI6MjYuMjU1MzkxOTI2ODQzNTJ9LHsieCI6MTQ2LjQwNzQ0MjA5Mjg5NTUsInkiOjY1LjYwOTM3NX0seyJ4IjoxNDYuOTA3NDQyMDkyODk1NSwieSI6MTAzLjEwOTM3NX1d"></path><path id="mermaid-3-L_i2_a4_0" marker-end="url(#mermaid-3_flowchart-v2-pointEnd)" d="m62.189 130.33-6.082 8.047c-6.081 8.046-18.243 24.139-24.25 37.769s-5.858 24.797-5.784 30.38l.075 5.584" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_i2_a4_0" data-look="classic" data-points="W3sieCI6NjIuMTg4NzE1NjI0MTk1Mjc1LCJ5IjoxMzAuMzMwMzA2NTAxNzY4OH0seyJ4IjoyNS43MDA5MTgxOTc2MzE4MzYsInkiOjE3OC42MDkzNzV9LHsieCI6MjYuMjAwOTE4MTk3NjMxODM2LCJ5IjoyMTYuMTA5Mzc1fV0="></path><path id="mermaid-3-L_i2_b2_0" marker-end="url(#mermaid-3_flowchart-v2-pointEnd)" d="m74.615 130.33 6.081 8.047c6.082 8.046 18.244 24.139 24.4 37.769s6.305 24.797 6.379 30.38l.074 5.584" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_i2_b2_0" data-look="classic" data-points="W3sieCI6NzQuNjE0OTU3MTY2MzMyMDYsInkiOjEzMC4zMzAzMDY1MDE3Njg4fSx7IngiOjExMS4xMDI3NTQ1OTI4OTU1MSwieSI6MTc4LjYwOTM3NX0seyJ4IjoxMTEuNjAyNzU0NTkyODk1NTEsInkiOjIxNi4xMDkzNzV9XQ=="></path></g><g class="edgeLabels"><g class="edgeLabel"><foreignObject width="32.031" height="24" class="label" data-id="L_o2_i2_0" transform="translate(52.386 53.61)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>bare</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="57.813" height="24" class="label" data-id="L_o2_a3_0" transform="translate(113.206 48.4)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>override</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="32.031" height="24" class="label" data-id="L_i2_a4_0" transform="translate(9.685 166.61)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>bare</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="57.813" height="24" class="label" data-id="L_i2_b2_0" transform="translate(82.197 166.61)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>override</p></span></div></foreignObject></g></g><g class="nodes"><g id="mermaid-3-flowchart-o2-0" class="node default" data-look="classic" transform="translate(107.405 18.305)"><circle r="10.305" class="basic label-container"></circle><g class="label" transform="translate(-2.805 -12)"><rect></rect><foreignObject width="5.609" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>•</p></span></div></foreignObject></g></g><g id="mermaid-3-flowchart-i2-1" class="node default" data-look="classic" transform="translate(68.402 122.11)"><circle r="10.305" class="basic label-container"></circle><g class="label" transform="translate(-2.805 -12)"><rect></rect><foreignObject width="5.609" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>•</p></span></div></foreignObject></g></g><g id="mermaid-3-flowchart-a3-3" class="node default" data-look="classic"><g class="basic label-container outer-path"><path fill="#ececff" stroke-width="0" d="M148.197 102.61h-3.579c.487.015.974.03 1.25.04l1.244.12c.38.06.758.122 1.234.199l1.219.278 1.198.356 1.173.431 1.143.506 1.108.579 1.07.648 1.025.715.977.78.925.84.87.898.81.951.748 1.002.682 1.048.613 1.089.542 1.126.47 1.159.393 1.186.317 1.21.24 1.226.16 1.24.08 1.247v1.25c-.021.319-.042.637-.08 1.248l-.16 1.24-.24 1.227-.317 1.209-.393 1.186-.47 1.159-.542 1.126-.613 1.089-.682 1.048-.748 1.001-.81.952-.87.898-.925.84-.977.78-1.026.715-1.069.648-1.108.578-1.143.506-1.173.432-1.198.356c-.332.075-.663.15-1.219.278-.405.065-.809.13-1.234.2l-1.244.12-1.25.04h3.579l-1.25-.04-1.244-.12-1.234-.2-1.219-.278-1.198-.356-1.173-.432-1.143-.506c-.309-.16-.618-.322-1.108-.578l-1.07-.648-1.025-.715-.977-.78-.925-.84-.87-.898-.81-.952-.748-1.001-.682-1.048-.613-1.09-.543-1.125-.469-1.159-.394-1.186-.317-1.21-.239-1.226-.16-1.24-.08-1.248v-1.25l.08-1.247.16-1.24.24-1.227.316-1.209.394-1.186.47-1.159.542-1.126c.17-.3.338-.601.613-1.09.26-.397.518-.795.682-1.047l.748-1.002.81-.951.87-.898.925-.84.977-.78 1.026-.715 1.069-.648 1.108-.579 1.143-.506 1.173-.431 1.198-.356 1.219-.278 1.234-.2 1.244-.12 1.25-.04"></path><path fill="none" stroke="#9370db" stroke-dasharray="0 0" stroke-width="1.3" d="M148.197 102.61h-3.579m3.579 0h-3.579m0 0c.472.014.943.03 1.25.04m-1.25-.04 1.25.04m0 0 1.244.12m-1.244-.12 1.244.12m0 0 1.234.199m-1.234-.2 1.234.2m0 0 1.219.278m-1.219-.278 1.219.278m0 0 1.198.356m-1.198-.356 1.198.356m0 0 1.173.431m-1.173-.431 1.173.431m0 0 1.143.506m-1.143-.506 1.143.506m0 0 1.108.579m-1.108-.579 1.108.579m0 0 1.07.648m-1.07-.648 1.07.648m0 0 1.025.715m-1.026-.715 1.026.715m0 0 .977.78m-.977-.78.977.78m0 0 .925.84m-.925-.84.925.84m0 0 .87.898m-.87-.898.87.898m0 0 .81.951m-.81-.951.81.951m0 0 .748 1.002m-.748-1.002.748 1.002m0 0 .682 1.048m-.682-1.048.682 1.048m0 0 .613 1.089m-.613-1.09.613 1.09m0 0 .542 1.126m-.542-1.126.542 1.126m0 0 .47 1.159m-.47-1.159.47 1.159m0 0 .393 1.186m-.393-1.186.393 1.186m0 0 .317 1.21m-.317-1.21.317 1.21m0 0 .24 1.226m-.24-1.227.24 1.227m0 0 .16 1.24m-.16-1.24c.056.438.112.876.16 1.24m0 0 .08 1.247m-.08-1.247.08 1.247m0 0v1.25m0-1.25v1.25m0 0-.08 1.248m.08-1.248-.08 1.248m0 0q-.082.622-.16 1.24m.16-1.24c-.046.348-.09.696-.16 1.24m0 0-.24 1.227m.24-1.227-.24 1.227m0 0-.317 1.209m.317-1.21c-.07.272-.142.543-.317 1.21m0 0-.393 1.186m.393-1.186-.393 1.186m0 0-.47 1.159m.47-1.159-.47 1.159m0 0-.542 1.126m.542-1.126-.542 1.126m0 0-.613 1.089m.613-1.09-.613 1.09m0 0-.682 1.048m.682-1.048-.682 1.048m0 0-.748 1.001m.748-1.001c-.18.24-.36.48-.748 1.001m0 0-.81.952m.81-.952-.81.952m0 0-.87.898m.87-.898-.87.898m0 0-.925.84m.925-.84-.925.84m0 0-.977.78m.977-.78-.977.78m0 0-1.026.715m1.026-.715-1.026.715m0 0-1.069.648m1.07-.648-1.07.648m0 0-1.108.578m1.108-.578-1.108.578m0 0-1.143.506m1.143-.506-1.143.506m0 0-1.173.432m1.173-.432-1.173.432m0 0-1.198.356m1.198-.356-1.198.356m0 0-1.219.278m1.219-.278-1.219.278m0 0-1.234.2m1.234-.2-1.234.2m0 0-1.244.12m1.244-.12c-.41.039-.82.078-1.244.12m0 0c-.33.01-.66.02-1.25.04m1.25-.04-1.25.04m0 0h3.579m-3.579 0h3.579m0 0-1.25-.04m1.25.04-1.25-.04m0 0-1.244-.12m1.244.12-1.244-.12m0 0c-.46-.075-.918-.15-1.234-.2m1.234.2-1.234-.2m0 0-1.219-.278m1.219.278-1.219-.278m0 0-1.198-.356m1.198.356-1.198-.356m0 0-1.173-.432m1.173.432-1.173-.432m0 0-1.143-.506m1.143.506-1.143-.506m0 0-1.108-.578m1.108.578-1.108-.578m0 0-1.07-.648m1.07.648-1.07-.648m0 0-1.025-.715m1.026.715-1.026-.715m0 0-.977-.78m.977.78-.977-.78m0 0-.925-.84m.925.84-.925-.84m0 0-.87-.898m.87.898-.87-.898m0 0-.81-.952m.81.952-.81-.952m0 0-.748-1.001m.748 1.001-.748-1.001m0 0-.682-1.048m.682 1.048-.682-1.048m0 0-.613-1.09m.613 1.09-.613-1.09m0 0-.543-1.125m.543 1.126-.543-1.126m0 0-.469-1.159m.47 1.159-.47-1.159m0 0-.394-1.186m.394 1.186-.394-1.186m0 0-.317-1.21m.317 1.21-.317-1.21m0 0-.239-1.226m.24 1.227-.24-1.227m0 0-.16-1.24m.16 1.24-.16-1.24m0 0-.08-1.248m.08 1.248c-.02-.331-.042-.662-.08-1.248m0 0v-1.25m0 1.25v-1.25m0 0 .08-1.247m-.08 1.247.08-1.247m0 0c.06-.46.12-.92.16-1.24m-.16 1.24.16-1.24m0 0 .24-1.227m-.24 1.227.24-1.227m0 0 .316-1.209m-.317 1.21.317-1.21m0 0 .394-1.186m-.394 1.186.394-1.186m0 0 .47-1.159m-.47 1.159.47-1.159m0 0 .542-1.126m-.543 1.126.543-1.126m0 0 .613-1.09m-.613 1.09.613-1.09m0 0 .682-1.047m-.682 1.048.682-1.048m0 0 .748-1.002m-.748 1.002.748-1.002m0 0 .81-.951m-.81.951.81-.951m0 0 .87-.898m-.87.898.87-.898m0 0 .925-.84m-.925.84.925-.84m0 0 .977-.78m-.977.78.977-.78m0 0 1.026-.715m-1.026.715 1.026-.715m0 0 1.069-.648m-1.07.648 1.07-.648m0 0 1.108-.579m-1.108.579 1.108-.579m0 0 1.143-.506m-1.143.506 1.143-.506m0 0 1.173-.431m-1.173.431 1.173-.431m0 0 1.198-.356m-1.198.356 1.198-.356m0 0 1.219-.278m-1.219.278 1.219-.278m0 0 1.234-.2m-1.234.2 1.234-.2m0 0 1.244-.12m-1.244.12 1.244-.12m0 0 1.25-.04m-1.25.04 1.25-.04m0 0"></path></g><g class="label" transform="translate(141.072 110.11)"><rect></rect><foreignObject width="10.672" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>A</p></span></div></foreignObject></g></g><g id="mermaid-3-flowchart-a4-5" class="node default" data-look="classic"><g class="basic label-container outer-path"><path fill="#ececff" stroke-width="0" d="M27.49 215.61h-3.578l1.25.04 1.243.12 1.234.199 1.22.278 1.197.356 1.174.431 1.143.506 1.108.579 1.069.648 1.025.715.977.78.926.84.87.898.81.951.747 1.002.682 1.048.614 1.089.542 1.126.469 1.159.394 1.186.317 1.21.239 1.226c.05.396.102.79.16 1.24l.08 1.247v1.25l-.08 1.248-.16 1.24-.24 1.227-.316 1.209-.394 1.186-.47 1.159-.541 1.126-.614 1.089-.682 1.048-.747 1.001-.81.952-.87.898-.926.84-.977.78-1.025.715-1.07.648-1.107.578-1.143.506-1.174.432-1.198.356-1.219.278-1.234.2-1.244.12c-.473.014-.947.03-1.25.04h3.579l-1.25-.04-1.244-.12c-.394-.065-.79-.128-1.234-.2l-1.218-.278-1.199-.356-1.173-.432-1.143-.506-1.108-.578-1.069-.648-1.025-.715-.977-.78-.926-.84-.87-.898-.81-.952-.747-1.001-.682-1.048-.614-1.09-.542-1.125-.47-1.159-.393-1.186-.317-1.21-.24-1.226-.159-1.24-.08-1.248v-1.25l.08-1.247.16-1.24.239-1.227.317-1.209.394-1.186.469-1.159.542-1.126.614-1.09.682-1.047.747-1.002.81-.951.87-.898.926-.84.977-.78 1.025-.715 1.069-.648 1.108-.579 1.143-.506 1.173-.431 1.199-.356 1.218-.278 1.234-.2 1.245-.12 1.249-.04"></path><path fill="none" stroke="#9370db" stroke-dasharray="0 0" stroke-width="1.3" d="M27.49 215.61h-3.578m3.578 0h-3.578m0 0 1.25.04m-1.25-.04 1.25.04m0 0c.322.03.644.062 1.243.12m-1.244-.12 1.244.12m0 0 1.234.199m-1.234-.2c.302.05.604.098 1.234.2m0 0 1.22.278m-1.22-.278 1.22.278m0 0 1.197.356m-1.198-.356 1.198.356m0 0 1.174.431m-1.174-.431 1.174.431m0 0 1.143.506m-1.143-.506 1.143.506m0 0 1.108.579m-1.108-.579 1.108.579m0 0 1.069.648m-1.07-.648 1.07.648m0 0 1.025.715m-1.025-.715 1.025.715m0 0 .977.78m-.977-.78.977.78m0 0 .926.84m-.926-.84c.37.334.738.67.926.84m0 0 .87.898m-.87-.898.87.898m0 0 .81.951m-.81-.951.81.951m0 0 .747 1.002m-.747-1.002.747 1.002m0 0 .682 1.048m-.682-1.048.682 1.048m0 0 .614 1.089m-.614-1.09.614 1.09m0 0 .542 1.126m-.542-1.126.542 1.126m0 0 .469 1.159m-.47-1.159.47 1.159m0 0 .394 1.186m-.394-1.186.394 1.186m0 0 .317 1.21m-.317-1.21.317 1.21m0 0 .239 1.226m-.24-1.227.24 1.227m0 0 .16 1.24m-.16-1.24.16 1.24m0 0 .08 1.247m-.08-1.247.08 1.247m0 0v1.25m0-1.25v1.25m0 0-.08 1.248m.08-1.248-.08 1.248m0 0-.16 1.24m.16-1.24-.16 1.24m0 0-.24 1.227m.24-1.227-.24 1.227m0 0-.316 1.209m.317-1.21-.317 1.21m0 0-.394 1.186m.394-1.186-.394 1.186m0 0-.47 1.159m.47-1.159-.47 1.159m0 0-.541 1.126m.542-1.126-.542 1.126m0 0-.614 1.089m.614-1.09-.614 1.09m0 0-.682 1.048m.682-1.048-.682 1.048m0 0-.747 1.001m.747-1.001-.747 1.001m0 0-.81.952m.81-.952-.81.952m0 0-.87.898m.87-.898-.87.898m0 0-.926.84m.926-.84-.926.84m0 0-.977.78m.977-.78-.977.78m0 0-1.025.715m1.025-.715-1.025.715m0 0-1.07.648m1.07-.648-1.07.648m0 0-1.107.578m1.108-.578-1.108.578m0 0-1.143.506m1.143-.506-1.143.506m0 0-1.174.432m1.174-.432-1.174.432m0 0-1.198.356m1.198-.356-1.198.356m0 0-1.219.278m1.22-.278-1.22.278m0 0-1.234.2m1.234-.2-1.234.2m0 0-1.244.12m1.244-.12-1.244.12m0 0-1.25.04m1.25-.04-1.25.04m0 0h3.579m-3.578 0h3.578m0 0-1.25-.04m1.25.04-1.25-.04m0 0-1.244-.12m1.245.12-1.245-.12m0 0-1.234-.2m1.234.2-1.234-.2m0 0-1.218-.278m1.218.278-1.218-.278m0 0-1.199-.356m1.199.356-1.199-.356m0 0-1.173-.432m1.173.432c-.365-.135-.73-.27-1.173-.432m0 0-1.143-.506m1.143.506-1.143-.506m0 0-1.108-.578m1.108.578-1.108-.578m0 0-1.069-.648m1.069.648-1.069-.648m0 0-1.025-.715m1.025.715-1.025-.715m0 0-.977-.78m.977.78-.977-.78m0 0-.926-.84m.926.84-.926-.84m0 0-.87-.898m.87.898-.87-.898m0 0-.81-.952m.81.952-.81-.952m0 0-.747-1.001m.747 1.001-.747-1.001m0 0-.682-1.048m.682 1.048-.682-1.048m0 0-.614-1.09m.614 1.09c-.2-.354-.4-.708-.614-1.09m0 0-.542-1.125m.542 1.126-.542-1.126m0 0-.47-1.159m.47 1.159-.47-1.159m0 0-.393-1.186m.394 1.186-.394-1.186m0 0-.317-1.21m.317 1.21-.317-1.21m0 0-.24-1.226m.24 1.227-.24-1.227m0 0-.159-1.24m.16 1.24-.16-1.24m0 0L8 235.734m.08 1.248L8 235.734m0 0v-1.25m0 1.25v-1.25m0 0 .08-1.247M8 234.484l.08-1.247m0 0 .16-1.24m-.16 1.24.16-1.24m0 0 .239-1.227m-.24 1.227.24-1.227m0 0 .317-1.209m-.317 1.21.317-1.21m0 0 .394-1.186m-.394 1.186.394-1.186m0 0 .469-1.159m-.47 1.159.47-1.159m0 0 .542-1.126m-.542 1.126.542-1.126m0 0 .614-1.09m-.614 1.09.614-1.09m0 0 .682-1.047m-.682 1.048.682-1.048m0 0 .747-1.002m-.747 1.002.747-1.002m0 0 .81-.951m-.81.951.81-.951m0 0 .87-.898m-.87.898.87-.898m0 0 .926-.84m-.926.84.926-.84m0 0 .977-.78m-.977.78.977-.78m0 0 1.025-.715m-1.025.715 1.025-.715m0 0 1.069-.648m-1.069.648 1.069-.648m0 0 1.108-.579m-1.108.579 1.108-.579m0 0 1.143-.506m-1.143.506 1.143-.506m0 0 1.173-.431m-1.173.431 1.173-.431m0 0 1.199-.356m-1.199.356 1.199-.356m0 0 1.218-.278m-1.218.278 1.218-.278m0 0 1.234-.2m-1.234.2 1.234-.2m0 0 1.245-.12m-1.245.12 1.245-.12m0 0 1.249-.04m-1.25.04c.345-.01.689-.022 1.25-.04m0 0"></path></g><g class="label" transform="translate(20.365 223.11)"><rect></rect><foreignObject width="10.672" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>A</p></span></div></foreignObject></g></g><g id="mermaid-3-flowchart-b2-7" class="node default" data-look="classic"><g class="basic label-container outer-path"><path fill="#ececff" stroke-width="0" d="M112.892 215.61h-3.578l1.25.04 1.243.12 1.234.199 1.219.278 1.198.356 1.173.431 1.143.506 1.109.579 1.069.648 1.025.715.977.78.926.84.87.898.81.951.747 1.002.682 1.048.613 1.089.543 1.126.469 1.159.394 1.186.317 1.21.239 1.226.16 1.24.08 1.247v1.25l-.08 1.248-.16 1.24-.24 1.227-.316 1.209-.394 1.186-.47 1.159-.542 1.126-.613 1.089-.682 1.048c-.26.35-.522.698-.748 1.001l-.81.952-.87.898-.925.84-.977.78-1.025.715-1.07.648-1.108.578-1.143.506-1.173.432-1.198.356-1.219.278-1.234.2-1.244.12c-.282.008-.565.017-1.25.04h3.579l-1.25-.04-1.244-.12-1.234-.2-1.218-.278-1.199-.356-1.173-.432-1.143-.506-1.108-.578-1.07-.648-1.024-.715-.978-.78-.925-.84-.87-.898c-.29-.34-.58-.68-.81-.952l-.748-1.001-.681-1.048-.614-1.09-.542-1.125-.47-1.159c-.14-.426-.282-.851-.393-1.186l-.317-1.21-.24-1.226-.16-1.24c-.017-.283-.035-.565-.08-1.248v-1.25c.02-.283.037-.567.08-1.247l.16-1.24.24-1.227.317-1.209.394-1.186.469-1.159.542-1.126.614-1.09c.19-.29.379-.582.681-1.047l.748-1.002.81-.951.87-.898.925-.84.978-.78 1.025-.715 1.069-.648 1.108-.579c.252-.111.504-.222 1.143-.506l1.173-.431 1.199-.356 1.218-.278 1.234-.2 1.244-.12 1.25-.04"></path><path fill="none" stroke="#9370db" stroke-dasharray="0 0" stroke-width="1.3" d="M112.892 215.61h-3.578m3.578 0h-3.578m0 0c.331.01.663.02 1.25.04m-1.25-.04 1.25.04m0 0 1.243.12m-1.244-.12 1.244.12m0 0 1.234.199m-1.234-.2 1.234.2m0 0 1.219.278m-1.219-.278 1.219.278m0 0 1.198.356m-1.198-.356 1.198.356m0 0 1.173.431m-1.173-.431 1.173.431m0 0 1.143.506m-1.143-.506 1.143.506m0 0 1.109.579m-1.109-.579 1.109.579m0 0 1.069.648m-1.07-.648 1.07.648m0 0 1.025.715m-1.025-.715 1.025.715m0 0 .977.78m-.977-.78.977.78m0 0 .926.84m-.926-.84.926.84m0 0 .87.898m-.87-.898.87.898m0 0c.19.225.382.45.81.951m-.81-.951.81.951m0 0 .747 1.002m-.748-1.002.748 1.002m0 0 .682 1.048m-.682-1.048.682 1.048m0 0 .613 1.089m-.613-1.09.613 1.09m0 0 .543 1.126m-.543-1.126.543 1.126m0 0 .469 1.159m-.47-1.159.47 1.159m0 0 .394 1.186m-.394-1.186.394 1.186m0 0 .317 1.21m-.317-1.21.317 1.21m0 0 .239 1.226m-.24-1.227.24 1.227m0 0 .16 1.24m-.16-1.24.16 1.24m0 0 .08 1.247m-.08-1.247.08 1.247m0 0v1.25m0-1.25v1.25m0 0-.08 1.248m.08-1.248c-.03.448-.058.896-.08 1.248m0 0-.16 1.24m.16-1.24-.16 1.24m0 0-.24 1.227m.24-1.227-.24 1.227m0 0-.316 1.209m.317-1.21-.317 1.21m0 0-.394 1.186m.394-1.186-.394 1.186m0 0-.47 1.159m.47-1.159-.47 1.159m0 0-.542 1.126m.543-1.126-.543 1.126m0 0-.613 1.089m.613-1.09-.613 1.09m0 0-.682 1.048m.682-1.048-.682 1.048m0 0-.748 1.001m.748-1.001-.748 1.001m0 0-.81.952m.81-.952-.81.952m0 0-.87.898m.87-.898-.87.898m0 0-.925.84m.926-.84-.926.84m0 0-.977.78m.977-.78-.977.78m0 0-1.025.715m1.025-.715-1.025.715m0 0-1.07.648m1.07-.648-1.07.648m0 0-1.108.578m1.109-.578-1.109.578m0 0-1.143.506m1.143-.506-1.143.506m0 0-1.173.432m1.173-.432-1.173.432m0 0-1.198.356m1.198-.356-1.198.356m0 0-1.219.278m1.219-.278-1.219.278m0 0-1.234.2m1.234-.2-1.234.2m0 0c-.267.025-.535.05-1.244.12m1.244-.12-1.244.12m0 0-1.25.04m1.25-.04-1.25.04m0 0h3.579m-3.578 0h3.578m0 0c-.294-.01-.588-.02-1.25-.04m1.25.04-1.25-.04m0 0-1.244-.12m1.244.12-1.244-.12m0 0-1.234-.2m1.234.2-1.234-.2m0 0-1.218-.278m1.218.278c-.348-.08-.696-.16-1.218-.278m0 0-1.199-.356m1.199.356-1.199-.356m0 0-1.173-.432m1.173.432-1.173-.432m0 0-1.143-.506m1.143.506-1.143-.506m0 0-1.108-.578m1.108.578-1.108-.578m0 0-1.07-.648m1.07.648-1.07-.648m0 0-1.024-.715m1.025.715-1.025-.715m0 0-.978-.78m.978.78-.978-.78m0 0-.925-.84m.925.84-.925-.84m0 0-.87-.898m.87.898-.87-.898m0 0-.81-.952m.81.952-.81-.952m0 0-.748-1.001m.748 1.001-.748-1.001m0 0-.681-1.048m.681 1.048-.681-1.048m0 0-.614-1.09m.614 1.09-.614-1.09m0 0-.542-1.125m.542 1.126-.542-1.126m0 0-.47-1.159m.47 1.159-.47-1.159m0 0-.393-1.186m.394 1.186-.394-1.186m0 0-.317-1.21m.317 1.21-.317-1.21m0 0-.24-1.226m.24 1.227-.24-1.227m0 0-.16-1.24m.16 1.24c-.035-.28-.071-.56-.16-1.24m0 0-.08-1.248m.08 1.248c-.015-.25-.031-.501-.08-1.248m0 0v-1.25m0 1.25v-1.25m0 0 .08-1.247m-.08 1.247c.02-.289.038-.578.08-1.247m0 0c.062-.471.122-.942.16-1.24m-.16 1.24c.035-.262.069-.525.16-1.24m0 0 .24-1.227m-.24 1.227.24-1.227m0 0 .317-1.209m-.317 1.21.317-1.21m0 0c.12-.363.24-.726.394-1.186m-.394 1.186c.125-.378.25-.756.394-1.186m0 0 .469-1.159m-.47 1.159.47-1.159m0 0 .542-1.126m-.542 1.126.542-1.126m0 0 .614-1.09m-.614 1.09.614-1.09m0 0c.21-.321.419-.643.681-1.047m-.681 1.048.681-1.048m0 0 .748-1.002m-.748 1.002.748-1.002m0 0 .81-.951m-.81.951.81-.951m0 0 .87-.898m-.87.898.87-.898m0 0 .925-.84m-.925.84q.461-.42.925-.84m0 0 .978-.78m-.978.78.978-.78m0 0 1.025-.715m-1.025.715 1.025-.715m0 0 1.069-.648m-1.07.648 1.07-.648m0 0 1.108-.579m-1.108.579 1.108-.579m0 0 1.143-.506m-1.143.506 1.143-.506m0 0 1.173-.431m-1.173.431 1.173-.431m0 0 1.199-.356m-1.199.356 1.199-.356m0 0 1.218-.278m-1.218.278 1.218-.278m0 0c.377-.06.753-.122 1.234-.2m-1.234.2 1.234-.2m0 0 1.244-.12m-1.244.12 1.244-.12m0 0 1.25-.04m-1.25.04 1.25-.04m0 0"></path></g><g class="label" transform="translate(105.767 223.11)"><rect></rect><foreignObject width="10.672" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>B</p></span></div></foreignObject></g></g></g></g><defs><filter id="mermaid-3-drop-shadow" width="130%" height="130%"><feDropShadow dx="4" dy="4" flood-color="#000" flood-opacity=".06" stdDeviation="0"></feDropShadow></filter></defs><defs><filter id="mermaid-3-drop-shadow-small" width="150%" height="150%"><feDropShadow dx="2" dy="2" flood-color="#000" flood-opacity=".06" stdDeviation="0"></feDropShadow></filter></defs></svg>
<p>And the runtime behavior differs too:</p>
<ul>
<li>Construction 1 (<code>A.wohs(B.wohs(A))</code>): <code>A</code>’s halt goes to a wrapper “<code>B</code> with halt redirected to <code>A</code>”. Runtime walk: <code>A → B → A</code>.</li>
<li>Construction 2 (<code>A.wohs(B).wohs(A)</code>): the wrapper “<code>A</code> with halt redirected to <code>B</code>” is wrapped once more — halt now goes to <code>A</code>. Runtime walk: <code>A → A</code>. The inner <code>B</code> override is dead: only the outermost <code>.wohs()</code>’s override makes it onto the halt stack.</li>
</ul>
<p>Same name. Just because the flat <code>></code> separator doesn’t remember <em>where</em> in the construction tree each arrow sat. And there was a tree there.</p>
<h2 id="the-tree-we-forgot"><a class="heading-anchor" href="#the-tree-we-forgot">The tree we forgot</a></h2>
<p><code>withOverrodeHaltState</code> is a binary operation: a left argument (<code>this</code>) and a right argument (<code>override</code>). Each application is a new node in the tree. The node has two children: the bare and the override. If a child is itself a wrapper, the tree continues there with another node; otherwise it’s a plain <code>State</code> — a <em>leaf</em>. After N applications: N wrapper-nodes and N+1 leaves — standard binary-tree property. For <code>minusOne</code> above: 3 applications (3 wrapper-nodes), 4 leaves (<code>invertNumber</code>, <code>plusOne</code>, <code>invertNumber</code>, <code>normalizeNumber</code>). Here’s the tree explicitly:</p>
<svg xmlns="http://www.w3.org/2000/svg" id="mermaid-4" width="100%" aria-roledescription="flowchart-v2" class="flowchart" style="font-family:arial,sans-serif;font-size:16px;fill:#333;max-width:416.73614501953125px" viewBox="0 -1.695 416.736 377.305"><style>@keyframes edge-animation-frame{0%{stroke-dashoffset:0}}@keyframes dash{to{stroke-dashoffset:0}}#mermaid-4 .edge-thickness-normal{stroke-width:1px}#mermaid-4 .edge-pattern-solid{stroke-dasharray:0}#mermaid-4 .marker{fill:#333;stroke:#333}#mermaid-4 .marker.cross{stroke:#333}#mermaid-4 svg{font-family:arial,sans-serif;font-size:16px}#mermaid-4 p{margin:0}#mermaid-4 .label{font-family:arial,sans-serif;color:#333}#mermaid-4 span{fill:#333;color:#333}#mermaid-4 .node circle,#mermaid-4 .node path,#mermaid-4 .node rect{fill:#ececff;stroke:#9370db;stroke-width:1px}#mermaid-4 .flowchart-link{stroke:#333;fill:none}#mermaid-4 .edgeLabel,#mermaid-4 .node .label{text-align:center}#mermaid-4 .edgeLabel,#mermaid-4 .edgeLabel p,#mermaid-4 .edgeLabel rect{background-color:rgba(232,232,232,.8)}#mermaid-4 .edgeLabel rect{opacity:.5;fill:rgba(232,232,232,.8)}#mermaid-4 .labelBkg{background-color:rgba(232,232,232,.5)}#mermaid-4 [data-look=neo].node circle,#mermaid-4 [data-look=neo].node rect{stroke:#9370db;filter:drop-shadow(1px 2px 2px #b9b9b9)}#mermaid-4 [data-look=neo].node path{stroke:#9370db;stroke-width:1px}#mermaid-4 [data-look=neo].node .outer-path{filter:drop-shadow(1px 2px 2px #b9b9b9)}#mermaid-4 :root{--mermaid-font-family:arial,sans-serif}</style><marker id="mermaid-4_flowchart-v2-pointEnd" class="marker flowchart-v2" markerHeight="8" markerUnits="userSpaceOnUse" markerWidth="8" orient="auto" refX="5" refY="5" viewBox="0 0 10 10"><path d="m0 0 10 5-10 5z" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></path></marker><marker id="mermaid-4_flowchart-v2-pointStart" class="marker flowchart-v2" markerHeight="8" markerUnits="userSpaceOnUse" markerWidth="8" orient="auto" refX="4.5" refY="5" viewBox="0 0 10 10"><path d="m0 5 10 5V0z" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></path></marker><marker id="mermaid-4_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="10.5" orient="auto" refX="11.5" refY="7" viewBox="0 0 11.5 14"><path d="m0 0 11.5 7L0 14z" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></path></marker><marker id="mermaid-4_flowchart-v2-pointStart-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="11.5" orient="auto" refX="1" refY="7" viewBox="0 0 11.5 14"><path d="m0 7 11.5 7V0z" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></path></marker><marker id="mermaid-4_flowchart-v2-circleEnd" class="marker flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="11" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-4_flowchart-v2-circleStart" class="marker flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="-1" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-4_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="14" orient="auto" refX="12.25" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-4_flowchart-v2-circleStart-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="14" orient="auto" refX="-2" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-4_flowchart-v2-crossEnd" class="marker cross flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="12" refY="5.2" viewBox="0 0 11 11"><path d="m1 1 9 9m0-9-9 9" class="arrowMarkerPath" style="stroke-width:2;stroke-dasharray:1,0"></path></marker><marker id="mermaid-4_flowchart-v2-crossStart" class="marker cross flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="-1" refY="5.2" viewBox="0 0 11 11"><path d="m1 1 9 9m0-9-9 9" class="arrowMarkerPath" style="stroke-width:2;stroke-dasharray:1,0"></path></marker><marker id="mermaid-4_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" markerHeight="12" markerUnits="userSpaceOnUse" markerWidth="12" orient="auto" refX="17.7" refY="7.5" viewBox="0 0 15 15"><path d="m1 1 13 13M1 14 14 1" class="arrowMarkerPath" style="stroke-width:2.5"></path></marker><marker id="mermaid-4_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" markerHeight="12" markerUnits="userSpaceOnUse" markerWidth="12" orient="auto" refX="-3.5" refY="7.5" viewBox="0 0 15 15"><path d="m1 1 13 13M1 14 14 1" class="arrowMarkerPath" style="stroke-width:2.5;stroke-dasharray:1,0"></path></marker><g class="root"><g class="edgePaths"><path id="mermaid-4-L_n1_invertA_0" marker-end="url(#mermaid-4_flowchart-v2-pointEnd)" d="m120.613 24.662-8.705 6.825c-8.705 6.824-26.116 20.473-34.747 32.881s-8.483 23.575-8.408 29.158l.074 5.584" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_n1_invertA_0" data-look="classic" data-points="W3sieCI6MTIwLjYxMzQ4MzY1OTI1NTg4LCJ5IjoyNC42NjIyMTc3MzczOTU1NX0seyJ4Ijo2OC4zODA2MDc2MDQ5ODA0NywieSI6NjUuNjA5Mzc1fSx7IngiOjY4Ljg4MDYwNzYwNDk4MDQ3LCJ5IjoxMDMuMTA5Mzc1fV0="></path><path id="mermaid-4-L_n1_n2_0" marker-end="url(#mermaid-4_flowchart-v2-pointEnd)" d="m136.833 24.662 8.706 6.825c8.705 6.824 26.116 20.473 34.821 34.33 8.706 13.857 8.706 27.923 8.706 34.955v7.033" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_n1_n2_0" data-look="classic" data-points="W3sieCI6MTM2LjgzMzAyNjY1NTY4NTUzLCJ5IjoyNC42NjIyMTc3MzczOTU1NX0seyJ4IjoxODkuMDY1OTAyNzA5OTYwOTQsInkiOjY1LjYwOTM3NX0seyJ4IjoxODkuMDY1OTAyNzA5OTYwOTQsInkiOjExMS44MDQ2ODc1fV0="></path><path id="mermaid-4-L_n2_plus_0" marker-end="url(#mermaid-4_flowchart-v2-pointEnd)" d="m182.144 129.743-7.385 8.144c-7.386 8.145-22.156 24.434-29.467 38.161-7.31 13.728-7.162 24.895-7.087 30.478l.074 5.584" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_n2_plus_0" data-look="classic" data-points="W3sieCI6MTgyLjE0Mzg2ODc1NzI0MDk0LCJ5IjoxMjkuNzQyOTg2ODg2MjU5ODR9LHsieCI6MTM3LjgzMjYzMDE1NzQ3MDcsInkiOjE3OC42MDkzNzV9LHsieCI6MTM4LjMzMjYzMDE1NzQ3MDcsInkiOjIxNi4xMDkzNzV9XQ=="></path><path id="mermaid-4-L_n2_n3_0" marker-end="url(#mermaid-4_flowchart-v2-pointEnd)" d="m195.988 129.743 7.385 8.144c7.385 8.145 22.156 24.434 29.541 39.611s7.385 29.242 7.385 36.274v7.033" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_n2_n3_0" data-look="classic" data-points="W3sieCI6MTk1Ljk4NzkzNjY2MjY4MDk0LCJ5IjoxMjkuNzQyOTg2ODg2MjU5ODR9LHsieCI6MjQwLjI5OTE3NTI2MjQ1MTE3LCJ5IjoxNzguNjA5Mzc1fSx7IngiOjI0MC4yOTkxNzUyNjI0NTExNywieSI6MjI0LjgwNDY4NzV9XQ=="></path><path id="mermaid-4-L_n3_invertB_0" marker-end="url(#mermaid-4_flowchart-v2-pointEnd)" d="m231.494 240.462-14.022 8.525c-14.023 8.524-42.067 25.573-56.015 39.681s-13.799 25.275-13.725 30.858l.075 5.584" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_n3_invertB_0" data-look="classic" data-points="W3sieCI6MjMxLjQ5MzkxMDk1NzE2MzUsInkiOjI0MC40NjIzMDkyNDA4MzMwNn0seyJ4IjoxNDcuMzU5OTczOTA3NDcwNywieSI6MjkxLjYwOTM3NX0seyJ4IjoxNDcuODU5OTczOTA3NDcwNywieSI6MzI5LjEwOTM3NX1d"></path><path id="mermaid-4-L_n3_norm_0" marker-end="url(#mermaid-4_flowchart-v2-pointEnd)" d="m249.104 240.462 14.023 8.525c14.022 8.524 42.067 25.573 56.163 39.681 14.097 14.108 14.246 25.275 14.321 30.858l.074 5.584" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_n3_norm_0" data-look="classic" data-points="W3sieCI6MjQ5LjEwNDQzOTU2NzczODg0LCJ5IjoyNDAuNDYyMzA5MjQwODMzMDZ9LHsieCI6MzMzLjIzODM3NjYxNzQzMTY0LCJ5IjoyOTEuNjA5Mzc1fSx7IngiOjMzMy43MzgzNzY2MTc0MzE2NCwieSI6MzI5LjEwOTM3NX1d"></path></g><g class="edgeLabels"><g class="edgeLabel"><foreignObject width="32.031" height="24" class="label" data-id="L_n1_invertA_0" transform="translate(63.724 44.705)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>bare</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="57.813" height="24" class="label" data-id="L_n1_n2_0" transform="translate(160.16 53.61)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>override</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="32.031" height="24" class="label" data-id="L_n2_plus_0" transform="translate(121.817 166.61)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>bare</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="57.813" height="24" class="label" data-id="L_n2_n3_0" transform="translate(211.393 166.61)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>override</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="32.031" height="24" class="label" data-id="L_n3_invertB_0" transform="translate(157.388 263.777)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>bare</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="57.813" height="24" class="label" data-id="L_n3_norm_0" transform="translate(304.332 279.61)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>override</p></span></div></foreignObject></g></g><g class="nodes"><g id="mermaid-4-flowchart-n1-0" class="node default" data-look="classic" transform="translate(128.723 18.305)"><circle r="10.305" class="basic label-container"></circle><g class="label" transform="translate(-2.805 -12)"><rect></rect><foreignObject width="5.609" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>•</p></span></div></foreignObject></g></g><g id="mermaid-4-flowchart-invertA-1" class="node default" data-look="classic"><g class="basic label-container outer-path"><path fill="#ececff" stroke-width="0" d="M27.49 102.61h81.781c.332.01.664.02 1.25.04l1.244.12 1.234.199 1.218.278 1.199.356 1.173.431c.44.196.881.39 1.143.506l1.108.579 1.07.648 1.024.715.978.78.925.84.87.898.81.951.748 1.002.682 1.048.613 1.089c.215.445.43.891.542 1.126l.47 1.159.393 1.186.317 1.21.24 1.226.16 1.24c.025.408.051.815.08 1.247v1.25l-.08 1.248c-.063.479-.124.958-.16 1.24l-.24 1.227c-.07.269-.14.538-.317 1.209l-.394 1.186-.469 1.159-.542 1.126-.613 1.089c-.145.222-.29.443-.682 1.048l-.748 1.001-.81.952-.87.898-.925.84-.978.78-1.025.715-1.069.648-1.108.578-1.143.506-1.173.432-1.199.356-1.218.278-1.234.2-1.244.12-1.25.04H27.49l-1.25-.04-1.244-.12-1.234-.2c-.304-.07-.608-.14-1.218-.278l-1.199-.356-1.173-.432-1.143-.506-1.108-.578-1.069-.648-1.025-.715-.977-.78-.926-.84-.87-.898-.81-.952-.747-1.001-.682-1.048-.614-1.09-.542-1.125c-.145-.36-.29-.718-.47-1.159l-.393-1.186-.317-1.21-.24-1.226-.159-1.24-.08-1.248v-1.25l.08-1.247.16-1.24.239-1.227.317-1.209.394-1.186c.17-.423.342-.845.469-1.159l.542-1.126.614-1.09.682-1.047.747-1.002.81-.951.87-.898.926-.84c.374-.3.75-.599.977-.78l1.025-.715 1.069-.648 1.108-.579 1.143-.506 1.173-.431 1.199-.356 1.218-.278 1.234-.2 1.245-.12 1.249-.04"></path><path fill="none" stroke="#9370db" stroke-dasharray="0 0" stroke-width="1.3" d="M27.49 102.61h81.781m-81.781 0h81.781m0 0 1.25.04m-1.25-.04 1.25.04m0 0 1.244.12m-1.244-.12 1.244.12m0 0 1.234.199m-1.234-.2 1.234.2m0 0 1.218.278M113 102.97l1.218.278m0 0 1.199.356m-1.199-.356 1.199.356m0 0 1.173.431m-1.173-.431 1.173.431m0 0 1.143.506m-1.143-.506 1.143.506m0 0 1.108.579m-1.108-.579 1.108.579m0 0 1.07.648m-1.07-.648 1.07.648m0 0 1.024.715m-1.025-.715 1.025.715m0 0c.296.235.591.47.978.78m-.978-.78.978.78m0 0 .925.84m-.925-.84.925.84m0 0 .87.898m-.87-.898.87.898m0 0 .81.951m-.81-.951.81.951m0 0 .748 1.002m-.748-1.002.748 1.002m0 0 .682 1.048m-.682-1.048.682 1.048m0 0 .613 1.089m-.613-1.09.613 1.09m0 0 .542 1.126m-.542-1.126.542 1.126m0 0 .47 1.159m-.47-1.159.47 1.159m0 0 .393 1.186m-.394-1.186.394 1.186m0 0 .317 1.21m-.317-1.21.317 1.21m0 0 .24 1.226m-.24-1.227.24 1.227m0 0c.04.323.082.645.16 1.24m-.16-1.24c.04.316.08.631.16 1.24m0 0 .08 1.247m-.08-1.247c.029.462.058.925.08 1.247m0 0v1.25m0-1.25v1.25m0 0c-.031.475-.062.949-.08 1.248m.08-1.248-.08 1.248m0 0c-.04.304-.08.609-.16 1.24m.16-1.24c-.053.402-.105.804-.16 1.24m0 0-.24 1.227m.24-1.227-.24 1.227m0 0-.317 1.209m.317-1.21-.317 1.21m0 0-.394 1.186m.394-1.186-.394 1.186m0 0-.469 1.159m.47-1.159-.47 1.159m0 0-.542 1.126m.542-1.126-.542 1.126m0 0-.613 1.089m.613-1.09-.613 1.09m0 0-.682 1.048m.682-1.048-.682 1.048m0 0-.748 1.001m.748-1.001-.748 1.001m0 0-.81.952m.81-.952-.81.952m0 0-.87.898m.87-.898-.87.898m0 0-.925.84m.925-.84-.925.84m0 0-.978.78m.978-.78-.978.78m0 0-1.025.715m1.025-.715-1.025.715m0 0-1.069.648m1.07-.648-1.07.648m0 0-1.108.578m1.108-.578-1.108.578m0 0-1.143.506m1.143-.506-1.143.506m0 0-1.173.432m1.173-.432-1.173.432m0 0-1.199.356m1.199-.356-1.199.356m0 0-1.218.278m1.218-.278-1.218.278m0 0-1.234.2m1.234-.2-1.234.2m0 0c-.37.035-.74.07-1.244.12m1.244-.12c-.475.045-.95.09-1.244.12m0 0-1.25.04m1.25-.04-1.25.04m0 0H27.49m81.781 0H27.49m0 0c-.357-.012-.713-.024-1.25-.04m1.25.04c-.464-.016-.928-.03-1.25-.04m0 0c-.278-.028-.557-.055-1.244-.12m1.245.12c-.378-.037-.755-.074-1.245-.12m0 0-1.234-.2m1.234.2-1.234-.2m0 0-1.218-.278m1.218.278-1.218-.278m0 0-1.199-.356m1.199.356c-.284-.085-.569-.17-1.199-.356m0 0-1.173-.432m1.173.432-1.173-.432m0 0-1.143-.506m1.143.506-1.143-.506m0 0-1.108-.578m1.108.578-1.108-.578m0 0-1.069-.648m1.069.648-1.069-.648m0 0-1.025-.715m1.025.715-1.025-.715m0 0-.977-.78m.977.78-.977-.78m0 0-.926-.84m.926.84-.926-.84m0 0-.87-.898m.87.898-.87-.898m0 0-.81-.952m.81.952-.81-.952m0 0-.747-1.001m.747 1.001-.747-1.001m0 0-.682-1.048m.682 1.048-.682-1.048m0 0-.614-1.09m.614 1.09-.614-1.09m0 0-.542-1.125m.542 1.126-.542-1.126m0 0-.47-1.159m.47 1.159-.47-1.159m0 0-.393-1.186m.394 1.186-.394-1.186m0 0-.317-1.21m.317 1.21-.317-1.21m0 0-.24-1.226m.24 1.227-.24-1.227m0 0c-.045-.355-.09-.71-.159-1.24m.16 1.24-.16-1.24m0 0L8 122.734m.08 1.248L8 122.734m0 0v-1.25m0 1.25v-1.25m0 0 .08-1.247M8 121.484l.08-1.247m0 0 .16-1.24m-.16 1.24.16-1.24m0 0 .239-1.227m-.24 1.227.24-1.227m0 0 .317-1.209m-.317 1.21.317-1.21m0 0 .394-1.186m-.394 1.186.394-1.186m0 0 .469-1.159m-.47 1.159.47-1.159m0 0 .542-1.126m-.542 1.126.542-1.126m0 0 .614-1.09m-.614 1.09.614-1.09m0 0 .682-1.047m-.682 1.048c.233-.36.467-.718.682-1.048m0 0 .747-1.002m-.747 1.002.747-1.002m0 0c.206-.24.41-.482.81-.951m-.81.951.81-.951m0 0 .87-.898m-.87.898.87-.898m0 0 .926-.84m-.926.84.926-.84m0 0 .977-.78m-.977.78c.215-.173.431-.345.977-.78m0 0 1.025-.715m-1.025.715 1.025-.715m0 0 1.069-.648m-1.069.648 1.069-.648m0 0 1.108-.579m-1.108.579 1.108-.579m0 0 1.143-.506m-1.143.506 1.143-.506m0 0 1.173-.431m-1.173.431 1.173-.431m0 0 1.199-.356m-1.199.356 1.199-.356m0 0 1.218-.278m-1.218.278 1.218-.278m0 0 1.234-.2m-1.234.2 1.234-.2m0 0 1.245-.12m-1.245.12 1.245-.12m0 0 1.249-.04m-1.25.04 1.25-.04m0 0"></path></g><g class="label" transform="translate(20.365 110.11)"><rect></rect><foreignObject width="96.031" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>invertNumber</p></span></div></foreignObject></g></g><g id="mermaid-4-flowchart-n2-3" class="node default" data-look="classic" transform="translate(189.066 122.11)"><circle r="10.305" class="basic label-container"></circle><g class="label" transform="translate(-2.805 -12)"><rect></rect><foreignObject width="5.609" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>•</p></span></div></foreignObject></g></g><g id="mermaid-4-flowchart-plus-5" class="node default" data-look="classic"><g class="basic label-container outer-path"><path fill="#ececff" stroke-width="0" d="M115.16 215.61h45.345l1.249.04 1.244.12c.255.04.51.082 1.234.199l1.219.278 1.198.356 1.173.431 1.143.506 1.108.579 1.07.648 1.025.715.977.78.925.84.87.898.81.951.748 1.002.682 1.048.613 1.089.543 1.126.469 1.159.394 1.186.317 1.21.239 1.226.16 1.24.08 1.247v1.25l-.08 1.248c-.052.395-.103.791-.16 1.24l-.24 1.227-.316 1.209c-.1.299-.2.598-.394 1.186l-.47 1.159-.542 1.126-.613 1.089-.682 1.048-.748 1.001-.81.952-.87.898-.925.84-.977.78-1.026.715-1.069.648-1.108.578-1.143.506-1.173.432-1.198.356-1.219.278-1.234.2-1.244.12c-.354.01-.708.022-1.25.04h-45.343c-.434-.015-.868-.028-1.25-.04-.454-.045-.908-.088-1.244-.12-.462-.076-.925-.15-1.234-.2l-1.219-.278-1.198-.356-1.173-.432-1.143-.506-1.108-.578-1.07-.648-1.024-.715-.978-.78-.925-.84-.87-.898-.81-.952-.748-1.001-.682-1.048-.613-1.09-.542-1.125-.47-1.159-.393-1.186c-.12-.456-.24-.911-.317-1.21l-.24-1.226-.16-1.24c-.02-.332-.042-.664-.08-1.248v-1.25l.08-1.247c.06-.455.118-.91.16-1.24l.24-1.227.317-1.209.394-1.186.469-1.159.542-1.126.613-1.09c.247-.379.495-.758.682-1.047l.748-1.002.81-.951.87-.898.925-.84.978-.78c.379-.265.758-.53 1.025-.715l1.069-.648 1.108-.579 1.143-.506 1.173-.431 1.198-.356 1.22-.278 1.233-.2 1.244-.12 1.25-.04"></path><path fill="none" stroke="#9370db" stroke-dasharray="0 0" stroke-width="1.3" d="M115.16 215.61h45.345m-45.344 0h45.344m0 0 1.249.04m-1.25-.04 1.25.04m0 0 1.244.12m-1.244-.12 1.244.12m0 0 1.234.199m-1.234-.2 1.234.2m0 0 1.219.278m-1.219-.278 1.219.278m0 0 1.198.356m-1.198-.356 1.198.356m0 0 1.173.431m-1.173-.431 1.173.431m0 0 1.143.506m-1.143-.506 1.143.506m0 0c.442.23.883.46 1.108.579m-1.108-.579 1.108.579m0 0 1.07.648m-1.07-.648 1.07.648m0 0 1.025.715m-1.026-.715 1.026.715m0 0 .977.78m-.977-.78.977.78m0 0 .925.84m-.925-.84.925.84m0 0 .87.898m-.87-.898.87.898m0 0 .81.951m-.81-.951.81.951m0 0 .748 1.002m-.748-1.002.748 1.002m0 0 .682 1.048m-.682-1.048.682 1.048m0 0 .613 1.089m-.613-1.09.613 1.09m0 0 .543 1.126m-.543-1.126.543 1.126m0 0 .469 1.159m-.47-1.159.47 1.159m0 0 .394 1.186m-.394-1.186.394 1.186m0 0 .317 1.21m-.317-1.21.317 1.21m0 0 .239 1.226m-.24-1.227.24 1.227m0 0 .16 1.24m-.16-1.24.16 1.24m0 0 .08 1.247m-.08-1.247c.02.323.04.645.08 1.247m0 0v1.25m0-1.25v1.25m0 0-.08 1.248m.08-1.248-.08 1.248m0 0c-.055.418-.108.836-.16 1.24m.16-1.24-.16 1.24m0 0-.24 1.227m.24-1.227-.24 1.227m0 0-.316 1.209m.317-1.21-.317 1.21m0 0-.394 1.186m.394-1.186-.394 1.186m0 0-.47 1.159m.47-1.159-.47 1.159m0 0-.542 1.126m.543-1.126-.543 1.126m0 0-.613 1.089m.613-1.09-.613 1.09m0 0-.682 1.048m.682-1.048c-.203.31-.405.622-.682 1.048m0 0-.748 1.001m.748-1.001-.748 1.001m0 0-.81.952m.81-.952-.81.952m0 0-.87.898m.87-.898-.87.898m0 0-.925.84m.925-.84-.925.84m0 0-.977.78m.977-.78-.977.78m0 0-1.026.715m1.026-.715-1.026.715m0 0-1.069.648m1.07-.648-1.07.648m0 0-1.108.578m1.108-.578-1.108.578m0 0-1.143.506m1.143-.506-1.143.506m0 0-1.173.432m1.173-.432-1.173.432m0 0-1.198.356m1.198-.356-1.198.356m0 0-1.219.278m1.219-.278-1.219.278m0 0-1.234.2m1.234-.2-1.234.2m0 0-1.244.12m1.244-.12-1.244.12m0 0-1.25.04m1.25-.04-1.25.04m0 0h-45.343m45.344 0H115.16m0 0c-.28-.01-.561-.019-1.25-.04m1.25.04c-.39-.013-.78-.026-1.25-.04m0 0-1.244-.12m1.244.12-1.244-.12m0 0-1.234-.2m1.234.2c-.45-.074-.9-.146-1.234-.2m0 0-1.219-.278m1.22.278-1.22-.278m0 0-1.198-.356m1.198.356c-.25-.075-.501-.15-1.198-.356m0 0-1.173-.432m1.173.432-1.173-.432m0 0c-.318-.14-.635-.28-1.143-.506m1.143.506-1.143-.506m0 0-1.108-.578m1.108.578-1.108-.578m0 0-1.07-.648m1.07.648-1.07-.648m0 0-1.024-.715m1.025.715-1.025-.715m0 0-.978-.78m.978.78-.978-.78m0 0-.925-.84m.925.84-.925-.84m0 0-.87-.898m.87.898-.87-.898m0 0-.81-.952m.81.952-.81-.952m0 0-.748-1.001m.748 1.001-.748-1.001m0 0-.682-1.048m.682 1.048-.682-1.048m0 0-.613-1.09m.613 1.09-.613-1.09m0 0-.542-1.125m.542 1.126-.542-1.126m0 0-.47-1.159m.47 1.159-.47-1.159m0 0-.393-1.186m.394 1.186-.394-1.186m0 0-.317-1.21m.317 1.21-.317-1.21m0 0-.24-1.226m.24 1.227-.24-1.227m0 0-.16-1.24m.16 1.24-.16-1.24m0 0c-.03-.49-.062-.982-.08-1.248m.08 1.248c-.02-.33-.041-.66-.08-1.248m0 0v-1.25m0 1.25v-1.25m0 0 .08-1.247m-.08 1.247c.03-.448.058-.897.08-1.247m0 0c.036-.27.07-.54.16-1.24m-.16 1.24c.039-.294.077-.588.16-1.24m0 0 .24-1.227m-.24 1.227.24-1.227m0 0 .317-1.209m-.317 1.21.317-1.21m0 0 .394-1.186m-.394 1.186.394-1.186m0 0 .469-1.159m-.47 1.159.47-1.159m0 0 .542-1.126m-.542 1.126.542-1.126m0 0 .613-1.09m-.613 1.09.613-1.09m0 0 .682-1.047m-.682 1.048.682-1.048m0 0 .748-1.002m-.748 1.002.748-1.002m0 0 .81-.951m-.81.951.81-.951m0 0 .87-.898m-.87.898.87-.898m0 0 .925-.84m-.925.84.925-.84m0 0 .978-.78m-.978.78.978-.78m0 0 1.025-.715m-1.025.715 1.025-.715m0 0 1.069-.648m-1.07.648 1.07-.648m0 0 1.108-.579m-1.108.579 1.108-.579m0 0 1.143-.506m-1.143.506 1.143-.506m0 0 1.173-.431m-1.173.431 1.173-.431m0 0 1.198-.356m-1.198.356 1.198-.356m0 0 1.22-.278m-1.22.278 1.22-.278m0 0 1.233-.2m-1.234.2 1.234-.2m0 0 1.244-.12m-1.244.12c.472-.045.944-.09 1.244-.12m0 0 1.25-.04m-1.25.04 1.25-.04m0 0"></path></g><g class="label" transform="translate(108.036 223.11)"><rect></rect><foreignObject width="59.594" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>plusOne</p></span></div></foreignObject></g></g><g id="mermaid-4-flowchart-n3-7" class="node default" data-look="classic" transform="translate(240.3 235.11)"><circle r="10.305" class="basic label-container"></circle><g class="label" transform="translate(-2.805 -12)"><rect></rect><foreignObject width="5.609" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>•</p></span></div></foreignObject></g></g><g id="mermaid-4-flowchart-invertB-9" class="node default" data-look="classic"><g class="basic label-container outer-path"><path fill="#ececff" stroke-width="0" d="M106.47 328.61h81.78c.355.01.71.022 1.25.04.325.03.65.062 1.244.12l1.234.199 1.219.278 1.198.356 1.173.431 1.143.506 1.109.579 1.069.648 1.025.715.977.78c.275.249.55.498.925.84l.87.898.81.951.748 1.002.682 1.048.613 1.089.543 1.126.469 1.159.394 1.186.317 1.21.239 1.226.16 1.24.08 1.247v1.25l-.08 1.248-.16 1.24-.24 1.227-.316 1.209-.394 1.186-.47 1.159-.542 1.126-.613 1.089-.682 1.048-.748 1.001-.81.952-.87.898-.925.84-.977.78-1.025.715-1.07.648-1.108.578-1.143.506-1.173.432-1.198.356-1.219.278-1.234.2c-.354.033-.708.068-1.244.12l-1.25.04h-81.78c-.343-.012-.685-.023-1.25-.04-.33-.033-.661-.064-1.244-.12l-1.234-.2-1.219-.278-1.198-.356-1.173-.432-1.143-.506-1.109-.578-1.069-.648-1.025-.715-.977-.78c-.244-.22-.487-.442-.925-.84l-.87-.898-.81-.952-.748-1.001-.682-1.048-.613-1.09-.543-1.125-.469-1.159-.394-1.186-.317-1.21-.239-1.226-.16-1.24-.08-1.248v-1.25l.08-1.247.16-1.24.24-1.227.316-1.209.394-1.186.47-1.159.542-1.126.613-1.09.682-1.047.748-1.002.81-.951.87-.898.925-.84.977-.78 1.025-.715 1.07-.648 1.108-.579 1.143-.506 1.173-.431 1.198-.356 1.219-.278 1.234-.2 1.244-.12 1.25-.04"></path><path fill="none" stroke="#9370db" stroke-dasharray="0 0" stroke-width="1.3" d="M106.47 328.61h81.78m-81.78 0h81.78m0 0 1.25.04m-1.25-.04 1.25.04m0 0c.266.025.532.05 1.244.12m-1.244-.12c.275.026.55.052 1.244.12m0 0 1.234.199m-1.234-.2 1.234.2m0 0 1.219.278m-1.219-.278 1.219.278m0 0 1.198.356m-1.198-.356 1.198.356m0 0 1.173.431m-1.173-.431 1.173.431m0 0 1.143.506m-1.143-.506 1.143.506m0 0 1.109.579m-1.109-.579c.31.163.621.325 1.109.579m0 0 1.069.648m-1.07-.648 1.07.648m0 0 1.025.715m-1.025-.715 1.025.715m0 0c.339.27.678.54.977.78m-.977-.78.977.78m0 0 .925.84m-.925-.84c.277.25.554.502.925.84m0 0c.179.183.357.367.87.898m-.87-.898.87.898m0 0 .81.951m-.81-.951.81.951m0 0 .748 1.002m-.748-1.002.748 1.002m0 0 .682 1.048m-.682-1.048.682 1.048m0 0 .613 1.089m-.613-1.09.613 1.09m0 0 .543 1.126m-.543-1.126.543 1.126m0 0 .469 1.159m-.47-1.159.47 1.159m0 0 .394 1.186m-.394-1.186.394 1.186m0 0 .317 1.21m-.317-1.21.317 1.21m0 0 .239 1.226m-.24-1.227.24 1.227m0 0 .16 1.24m-.16-1.24.16 1.24m0 0 .08 1.247m-.08-1.247.08 1.247m0 0v1.25m0-1.25v1.25m0 0-.08 1.248m.08-1.248c-.03.452-.058.904-.08 1.248m0 0-.16 1.24m.16-1.24-.16 1.24m0 0-.24 1.227m.24-1.227-.24 1.227m0 0-.316 1.209m.317-1.21-.317 1.21m0 0-.394 1.186m.394-1.186-.394 1.186m0 0-.47 1.159m.47-1.159-.47 1.159m0 0-.542 1.126m.543-1.126-.543 1.126m0 0-.613 1.089m.613-1.09-.613 1.09m0 0-.682 1.048m.682-1.048-.682 1.048m0 0-.748 1.001m.748-1.001-.748 1.001m0 0-.81.952m.81-.952-.81.952m0 0-.87.898m.87-.898-.87.898m0 0-.925.84m.925-.84-.925.84m0 0-.977.78m.977-.78-.977.78m0 0-1.025.715m1.025-.715-1.025.715m0 0-1.07.648m1.07-.648-1.07.648m0 0-1.108.578m1.109-.578c-.421.22-.842.44-1.109.578m0 0-1.143.506m1.143-.506-1.143.506m0 0-1.173.432m1.173-.432-1.173.432m0 0-1.198.356m1.198-.356-1.198.356m0 0-1.219.278m1.219-.278-1.219.278m0 0-1.234.2m1.234-.2-1.234.2m0 0-1.244.12m1.244-.12-1.244.12m0 0-1.25.04m1.25-.04c-.352.01-.705.022-1.25.04m0 0h-81.78m81.78 0h-81.78m0 0c-.293-.01-.586-.02-1.25-.04m1.25.04-1.25-.04m0 0c-.259-.026-.518-.05-1.244-.12m1.244.12c-.285-.028-.57-.056-1.244-.12m0 0-1.234-.2m1.234.2-1.234-.2m0 0-1.219-.278m1.219.278-1.219-.278m0 0-1.198-.356m1.198.356-1.198-.356m0 0-1.173-.432m1.173.432-1.173-.432m0 0-1.143-.506m1.143.506-1.143-.506m0 0L96.9 365.1m1.109.578L96.9 365.1m0 0-1.069-.648m1.07.648-1.07-.648m0 0-1.025-.715m1.025.715-1.025-.715m0 0-.977-.78m.977.78-.977-.78m0 0-.925-.84m.925.84-.925-.84m0 0-.87-.898m.87.898-.87-.898m0 0-.81-.952m.81.952-.81-.952m0 0-.748-1.001m.748 1.001-.748-1.001m0 0-.682-1.048m.682 1.048-.682-1.048m0 0-.613-1.09m.613 1.09-.613-1.09m0 0-.543-1.125m.543 1.126-.543-1.126m0 0-.469-1.159m.47 1.159-.47-1.159m0 0-.394-1.186m.394 1.186-.394-1.186m0 0-.317-1.21m.317 1.21-.317-1.21m0 0-.239-1.226m.24 1.227-.24-1.227m0 0-.16-1.24m.16 1.24-.16-1.24m0 0-.08-1.248m.08 1.248c-.025-.399-.05-.797-.08-1.248m0 0v-1.25m0 1.25v-1.25m0 0 .08-1.247m-.08 1.247.08-1.247m0 0 .16-1.24m-.16 1.24.16-1.24m0 0 .24-1.227m-.24 1.227.24-1.227m0 0 .316-1.209m-.317 1.21.317-1.21m0 0 .394-1.186m-.394 1.186.394-1.186m0 0 .47-1.159m-.47 1.159.47-1.159m0 0 .542-1.126m-.543 1.126.543-1.126m0 0 .613-1.09m-.613 1.09.613-1.09m0 0c.26-.397.518-.795.682-1.047m-.682 1.048.682-1.048m0 0 .748-1.002m-.748 1.002.748-1.002m0 0 .81-.951m-.81.951.81-.951m0 0c.273-.282.545-.564.87-.898m-.87.898.87-.898m0 0 .925-.84m-.925.84.925-.84m0 0 .977-.78m-.977.78.977-.78m0 0 1.025-.715m-1.025.715 1.025-.715m0 0c.288-.175.576-.35 1.07-.648m-1.07.648 1.07-.648m0 0 1.108-.579m-1.109.579 1.109-.579m0 0 1.143-.506m-1.143.506 1.143-.506m0 0 1.173-.431m-1.173.431 1.173-.431m0 0 1.198-.356m-1.198.356 1.198-.356m0 0 1.219-.278m-1.219.278 1.219-.278m0 0 1.234-.2m-1.234.2 1.234-.2m0 0 1.244-.12m-1.244.12 1.244-.12m0 0 1.25-.04m-1.25.04 1.25-.04m0 0"></path></g><g class="label" transform="translate(99.344 336.11)"><rect></rect><foreignObject width="96.031" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>invertNumber</p></span></div></foreignObject></g></g><g id="mermaid-4-flowchart-norm-11" class="node default" data-look="classic"><g class="basic label-container outer-path"><path fill="#ececff" stroke-width="0" d="M277.23 328.61h112.016l1.25.04 1.244.12 1.234.199 1.218.278 1.199.356 1.173.431 1.143.506 1.108.579 1.07.648 1.024.715.978.78.925.84.87.898.81.951.748 1.002.681 1.048.614 1.089.542 1.126.47 1.159.393 1.186.317 1.21c.076.386.15.772.24 1.226l.16 1.24c.026.421.053.843.08 1.247v1.25l-.08 1.248-.16 1.24-.24 1.227-.317 1.209-.394 1.186-.469 1.159-.542 1.126-.614 1.089-.681 1.048-.748 1.001-.81.952-.87.898-.925.84-.978.78-1.025.715-1.069.648-1.108.578-1.143.506-1.173.432-1.199.356-1.218.278-1.234.2-1.244.12c-.379.011-.758.024-1.25.04H277.231l-1.25-.04-1.244-.12c-.361-.06-.723-.118-1.234-.2-.39-.09-.782-.179-1.219-.278l-1.198-.356-1.173-.432-1.143-.506-1.108-.578-1.07-.648-1.025-.715-.977-.78-.925-.84-.87-.898-.81-.952-.748-1.001-.682-1.048-.613-1.09-.542-1.125-.47-1.159-.393-1.186-.318-1.21-.238-1.226-.16-1.24-.08-1.248v-1.25l.08-1.247.16-1.24.238-1.227.318-1.209.393-1.186.47-1.159.542-1.126.613-1.09.682-1.047.748-1.002.81-.951.87-.898.925-.84.977-.78 1.026-.715 1.069-.648 1.108-.579 1.143-.506 1.173-.431 1.198-.356 1.219-.278 1.234-.2 1.244-.12 1.25-.04"></path><path fill="none" stroke="#9370db" stroke-dasharray="0 0" stroke-width="1.3" d="M277.23 328.61h112.016m-112.015 0h112.015m0 0 1.25.04m-1.25-.04 1.25.04m0 0 1.244.12m-1.244-.12 1.244.12m0 0 1.234.199m-1.234-.2 1.234.2m0 0 1.218.278m-1.218-.278 1.218.278m0 0 1.199.356m-1.199-.356 1.199.356m0 0 1.173.431m-1.173-.431 1.173.431m0 0 1.143.506m-1.143-.506 1.143.506m0 0 1.108.579m-1.108-.579 1.108.579m0 0 1.07.648m-1.07-.648 1.07.648m0 0 1.024.715m-1.025-.715 1.025.715m0 0 .978.78m-.978-.78.978.78m0 0 .925.84m-.925-.84.925.84m0 0 .87.898m-.87-.898.87.898m0 0 .81.951m-.81-.951.81.951m0 0 .748 1.002m-.748-1.002.748 1.002m0 0 .681 1.048m-.681-1.048.681 1.048m0 0 .614 1.089m-.614-1.09.614 1.09m0 0 .542 1.126m-.542-1.126.542 1.126m0 0 .47 1.159m-.47-1.159.47 1.159m0 0c.095.29.192.579.393 1.186m-.394-1.186.394 1.186m0 0 .317 1.21m-.317-1.21.317 1.21m0 0 .24 1.226m-.24-1.227.24 1.227m0 0 .16 1.24m-.16-1.24c.06.479.123.957.16 1.24m0 0 .08 1.247m-.08-1.247c.02.335.042.67.08 1.247m0 0v1.25m0-1.25v1.25m0 0-.08 1.248m.08-1.248c-.02.29-.038.579-.08 1.248m0 0-.16 1.24m.16-1.24c-.05.378-.098.756-.16 1.24m0 0-.24 1.227m.24-1.227c-.073.368-.144.737-.24 1.227m0 0-.317 1.209m.317-1.21-.317 1.21m0 0-.394 1.186m.394-1.186-.394 1.186m0 0-.469 1.159m.47-1.159-.47 1.159m0 0-.542 1.126m.542-1.126-.542 1.126m0 0-.614 1.089m.614-1.09-.614 1.09m0 0-.681 1.048m.681-1.048-.681 1.048m0 0-.748 1.001m.748-1.001-.748 1.001m0 0-.81.952m.81-.952-.81.952m0 0-.87.898m.87-.898-.87.898m0 0-.925.84m.925-.84-.925.84m0 0-.978.78m.978-.78-.978.78m0 0-1.025.715m1.025-.715-1.025.715m0 0-1.069.648m1.07-.648-1.07.648m0 0-1.108.578m1.108-.578-1.108.578m0 0-1.143.506m1.143-.506-1.143.506m0 0-1.173.432m1.173-.432-1.173.432m0 0-1.199.356m1.199-.356-1.199.356m0 0-1.218.278m1.218-.278-1.218.278m0 0-1.234.2m1.234-.2-1.234.2m0 0-1.244.12m1.244-.12-1.244.12m0 0-1.25.04m1.25-.04-1.25.04m0 0H277.231m112.015 0H277.231m0 0-1.25-.04m1.25.04c-.28-.01-.56-.019-1.25-.04m0 0-1.244-.12m1.244.12c-.285-.028-.57-.056-1.244-.12m0 0-1.234-.2m1.234.2-1.234-.2m0 0-1.219-.278m1.219.278-1.219-.278m0 0-1.198-.356m1.198.356-1.198-.356m0 0-1.173-.432m1.173.432-1.173-.432m0 0-1.143-.506m1.143.506-1.143-.506m0 0-1.108-.578m1.108.578-1.108-.578m0 0-1.07-.648m1.07.648-1.07-.648m0 0-1.025-.715m1.026.715-1.026-.715m0 0-.977-.78m.977.78-.977-.78m0 0-.925-.84m.925.84-.925-.84m0 0-.87-.898m.87.898-.87-.898m0 0-.81-.952m.81.952-.81-.952m0 0-.748-1.001m.748 1.001-.748-1.001m0 0-.682-1.048m.682 1.048-.682-1.048m0 0-.613-1.09m.613 1.09-.613-1.09m0 0-.542-1.125m.542 1.126-.542-1.126m0 0-.47-1.159m.47 1.159-.47-1.159m0 0-.393-1.186m.393 1.186-.393-1.186m0 0-.318-1.21m.318 1.21-.318-1.21m0 0-.238-1.226m.238 1.227-.238-1.227m0 0-.16-1.24m.16 1.24-.16-1.24m0 0-.08-1.248m.08 1.248-.08-1.248m0 0v-1.25m0 1.25v-1.25m0 0 .08-1.247m-.08 1.247.08-1.247m0 0 .16-1.24m-.16 1.24.16-1.24m0 0 .238-1.227m-.238 1.227.238-1.227m0 0 .318-1.209m-.318 1.21.318-1.21m0 0 .393-1.186m-.393 1.186.393-1.186m0 0 .47-1.159m-.47 1.159.47-1.159m0 0 .542-1.126m-.542 1.126.542-1.126m0 0 .613-1.09m-.613 1.09.613-1.09m0 0 .682-1.047m-.682 1.048.682-1.048m0 0c.26-.35.522-.699.748-1.002m-.748 1.002.748-1.002m0 0 .81-.951m-.81.951.81-.951m0 0 .87-.898m-.87.898.87-.898m0 0 .925-.84m-.925.84c.3-.274.601-.547.925-.84m0 0 .977-.78m-.977.78.977-.78m0 0 1.026-.715m-1.026.715 1.026-.715m0 0 1.069-.648m-1.07.648 1.07-.648m0 0 1.108-.579m-1.108.579 1.108-.579m0 0c.251-.11.503-.222 1.143-.506m-1.143.506 1.143-.506m0 0 1.173-.431m-1.173.431 1.173-.431m0 0 1.198-.356m-1.198.356c.4-.12.802-.238 1.198-.356m0 0 1.219-.278m-1.219.278c.4-.09.798-.182 1.219-.278m0 0 1.234-.2m-1.234.2 1.234-.2m0 0 1.244-.12m-1.244.12 1.244-.12m0 0 1.25-.04m-1.25.04 1.25-.04m0 0"></path></g><g class="label" transform="translate(270.106 336.11)"><rect></rect><foreignObject width="126.266" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>normalizeNumber</p></span></div></foreignObject></g></g></g></g><defs><filter id="mermaid-4-drop-shadow" width="130%" height="130%"><feDropShadow dx="4" dy="4" flood-color="#000" flood-opacity=".06" stdDeviation="0"></feDropShadow></filter></defs><defs><filter id="mermaid-4-drop-shadow-small" width="150%" height="150%"><feDropShadow dx="2" dy="2" flood-color="#000" flood-opacity=".06" stdDeviation="0"></feDropShadow></filter></defs></svg>
<p>The name, meanwhile, is <em>flat</em>: a concatenation joined by <code>></code>. A binary tree gets serialized into a string, and the string can be reversed back into the tree only if the naming convention is <em>bijective</em>. The flat <code>></code> notation isn’t.</p>
<p>How many trees can correspond to one name with N separators? The standard answer from combinatorics: the <a href="https://en.wikipedia.org/wiki/Catalan_number">Catalan number</a> <math><msub><mi>C</mi><mi>N</mi></msub></math>.</p>
<p><math><mrow><msub><mi>C</mi><mi>n</mi></msub><mo>=</mo><mfrac><mn>1</mn><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></mfrac><mrow><mo fence="true">(</mo><mfrac linethickness="0px"><mrow><mn>2</mn><mi>n</mi></mrow><mi>n</mi></mfrac><mo fence="true">)</mo></mrow></mrow></math> — the sequence that counts: the number of binary trees with n+1 leaves, the number of balanced-paren strings of length 2n, the number of Dyck paths of length 2n, the number of triangulations of an (n+2)-gon, and a dozen other isomorphic combinatorial objects. The kind of number that turns up <em>everywhere</em>.</p>
<p>The most direct angle for our case: parenthesization. For an arbitrary binary operator <code>•</code>, the number of ways to parenthesize <code>a • b • c • ...</code> (with n+1 operands) is <math><msub><mi>C</mi><mi>n</mi></msub></math>. <code>withOverrodeHaltState</code> is exactly such an operator — each parenthesization corresponds to a distinct composition tree.</p>
<p>The first eight values: <math><mrow><msub><mi>C</mi><mn>0</mn></msub><mo>=</mo><mn>1</mn></mrow></math>, <math><mrow><msub><mi>C</mi><mn>1</mn></msub><mo>=</mo><mn>1</mn></mrow></math>, <math><mrow><msub><mi>C</mi><mn>2</mn></msub><mo>=</mo><mn>2</mn></mrow></math>, <math><mrow><msub><mi>C</mi><mn>3</mn></msub><mo>=</mo><mn>5</mn></mrow></math>, <math><mrow><msub><mi>C</mi><mn>4</mn></msub><mo>=</mo><mn>14</mn></mrow></math>, <math><mrow><msub><mi>C</mi><mn>5</mn></msub><mo>=</mo><mn>42</mn></mrow></math>, <math><mrow><msub><mi>C</mi><mn>6</mn></msub><mo>=</mo><mn>132</mn></mrow></math>, <math><mrow style="font-weight:bold;"><msub><mi>𝑪</mi><mstyle style="font-style:italic;font-family:Cambria, &#x27;Times New Roman&#x27;, serif;font-weight:bold;"><mn>7</mn></mstyle></msub><mo>=</mo><mstyle style="font-style:italic;font-family:Cambria, &#x27;Times New Roman&#x27;, serif;font-weight:bold;"><mn>4</mn></mstyle><mstyle style="font-style:italic;font-family:Cambria, &#x27;Times New Roman&#x27;, serif;font-weight:bold;"><mn>2</mn></mstyle><mstyle style="font-style:italic;font-family:Cambria, &#x27;Times New Roman&#x27;, serif;font-weight:bold;"><mn>9</mn></mstyle></mrow></math>.</p>
<p>For our <code>A>B>B>A>A>B>B>A</code>, that means 429 different construction trees, each with its own parent-child wiring, all collapsing to the same string. And 429 isn’t a theoretical upper bound — it’s the exact number of distinct structures hiding behind that one name.</p>
<p>A smaller example — <code>A>B>C>D</code> (three separators). By the formula, <math><mrow><msub><mi>C</mi><mn>3</mn></msub><mo>=</mo><mn>5</mn></mrow></math>; here are the five construction trees, written as code:</p>
<pre class="shiki shiki-themes github-light github-dark language-javascript" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// 1. fully left-associative</span></span>
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">((</span><span style="color:#005CC5;--shiki-dark:#79B8FF">A</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">wohs</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">B</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)).</span><span style="color:#6F42C1;--shiki-dark:#B392F0">wohs</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">C</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)).</span><span style="color:#6F42C1;--shiki-dark:#B392F0">wohs</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">D</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// 2.</span></span>
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">A</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">wohs</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">B</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">wohs</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">C</span><span style="color:#24292E;--shiki-dark:#E1E4E8">))).</span><span style="color:#6F42C1;--shiki-dark:#B392F0">wohs</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">D</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// 3.</span></span>
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">A</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">wohs</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">B</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)).</span><span style="color:#6F42C1;--shiki-dark:#B392F0">wohs</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">C</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">wohs</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">D</span><span style="color:#24292E;--shiki-dark:#E1E4E8">))</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// 4.</span></span>
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF">A</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">wohs</span><span style="color:#24292E;--shiki-dark:#E1E4E8">((</span><span style="color:#005CC5;--shiki-dark:#79B8FF">B</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">wohs</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">C</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)).</span><span style="color:#6F42C1;--shiki-dark:#B392F0">wohs</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">D</span><span style="color:#24292E;--shiki-dark:#E1E4E8">))</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// 5. fully right-associative</span></span>
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF">A</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">wohs</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">B</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">wohs</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">C</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">wohs</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">D</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)))</span></span></code></pre>
<p>All five collapse to the same flat string <code>A>B>C>D</code>. Under the paren notation v7 will ship, each gets a distinct name — more on that below.</p>
<h2 id="the-fix-is-parens"><a class="heading-anchor" href="#the-fix-is-parens">The fix is parens</a></h2>
<p>If a flat separator throws the tree away, parens keep it. v7 (<a href="https://github.com/mellonis/turing-machine-js/issues/148"><code>turing-machine-js#148</code></a>) changes the naming rule to:</p>
<pre class="shiki shiki-themes github-light github-dark language-javascript" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">state.#name </span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> `${</span><span style="color:#005CC5;--shiki-dark:#79B8FF">this</span><span style="color:#032F62;--shiki-dark:#9ECBFF">.</span><span style="color:#24292E;--shiki-dark:#E1E4E8">name</span><span style="color:#032F62;--shiki-dark:#9ECBFF">}(${</span><span style="color:#24292E;--shiki-dark:#E1E4E8">override</span><span style="color:#032F62;--shiki-dark:#9ECBFF">.</span><span style="color:#24292E;--shiki-dark:#E1E4E8">name</span><span style="color:#032F62;--shiki-dark:#9ECBFF">})`</span><span style="color:#24292E;--shiki-dark:#E1E4E8">;</span></span></code></pre>
<p><code>A.withOverrodeHaltState(B)</code> is now named <code>A(B)</code>. Back to our two <code>A>B>A</code> constructions:</p>
<pre class="shiki shiki-themes github-light github-dark language-javascript" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Construction 1: A(B(A))</span></span>
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">const</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> c1</span><span style="color:#D73A49;--shiki-dark:#F97583"> =</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> A</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">withOverrodeHaltState</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">B</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">withOverrodeHaltState</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">A</span><span style="color:#24292E;--shiki-dark:#E1E4E8">));</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Construction 2: A(B)(A) — in pure paren notation</span></span>
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">const</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> c2</span><span style="color:#D73A49;--shiki-dark:#F97583"> =</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> A</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">withOverrodeHaltState</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">B</span><span style="color:#24292E;--shiki-dark:#E1E4E8">).</span><span style="color:#6F42C1;--shiki-dark:#B392F0">withOverrodeHaltState</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">A</span><span style="color:#24292E;--shiki-dark:#E1E4E8">);</span></span></code></pre>
<p>Same characters, different brackets, different trees. Names distinguish them. Bijection!</p>
<p>And this isn’t an <em>invented</em> convention. Balanced-paren strings of length 2n are the canonical encoding of binary trees with n+1 leaves in combinatorics — the same bijection underlying one of the foundational counting results for Catalan numbers. A better convention wasn’t <em>designed</em> — what gets <em>recovered</em> is the structure the <code>></code> notation was always discarding.</p>
<p>The cost: state names from users can no longer contain <code>(</code> or <code>)</code> — the <code>State</code> constructor throws. Parens are reserved for composition. In exchange, <code>></code> is no longer reserved and is fine in user-provided names again.</p>
<h2 id="the-other-half-of-the-story"><a class="heading-anchor" href="#the-other-half-of-the-story">The other half of the story</a></h2>
<p>The clean paren bijection above is about <em>naming</em>. v7 also cleans up the runtime alongside. <a href="https://github.com/mellonis/turing-machine-js/issues/176"><code>turing-machine-js#176</code></a> adds chain-collapse: inside <code>withOverrodeHaltState</code>, we now do <code>bare = this.#bareState ?? this</code>. So <code>A.wohs(B).wohs(A)</code> is recognized as “wrapping an already-wrapped A” — the inner override (<code>B</code>) is dead at runtime anyway (only the <em>outermost</em> wrapper’s override gets pushed onto the halt-stack), and instead of <code>A(B)(A)</code> you get <code>A(A)</code>.</p>
<p>So in actual v7, Construction 2 doesn’t give you <code>A(B)(A)</code> — at construction time it collapses to <code>A(A)</code>. Paren naming on its own is bijective (one tree, one name); chain-collapse adds a step on top, removing trees that are indistinguishable at runtime. The composite name in v7 describes how the machine behaves, not how it was built.</p>
<p>And while we were touching the operator: the method gets renamed. <code>withOverrodeHaltState</code> → <code>withOverriddenHaltState</code> (<a href="https://github.com/mellonis/turing-machine-js/issues/149"><code>turing-machine-js#149</code></a>). Past-tense <code>overrode</code> never fit the idiom — it should have been the past participle <code>overridden</code>. A seven-year grammar typo on a public API. Hard cutover, no alias.</p>
<h2 id="other-places-this-shows-up"><a class="heading-anchor" href="#other-places-this-shows-up">Other places this shows up</a></h2>
<p>Non-injective serialization is a general pattern. If your codebase has a “name” formed by flat-separator concatenation of something tree-shaped, the odds of a C_n bug aren’t zero. A few examples:</p>
<ul>
<li><strong>File-extension chains</strong> — <code>.tar.gz</code>, <code>.spec.ts</code>, <code>.d.ts</code>. Works by convention because the extensions are well-known. Put a dot in the filename and the ambiguity is immediate: is <code>my.app.tar.gz</code> the basename <code>my.app</code> with extension <code>.tar.gz</code>, or the basename <code>my.app.tar</code> with extension <code>.gz</code>? Different tools answer differently.</li>
<li><strong>DB column aliases</strong> with <code>_</code> separators: <code>user_address_country</code>. If <code>user_address</code> is already a table name (underscore is part of the identifier), then <code>user_address_country</code> is ambiguous: is it <code>user.address_country</code> or <code>user_address.country</code>? Fix via qualified namespacing or explicit aliases.</li>
<li><strong>Module paths in Java/Python</strong> — <code>com.example.foo.Bar</code>. Could be class <code>Bar</code> in package <code>com.example.foo</code> or nested class <code>foo.Bar</code> in package <code>com.example</code>. Resolved by convention (uppercase = class), not by the naming itself.</li>
</ul>
<p>Code-review heuristic: <strong>if your “identifier” is a flat-separator concatenation of something tree-shaped, look for the C_n bug</strong>. It’s almost always <em>latent</em>: in production the names happen not to collide on the actual data, but architecturally the hole is always there.</p>
<p>In my library the C_n bug hid for seven years because no one was trying to catch the engine on a name collision. To find it, you’d have to know to construct two structurally distinct trees and check whether their names differ. Nobody writes that test until they hear the collision is possible.</p>
<h2 id="what-v7-ships"><a class="heading-anchor" href="#what-v7-ships">What v7 ships</a></h2>
<p>Three tickets that were planned as three separate changes but, on closer look, are the same thought:</p>
<ul>
<li>
<p><strong>Paren-based naming</strong> (<a href="https://github.com/mellonis/turing-machine-js/issues/148"><code>turing-machine-js#148</code></a>). The bijection between composition trees and their names.</p>
</li>
<li>
<p><strong>Cleaner Mermaid emit</strong> (<a href="https://github.com/mellonis/turing-machine-js/issues/138"><code>turing-machine-js#138</code></a>, <a href="https://github.com/mellonis/turing-machine-js/issues/174"><code>turing-machine-js#174</code></a>). Wrappers emit as separate <code>[[composite-name]]</code> nodes; the bare’s reachable subtree becomes a subgraph <code>callable subtree of NAME</code> block. The structural clarity of the name shows up as visual clarity in the diagram:</p>
<svg xmlns="http://www.w3.org/2000/svg" id="mermaid-5" width="100%" aria-roledescription="flowchart-v2" class="flowchart" style="font-family:arial,sans-serif;font-size:16px;fill:#333;max-width:706.8036499023438px" viewBox="0 0 706.804 226.898"><style>@keyframes edge-animation-frame{0%{stroke-dashoffset:0}}@keyframes dash{to{stroke-dashoffset:0}}#mermaid-5 .edge-thickness-normal{stroke-width:1px}#mermaid-5 .edge-pattern-solid{stroke-dasharray:0}#mermaid-5 .edge-pattern-dotted{stroke-dasharray:2}#mermaid-5 .marker{fill:#333;stroke:#333}#mermaid-5 .marker.cross{stroke:#333}#mermaid-5 svg{font-family:arial,sans-serif;font-size:16px}#mermaid-5 p{margin:0}#mermaid-5 .label{font-family:arial,sans-serif;color:#333}#mermaid-5 span{fill:#333;color:#333}#mermaid-5 .node circle,#mermaid-5 .node path,#mermaid-5 .node rect{fill:#ececff;stroke:#9370db;stroke-width:1px}#mermaid-5 .flowchart-link{stroke:#333;fill:none}#mermaid-5 .edgeLabel,#mermaid-5 .node .label{text-align:center}#mermaid-5 .edgeLabel,#mermaid-5 .edgeLabel p,#mermaid-5 .edgeLabel rect{background-color:rgba(232,232,232,.8)}#mermaid-5 .edgeLabel rect{opacity:.5;fill:rgba(232,232,232,.8)}#mermaid-5 .labelBkg{background-color:rgba(232,232,232,.5)}#mermaid-5 [data-look=neo].cluster rect,#mermaid-5 [data-look=neo].node circle,#mermaid-5 [data-look=neo].node rect{stroke:#9370db;filter:drop-shadow(1px 2px 2px #b9b9b9)}#mermaid-5 [data-look=neo].node path{stroke:#9370db;stroke-width:1px}#mermaid-5 [data-look=neo].node .outer-path{filter:drop-shadow(1px 2px 2px #b9b9b9)}#mermaid-5 :root{--mermaid-font-family:arial,sans-serif}</style><marker id="mermaid-5_flowchart-v2-pointEnd" class="marker flowchart-v2" markerHeight="8" markerUnits="userSpaceOnUse" markerWidth="8" orient="auto" refX="5" refY="5" viewBox="0 0 10 10"><path d="m0 0 10 5-10 5z" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></path></marker><marker id="mermaid-5_flowchart-v2-pointStart" class="marker flowchart-v2" markerHeight="8" markerUnits="userSpaceOnUse" markerWidth="8" orient="auto" refX="4.5" refY="5" viewBox="0 0 10 10"><path d="m0 5 10 5V0z" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></path></marker><marker id="mermaid-5_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="10.5" orient="auto" refX="11.5" refY="7" viewBox="0 0 11.5 14"><path d="m0 0 11.5 7L0 14z" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></path></marker><marker id="mermaid-5_flowchart-v2-pointStart-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="11.5" orient="auto" refX="1" refY="7" viewBox="0 0 11.5 14"><path d="m0 7 11.5 7V0z" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></path></marker><marker id="mermaid-5_flowchart-v2-circleEnd" class="marker flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="11" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-5_flowchart-v2-circleStart" class="marker flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="-1" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-5_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="14" orient="auto" refX="12.25" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-5_flowchart-v2-circleStart-margin" class="marker flowchart-v2" markerHeight="14" markerUnits="userSpaceOnUse" markerWidth="14" orient="auto" refX="-2" refY="5" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:0;stroke-dasharray:1,0"></circle></marker><marker id="mermaid-5_flowchart-v2-crossEnd" class="marker cross flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="12" refY="5.2" viewBox="0 0 11 11"><path d="m1 1 9 9m0-9-9 9" class="arrowMarkerPath" style="stroke-width:2;stroke-dasharray:1,0"></path></marker><marker id="mermaid-5_flowchart-v2-crossStart" class="marker cross flowchart-v2" markerHeight="11" markerUnits="userSpaceOnUse" markerWidth="11" orient="auto" refX="-1" refY="5.2" viewBox="0 0 11 11"><path d="m1 1 9 9m0-9-9 9" class="arrowMarkerPath" style="stroke-width:2;stroke-dasharray:1,0"></path></marker><marker id="mermaid-5_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" markerHeight="12" markerUnits="userSpaceOnUse" markerWidth="12" orient="auto" refX="17.7" refY="7.5" viewBox="0 0 15 15"><path d="m1 1 13 13M1 14 14 1" class="arrowMarkerPath" style="stroke-width:2.5"></path></marker><marker id="mermaid-5_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" markerHeight="12" markerUnits="userSpaceOnUse" markerWidth="12" orient="auto" refX="-3.5" refY="7.5" viewBox="0 0 15 15"><path d="m1 1 13 13M1 14 14 1" class="arrowMarkerPath" style="stroke-width:2.5;stroke-dasharray:1,0"></path></marker><g class="root"><g class="clusters"><g id="mermaid-5-frame" class="cluster" data-look="classic"><path d="M298.902 8h399.902v136.898H298.902z" style="fill:#ffffde;stroke:#aa3;stroke-width:1px"></path><foreignObject width="144.094" height="24" class="cluster-label" transform="translate(426.806 8)"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5"><span class="nodeLabel" style="color:#333"><p style="background-color:transparent">callable subtree of A</p></span></div></foreignObject></g></g><g class="edgePaths"><path id="mermaid-5-L_idle_W_0" marker-end="url(#mermaid-5_flowchart-v2-pointEnd)" d="m58.136 103.949 7.123-.083c7.122-.083 21.367-.25 35.112-.258 13.744-.007 26.989.144 33.612.22l6.622.075" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_idle_W_0" data-look="classic" data-points="W3sieCI6NTguMTM2MjEyNDMxODI2NzEsInkiOjEwMy45NDkyMTg3NX0seyJ4IjoxMDAuODcwNTg2Mzk1MjYzNjcsInkiOjEwMy40NDkyMTg3NX0seyJ4IjoxNDQuNjA0OTYxMzk1MjYzNjcsInkiOjEwMy45NDkyMTg3NX1d"></path><path id="mermaid-5-L_W_A_0" marker-end="url(#mermaid-5_flowchart-v2-pointEnd)" d="m207.605 86.042 7.566-4.432c7.567-4.432 22.7-13.297 37.916-17.729s30.515-4.432 42.125-2.356c11.61 2.075 19.529 6.226 23.489 8.301l3.96 2.075" class="edge-pattern-solid edge-thickness-normal flowchart-link" data-edge="true" data-et="edge" data-id="L_W_A_0" data-look="classic" data-points="W3sieCI6MjA3LjYwNDk2MTM5NTI2MzY3LCJ5Ijo4Ni4wNDE4ODA1MDQzMTUxM30seyJ4IjoyNTMuMDAzMzk4ODk1MjYzNjcsInkiOjU5LjQ0OTIxODc1fSx7IngiOjI5OC45MDE4MzYzOTUyNjM3LCJ5Ijo1OS40NDkyMTg3NX0seyJ4IjozMjYuMjA0MjAzNDc2MDU1MSwieSI6NzMuNzU4MTAzOTEzNzQxMzd9XQ==" style="stroke-width:3.5px"></path><path id="mermaid-5-L_A_A1_0" marker-end="url(#mermaid-5_flowchart-v2-pointEnd)" d="m359.804 81.949 7.491-.083c7.49-.083 22.472-.25 36.871-.333 14.398-.084 28.213-.084 35.121-.084h6.907" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_A_A1_0" data-look="classic" data-points="W3sieCI6MzU5LjgwMzY3MzgyNzA5MTEsInkiOjgxLjk0OTIxODc1fSx7IngiOjQwNC43NDg5ODUyOTA1MjczNCwieSI6ODEuNDQ5MjE4NzV9LHsieCI6NDUwLjE5NDI5Nzc5MDUyNzM0LCJ5Ijo4MS40NDkyMTg3NX1d"></path><path id="mermaid-5-L_A1_h_0" marker-end="url(#mermaid-5_flowchart-v2-pointEnd)" d="M529.772 81.449h84.235" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_A1_h_0" data-look="classic" data-points="W3sieCI6NTI5Ljc3MjQyMjc5MDUyNzMsInkiOjgxLjQ0OTIxODc1fSx7IngiOjU3My44ODk2MTAyOTA1MjczLCJ5Ijo4MS40NDkyMTg3NX0seyJ4Ijo2MTguMDA2Nzk3NzkwNTI3MywieSI6ODEuNDQ5MjE4NzV9XQ=="></path><path id="mermaid-5-L_W_B_0" marker-end="url(#mermaid-5_flowchart-v2-pointEnd)" d="m191.835 123.449 10.195 12.658c10.194 12.659 30.584 37.975 48.428 50.633 17.845 12.658 33.144 12.658 44.378 12.729 11.233.07 18.4.21 21.983.281l3.584.07" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_W_B_0" data-look="classic" data-points="W3sieCI6MTkxLjgzNDgzOTY2NzQ2MTcsInkiOjEyMy40NDkyMTg3NX0seyJ4IjoyNTMuMDAzMzk4ODk1MjYzNjcsInkiOjE5OS4zOTg0Mzc1fSx7IngiOjI5OC45MDE4MzYzOTUyNjM3LCJ5IjoxOTkuMzk4NDM3NX0seyJ4IjozMjQuNDAxODM2Mzk1MjY4NywieSI6MTk5Ljg5ODQzNzV9XQ=="></path><path id="mermaid-5-L_frame_W_0" marker-end="url(#mermaid-5_flowchart-v2-pointEnd)" d="M298.902 90.14v2.218c0 2.219 0 6.655-7.65 8.873s-22.949 2.218-37.499 2.294c-14.549.076-28.349.228-35.249.304l-6.899.076" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" data-edge="true" data-et="edge" data-id="L_frame_W_0" data-look="classic" data-points="W3sieCI6MzI2LjIwNDIwMzQ3NjA1MjU2LCJ5Ijo5MC4xNDAzMzM1ODYyNTk5Nn0seyJ4IjoyOTguOTAxODM2Mzk1MjYzNywieSI6MTAzLjQ0OTIxODc1fSx7IngiOjI1My4wMDMzOTg4OTUyNjM2NywieSI6MTAzLjQ0OTIxODc1fSx7IngiOjIwNy42MDQ5NjEzOTUyNjM2NywieSI6MTAzLjk0OTIxODc1fV0="></path></g><g class="edgeLabels"><g class="edgeLabel"><foreignObject width="36.469" height="24" class="label" data-id="L_idle_W_0" transform="translate(83.136 91.455)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>enter</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="24.016" height="24" class="label" data-id="L_W_A_0" transform="translate(240.996 47.45)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>call</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="40.891" height="24" class="label" data-id="L_A_A1_0" transform="translate(384.304 69.45)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>x: y/R</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="38.234" height="24" class="label" data-id="L_A1_h_0" transform="translate(554.772 69.45)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>y: y/L</p></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="0" height="0" class="label" data-id="L_W_B_0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"></span></div></foreignObject></g><g class="edgeLabel"><foreignObject width="41.797" height="24" class="label" data-id="L_frame_W_0" transform="translate(239.008 91.45)"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="edgeLabel"><p>return</p></span></div></foreignObject></g></g><g class="nodes"><g id="mermaid-5-flowchart-idle-0" class="node default" data-look="classic"><g class="basic label-container outer-path"><path fill="#ececff" stroke-width="0" d="M27.49 83.95h10.656l1.25.04 1.244.12 1.234.199 1.218.278 1.199.356 1.173.431 1.143.506 1.108.579 1.07.648 1.024.715.978.779.925.84.87.898c.26.306.52.613.81.952l.748 1.002.682 1.048.613 1.089c.2.413.398.827.542 1.126l.47 1.159.393 1.186c.105.398.21.797.317 1.21l.24 1.226.16 1.24c.022.361.046.723.08 1.247v1.25c-.025.372-.049.743-.08 1.248l-.16 1.24-.24 1.226-.317 1.21-.394 1.186-.469 1.158-.542 1.127-.613 1.089-.682 1.047-.748 1.002-.81.952-.87.898-.925.84-.978.78-1.025.715-1.069.648-1.108.578-1.143.506-1.173.432-1.199.355-1.218.279-1.234.2c-.458.043-.916.087-1.244.12l-1.25.04H27.49l-1.25-.04c-.439-.043-.878-.086-1.244-.12-.427-.07-.854-.14-1.234-.2l-1.218-.279-1.199-.355-1.173-.432-1.143-.506-1.108-.578-1.069-.648-1.025-.715-.977-.78-.926-.84-.87-.898-.81-.952-.747-1.002-.682-1.047-.614-1.09-.542-1.126-.47-1.158-.393-1.186-.317-1.21-.24-1.227-.159-1.24-.08-1.247v-1.25l.08-1.247.16-1.24.239-1.227.317-1.21.394-1.185.469-1.16.542-1.125.614-1.09.682-1.047.747-1.002.81-.952.87-.898.926-.84.977-.78 1.025-.714 1.069-.648 1.108-.579 1.143-.506 1.173-.431 1.199-.356 1.218-.278 1.234-.2 1.245-.12 1.249-.04"></path><path fill="none" stroke="#9370db" stroke-dasharray="0 0" stroke-width="1.3" d="M27.49 83.95h10.656m-10.656 0h10.656m0 0 1.25.04m-1.25-.04 1.25.04m0 0 1.244.12m-1.244-.12 1.244.12m0 0 1.234.199m-1.234-.2 1.234.2m0 0 1.218.278m-1.218-.278 1.218.278m0 0 1.199.356m-1.199-.356 1.199.356m0 0 1.173.431m-1.173-.431 1.173.431m0 0 1.143.506m-1.143-.506 1.143.506m0 0 1.108.579m-1.108-.579 1.108.579m0 0 1.07.648m-1.07-.648 1.07.648m0 0 1.024.715m-1.025-.715 1.025.715m0 0 .978.779m-.978-.78.978.78m0 0 .925.84m-.925-.84.925.84m0 0 .87.898m-.87-.898.87.898m0 0 .81.952m-.81-.952.81.952m0 0 .748 1.002m-.748-1.002.748 1.002m0 0 .682 1.048m-.682-1.048.682 1.048m0 0 .613 1.089m-.613-1.09.613 1.09m0 0 .542 1.126m-.542-1.126.542 1.126m0 0 .47 1.159m-.47-1.16.47 1.16m0 0 .393 1.186m-.394-1.186.394 1.186m0 0 .317 1.21m-.317-1.21.317 1.21m0 0 .24 1.226m-.24-1.227.24 1.227m0 0 .16 1.24m-.16-1.24c.048.377.096.754.16 1.24m0 0 .08 1.247m-.08-1.247.08 1.247m0 0v1.25m0-1.25v1.25m0 0-.08 1.248m.08-1.248c-.027.402-.052.803-.08 1.248m0 0-.16 1.24m.16-1.24-.16 1.24m0 0-.24 1.226m.24-1.227-.24 1.227m0 0-.317 1.21m.317-1.21-.317 1.21m0 0-.394 1.186m.394-1.186-.394 1.186m0 0-.469 1.158m.47-1.158-.47 1.158m0 0-.542 1.127m.542-1.127-.542 1.127m0 0-.613 1.089m.613-1.09-.613 1.09m0 0-.682 1.047m.682-1.047-.682 1.047m0 0-.748 1.002m.748-1.002-.748 1.002m0 0-.81.952m.81-.952-.81.952m0 0-.87.898m.87-.898-.87.898m0 0-.925.84m.925-.84-.925.84m0 0-.978.78m.978-.78-.978.78m0 0-1.025.715m1.025-.715-1.025.715m0 0-1.069.648m1.07-.648-1.07.648m0 0-1.108.578m1.108-.578c-.29.15-.579.302-1.108.578m0 0-1.143.506m1.143-.506-1.143.506m0 0-1.173.432m1.173-.432-1.173.432m0 0-1.199.355m1.199-.355-1.199.355m0 0-1.218.279m1.218-.279-1.218.279m0 0-1.234.2m1.234-.2-1.234.2m0 0c-.38.036-.759.072-1.244.12m1.244-.12c-.284.026-.568.054-1.244.12m0 0c-.487.015-.974.03-1.25.04m1.25-.04c-.445.013-.89.028-1.25.04m0 0H27.49m10.656 0H27.49m0 0-1.25-.04m1.25.04-1.25-.04m0 0c-.439-.043-.878-.086-1.244-.12m1.245.12c-.408-.04-.817-.08-1.245-.12m0 0-1.234-.2m1.234.2-1.234-.2m0 0-1.218-.279m1.218.279-1.218-.279m0 0-1.199-.355m1.199.355-1.199-.355m0 0-1.173-.432m1.173.432-1.173-.432m0 0-1.143-.506m1.143.506-1.143-.506m0 0-1.108-.578m1.108.578-1.108-.578m0 0-1.069-.648m1.069.648-1.069-.648m0 0-1.025-.715m1.025.715-1.025-.715m0 0-.977-.78m.977.78-.977-.78m0 0-.926-.84m.926.84-.926-.84m0 0-.87-.898m.87.898-.87-.898m0 0-.81-.952m.81.952-.81-.952m0 0-.747-1.002m.747 1.002-.747-1.002m0 0-.682-1.047m.682 1.047-.682-1.047m0 0-.614-1.09m.614 1.09-.614-1.09m0 0-.542-1.126m.542 1.127-.542-1.127m0 0-.47-1.158m.47 1.158-.47-1.158m0 0-.393-1.186m.394 1.186-.394-1.186m0 0-.317-1.21m.317 1.21-.317-1.21m0 0-.24-1.227m.24 1.227-.24-1.227m0 0-.159-1.24m.16 1.24-.16-1.24m0 0L8 104.075m.08 1.248L8 104.074m0 0v-1.25m0 1.25v-1.25m0 0 .08-1.247M8 102.824l.08-1.247m0 0 .16-1.24m-.16 1.24.16-1.24m0 0 .239-1.227m-.24 1.227.24-1.227m0 0 .317-1.21m-.317 1.21.317-1.21m0 0 .394-1.185M8.796 97.9l.394-1.186m0 0 .469-1.16m-.47 1.16.47-1.16m0 0 .542-1.125m-.542 1.126.542-1.126m0 0 .614-1.09m-.614 1.09.614-1.09m0 0 .682-1.047m-.682 1.048c.175-.27.35-.54.682-1.048m0 0 .747-1.002m-.747 1.002.747-1.002m0 0 .81-.952m-.81.952.81-.952m0 0 .87-.898m-.87.898c.306-.315.612-.63.87-.898m0 0 .926-.84m-.926.84.926-.84m0 0 .977-.78m-.977.78.977-.78m0 0 1.025-.714m-1.025.715 1.025-.715m0 0 1.069-.648m-1.069.648 1.069-.648m0 0 1.108-.579m-1.108.579 1.108-.579m0 0 1.143-.506m-1.143.506 1.143-.506m0 0 1.173-.431m-1.173.431 1.173-.431m0 0 1.199-.356m-1.199.356 1.199-.356m0 0 1.218-.278m-1.218.278 1.218-.278m0 0 1.234-.2m-1.234.2 1.234-.2m0 0 1.245-.12m-1.245.12 1.245-.12m0 0 1.249-.04m-1.25.04 1.25-.04m0 0"></path></g><g class="label" transform="translate(20.365 91.45)"><rect></rect><foreignObject width="24.906" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>idle</p></span></div></foreignObject></g></g><g id="mermaid-5-flowchart-W-1" class="node default" data-look="classic"><path d="M0 0h47v-39H0V0h-8 63v-39H-8V0z" class="label-container" style="fill:#ececff;stroke:#9370db;stroke-width:1px" transform="translate(152.105 122.95)"></path><g class="label" transform="translate(159.605 91.45)"><rect></rect><foreignObject width="32" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>A(B)</p></span></div></foreignObject></g></g><g id="mermaid-5-flowchart-A-3" class="node default" data-look="classic"><g class="basic label-container outer-path"><path fill="#ececff" stroke-width="0" d="M343.392 61.95h-3.578c.414.012.827.026 1.25.04l1.243.12 1.234.199 1.219.278 1.198.356 1.173.431 1.143.506 1.109.579 1.069.648 1.025.715.977.779.926.84c.231.24.463.479.87.898.243.287.487.574.81.952l.747 1.002.682 1.048.613 1.089.543 1.126.469 1.159.394 1.186.317 1.21.239 1.226.16 1.24.08 1.247v1.25l-.08 1.248-.16 1.24-.24 1.226-.316 1.21c-.1.299-.2.598-.394 1.186l-.47 1.158c-.13.272-.26.544-.542 1.127-.19.34-.382.679-.613 1.089l-.682 1.047-.748 1.002-.81.952-.87.898-.925.84-.977.78-1.025.715-1.07.648-1.108.578-1.143.506-1.173.432-1.198.355-1.219.279-1.234.2c-.301.028-.603.057-1.244.12l-1.25.04h3.579c-.286-.01-.572-.02-1.25-.04-.372-.037-.744-.073-1.244-.12l-1.234-.2-1.218-.279-1.199-.355-1.173-.432-1.143-.506-1.108-.578-1.07-.648-1.024-.715-.978-.78-.925-.84-.87-.898-.81-.952-.748-1.002-.681-1.047-.614-1.09-.542-1.126-.47-1.158-.393-1.186-.317-1.21-.24-1.227c-.056-.438-.112-.877-.16-1.24-.015-.25-.031-.5-.08-1.247v-1.25c.033-.496.065-.993.08-1.247.063-.48.125-.959.16-1.24l.24-1.227.317-1.21.394-1.185c.14-.349.282-.697.469-1.16l.542-1.125.614-1.09.681-1.047.748-1.002.81-.952.87-.898.925-.84.978-.78 1.025-.714 1.069-.648 1.108-.579 1.143-.506 1.173-.431 1.199-.356 1.218-.278 1.234-.2 1.244-.12 1.25-.04"></path><path fill="none" stroke="#9370db" stroke-dasharray="0 0" stroke-width="1.3" d="M343.392 61.95h-3.578m3.578 0h-3.578m0 0 1.25.04m-1.25-.04c.349.01.698.022 1.25.04m0 0c.28.026.56.053 1.243.12m-1.244-.12 1.244.12m0 0 1.234.199m-1.234-.2 1.234.2m0 0 1.219.278m-1.219-.278 1.219.278m0 0 1.198.356m-1.198-.356 1.198.356m0 0 1.173.431m-1.173-.431 1.173.431m0 0 1.143.506m-1.143-.506 1.143.506m0 0 1.109.579m-1.109-.579 1.109.579m0 0 1.069.648m-1.07-.648 1.07.648m0 0 1.025.715m-1.025-.715 1.025.715m0 0 .977.779m-.977-.78.977.78m0 0 .926.84m-.926-.84.926.84m0 0 .87.898m-.87-.898c.265.275.531.55.87.898m0 0c.206.243.413.487.81.952m-.81-.952.81.952m0 0 .747 1.002m-.748-1.002.748 1.002m0 0 .682 1.048m-.682-1.048.682 1.048m0 0 .613 1.089m-.613-1.09.613 1.09m0 0 .543 1.126m-.543-1.126.543 1.126m0 0 .469 1.159m-.47-1.16.47 1.16m0 0 .394 1.186m-.394-1.186.394 1.186m0 0 .317 1.21m-.317-1.21.317 1.21m0 0 .239 1.226m-.24-1.227.24 1.227m0 0 .16 1.24m-.16-1.24.16 1.24m0 0 .08 1.247m-.08-1.247.08 1.247m0 0v1.25m0-1.25v1.25m0 0-.08 1.248m.08-1.248-.08 1.248m0 0-.16 1.24m.16-1.24-.16 1.24m0 0-.24 1.226m.24-1.227-.24 1.227m0 0-.316 1.21m.317-1.21-.317 1.21m0 0-.394 1.186m.394-1.186-.394 1.186m0 0-.47 1.158m.47-1.158-.47 1.158m0 0-.542 1.127m.543-1.127-.543 1.127m0 0-.613 1.089m.613-1.09-.613 1.09m0 0-.682 1.047m.682-1.047-.682 1.047m0 0-.748 1.002m.748-1.002-.748 1.002m0 0-.81.952m.81-.952-.81.952m0 0-.87.898m.87-.898-.87.898m0 0-.925.84m.926-.84-.926.84m0 0-.977.78m.977-.78-.977.78m0 0-1.025.715m1.025-.715-1.025.715m0 0-1.07.648m1.07-.648-1.07.648m0 0-1.108.578m1.109-.578-1.109.578m0 0-1.143.506m1.143-.506-1.143.506m0 0-1.173.432m1.173-.432-1.173.432m0 0-1.198.355m1.198-.355-1.198.355m0 0-1.219.279m1.219-.279-1.219.279m0 0-1.234.2m1.234-.2-1.234.2m0 0-1.244.12m1.244-.12c-.292.027-.584.055-1.244.12m0 0-1.25.04m1.25-.04c-.36.01-.722.022-1.25.04m0 0h3.579m-3.578 0h3.578m0 0-1.25-.04m1.25.04-1.25-.04m0 0-1.244-.12m1.244.12c-.456-.045-.913-.089-1.244-.12m0 0-1.234-.2m1.234.2c-.487-.08-.974-.158-1.234-.2m0 0-1.218-.279m1.218.279-1.218-.279m0 0-1.199-.355m1.199.355-1.199-.355m0 0-1.173-.432m1.173.432-1.173-.432m0 0-1.143-.506m1.143.506-1.143-.506m0 0-1.108-.578m1.108.578-1.108-.578m0 0-1.07-.648m1.07.648-1.07-.648m0 0-1.024-.715m1.025.715-1.025-.715m0 0-.978-.78m.978.78-.978-.78m0 0-.925-.84m.925.84-.925-.84m0 0-.87-.898m.87.898-.87-.898m0 0-.81-.952m.81.952-.81-.952m0 0-.748-1.002m.748 1.002-.748-1.002m0 0-.681-1.047m.681 1.047-.681-1.047m0 0-.614-1.09m.614 1.09-.614-1.09m0 0-.542-1.126m.542 1.127-.542-1.127m0 0-.47-1.158m.47 1.158-.47-1.158m0 0c-.125-.379-.25-.758-.393-1.186m.394 1.186-.394-1.186m0 0-.317-1.21m.317 1.21-.317-1.21m0 0-.24-1.227m.24 1.227-.24-1.227m0 0-.16-1.24m.16 1.24-.16-1.24m0 0c-.021-.343-.043-.686-.08-1.247m.08 1.248c-.03-.478-.06-.956-.08-1.248m0 0v-1.25m0 1.25v-1.25m0 0c.029-.431.056-.863.08-1.247m-.08 1.247.08-1.247m0 0 .16-1.24m-.16 1.24c.052-.395.103-.79.16-1.24m0 0 .24-1.227m-.24 1.227c.09-.454.178-.909.24-1.227m0 0 .317-1.21m-.317 1.21.317-1.21m0 0 .394-1.185m-.394 1.186.394-1.186m0 0c.12-.3.242-.598.469-1.16m-.47 1.16.47-1.16m0 0 .542-1.125m-.542 1.126.542-1.126m0 0 .614-1.09m-.614 1.09.614-1.09m0 0 .681-1.047m-.681 1.048c.174-.27.35-.538.681-1.048m0 0 .748-1.002m-.748 1.002.748-1.002m0 0 .81-.952m-.81.952.81-.952m0 0 .87-.898m-.87.898.87-.898m0 0 .925-.84m-.925.84c.222-.2.443-.402.925-.84m0 0 .978-.78m-.978.78.978-.78m0 0 1.025-.714m-1.025.715 1.025-.715m0 0c.25-.153.502-.305 1.069-.648m-1.07.648 1.07-.648m0 0 1.108-.579m-1.108.579 1.108-.579m0 0 1.143-.506m-1.143.506 1.143-.506m0 0 1.173-.431m-1.173.431 1.173-.431m0 0 1.199-.356m-1.199.356 1.199-.356m0 0 1.218-.278m-1.218.278 1.218-.278m0 0 1.234-.2m-1.234.2 1.234-.2m0 0 1.244-.12m-1.244.12 1.244-.12m0 0 1.25-.04m-1.25.04 1.25-.04m0 0"></path></g><g class="label" transform="translate(336.267 69.45)"><rect></rect><foreignObject width="10.672" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>A</p></span></div></foreignObject></g></g><g id="mermaid-5-flowchart-A1-5" class="node default" data-look="classic"><path d="M450.194 54.45h79.578v54h-79.578z" class="basic label-container"></path><g class="label" transform="translate(480.194 69.45)"><rect></rect><foreignObject width="19.578" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>A1</p></span></div></foreignObject></g></g><g id="mermaid-5-flowchart-h-7" class="node default" data-look="classic"><g class="basic label-container" transform="translate(645.905 81.45)"><circle r="27.898" class="outer-circle"></circle><circle r="22.898" class="inner-circle"></circle></g><g class="label" transform="translate(633.007 69.45)"><rect></rect><foreignObject width="25.797" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>halt</p></span></div></foreignObject></g></g><g id="mermaid-5-flowchart-B-11" class="node default" data-look="classic"><g class="basic label-container outer-path"><path fill="#ececff" stroke-width="0" d="M343.392 179.898h-3.578l1.25.04 1.243.12 1.234.2 1.219.278 1.198.356 1.173.432c.29.127.578.255 1.143.506l1.109.578 1.069.648 1.025.715.977.78.926.84.87.898.81.951c.17.23.34.458.747 1.002l.682 1.048.613 1.089.543 1.126.469 1.159.394 1.186.317 1.21.239 1.226.16 1.24c.02.328.042.657.08 1.247v1.25l-.08 1.248-.16 1.24-.24 1.227-.316 1.209-.394 1.186-.47 1.159-.542 1.126-.613 1.09-.682 1.047-.748 1.001-.81.952-.87.898-.925.84-.977.78-1.025.715-1.07.648-1.108.578-1.143.506-1.173.432-1.198.356-1.219.278-1.234.2-1.244.12c-.36.01-.72.022-1.25.04h3.579l-1.25-.04-1.244-.12-1.234-.2-1.218-.278-1.199-.356-1.173-.432-1.143-.506-1.108-.578-1.07-.648-1.024-.715-.978-.78-.925-.84-.87-.898-.81-.952-.748-1.001-.681-1.048c-.224-.398-.449-.795-.614-1.09l-.542-1.125-.47-1.159-.393-1.186-.317-1.21-.24-1.226c-.049-.385-.098-.77-.16-1.24l-.08-1.248v-1.25c.023-.349.046-.698.08-1.247l.16-1.24.24-1.227.317-1.209.394-1.186.469-1.159.542-1.126.614-1.09.681-1.047.748-1.002.81-.951.87-.898.925-.84.978-.78 1.025-.715 1.069-.648 1.108-.578 1.143-.506 1.173-.432 1.199-.356 1.218-.278 1.234-.2c.27-.025.54-.051 1.244-.12l1.25-.04"></path><path fill="none" stroke="#9370db" stroke-dasharray="0 0" stroke-width="1.3" d="M343.392 179.898h-3.578m3.578 0h-3.578m0 0c.293.01.586.02 1.25.04m-1.25-.04 1.25.04m0 0 1.243.12m-1.244-.12 1.244.12m0 0 1.234.2m-1.234-.2 1.234.2m0 0 1.219.278m-1.219-.278 1.219.278m0 0 1.198.356m-1.198-.356 1.198.356m0 0 1.173.432m-1.173-.432 1.173.432m0 0 1.143.506m-1.143-.506 1.143.506m0 0 1.109.578m-1.109-.578c.39.202.778.405 1.109.578m0 0 1.069.648m-1.07-.648 1.07.648m0 0 1.025.715m-1.025-.715 1.025.715m0 0 .977.78m-.977-.78.977.78m0 0 .926.84m-.926-.84.926.84m0 0 .87.898m-.87-.898.87.898m0 0 .81.951m-.81-.951.81.951m0 0 .747 1.002m-.748-1.002.748 1.002m0 0 .682 1.048m-.682-1.048.682 1.048m0 0 .613 1.089m-.613-1.09.613 1.09m0 0 .543 1.126m-.543-1.126.543 1.126m0 0 .469 1.159m-.47-1.159.47 1.159m0 0 .394 1.186m-.394-1.186.394 1.186m0 0 .317 1.21m-.317-1.21.317 1.21m0 0 .239 1.226m-.24-1.227.24 1.227m0 0 .16 1.24m-.16-1.24.16 1.24m0 0 .08 1.247m-.08-1.247.08 1.247m0 0v1.25m0-1.25v1.25m0 0-.08 1.248m.08-1.248-.08 1.248m0 0-.16 1.24m.16-1.24-.16 1.24m0 0-.24 1.227m.24-1.227-.24 1.227m0 0-.316 1.209m.317-1.21-.317 1.21m0 0-.394 1.186m.394-1.186-.394 1.186m0 0-.47 1.159m.47-1.159c-.146.36-.29.718-.47 1.159m0 0-.542 1.126m.543-1.126-.543 1.126m0 0-.613 1.09m.613-1.09-.613 1.09m0 0-.682 1.047m.682-1.048-.682 1.048m0 0-.748 1.001m.748-1.001-.748 1.001m0 0-.81.952m.81-.952-.81.952m0 0-.87.898m.87-.898-.87.898m0 0-.925.84m.926-.84-.926.84m0 0-.977.78m.977-.78-.977.78m0 0-1.025.715m1.025-.715-1.025.715m0 0-1.07.648m1.07-.648-1.07.648m0 0-1.108.578m1.109-.578-1.109.578m0 0-1.143.506m1.143-.506-1.143.506m0 0-1.173.432m1.173-.432-1.173.432m0 0-1.198.356m1.198-.356-1.198.356m0 0-1.219.278m1.219-.278-1.219.278m0 0-1.234.2m1.234-.2-1.234.2m0 0c-.493.047-.986.094-1.244.12m1.244-.12-1.244.12m0 0-1.25.04m1.25-.04-1.25.04m0 0h3.579m-3.578 0h3.578m0 0-1.25-.04m1.25.04-1.25-.04m0 0-1.244-.12m1.244.12c-.305-.03-.61-.06-1.244-.12m0 0-1.234-.2m1.234.2-1.234-.2m0 0c-.26-.06-.521-.12-1.218-.278m1.218.278-1.218-.278m0 0-1.199-.356m1.199.356-1.199-.356m0 0-1.173-.432m1.173.432-1.173-.432m0 0-1.143-.506m1.143.506-1.143-.506m0 0-1.108-.578m1.108.578-1.108-.578m0 0-1.07-.648m1.07.648-1.07-.648m0 0-1.024-.715m1.025.715-1.025-.715m0 0-.978-.78m.978.78-.978-.78m0 0-.925-.84m.925.84-.925-.84m0 0-.87-.898m.87.898c-.209-.215-.418-.43-.87-.898m0 0-.81-.952m.81.952-.81-.952m0 0-.748-1.001m.748 1.001-.748-1.001m0 0-.681-1.048m.681 1.048-.681-1.048m0 0-.614-1.09m.614 1.09-.614-1.09m0 0-.542-1.125m.542 1.126-.542-1.126m0 0-.47-1.159m.47 1.159-.47-1.159m0 0-.393-1.186m.394 1.186-.394-1.186m0 0-.317-1.21m.317 1.21-.317-1.21m0 0-.24-1.226m.24 1.227c-.09-.464-.18-.928-.24-1.227m0 0c-.037-.291-.074-.582-.16-1.24m.16 1.24c-.057-.451-.116-.903-.16-1.24m0 0-.08-1.248m.08 1.248-.08-1.248m0 0v-1.25m0 1.25v-1.25m0 0 .08-1.247m-.08 1.247.08-1.247m0 0c.033-.252.066-.503.16-1.24m-.16 1.24c.06-.452.118-.905.16-1.24m0 0 .24-1.227m-.24 1.227.24-1.227m0 0 .317-1.209m-.317 1.21.317-1.21m0 0 .394-1.186m-.394 1.186.394-1.186m0 0 .469-1.159m-.47 1.159.47-1.159m0 0 .542-1.126m-.542 1.126.542-1.126m0 0 .614-1.09m-.614 1.09.614-1.09m0 0c.234-.36.47-.72.681-1.047m-.681 1.048.681-1.048m0 0 .748-1.002m-.748 1.002.748-1.002m0 0 .81-.951m-.81.951.81-.951m0 0 .87-.898m-.87.898.87-.898m0 0 .925-.84m-.925.84.925-.84m0 0 .978-.78m-.978.78.978-.78m0 0 1.025-.715m-1.025.715 1.025-.715m0 0 1.069-.648m-1.07.648 1.07-.648m0 0 1.108-.578m-1.108.578 1.108-.578m0 0 1.143-.506m-1.143.506c.281-.125.562-.25 1.143-.506m0 0 1.173-.432m-1.173.432 1.173-.432m0 0 1.199-.356m-1.199.356 1.199-.356m0 0 1.218-.278m-1.218.278 1.218-.278m0 0 1.234-.2m-1.234.2 1.234-.2m0 0 1.244-.12m-1.244.12 1.244-.12m0 0 1.25-.04m-1.25.04 1.25-.04m0 0"></path></g><g class="label" transform="translate(336.267 187.398)"><rect></rect><foreignObject width="10.672" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center"><span class="nodeLabel"><p>B</p></span></div></foreignObject></g></g></g></g><defs><filter id="mermaid-5-drop-shadow" width="130%" height="130%"><feDropShadow dx="4" dy="4" flood-color="#000" flood-opacity=".06" stdDeviation="0"></feDropShadow></filter></defs><defs><filter id="mermaid-5-drop-shadow-small" width="150%" height="150%"><feDropShadow dx="2" dy="2" flood-color="#000" flood-opacity=".06" stdDeviation="0"></feDropShadow></filter></defs></svg>
<p>Wrapper — <em>call site</em>; bare’s body — <em>callable subtree</em>; halt — <em>return</em>. Composition in the engine literally became a function call.</p>
</li>
<li>
<p><strong><code>withOverrodeHaltState</code> → <code>withOverriddenHaltState</code></strong> (<a href="https://github.com/mellonis/turing-machine-js/issues/149"><code>turing-machine-js#149</code></a>). Grammar on a public API.</p>
</li>
</ul>
<p>All three are one idea: composition is tree-shaped, and its representations should keep the tree, not smear it.</p>
<h2 id="closing"><a class="heading-anchor" href="#closing">Closing</a></h2>
<p>A visualization cleanup turned into a naming overhaul. That’s the same pattern I described in <a href="https://mellonis.ru/en/articles/dva-mazhora-odin-readme-odno-demo/">“Two majors, one README, one demo”</a>: a design review tests can’t run catches what tests can’t see. There it was docs and the first consumer. Here it’s visualization. The genre is the same: put yourself in front of the task of <em>showing the structure</em>, and if the structure is bent, it starts protruding. Tests don’t do that — tests check behavior, and structural bentness is usually visible only in the <em>representation</em>.</p>
<p>Seven arrows, 429 trees. A name that looked like a traversal trace turned out to be one of 429 possible ones. v7 gives each its own name — and lets the visualization show how that tree actually grew. That the wrapper IS a call-frame and deserves its own type — that’s another story (<a href="https://github.com/mellonis/turing-machine-js/issues/213"><code>turing-machine-js#213</code></a>).</p>]]></content:encoded>
    </item>
    <item>
      <title>A pause with two sides: the hook contract and the worker protocol</title>
      <link>https://mellonis.ru/en/articles/pauza-dvojstvennaya-po-prirode/</link>
      <guid isPermaLink="false">https://mellonis.ru/en/articles/pauza-dvojstvennaya-po-prirode/</guid>
      <pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate>
      <description>Implementing a pause inside a worker isn’t one decision — it’s two contracts at once: the engine’s hook and the worker-main protocol.</description>
      <content:encoded><![CDATA[<p>Suppose you’re writing a Turing-machine interpreter that runs in a Web Worker. The UI needs to show a trace — how the machine steps from state to state, what gets written to the tape, how the head moves. For the user to keep up with what’s on screen, the engine needs a short delay between iterations — milliseconds, regularly, on every step. That’s a throttle of the engine between iterations — regular and predictable, not the “Pause” of the UI button (which stops the machine until the user clicks “Continue”).</p>
<p>So where exactly in the iteration cycle does the worker apply that throttle? There are two candidates, and the choice between them pins two contracts at once: the engine’s hooks and the protocol between worker and main thread. Pick the right point, and you design both sides at once; pick the wrong one, and you break both. This article is about that choice.</p>
<figure><img src="https://mellonis.ru/articles/pauza-dvojstvennaya-po-prirode/dual-pause.webp?v=eeb1e2a2" alt="Screenshot of demo.machines.mellonis.ru: a Turing machine in RUNNING_AUTO mode with the Pause button highlighted by a zoom-circle, the step-by-step execution trace visible on the left" width="3680" height="2392"><figcaption>Screenshot of demo.machines.mellonis.ru: a Turing machine in RUNNING_AUTO mode with the Pause button highlighted by a zoom-circle, the step-by-step execution trace visible on the left</figcaption></figure>
<h2 id="setup"><a class="heading-anchor" href="#setup">Setup</a></h2>
<p><a href="https://github.com/mellonis/turing-machine-js"><code>turing-machine-js</code></a> is a Turing-machine interpreter. The engine has an <code>onStep</code> hook — the handler runs after each machine step. That’s all the engine background you need for this article. For the rest of the engine’s design and previous API changes, see <a href="https://mellonis.ru/en/articles/three-majors-two-mistakes/">“Three majors, two mistakes: designing a pause API for a Turing-machine interpreter”</a> (1) and <a href="https://mellonis.ru/en/articles/dva-mazhora-odin-readme-odno-demo/">“Two majors, one README, one demo: two cheap design reviews”</a> (2).</p>
<p>The first real consumer of the engine is <a href="https://demo.machines.mellonis.ru"><code>machines-demo</code></a>, an interactive debugger. The user’s machine runs in a Web Worker; the UI on the main thread shows the trace. The same demo that, in <a href="https://mellonis.ru/en/articles/dva-mazhora-odin-readme-odno-demo/">article (2)</a>, surfaced two engine majors (<code>#109</code>, <code>#108</code>). This article is the next episode in the life of the same engine: v6.2 → v6.3 → v6.4.</p>
<p>The demo has a RUNNING_AUTO mode: the user picks an interval, clicks “Start”, and the machine steps automatically. Originally the mode was straightforward — the main thread drove step-by-step execution (via <code>runner.step()</code>, a wrapper over the engine’s <code>runStepByStep()</code> in the worker), with <code>setTimeout(intervalMs)</code> inserted between steps for the trace. Simple, and it worked — until the user set a breakpoint.</p>
<p>Breakpoints in the engine fire inside <code>machine.run()</code>: the iteration loop lives in the engine itself, and on hitting a <code>debug</code>-marked state, it pauses itself. <code>runStepByStep()</code>, on the other hand, is a generator: the consumer drives the loop, and breakpoints are invisible to it. <a href="https://github.com/mellonis/machines-demo/issues/43"><code>machines-demo#43</code></a> was this hole — the user sets a breakpoint in RUNNING_AUTO mode, clicks “Start”, and the breakpoint is ignored. For breakpoints to fire, RUNNING_AUTO had to switch from <code>runStepByStep()</code> to <code>run()</code>.</p>
<p>But <code>run()</code> keeps its iteration loop inside the engine and doesn’t yield control back. Previously the throttle lived between <code>runner.step()</code> calls on the main thread — that is, on the consumer side, where the consumer controlled the interval between steps. With the switch to <code>run()</code>, that consumer-side gap is gone — the throttle has to either be moved inside the engine (into an existing or new hook) or be dropped. That became the design question.</p>
<p>One more architectural detail we need: the main thread holds a watchdog timer over the worker. If the worker stays silent on messages longer than <code>WORKER_TIMEOUT_MS</code>, the main thread considers it hung (e.g., the user’s machine never reaches halt) and kills it. Whatever place we put the throttle in has to live with that timer.</p>
<h2 id="where-the-throttle-can-live"><a class="heading-anchor" href="#where-the-throttle-can-live">Where the throttle can live</a></h2>
<p>Two candidates:</p>
<ol>
<li><strong>Inside <code>onStep</code></strong> — the synchronous hook the engine calls after each step. Its current signature is <code>(state) => void</code>. You could widen it to <code>(state) => void | Promise&#x3C;void></code>, and then the handler can <code>await</code> the delay right there.</li>
<li><strong>At the iteration boundary</strong> — add a new hook, designed for async waits. Naming aside, what matters is that it fires once at the end of each engine iteration, and the engine awaits the returned Promise.</li>
</ol>
<p>Both candidates answer “where does the throttle live”. But at the same time they dictate what the worker-main protocol looks like.</p>
<p>If the throttle sits in <code>onStep</code>, it ends up in the middle of each engine iteration — at the point where <code>onStep</code> is called. Everything else in the protocol has to be pinned to that same point: the watchdog timer and the user’s click on “Pause” both hang off this mid-iter delay.</p>
<p>If the throttle sits at the iteration boundary, the worker has a moment at the end of every iteration — the engine isn’t running, it’s awaiting a Promise. In that moment, it’s easy to make peace with the watchdog timer and to be ready for a click on “Pause”.</p>
<p>Now both contracts, one at a time.</p>
<h2 id="contract-inside-onstep"><a class="heading-anchor" href="#contract-inside-onstep">Contract “Inside <code>onStep</code>”</a></h2>
<p>v6.2.0 took the first path — it widened <code>onStep</code>’s signature from <code>(state) => void</code> to <code>(state) => void | Promise&#x3C;void></code>. The handler could now <code>await</code> the delay right where it used to only look at state. From the worker’s side it looked clean — one hook, one wait point, no new entities.</p>
<p>Within a few hours, I marked v6.2.0 as deprecated on npm. Not “a newer version is out, upgrade at your convenience”, but an explicit warning: this version is <em>wrong</em>.</p>
<p>v6.3.0 reverted the signature widening. The reason was straightforward: <code>onStep</code> was meant as an observation hook, not a coordination one. It runs synchronously, in the middle of each iteration, so the consumer can look at state and record it somewhere. Adding <code>await</code> to its signature glues two different jobs into one: observe and hold the engine. A reader of the signature can no longer tell: is this hook “look at this state” or “hold the engine here”? The hook’s purpose stops being visible from the signature.</p>
<p>The symptom that something was wrong showed up in the docs. The README had to explain how to use the widened <code>onStep</code>. An honest paragraph opened with a hedge: “<code>onStep</code> is an observation hook, but you can return a Promise from it, and the engine will await it before the next iteration.” Neither the “but” nor the second half could be cut. The docs were doing exactly what’s described in <a href="https://mellonis.ru/en/articles/dva-mazhora-odin-readme-odno-demo/">article (2)</a>: prose was pushing on shape — and the shape cracked.</p>
<p>v6.4.0 added a separate hook — <code>onIter</code>. Signature: <code>(state) => void | Promise&#x3C;void></code>. Contract: fires once at the end of every iteration, asynchronously, unconditionally. The name — <code>iteration boundary</code> — describes <em>what</em> the hook does (gives a point at the end of an iteration where you can wait), not <em>why</em> a consumer would use it. And it can be used in different ways: for throttling between trace steps, for syncing with the UI, for aborting a run (e.g., via <code>AbortSignal</code>).</p>
<p>The engine’s hook contract now distinguishes three jobs:</p>
<ul>
<li><strong><code>onStep</code></strong> — synchronous, mid-iteration. Observation of state.</li>
<li><strong><code>onPause</code></strong> — asynchronous, <em>conditional</em> (fires only on breakpoints). The boundary between running and stopped.</li>
<li><strong><code>onIter</code></strong> — asynchronous, <em>unconditional</em> (fires on every iteration). Coordination: holding the engine for the consumer’s async work.</li>
</ul>
<p>Three hooks, three jobs. Observation shouldn’t hold the engine; for that, there’s a separate asynchronous hook. Holding shouldn’t hide inside an observation hook; for that, there’s <code>onIter</code>. A pause from a breakpoint is its own scenario altogether; for that, there’s <code>onPause</code>, whose firing event is spelled out in its name.</p>
<h2 id="contract-at-the-iteration-boundary"><a class="heading-anchor" href="#contract-at-the-iteration-boundary">Contract “At the iteration boundary”</a></h2>
<p>Where the throttle lives is now clear: inside the <code>onIter</code> handler. But the <code>onIter</code> handler runs <em>inside</em> the worker, while the user’s pause comes from <em>outside</em> — from the main thread, on a click. They need a protocol.</p>
<p>This protocol has four mechanisms: a pair of <code>idle</code>/<code>busy</code> messages, a <code>stepRequested</code> flag, a synthetic <code>paused</code> event, and an <code>intervalMs</code> field in <code>resume</code>. Each one closes a specific problem that the throttle’s location creates.</p>
<h3 id="the-idle-and-busy-messages-pausing-the-watchdog"><a class="heading-anchor" href="#the-idle-and-busy-messages-pausing-the-watchdog">The <code>idle</code> and <code>busy</code> messages: pausing the watchdog</a></h3>
<p>The watchdog timer mentioned earlier starts to get in the way once we’re in <code>onIter</code>.</p>
<p>A throttle in <code>onIter</code>, on every iteration, can easily exceed the timeout — especially if the user dials <code>intervalMs</code> to “slow” (the demo lets you set the interval to, say, two seconds). The result is a false alarm: the worker isn’t hung, it’s just waiting.</p>
<p>The solution: the worker itself tells the main thread when it’s “working” and when it’s “waiting”. Before <code>await</code>-ing the throttle in <code>onIter</code>, the worker sends an <code>idle</code> message. After the throttle resolves, it sends a <code>busy</code>. The main thread suspends the watchdog for the gap between <code>idle</code> and <code>busy</code>. The watchdog still catches real hangs (e.g., an unreachable halt state) but no longer confuses them with legitimate trace slowdown.</p>
<p>Without this wrapping, the watchdog has two bad options. Either pick a generous threshold — then real hangs go undetected (or detected too late). Or pick a tight threshold — and you raise the probability of a false alarm (the worker gets killed on a legitimate delay). The <code>idle</code>/<code>busy</code> messages resolve both at once.</p>
<h3 id="step-is-a-flag-inside-the-worker-not-engine-state"><a class="heading-anchor" href="#step-is-a-flag-inside-the-worker-not-engine-state">Step is a flag inside the worker, not engine state</a></h3>
<p>When the user clicks “Step”, the main thread sends the worker a <code>resume</code> message with a <code>step: true</code> flag — “advance the machine one iteration and pause again”. The implementation: the worker sets <code>stepRequested = true</code>. On the next <code>onIter</code>, the handler sees the flag, resets it to <code>false</code>, synthesizes a <code>paused</code> event, and waits again. The machine has run exactly one iteration.</p>
<p>The key point: “step” is a flag <em>inside the worker</em>, not part of the engine’s state. The engine doesn’t know what “step” means — it simply finds itself in a waiting state again on the next iteration. The coordination lives outside the engine. <code>onIter</code> remains a thin <code>await</code> hook — it doesn’t mutate the engine, it only pauses the engine’s execution. That’s what made <code>onIter</code> viable as a contract: there’s no “step-specific logic” in it, only a Promise the worker controls itself. If “step” had been part of the engine’s state, the <code>onIter</code> contract would have to extend to “and also flip this flag”, and the hook would stop being thin.</p>
<h3 id="no-throttle-needed-when-step-is-clicked"><a class="heading-anchor" href="#no-throttle-needed-when-step-is-clicked">No throttle needed when Step is clicked</a></h3>
<p>When the user clicks “Step”, a throttle is redundant — the user plays the role of the timer, clicking as many times and as fast as they need. The implementation reflects this: on Step, <code>intervalMs</code> is ignored, and the <code>onIter</code> handler doesn’t insert a wait. This is the cleanest expression of “observation ≠ coordination” inside the worker: when the user is in control, the engine follows.</p>
<h3 id="synthetic-pause-on-click"><a class="heading-anchor" href="#synthetic-pause-on-click">Synthetic pause on click</a></h3>
<p>The scenario: the machine is in RUNNING_AUTO — the engine is running with <code>onIter</code> awaiting <code>intervalMs</code> between iterations. The user clicks the “Pause” button in the UI. The click arrives on the main thread. The main thread sends the worker a <code>pause</code> message. At that moment, the worker is holding the engine in a throttle — the Promise hasn’t resolved yet. What do we do?</p>
<p>The solution is to synthesize the same kind of pause as one from a breakpoint. The UI already has a handler in place: on <code>paused</code> from the worker, it switches to “stopped”. If the “Pause” click went down a different path, a second branch with the same behavior would appear. That’s why the worker synthesizes <code>paused</code> — to the UI, a “Pause” click is indistinguishable from a breakpoint firing.</p>
<p>The worker cancels the throttle (resolves it forcibly, ahead of schedule), sets <code>stepRequested = false</code>, and, from inside <code>onIter</code> after returning from the wait, dispatches a <code>paused</code> event — <em>synthetic</em>, not one that arose from the engine’s normal flow. Under the hood, the two scenarios differ (one cancels the throttle, the other lets it finish naturally), but the contract from outside is one — a single “pause” scenario.</p>
<h3 id="intervalms-is-a-parameter-of-resume-not-run"><a class="heading-anchor" href="#intervalms-is-a-parameter-of-resume-not-run"><code>intervalMs</code> is a parameter of <code>resume</code>, not <code>run()</code></a></h3>
<p>The throttle in <code>onIter</code> is sized by <code>intervalMs</code>. Where does the worker get that value from? Not from the parameters passed to <code>run()</code> at start. From the latest <code>resume</code> message: each one arrives carrying a current <code>intervalMs</code> from the main thread.</p>
<p>The reason is that the user must be able to change the delay between throttles during the run. The value in the UI is read <em>at click time</em>, not at <code>run()</code> start; the next <code>resume</code> carries the new value, and starting with the next iteration, the throttle adjusts. A small cost for the protocol, a big win for the UX.</p>
<h2 id="duality-explicit"><a class="heading-anchor" href="#duality-explicit">Duality, explicit</a></h2>
<p>The throttle lives in one point of an iteration. From the engine’s perspective, that point is the <code>onIter</code> handler: a hook called once at the end of each iteration, asynchronously. From the protocol’s perspective, the same point is the gap between <code>idle</code> and <code>busy</code> messages — a gap where the watchdog is suspended, a “Pause” click can softly cancel the throttle, and <code>intervalMs</code> is read from the latest <code>resume</code>.</p>
<p>One point, two APIs. Every downstream design choice depends on this one. Put it in the middle of an observation hook, and you break both sides at once: the docs on a widened <code>onStep</code> can’t be written without a “but”, the <code>idle</code>/<code>busy</code> wrapping has nothing to attach to (the same hook stands for both observation and waiting), and the synthetic <code>paused</code> event has to be dispatched from an unnatural place. Without a clean iteration boundary, both the hook and the protocol suffer.</p>
<h2 id="conclusion"><a class="heading-anchor" href="#conclusion">Conclusion</a></h2>
<p>Separating observation from coordination is the reason the engine’s hook contract distinguishes three jobs instead of merging them into one. Gluing them together is the temptation v6.2.0 succumbed to. And the only thing that let me realize the approach was wrong within a few hours was that the engine’s README couldn’t be written honestly, and the demo’s smoke test wouldn’t pass. Two almost-free design reviews (<a href="https://mellonis.ru/en/articles/dva-mazhora-odin-readme-odno-demo/">article (2)</a>).</p>
<hr>
<p><em>Code: <a href="https://github.com/mellonis/turing-machine-js"><code>turing-machine-js</code></a> (engine, v6.2 → v6.4) and <a href="https://demo.machines.mellonis.ru"><code>machines-demo</code></a> (the demo).</em></p>]]></content:encoded>
    </item>
    <item>
      <title>Two majors, one README, one demo: two cheap design reviews</title>
      <link>https://mellonis.ru/en/articles/dva-mazhora-odin-readme-odno-demo/</link>
      <guid isPermaLink="false">https://mellonis.ru/en/articles/dva-mazhora-odin-readme-odno-demo/</guid>
      <pubDate>Mon, 18 May 2026 00:00:00 GMT</pubDate>
      <description>Of the three majors covered by the previous article, two never surfaced in the test suite. They surfaced in the two design reviews tests can’t run.</description>
      <content:encoded><![CDATA[<blockquote>
<p>Writing the docs is what surfaced both mistakes. There’s a meta-lesson in there about how docs are the cheapest design review you can run, but that’s another post.</p>
</blockquote>
<p>This is “that other post” — and the first thing it has to do is correct the teaser. The teaser oversells. Docs caught one of the two mistakes. The other was caught by the first real consumer of the API, which I was building in parallel. The two reviews worked in tandem: docs review the shape of an API, the consumer reviews the use of it. Together they catch what tests can’t see.</p>
<p>If you ship anything behind an interface — a library, a CLI, any entity behind a contract — these are the two reviews you don’t want to skip.</p>
<figure><img src="https://mellonis.ru/articles/dva-mazhora-odin-readme-odno-demo/bf-tiser.webp?v=78281bd0" alt="Screenshot of demo.machines.mellonis.ru running a Brainfuck UTM: multi-tape view on the left, engine source on the right" width="3680" height="2392"><figcaption>Screenshot of demo.machines.mellonis.ru running a Brainfuck UTM: multi-tape view on the left, engine source on the right</figcaption></figure>
<h2 id="recap"><a class="heading-anchor" href="#recap">Recap</a></h2>
<p><a href="https://mellonis.ru/en/articles/three-majors-two-mistakes/">“Three majors, two mistakes”</a> covers the engine and the v4 pause API — <code>onStep</code>, <code>onDebugBreak</code>, per-state <code>debug</code> flags — in detail. I’ll lean on it here without rehashing it. The v4 → v6 trajectory shipped three breaking majors: a hook rename, a halt-semantics hardening, and a dispatch-tick collapse. The first two surfaced in the demo. The third surfaced in the docs.</p>
<h2 id="the-demo-case-v4-v5"><a class="heading-anchor" href="#the-demo-case-v4-v5">The demo case: v4 → v5</a></h2>
<p>While shipping v4 I started building <a href="https://demo.machines.mellonis.ru"><code>machines-demo</code></a> — an interactive Turing-machine debugger and the engine's first non-test client.</p>
<p>The demo is a natural first consumer: it has a dual purpose. The product goal — public distribution and showing the engine in action. The technical goal — road-testing changes and validating concepts against a live API surface. Both goals make building the demo an integral part of the release cycle, not an optional add-on.</p>
<p>The demo used both hooks at once: <code>onStep</code> populated a per-iteration command buffer for the trace UI; <code>onDebugBreak</code> drove the pause/resume cycle.</p>
<p>The demo built. The tests passed. But it was uncomfortable to write, for two reasons.</p>
<p>First, <code>onDebugBreak</code>’s after-fire came with data from the previous yield — the same data the previous <code>onStep</code> had already shown. The demo processed the same thing twice, and the question “why two hooks for one event?” was being asked not by me but by the code itself, in a way. I filed <a href="https://github.com/mellonis/turing-machine-js/issues/109"><code>turing-machine-js#109</code></a> as an RFC about the relationship between these hooks, listing four sketches; the resolution narrowed to <em>naming</em>. <code>onDebugBreak</code> framed the purpose of use as “debugging”, while the consumer’s verb was “pause”. Shameless rename, no alias. v5.</p>
<p>Second, the demo’s UI gained a “pause before halt” scenario — letting the user glimpse the machine’s final state before it shuts down. The natural implementation: a <code>debug</code> flag on <code>haltState</code> itself. The first test case set <code>haltState.debug = { before: true, after: true }</code> because the symmetry looked right. Only <code>before</code> fired. Worse: the after-fire on the iteration that <em>led to</em> halt never reached the consumer — the loop exited as soon as <code>state.isHalt</code> became <code>true</code>. <a href="https://github.com/mellonis/turing-machine-js/issues/108"><code>turing-machine-js#108</code></a> split it in two: restore the lost after-fire (bug); throw on assignment to <code>haltState.debug.after</code> (API).</p>
<p>Both complaints came from the consumer side. The demo didn’t surface a code bug — it surfaced an <em>API interaction format</em>. The names didn’t fit the use. Being permissive in input didn’t match what the user was trying to do. The tests verified behavior against the engine’s own internal model — ok, green. The demo verified behavior against the consumer’s mental model — and produced two specific complaints (not ok).</p>
<h2 id="the-docs-case-v5-v6"><a class="heading-anchor" href="#the-docs-case-v5-v6">The docs case: v5 → v6</a></h2>
<p>v5 shipped. The README needed updating. The new dispatch-order section had to explain — in words — when each of <code>onPause(before)</code>, <code>onStep</code>, and <code>onPause(after)</code> fired relative to the iteration they described.</p>
<p>The first honest paragraph went something like:</p>
<blockquote>
<p><code>onPause(after, K)</code> fires on iteration K+1’s yield, with the payload substituted from iteration K’s snapshot, before <code>onPause(before, K+1)</code> or <code>onStep(K+1)</code> fire.</p>
</blockquote>
<p>I stared at that sentence for a while. There was no shorter version. The reader wasn’t supposed to need a sentence about substitution.</p>
<p>The code worked. The tests passed. The demo consumed the hooks correctly. The mistake wasn’t in any of those — it was in the <em>shape</em> of the dispatch, and that shape was only visible when you had to put it into words.</p>
<p>The fix collapsed the lifecycle: <code>before(K) → step(K) → after(K)</code> on the same yield. No substitution. No cross-iteration scheduling. No final drain for the halting iteration (in “Three majors, two mistakes” I called it “post-loop drain”; I’d probably shorten it to “final drain” now). The README paragraph now reads:</p>
<blockquote>
<p>On iteration K’s yield, hooks fire in lifecycle order.</p>
</blockquote>
<p>And that’s the kind of sentence the reader glides past without effort. <a href="https://github.com/mellonis/turing-machine-js/issues/119"><code>turing-machine-js#119</code></a> shipped as v6.</p>
<p>A direct quote from the previous article:</p>
<blockquote>
<p>The code worked, the tests passed, and the docs were correct. The shape was just wrong.</p>
</blockquote>
<p>What I’d add: the docs were correct only on the condition that the reader accepted three explanatory sentences they shouldn’t have had to read. That’s not “correct docs” — that’s docs apologizing for the shape.</p>
<p>The docs review caught the <em>shape</em>, not the <em>use</em>. The demo worked. The tests passed. This time, only <em>prose pressure</em> uncovered the issues hiding in the implementation.</p>
<h2 id="three-reviews-three-layers"><a class="heading-anchor" href="#three-reviews-three-layers">Three reviews, three layers</a></h2>
<p>Here’s what each one checks:</p>
<ul>
<li><strong>Tests</strong> verify code against itself. Internal consistency. The engine yields what the engine should yield. Green tests are the baseline.</li>
<li><strong>The first real consumer</strong> verifies code against a consumer’s mental model. <em>Does the API format match what the user is trying to do?</em> Reviewing real interaction with the API forced API changes: a rename and a halt-after restriction.</li>
<li><strong>The docs as <em>prose</em></strong> (not JSDoc — a connected README narrative) verify code against the author’s own explanation. <em>Does the design have an honest one-paragraph description?</em> Without one, we had to look hard at the substitution dance — and abandon it.</li>
</ul>
<p>Each review catches what the layer below misses. Tests don’t catch shape; the consumer doesn’t catch interaction problems it can skillfully bypass; the docs don’t catch UX wrinkles they don’t have to mention.</p>
<p>The cost is asymmetric. Building a real consumer is the most expensive of the three reviews; writing the docs is the cheapest. Still, even the most expensive costs less than reworking the API after the problems surface for users — hence “cheap” in the title. The real consumer has to be built <em>before</em> the major cut — it’s the only review that makes the API comfortable to use. Docs then paper over what’s left.</p>
<h2 id="heuristics-for-the-next-major"><a class="heading-anchor" href="#heuristics-for-the-next-major">Heuristics for the next major</a></h2>
<ol>
<li><strong>Build the first real consumer before cutting the major.</strong> Not a test fixture — a consumer with its own mental model. The difficulties it encounters are the same difficulties your users will encounter later.</li>
<li><strong>Write the dispatch-order paragraph before locking the dispatch order.</strong> If you can’t describe in one sentence what fires when, the dispatch is wrong. Decisions of this kind belong at the design stage, not documentation — when not a single line of code has been written yet.</li>
<li><strong>Read the docs back as a stranger.</strong> If a paragraph reads as an apology for the shape, the docs are working — they’ve <em>revealed</em> a shape mistake. Fix the shape, not the paragraph.</li>
</ol>
<p>Three majors. One README. One demo. The tests had nothing to say.</p>
<hr>
<p><em>Code: <a href="https://github.com/mellonis/turing-machine-js"><code>turing-machine-js</code></a> (engine) and <a href="https://demo.machines.mellonis.ru"><code>machines-demo</code></a> (the first non-test consumer where v4 → v5 surfaced).</em></p>]]></content:encoded>
    </item>
    <item>
      <title>Three majors, two mistakes: designing a pause API for a Turing-machine interpreter</title>
      <link>https://mellonis.ru/en/articles/three-majors-two-mistakes/</link>
      <guid isPermaLink="false">https://mellonis.ru/en/articles/three-majors-two-mistakes/</guid>
      <pubDate>Mon, 11 May 2026 00:00:00 GMT</pubDate>
      <description>Two design mistakes in a Turing-machine pause API, and the three major releases it took to get them out.</description>
      <content:encoded><![CDATA[<figure><img src="https://mellonis.ru/articles/three-majors-two-mistakes/tm.webp?v=4db093ab" alt="Screenshot of demo.machines.mellonis.ru running a Turing machine" width="3680" height="2392"><figcaption>Screenshot of demo.machines.mellonis.ru running a Turing machine</figcaption></figure>
<p>I spent the last two weeks shipping four breaking major versions of <a href="https://github.com/mellonis/turing-machine-js"><code>@turing-machine-js/machine</code></a> — v3, v4, v5, v6 — and the most interesting part wasn’t any single feature. It was watching the same API surface (a pause/breakpoint hook on the run loop) get redesigned twice in three versions, each time because the previous shape exposed something it shouldn’t have.</p>
<p>This post is the post-mortem. If you’re designing pause/step/breakpoint APIs for a generator-loop interpreter, scheduler, or DSL runtime, the mistakes I made are easy to make and worth seeing in someone else’s code first.</p>
<h2 id="the-setup"><a class="heading-anchor" href="#the-setup">The setup</a></h2>
<p>The engine runs a Turing machine. Internally it's a generator: each <code>yield</code> corresponds to one step (one transition firing on one tape symbol). The driver loop looks roughly like this:</p>
<pre class="shiki shiki-themes github-light github-dark language-javascript" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">async</span><span style="color:#D73A49;--shiki-dark:#F97583"> function</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> run</span><span style="color:#24292E;--shiki-dark:#E1E4E8">({ </span><span style="color:#E36209;--shiki-dark:#FFAB70">initialState</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#E36209;--shiki-dark:#FFAB70">onStep</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> }) {</span></span>
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">  for</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="color:#D73A49;--shiki-dark:#F97583">const</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> m</span><span style="color:#D73A49;--shiki-dark:#F97583"> of</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> runStepByStep</span><span style="color:#24292E;--shiki-dark:#E1E4E8">({ initialState })) {</span></span>
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">    await</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> onStep</span><span style="color:#24292E;--shiki-dark:#E1E4E8">?.(m);</span></span>
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">    if</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> (m.state.isHalt) </span><span style="color:#D73A49;--shiki-dark:#F97583">return</span><span style="color:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<p><code>MachineState</code> (<code>m</code>) is a snapshot per iteration: the state about to execute, the current and next symbols, the moves the heads will make. A consumer (a logger, a UI, a test) can hang off <code>onStep</code> to observe.</p>
<p>What I wanted to add in v4 was a way to <em>pause</em> execution at chosen points — like a breakpoint in a debugger. Any <code>State</code> should be able to carry a <code>debug</code> config:</p>
<pre class="shiki shiki-themes github-light github-dark language-javascript" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">myState.debug </span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> { before: [symA], after: [symA] };</span></span></code></pre>
<p>...and the run loop should give the consumer a chance to inspect the machine and decide when to resume.</p>
<h2 id="v4-ship-it"><a class="heading-anchor" href="#v4-ship-it">v4: ship it</a></h2>
<p>The v4 shape was straightforward. I made <code>run()</code> async, added an <code>onDebugBreak</code> hook, and routed it like this:</p>
<pre class="shiki shiki-themes github-light github-dark language-javascript" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">await</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> machine.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">run</span><span style="color:#24292E;--shiki-dark:#E1E4E8">({</span></span>
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">  initialState,</span></span>
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">  onStep</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: (</span><span style="color:#E36209;--shiki-dark:#FFAB70">m</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) </span><span style="color:#D73A49;--shiki-dark:#F97583">=></span><span style="color:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="color:#6A737D;--shiki-dark:#6A737D">/* every step */</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">  onDebugBreak</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#D73A49;--shiki-dark:#F97583">async</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="color:#E36209;--shiki-dark:#FFAB70">m</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) </span><span style="color:#D73A49;--shiki-dark:#F97583">=></span><span style="color:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">    if</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> (m.debugBreak?.before) console.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">log</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">'before:'</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, m.state.name);</span></span>
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">    if</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> (m.debugBreak?.after)  console.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">log</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">'after:'</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,  m.state.name);</span></span>
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">    // hold here until promise resolves</span></span>
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">});</span></span></code></pre>
<p>The per-state <code>debug</code> field is mutable. <code>state.debug = { before: true }</code> sets a pre-step break; <code>before: [symA]</code> filters by what the head is reading. The hook is awaited, so any consumer can implement “freeze until the human clicks Resume” by simply not resolving the promise.</p>
<p>I also wanted breakpoints on halt:</p>
<pre class="shiki shiki-themes github-light github-dark language-javascript" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">haltState.debug </span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> { before: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">true</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> };  </span><span style="color:#6A737D;--shiki-dark:#6A737D">// pause before exit</span></span></code></pre>
<p>That worked. Symbol-list filters on <code>haltState</code> were silent no-ops, because <code>haltState</code> has no head symbol to filter by. Fine, I thought — be permissive in input, the wildcard <code>true</code> is the one that matters.</p>
<p>Two things in this design were wrong. I didn’t notice either until I started writing docs and a UI on top.</p>
<h2 id="mistake-1-the-hook-describes-the-engine-not-the-consumer"><a class="heading-anchor" href="#mistake-1-the-hook-describes-the-engine-not-the-consumer">Mistake 1: the hook describes the engine, not the consumer</a></h2>
<p><code>onDebugBreak</code> reads, on paper, like a perfectly reasonable name. The engine fires a “debug break”; you hook into it.</p>
<p>But what does the consumer <em>do</em> in that hook? They pause. They inspect. They wait for input. They resume. The hook isn’t really notifying you that a thing happened — it’s offering you a cooperation point.</p>
<p>The name <code>onDebugBreak</code> carries one specific framing: “debugging”. But the same hook is exactly what you want for a step-through visualization, a slow-motion playback control, an animation tween, a “press space to advance” UI. None of those are debugging. They’re all <em>pausing</em>.</p>
<p>This sounds like a small thing. It’s not, because once consumers see the name they design around it: their code path is called <code>handleDebugBreak</code>, their state machine has a <code>debugging</code> boolean, their UI button says “Stop debugging”. The name leaks into every consumer’s vocabulary.</p>
<p>I wrote an RFC (<a href="https://github.com/mellonis/turing-machine-js/issues/109">turing-machine-js#109</a>) and renamed it in v5. Hard rename, no deprecation alias:</p>
<pre class="shiki shiki-themes github-light github-dark language-diff" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">await machine.run({</span></span>
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">    initialState,</span></span>
<span class="line"><span style="color:#B31D28;--shiki-dark:#FDAEB7">-   onDebugBreak: (m) => { ... },</span></span>
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">+   onPause: (m) => { ... },</span></span>
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">  });</span></span></code></pre>
<p>The payload field <code>m.debugBreak</code> stayed — it’s metadata describing <em>why</em> this yield fired (<code>{ before: true }</code> or <code>{ after: true }</code>), and “break” works fine inside the payload. But the hook name is the consumer’s contract: <code>onPause</code> describes what <em>they</em> do, not what the engine does.</p>
<p><strong>Rule for next time:</strong> when naming a hook, name the consumer’s verb, not the engine’s event. Hooks are cooperation points, not event listeners.</p>
<h2 id="restriction-haltstate-debug-after-is-nonsense"><a class="heading-anchor" href="#restriction-haltstate-debug-after-is-nonsense">Restriction: <code>haltState.debug.after</code> is nonsense</a></h2>
<p>The second v4 mistake hid under an instinct to be permissive in input. <code>haltState.debug.after</code> accepted writes silently. It just didn’t fire.</p>
<p>Why? Because the <code>after</code> semantics in this engine mean “fire on the iteration <em>after</em> the one where the filter matched”. That makes perfect sense for normal states — you transition out of state K, the next iter (K+1) runs, <em>and at that yield</em> the consumer is told “by the way, K’s after-filter fired last step”. But halt is terminal. There is no K+1 after halt. The <code>after</code> event has nothing to anchor on.</p>
<p>I’d silently swallowed <code>haltState.debug.after = true</code> in v4. Worse, I’d let <code>{ before: true, after: true }</code> through — half the assignment was meaningful, half was a no-op, and nothing told the consumer.</p>
<p>In v5 I made both throw at write time (<a href="https://github.com/mellonis/turing-machine-js/issues/108">turing-machine-js#108</a> part 2):</p>
<pre class="shiki shiki-themes github-light github-dark language-diff" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#B31D28;--shiki-dark:#FDAEB7">- haltState.debug = { before: true, after: true }; // v5: throws — 'after' on halt has nothing to anchor on</span></span>
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">+ haltState.debug = { before: true };</span></span></code></pre>
<p><strong>Rule for next time:</strong> if a configuration has no semantics, throw early. Silently no-op input <em>looks</em> user-friendly until a consumer spends an afternoon wondering why their UI doesn’t fire on halt. “Be permissive” is a false economy when permissiveness silences a real mistake.</p>
<p>While I was in there, I also fixed a related bug: the halting iter’s <em>own</em> <code>after</code> filter wasn’t firing either (<a href="https://github.com/mellonis/turing-machine-js/issues/108">turing-machine-js#108</a> part 1). The driver loop exited as soon as <code>state.isHalt</code> became true — and the after-event from the previous iter, which would normally fire on this final yield, got dropped on the floor. v5 added a post-loop drain to fire it.</p>
<p>I’ll come back to this.</p>
<p>And one v5 bonus: a master switch on <code>run()</code> for the whole pause system.</p>
<pre class="shiki shiki-themes github-light github-dark language-javascript" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">await</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> machine.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">run</span><span style="color:#24292E;--shiki-dark:#E1E4E8">({ initialState, debug: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">false</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, onPause: </span><span style="color:#D73A49;--shiki-dark:#F97583">...</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> });</span></span></code></pre>
<p>When <code>false</code>, all pause-fires are suppressed regardless of what <code>state.debug</code> says across the graph (<a href="https://github.com/mellonis/turing-machine-js/issues/106">turing-machine-js#106</a>). You can A/B “debug mode” without rewriting the graph or clearing every <code>state.debug</code> field. The flag dispatches <code>onPause</code>; the underlying <code>m.debugBreak</code> payload field still populates on the generator’s yields (it’s a property of the iteration, not of how <code>run()</code> chose to surface it).</p>
<h2 id="mistake-2-the-substitution-dance"><a class="heading-anchor" href="#mistake-2-the-substitution-dance">Mistake 2: the substitution dance</a></h2>
<p>This is the one I’m proudest to have caught, because the code worked, the tests passed, and the docs were correct. The shape was just wrong.</p>
<p>In v4 and v5, <code>after K</code> (the after-fire for iteration K) actually fired on iteration <strong>K+1</strong>’s yield. The driver loop carried a <code>pendingAfterFromPrev</code> flag across yields, and on the next iter’s yield it dispatched the <code>after</code> hook <em>first</em>, then the <code>before</code> hook, then <code>onStep</code>. The hook for K’s after-fire had to see K’s state — not K+1’s. So I <em>substituted</em> the previous yield’s snapshot into the <code>m.state</code> field of K+1’s yield, just for the duration of the <code>after</code> dispatch.</p>
<p>This worked. But it had three knock-on effects:</p>
<ol>
<li>
<p><strong>The substitution leaked.</strong> Consumers wanted access to the un-substituted, “real” iteration state (the one the <code>step</code> hook saw) — see <a href="https://github.com/mellonis/turing-machine-js/issues/107">turing-machine-js#107</a>. Some users were reading raw <code>MachineState.debugBreak</code> from <code>runStepByStep</code> directly and were surprised that <code>m.state</code> referred to the iter on which the after-fired-from, not the iter that produced it.</p>
</li>
<li>
<p><strong>The halt case needed a special path.</strong> As mentioned: the halting iter’s own <code>after</code> fires <em>after</em> the loop exits. v5 added a post-loop drain to handle it. That drain is its own code path, with its own substitution, separate from the in-loop dispatch.</p>
</li>
<li>
<p><strong>The generator’s return type widened.</strong> Because the post-loop drain needed to <em>return</em> a final yielded value out of the iterator, <code>runStepByStep</code>’s return type became <code>Generator&#x3C;MachineState, MachineState | null></code> — a yield type <em>and</em> a return type. The canonical <code>for..of</code> consumer doesn’t see the return value, but anyone reading the type signature now had to understand why there were two slots.</p>
</li>
</ol>
<p>All of this came from one design choice: dispatching <code>after K</code> on iter K+1’s yield instead of on iter K’s own yield.</p>
<p>In v6 I collapsed it (<a href="https://github.com/mellonis/turing-machine-js/issues/119">turing-machine-js#119</a>). The per-iter lifecycle is now plainly <code>before → step → after</code>. The <code>after</code> fire rides on the same yield as the iter that produced it. No substitution. No <code>pendingAfterFromPrev</code>. No post-loop drain. The generator return type narrows back to <code>Generator&#x3C;MachineState></code>.</p>
<pre class="shiki shiki-themes github-light github-dark language-javascript" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// v6</span></span>
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">await</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> machine.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">run</span><span style="color:#24292E;--shiki-dark:#E1E4E8">({</span></span>
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">  initialState,</span></span>
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">  onStep</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: (</span><span style="color:#E36209;--shiki-dark:#FFAB70">m</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) </span><span style="color:#D73A49;--shiki-dark:#F97583">=></span><span style="color:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="color:#6A737D;--shiki-dark:#6A737D">/* unchanged */</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">  onPause</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: (</span><span style="color:#E36209;--shiki-dark:#FFAB70">m</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) </span><span style="color:#D73A49;--shiki-dark:#F97583">=></span><span style="color:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">    if</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> (m.debugBreak?.before) console.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">log</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">'before:'</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, m.state.name);</span></span>
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">    if</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> (m.debugBreak?.after)  console.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">log</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">'after:'</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,  m.state.name);</span></span>
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">});</span></span></code></pre>
<p>The dispatch order <em>across</em> hooks changed (any test asserting <code>pause(after K-1) → pause(before K) → step(K)</code> had to flip to <code>pause(before K) → step(K) → pause(after K)</code>), but the set of dispatched calls and per-iter semantics are unchanged. Consumers treating the hooks as independent observers see no change at all (<a href="https://github.com/mellonis/turing-machine-js/issues/107">turing-machine-js#107</a> — “expose un-substituted state” — disappeared as a problem: there’s no substitution to expose around).</p>
<p><strong>Rule for next time:</strong> if your hook payload requires substituting state from a different iteration than the one that’s yielding, the dispatch sequence is wrong. Lifecycle phases (<code>before</code>, <code>step</code>, <code>after</code>) belong on the iter they describe. The substitution wasn’t a clever trick — it was a leak telling me the events were on the wrong tick.</p>
<h2 id="what-i-d-carry-to-the-next-pause-breakpoint-api"><a class="heading-anchor" href="#what-i-d-carry-to-the-next-pause-breakpoint-api">What I’d carry to the next pause/breakpoint API</a></h2>
<ol>
<li>
<p><strong>Name hooks for the consumer's verb, not the engine's event.</strong> <code>onPause</code>, not <code>onDebugBreak</code>. <code>onProgress</code>, not <code>onChunkReceived</code>. The name leaks into every consumer's mental model — pick the framing you want them to inherit.</p>
</li>
<li>
<p><strong>Throw on impossible configurations early.</strong> “Permissive in input” is fine for shapes that <em>might</em> be meaningful; it's a trap for shapes that <em>can't</em> be. <code>haltState.debug.after = true</code> had no possible semantics. Silently swallowing it cost an afternoon to one user before I noticed.</p>
</li>
<li>
<p><strong>Per-iter phases belong on the iter they describe.</strong> If you're tempted to dispatch <code>after K</code> on K+1's yield, ask what payload you have to substitute to make it look right. The substitution is the signal.</p>
</li>
<li>
<p><strong>A master switch is cheap and worth it.</strong> A boolean on the entry point to flip the whole feature off (without rewriting graph-level flags) makes the feature safe to ship to production and toggle in tests. <code>run({ debug: false })</code> was one of the smaller v5 adds and one of the most-used by downstream consumers.</p>
</li>
<li>
<p><strong>Breaking changes are worth the major bump.</strong> Three majors in two weeks sounds expensive. It isn't, if the lockstep downstream is one repo (in my case <a href="https://github.com/mellonis/post-machine-js"><code>@post-machine-js/machine</code></a>, which bumped its peer dep <code>^4.0.0</code> → <code>^6.0.0</code> and renamed its own internal <code>__onDebugBreak</code> → <code>__onPause</code> in step). API ergonomics compound across every consumer for the life of the library — pay the migration cost while the API is young.</p>
</li>
</ol>
<p>The v6 shape is the one I should have shipped in v4. I didn't have the vocabulary then — I was thinking “expose the engine's events” instead of “design the consumer's contract”. Writing the docs is what surfaced both mistakes. There's a meta-lesson in there about how docs are the cheapest design review you can run, but that's another post.</p>
<hr>
<p><em>Code:</em> <a href="https://github.com/mellonis/turing-machine-js"><code>turing-machine-js</code></a> <em>(engine) and</em> <a href="https://github.com/mellonis/post-machine-js"><code>post-machine-js</code></a> <em>(a Post machine built on top, kept in lockstep). The interactive demo at</em> <a href="https://demo.machines.mellonis.ru">demo.machines.mellonis.ru</a> <em>consumes the v6</em> <code>onPause</code> <em>hook for its Step / Run / Stop controls.</em></p>]]></content:encoded>
    </item>
  </channel>
</rss>