<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Architecture on Nick Liu - Software Engineer</title><link>https://nick-liu.com/tags/architecture/</link><description>Recent content in Architecture on Nick Liu - Software Engineer</description><generator>Hugo -- gohugo.io</generator><language>en</language><managingEditor>nickboy@users.noreply.github.com (Nick Liu)</managingEditor><webMaster>nickboy@users.noreply.github.com (Nick Liu)</webMaster><copyright>2026 Nick Liu</copyright><lastBuildDate>Sun, 30 Aug 2026 00:52:14 -0700</lastBuildDate><atom:link href="https://nick-liu.com/tags/architecture/index.xml" rel="self" type="application/rss+xml"/><item><title>I deleted six subsystems by swapping one dependency. The protocol billed me.</title><link>https://nick-liu.com/posts/herddeck-substrate-bet/</link><pubDate>Sun, 30 Aug 2026 00:00:00 +0000</pubDate><author>nickboy@users.noreply.github.com (Nick Liu)</author><guid>https://nick-liu.com/posts/herddeck-substrate-bet/</guid><description>&lt;div class="lead text-neutral-500 dark:text-neutral-400 !mb-9 text-xl"&gt;&#10; &#10;Six of the ten posts in my "Building ClaudeDeck" series document code that no longer exists. Over four days in August I rebuilt the plugin on herdr's socket API, and the hook dispatcher, the PTY runner, the statusline auto-patcher, the AppleScript focus path, the Claude project watcher and the shell-PID resolver all went in the bin, taking the `.app` bundle, the codesigning step and every TCC prompt with them. Then the substrate sent its invoice.&#10;&#10;&lt;/div&gt;&#10;&#10;&lt;nav class="series-progress" aria-label="Series progress"&gt;&#10; &lt;span class="series-progress-label"&gt;Deleting ClaudeDeck · Part 1 of 1&lt;/span&gt;&#10; &lt;ol class="series-progress-dots"&gt;&lt;li class="series-progress-dot is-current"&gt;&#10; &lt;a href="https://nick-liu.com/posts/herddeck-substrate-bet/" title="I deleted six subsystems by swapping one dependency. The protocol billed me." aria-current="step"&gt;1&lt;/a&gt;&#10; &lt;/li&gt;&lt;/ol&gt;&#10; &lt;/nav&gt;&#10;&lt;div class="tested-with" role="note"&gt;&#10; &lt;span class="tested-with-icon" aria-hidden="true"&gt;🧪&lt;/span&gt;&#10; &lt;span&gt;Tested with &lt;strong&gt;herdr&lt;/strong&gt; &lt;code&gt;0.8.0&lt;/code&gt; · macOS&lt;/span&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;p&gt;ClaudeDeck was complicated for exactly one reason. Claude Code has no control API, so every fact the plugin needed had to be stolen from somewhere it was not offered.&lt;/p&gt;</description><content:encoded>&lt;div class="lead text-neutral-500 dark:text-neutral-400 !mb-9 text-xl"&gt;&#10; &#10;Six of the ten posts in my "Building ClaudeDeck" series document code that no longer exists. Over four days in August I rebuilt the plugin on herdr's socket API, and the hook dispatcher, the PTY runner, the statusline auto-patcher, the AppleScript focus path, the Claude project watcher and the shell-PID resolver all went in the bin, taking the `.app` bundle, the codesigning step and every TCC prompt with them. Then the substrate sent its invoice.&#10;&#10;&lt;/div&gt;&#10;&#10;&lt;nav class="series-progress" aria-label="Series progress"&gt;&#10; &lt;span class="series-progress-label"&gt;Deleting ClaudeDeck · Part 1 of 1&lt;/span&gt;&#10; &lt;ol class="series-progress-dots"&gt;&lt;li class="series-progress-dot is-current"&gt;&#10; &lt;a href="https://nick-liu.com/posts/herddeck-substrate-bet/" title="I deleted six subsystems by swapping one dependency. The protocol billed me." aria-current="step"&gt;1&lt;/a&gt;&#10; &lt;/li&gt;&lt;/ol&gt;&#10; &lt;/nav&gt;&#10;&lt;div class="tested-with" role="note"&gt;&#10; &lt;span class="tested-with-icon" aria-hidden="true"&gt;🧪&lt;/span&gt;&#10; &lt;span&gt;Tested with &lt;strong&gt;herdr&lt;/strong&gt; &lt;code&gt;0.8.0&lt;/code&gt; · macOS&lt;/span&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;p&gt;ClaudeDeck was complicated for exactly one reason. Claude Code has no control API, so every fact the plugin needed had to be stolen from somewhere it was not offered.&lt;/p&gt;&#10;&lt;p&gt;To know an agent was blocked, it installed hooks and dispatched them. To know how full the context window was, it patched the statusline. To read what a pane was showing, it ran a PTY and kept a ring buffer. To jump to the right terminal tab it drove AppleScript, which meant Accessibility, which meant TCC, which meant codesigning. To know which project a shell belonged to, it resolved shell PIDs and watched the projects directory.&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="https://herdr.dev" target="_blank" rel="noreferrer"&gt;herdr&lt;/a&gt; is a terminal multiplexer built for coding agents. It already tracks all of that, and it exposes it on a Unix socket speaking NDJSON. Agent lifecycle, &lt;code&gt;idle&lt;/code&gt; and &lt;code&gt;working&lt;/code&gt; and &lt;code&gt;blocked&lt;/code&gt; and &lt;code&gt;done&lt;/code&gt;, is a first-class concept in the protocol rather than something you infer.&lt;/p&gt;&#10;&lt;p&gt;So the interesting artifact of this rebuild is not what I wrote. It is what came out.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;What all that code was for&#10; &lt;div id="what-all-that-code-was-for" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#what-all-that-code-was-for" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;ClaudeDeck subsystem&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;It existed because&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;HerdDeck instead&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Hook dispatch (&lt;a href="https://nick-liu.com/posts/claude-code-hooks-reality/" &gt;post&lt;/a&gt;)&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;nothing tells you an agent is blocked&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;agent_status&lt;/code&gt; is a field in the protocol&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Permission round-trip (&lt;a href="https://nick-liu.com/posts/permission-round-trip/" &gt;post&lt;/a&gt;)&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;approval meant parking an HTTP response on a Promise&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;herdr already knows a pane is waiting&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Statusline auto-patcher (&lt;a href="https://nick-liu.com/posts/statusline-side-channel/" &gt;post&lt;/a&gt;)&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;context fullness had to be smuggled out per turn&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;a statusline delegate you install yourself, never patched in behind your back&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;PTY runner and ring buffer (&lt;a href="https://nick-liu.com/posts/pty-wrap-migration/" &gt;post&lt;/a&gt;)&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;reading a pane meant owning the terminal&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;herdr owns the terminal&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;AppleScript, codesigning, TCC (&lt;a href="https://nick-liu.com/posts/tcc-cdhash-trap/" &gt;post&lt;/a&gt;)&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;focusing a tab needed Accessibility&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;one socket call&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Shell-PID resolver, project watcher&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;mapping a shell to a project&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;herdr tracks it&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;Two things fell out of that beyond the line count, and only one of them was planned.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;It works for every agent herdr recognises.&lt;/strong&gt; Claude Code, Codex, OpenCode. The old design was Claude-shaped because hooks are Claude-shaped. The new one asks herdr what is running and gets an answer that was never Claude-specific in the first place.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Remote came close to free.&lt;/strong&gt; herdr splits client from server, so the server holds the state and a remote server speaks the identical protocol. Forward the socket over SSH and the same daemon code drives agents on another machine.&lt;/p&gt;&#10;&lt;div class="not-prose diagram diagram-light"&gt;&lt;svg id="d21793c5c62197893light" width="100%" xmlns="http://www.w3.org/2000/svg" class="flowchart" style="max-width: 1228.5px;" viewBox="0 0 1228.5 94" role="graphics-document document" aria-roledescription="flowchart-v2"&gt;&lt;style&gt;#d21793c5c62197893light{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,noto sans,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#d21793c5c62197893light .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#d21793c5c62197893light .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#d21793c5c62197893light .error-icon{fill:rgb(255, 255, 255);}#d21793c5c62197893light .error-text{fill:#000000;stroke:#000000;}#d21793c5c62197893light .edge-thickness-normal{stroke-width:1px;}#d21793c5c62197893light .edge-thickness-thick{stroke-width:3.5px;}#d21793c5c62197893light .edge-pattern-solid{stroke-dasharray:0;}#d21793c5c62197893light .edge-thickness-invisible{stroke-width:0;fill:none;}#d21793c5c62197893light .edge-pattern-dashed{stroke-dasharray:3;}#d21793c5c62197893light .edge-pattern-dotted{stroke-dasharray:2;}#d21793c5c62197893light .marker{fill:rgb(74, 86, 92);stroke:rgb(74, 86, 92);}#d21793c5c62197893light .marker.cross{stroke:rgb(74, 86, 92);}#d21793c5c62197893light svg{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,noto sans,sans-serif;font-size:16px;}#d21793c5c62197893light p{margin:0;}#d21793c5c62197893light .label{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,noto sans,sans-serif;color:#333;}#d21793c5c62197893light .cluster-label text{fill:#000000;}#d21793c5c62197893light .cluster-label span{color:#000000;}#d21793c5c62197893light .cluster-label span p{background-color:transparent;}#d21793c5c62197893light .label text,#d21793c5c62197893light span{fill:#333;color:#333;}#d21793c5c62197893light .node rect,#d21793c5c62197893light .node circle,#d21793c5c62197893light .node ellipse,#d21793c5c62197893light .node polygon,#d21793c5c62197893light .node path{fill:rgb(255, 255, 255);stroke:rgb(204, 216, 222);stroke-width:1px;}#d21793c5c62197893light .rough-node .label text,#d21793c5c62197893light .node .label text,#d21793c5c62197893light .image-shape .label,#d21793c5c62197893light .icon-shape .label{text-anchor:middle;}#d21793c5c62197893light .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#d21793c5c62197893light .rough-node .label,#d21793c5c62197893light .node .label,#d21793c5c62197893light .image-shape .label,#d21793c5c62197893light .icon-shape .label{text-align:center;}#d21793c5c62197893light .node.clickable{cursor:pointer;}#d21793c5c62197893light .root .anchor path{fill:rgb(74, 86, 92)!important;stroke-width:0;stroke:rgb(74, 86, 92);}#d21793c5c62197893light .arrowheadPath{fill:#000000;}#d21793c5c62197893light .edgePath .path{stroke:rgb(74, 86, 92);stroke-width:1px;}#d21793c5c62197893light .flowchart-link{stroke:rgb(74, 86, 92);fill:none;}#d21793c5c62197893light .edgeLabel{background-color:rgb(182, 240, 255);text-align:center;}#d21793c5c62197893light .edgeLabel p{background-color:rgb(182, 240, 255);}#d21793c5c62197893light .edgeLabel rect{opacity:0.5;background-color:rgb(182, 240, 255);fill:rgb(182, 240, 255);}#d21793c5c62197893light .labelBkg{background-color:rgba(182, 240, 255, 0.5);}#d21793c5c62197893light .cluster rect{fill:rgb(255, 255, 255);stroke:rgb(129, 146, 154);stroke-width:1px;}#d21793c5c62197893light .cluster text{fill:#000000;}#d21793c5c62197893light .cluster span{color:#000000;}#d21793c5c62197893light div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,noto sans,sans-serif;font-size:12px;background:rgb(255, 255, 255);border:1px solid rgb(129, 146, 154);border-radius:2px;pointer-events:none;z-index:100;}#d21793c5c62197893light .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#d21793c5c62197893light rect.text{fill:none;stroke-width:0;}#d21793c5c62197893light .icon-shape,#d21793c5c62197893light .image-shape{background-color:rgb(182, 240, 255);text-align:center;}#d21793c5c62197893light .icon-shape p,#d21793c5c62197893light .image-shape p{background-color:rgb(182, 240, 255);padding:2px;}#d21793c5c62197893light .icon-shape .label rect,#d21793c5c62197893light .image-shape .label rect{opacity:0.5;background-color:rgb(182, 240, 255);fill:rgb(182, 240, 255);}#d21793c5c62197893light .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#d21793c5c62197893light .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#d21793c5c62197893light .node .neo-node{stroke:rgb(204, 216, 222);}#d21793c5c62197893light [data-look="neo"].node rect,#d21793c5c62197893light [data-look="neo"].cluster rect,#d21793c5c62197893light [data-look="neo"].node polygon{stroke:url(#d21793c5c62197893light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#d21793c5c62197893light [data-look="neo"].swimlane.cluster rect{filter:none;}#d21793c5c62197893light [data-look="neo"].node path{stroke:url(#d21793c5c62197893light-gradient);stroke-width:1px;}#d21793c5c62197893light [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#d21793c5c62197893light [data-look="neo"].node .neo-line path{stroke:rgb(204, 216, 222);filter:none;}#d21793c5c62197893light [data-look="neo"].node circle{stroke:url(#d21793c5c62197893light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#d21793c5c62197893light [data-look="neo"].node circle .state-start{fill:#000000;}#d21793c5c62197893light [data-look="neo"].icon-shape .icon{fill:url(#d21793c5c62197893light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#d21793c5c62197893light [data-look="neo"].icon-shape .icon-neo path{stroke:url(#d21793c5c62197893light-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#d21793c5c62197893light :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}&lt;/style&gt;&lt;g&gt;&lt;marker id="d21793c5c62197893light_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"&gt;&lt;path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893light_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"&gt;&lt;path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893light_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"&gt;&lt;path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893light_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"&gt;&lt;polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"&gt;&lt;/polygon&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893light_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"&gt;&lt;circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893light_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"&gt;&lt;circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893light_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"&gt;&lt;circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893light_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"&gt;&lt;circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893light_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"&gt;&lt;path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893light_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"&gt;&lt;path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893light_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"&gt;&lt;path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893light_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"&gt;&lt;path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;g class="root"&gt;&lt;g class="clusters"&gt;&lt;/g&gt;&lt;g class="edgePaths"&gt;&lt;path d="M202.781,47L206.948,47C211.115,47,219.448,47,227.115,47C234.781,47,241.781,47,245.281,47L248.781,47" id="d21793c5c62197893light-L_SD_P_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_SD_P_0" data-points="W3sieCI6MjAyLjc4MTI1LCJ5Ijo0N30seyJ4IjoyMjcuNzgxMjUsInkiOjQ3fSx7IngiOjI1Mi43ODEyNSwieSI6NDd9XQ==" data-look="classic" marker-end="url(#d21793c5c62197893light_flowchart-v2-pointEnd)"&gt;&lt;/path&gt;&lt;path d="M357.094,47L368.154,47C379.214,47,401.333,47,422.786,47C444.24,47,465.026,47,475.419,47L485.813,47" id="d21793c5c62197893light-L_P_D_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_P_D_0" data-points="W3sieCI6MzU3LjA5Mzc1LCJ5Ijo0N30seyJ4Ijo0MjMuNDUzMTI1LCJ5Ijo0N30seyJ4Ijo0ODkuODEyNSwieSI6NDd9XQ==" data-look="classic" marker-end="url(#d21793c5c62197893light_flowchart-v2-pointEnd)"&gt;&lt;/path&gt;&lt;path d="M680.984,47L696.965,47C712.945,47,744.906,47,776.201,47C807.495,47,838.122,47,853.436,47L868.75,47" id="d21793c5c62197893light-L_D_H_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_D_H_0" data-points="W3sieCI6NjgwLjk4NDM3NSwieSI6NDd9LHsieCI6Nzc2Ljg2NzE4NzUsInkiOjQ3fSx7IngiOjg3Mi43NSwieSI6NDd9XQ==" data-look="classic" marker-end="url(#d21793c5c62197893light_flowchart-v2-pointEnd)"&gt;&lt;/path&gt;&lt;path d="M1021.125,47L1025.292,47C1029.458,47,1037.792,47,1045.458,47C1053.125,47,1060.125,47,1063.625,47L1067.125,47" id="d21793c5c62197893light-L_H_A1_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_H_A1_0" data-points="W3sieCI6MTAyMS4xMjUsInkiOjQ3fSx7IngiOjEwNDYuMTI1LCJ5Ijo0N30seyJ4IjoxMDcxLjEyNSwieSI6NDd9XQ==" data-look="classic" marker-end="url(#d21793c5c62197893light_flowchart-v2-pointEnd)"&gt;&lt;/path&gt;&lt;/g&gt;&lt;g class="edgeLabels"&gt;&lt;g class="edgeLabel"&gt;&lt;g class="label" data-id="L_SD_P_0" transform="translate(0, 0)"&gt;&lt;foreignObject width="0" height="0"&gt;&lt;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;"&gt;&lt;span class="edgeLabel"&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class="edgeLabel" transform="translate(423.453125, 47)"&gt;&lt;g class="label" data-id="L_P_D_0" transform="translate(-41.359375, -12)"&gt;&lt;foreignObject width="82.71875" height="24"&gt;&lt;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;"&gt;&lt;span class="edgeLabel"&gt;&lt;p&gt;WebSocket&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class="edgeLabel" transform="translate(776.8671875, 47)"&gt;&lt;g class="label" data-id="L_D_H_0" transform="translate(-70.8828125, -24)"&gt;&lt;foreignObject width="141.765625" height="48"&gt;&lt;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;"&gt;&lt;span class="edgeLabel"&gt;&lt;p&gt;ssh -N -L&lt;br&gt;unix socket forward&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class="edgeLabel"&gt;&lt;g class="label" data-id="L_H_A1_0" transform="translate(0, 0)"&gt;&lt;foreignObject width="0" height="0"&gt;&lt;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;"&gt;&lt;span class="edgeLabel"&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class="nodes"&gt;&lt;g class="node default" id="d21793c5c62197893light-flowchart-SD-0" data-look="classic" transform="translate(105.390625, 47)"&gt;&lt;rect class="basic label-container" style="" x="-97.390625" y="-27" width="194.78125" height="54"&gt;&lt;/rect&gt;&lt;g class="label" style="" transform="translate(-67.390625, -12)"&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width="134.78125" height="24"&gt;&lt;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;"&gt;&lt;span class="nodeLabel"&gt;&lt;p&gt;Stream Deck MK.2&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class="node default" id="d21793c5c62197893light-flowchart-P-1" data-look="classic" transform="translate(304.9375, 47)"&gt;&lt;rect class="basic label-container" style="" x="-52.15625" y="-27" width="104.3125" height="54"&gt;&lt;/rect&gt;&lt;g class="label" style="" transform="translate(-22.15625, -12)"&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width="44.3125" height="24"&gt;&lt;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;"&gt;&lt;span class="nodeLabel"&gt;&lt;p&gt;plugin&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class="node default" id="d21793c5c62197893light-flowchart-D-3" data-look="classic" transform="translate(585.3984375, 47)"&gt;&lt;rect class="basic label-container" style="" x="-95.5859375" y="-39" width="191.171875" height="78"&gt;&lt;/rect&gt;&lt;g class="label" style="" transform="translate(-65.5859375, -24)"&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width="131.171875" height="48"&gt;&lt;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;"&gt;&lt;span class="nodeLabel"&gt;&lt;p&gt;herddeck daemon&lt;br&gt;(laptop, launchd)&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class="node default" id="d21793c5c62197893light-flowchart-H-5" data-look="classic" transform="translate(946.9375, 47)"&gt;&lt;rect class="basic label-container" style="" x="-74.1875" y="-39" width="148.375" height="78"&gt;&lt;/rect&gt;&lt;g class="label" style="" transform="translate(-44.1875, -24)"&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width="88.375" height="48"&gt;&lt;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;"&gt;&lt;span class="nodeLabel"&gt;&lt;p&gt;herdr server&lt;br&gt;(desktop)&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class="node default" id="d21793c5c62197893light-flowchart-A1-7" data-look="classic" transform="translate(1145.8125, 47)"&gt;&lt;rect class="basic label-container" style="" x="-74.6875" y="-27" width="149.375" height="54"&gt;&lt;/rect&gt;&lt;g class="label" style="" transform="translate(-44.6875, -12)"&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width="89.375" height="24"&gt;&lt;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;"&gt;&lt;span class="nodeLabel"&gt;&lt;p&gt;agent panes&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;defs&gt;&lt;filter id="d21793c5c62197893light-drop-shadow" height="130%" width="130%"&gt;&lt;feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"&gt;&lt;/feDropShadow&gt;&lt;/filter&gt;&lt;/defs&gt;&lt;defs&gt;&lt;filter id="d21793c5c62197893light-drop-shadow-small" height="150%" width="150%"&gt;&lt;feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"&gt;&lt;/feDropShadow&gt;&lt;/filter&gt;&lt;/defs&gt;&lt;linearGradient id="d21793c5c62197893light-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"&gt;&lt;stop offset="0%" stop-color="rgb(204, 216, 222)" stop-opacity="1"&gt;&lt;/stop&gt;&lt;stop offset="100%" stop-color="rgb(28, 209, 255)" stop-opacity="1"&gt;&lt;/stop&gt;&lt;/linearGradient&gt;&lt;/svg&gt;&lt;/div&gt;&#10; &lt;div class="not-prose diagram diagram-dark"&gt;&lt;svg id="d21793c5c62197893dark" width="100%" xmlns="http://www.w3.org/2000/svg" class="flowchart" style="max-width: 1228.5px;" viewBox="0 0 1228.5 94" role="graphics-document document" aria-roledescription="flowchart-v2"&gt;&lt;style&gt;#d21793c5c62197893dark{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,noto sans,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#d21793c5c62197893dark .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#d21793c5c62197893dark .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#d21793c5c62197893dark .error-icon{fill:#a44141;}#d21793c5c62197893dark .error-text{fill:#ddd;stroke:#ddd;}#d21793c5c62197893dark .edge-thickness-normal{stroke-width:1px;}#d21793c5c62197893dark .edge-thickness-thick{stroke-width:3.5px;}#d21793c5c62197893dark .edge-pattern-solid{stroke-dasharray:0;}#d21793c5c62197893dark .edge-thickness-invisible{stroke-width:0;fill:none;}#d21793c5c62197893dark .edge-pattern-dashed{stroke-dasharray:3;}#d21793c5c62197893dark .edge-pattern-dotted{stroke-dasharray:2;}#d21793c5c62197893dark .marker{fill:lightgrey;stroke:lightgrey;}#d21793c5c62197893dark .marker.cross{stroke:lightgrey;}#d21793c5c62197893dark svg{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,noto sans,sans-serif;font-size:16px;}#d21793c5c62197893dark p{margin:0;}#d21793c5c62197893dark .label{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,noto sans,sans-serif;color:#ccc;}#d21793c5c62197893dark .cluster-label text{fill:#F9FFFE;}#d21793c5c62197893dark .cluster-label span{color:#F9FFFE;}#d21793c5c62197893dark .cluster-label span p{background-color:transparent;}#d21793c5c62197893dark .label text,#d21793c5c62197893dark span{fill:#ccc;color:#ccc;}#d21793c5c62197893dark .node rect,#d21793c5c62197893dark .node circle,#d21793c5c62197893dark .node ellipse,#d21793c5c62197893dark .node polygon,#d21793c5c62197893dark .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#d21793c5c62197893dark .rough-node .label text,#d21793c5c62197893dark .node .label text,#d21793c5c62197893dark .image-shape .label,#d21793c5c62197893dark .icon-shape .label{text-anchor:middle;}#d21793c5c62197893dark .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#d21793c5c62197893dark .rough-node .label,#d21793c5c62197893dark .node .label,#d21793c5c62197893dark .image-shape .label,#d21793c5c62197893dark .icon-shape .label{text-align:center;}#d21793c5c62197893dark .node.clickable{cursor:pointer;}#d21793c5c62197893dark .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#d21793c5c62197893dark .arrowheadPath{fill:lightgrey;}#d21793c5c62197893dark .edgePath .path{stroke:lightgrey;stroke-width:1px;}#d21793c5c62197893dark .flowchart-link{stroke:lightgrey;fill:none;}#d21793c5c62197893dark .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#d21793c5c62197893dark .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#d21793c5c62197893dark .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#d21793c5c62197893dark .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#d21793c5c62197893dark .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#d21793c5c62197893dark .cluster text{fill:#F9FFFE;}#d21793c5c62197893dark .cluster span{color:#F9FFFE;}#d21793c5c62197893dark div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,noto sans,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#d21793c5c62197893dark .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#d21793c5c62197893dark rect.text{fill:none;stroke-width:0;}#d21793c5c62197893dark .icon-shape,#d21793c5c62197893dark .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#d21793c5c62197893dark .icon-shape p,#d21793c5c62197893dark .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#d21793c5c62197893dark .icon-shape .label rect,#d21793c5c62197893dark .image-shape .label rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#d21793c5c62197893dark .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#d21793c5c62197893dark .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#d21793c5c62197893dark .node .neo-node{stroke:#ccc;}#d21793c5c62197893dark [data-look="neo"].node rect,#d21793c5c62197893dark [data-look="neo"].cluster rect,#d21793c5c62197893dark [data-look="neo"].node polygon{stroke:url(#d21793c5c62197893dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#d21793c5c62197893dark [data-look="neo"].swimlane.cluster rect{filter:none;}#d21793c5c62197893dark [data-look="neo"].node path{stroke:url(#d21793c5c62197893dark-gradient);stroke-width:1px;}#d21793c5c62197893dark [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#d21793c5c62197893dark [data-look="neo"].node .neo-line path{stroke:#ccc;filter:none;}#d21793c5c62197893dark [data-look="neo"].node circle{stroke:url(#d21793c5c62197893dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#d21793c5c62197893dark [data-look="neo"].node circle .state-start{fill:#000000;}#d21793c5c62197893dark [data-look="neo"].icon-shape .icon{fill:url(#d21793c5c62197893dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#d21793c5c62197893dark [data-look="neo"].icon-shape .icon-neo path{stroke:url(#d21793c5c62197893dark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#d21793c5c62197893dark :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}&lt;/style&gt;&lt;g&gt;&lt;marker id="d21793c5c62197893dark_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"&gt;&lt;path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893dark_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"&gt;&lt;path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893dark_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"&gt;&lt;path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893dark_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"&gt;&lt;polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"&gt;&lt;/polygon&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893dark_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"&gt;&lt;circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893dark_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"&gt;&lt;circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893dark_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"&gt;&lt;circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893dark_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"&gt;&lt;circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893dark_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"&gt;&lt;path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893dark_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"&gt;&lt;path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893dark_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"&gt;&lt;path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id="d21793c5c62197893dark_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"&gt;&lt;path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;g class="root"&gt;&lt;g class="clusters"&gt;&lt;/g&gt;&lt;g class="edgePaths"&gt;&lt;path d="M202.781,47L206.948,47C211.115,47,219.448,47,227.115,47C234.781,47,241.781,47,245.281,47L248.781,47" id="d21793c5c62197893dark-L_SD_P_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_SD_P_0" data-points="W3sieCI6MjAyLjc4MTI1LCJ5Ijo0N30seyJ4IjoyMjcuNzgxMjUsInkiOjQ3fSx7IngiOjI1Mi43ODEyNSwieSI6NDd9XQ==" data-look="classic" marker-end="url(#d21793c5c62197893dark_flowchart-v2-pointEnd)"&gt;&lt;/path&gt;&lt;path d="M357.094,47L368.154,47C379.214,47,401.333,47,422.786,47C444.24,47,465.026,47,475.419,47L485.813,47" id="d21793c5c62197893dark-L_P_D_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_P_D_0" data-points="W3sieCI6MzU3LjA5Mzc1LCJ5Ijo0N30seyJ4Ijo0MjMuNDUzMTI1LCJ5Ijo0N30seyJ4Ijo0ODkuODEyNSwieSI6NDd9XQ==" data-look="classic" marker-end="url(#d21793c5c62197893dark_flowchart-v2-pointEnd)"&gt;&lt;/path&gt;&lt;path d="M680.984,47L696.965,47C712.945,47,744.906,47,776.201,47C807.495,47,838.122,47,853.436,47L868.75,47" id="d21793c5c62197893dark-L_D_H_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_D_H_0" data-points="W3sieCI6NjgwLjk4NDM3NSwieSI6NDd9LHsieCI6Nzc2Ljg2NzE4NzUsInkiOjQ3fSx7IngiOjg3Mi43NSwieSI6NDd9XQ==" data-look="classic" marker-end="url(#d21793c5c62197893dark_flowchart-v2-pointEnd)"&gt;&lt;/path&gt;&lt;path d="M1021.125,47L1025.292,47C1029.458,47,1037.792,47,1045.458,47C1053.125,47,1060.125,47,1063.625,47L1067.125,47" id="d21793c5c62197893dark-L_H_A1_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_H_A1_0" data-points="W3sieCI6MTAyMS4xMjUsInkiOjQ3fSx7IngiOjEwNDYuMTI1LCJ5Ijo0N30seyJ4IjoxMDcxLjEyNSwieSI6NDd9XQ==" data-look="classic" marker-end="url(#d21793c5c62197893dark_flowchart-v2-pointEnd)"&gt;&lt;/path&gt;&lt;/g&gt;&lt;g class="edgeLabels"&gt;&lt;g class="edgeLabel"&gt;&lt;g class="label" data-id="L_SD_P_0" transform="translate(0, 0)"&gt;&lt;foreignObject width="0" height="0"&gt;&lt;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;"&gt;&lt;span class="edgeLabel"&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class="edgeLabel" transform="translate(423.453125, 47)"&gt;&lt;g class="label" data-id="L_P_D_0" transform="translate(-41.359375, -12)"&gt;&lt;foreignObject width="82.71875" height="24"&gt;&lt;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;"&gt;&lt;span class="edgeLabel"&gt;&lt;p&gt;WebSocket&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class="edgeLabel" transform="translate(776.8671875, 47)"&gt;&lt;g class="label" data-id="L_D_H_0" transform="translate(-70.8828125, -24)"&gt;&lt;foreignObject width="141.765625" height="48"&gt;&lt;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;"&gt;&lt;span class="edgeLabel"&gt;&lt;p&gt;ssh -N -L&lt;br&gt;unix socket forward&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class="edgeLabel"&gt;&lt;g class="label" data-id="L_H_A1_0" transform="translate(0, 0)"&gt;&lt;foreignObject width="0" height="0"&gt;&lt;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;"&gt;&lt;span class="edgeLabel"&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class="nodes"&gt;&lt;g class="node default" id="d21793c5c62197893dark-flowchart-SD-0" data-look="classic" transform="translate(105.390625, 47)"&gt;&lt;rect class="basic label-container" style="" x="-97.390625" y="-27" width="194.78125" height="54"&gt;&lt;/rect&gt;&lt;g class="label" style="" transform="translate(-67.390625, -12)"&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width="134.78125" height="24"&gt;&lt;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;"&gt;&lt;span class="nodeLabel"&gt;&lt;p&gt;Stream Deck MK.2&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class="node default" id="d21793c5c62197893dark-flowchart-P-1" data-look="classic" transform="translate(304.9375, 47)"&gt;&lt;rect class="basic label-container" style="" x="-52.15625" y="-27" width="104.3125" height="54"&gt;&lt;/rect&gt;&lt;g class="label" style="" transform="translate(-22.15625, -12)"&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width="44.3125" height="24"&gt;&lt;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;"&gt;&lt;span class="nodeLabel"&gt;&lt;p&gt;plugin&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class="node default" id="d21793c5c62197893dark-flowchart-D-3" data-look="classic" transform="translate(585.3984375, 47)"&gt;&lt;rect class="basic label-container" style="" x="-95.5859375" y="-39" width="191.171875" height="78"&gt;&lt;/rect&gt;&lt;g class="label" style="" transform="translate(-65.5859375, -24)"&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width="131.171875" height="48"&gt;&lt;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;"&gt;&lt;span class="nodeLabel"&gt;&lt;p&gt;herddeck daemon&lt;br&gt;(laptop, launchd)&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class="node default" id="d21793c5c62197893dark-flowchart-H-5" data-look="classic" transform="translate(946.9375, 47)"&gt;&lt;rect class="basic label-container" style="" x="-74.1875" y="-39" width="148.375" height="78"&gt;&lt;/rect&gt;&lt;g class="label" style="" transform="translate(-44.1875, -24)"&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width="88.375" height="48"&gt;&lt;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;"&gt;&lt;span class="nodeLabel"&gt;&lt;p&gt;herdr server&lt;br&gt;(desktop)&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class="node default" id="d21793c5c62197893dark-flowchart-A1-7" data-look="classic" transform="translate(1145.8125, 47)"&gt;&lt;rect class="basic label-container" style="" x="-74.6875" y="-27" width="149.375" height="54"&gt;&lt;/rect&gt;&lt;g class="label" style="" transform="translate(-44.6875, -12)"&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width="89.375" height="24"&gt;&lt;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;"&gt;&lt;span class="nodeLabel"&gt;&lt;p&gt;agent panes&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;defs&gt;&lt;filter id="d21793c5c62197893dark-drop-shadow" height="130%" width="130%"&gt;&lt;feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#FFFFFF"&gt;&lt;/feDropShadow&gt;&lt;/filter&gt;&lt;/defs&gt;&lt;defs&gt;&lt;filter id="d21793c5c62197893dark-drop-shadow-small" height="150%" width="150%"&gt;&lt;feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#FFFFFF"&gt;&lt;/feDropShadow&gt;&lt;/filter&gt;&lt;/defs&gt;&lt;linearGradient id="d21793c5c62197893dark-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"&gt;&lt;stop offset="0%" stop-color="#cccccc" stop-opacity="1"&gt;&lt;/stop&gt;&lt;stop offset="100%" stop-color="hsl(180, 0%, 18.3529411765%)" stop-opacity="1"&gt;&lt;/stop&gt;&lt;/linearGradient&gt;&lt;/svg&gt;&lt;/div&gt;&#10;&lt;p&gt;I want to be careful about the word &amp;ldquo;free&amp;rdquo;, because there is a caveat and the obvious guess about it is wrong. &lt;code&gt;herdr --remote&lt;/code&gt; makes the human terminal experience a thin client, but it does not expose a local API socket proxying the remote server. The local &lt;code&gt;herdr-client.sock&lt;/code&gt; is a TUI attach endpoint and nothing more. The daemon needs its own forward. And the auto-sync that keeps herdr versions matched only fires on a human &lt;code&gt;--remote&lt;/code&gt; attach, never on the daemon&amp;rsquo;s forward, so a box you rarely attach to can quietly drift to an older protocol. Every target therefore gets pinged and version-checked on connect and drops to a warning state on mismatch, rather than being assumed compatible.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;The bet, and it was a bet&#10; &lt;div id="the-bet-and-it-was-a-bet" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#the-bet-and-it-was-a-bet" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;I would rather leave this part out.&lt;/p&gt;&#10;&lt;p&gt;I have &lt;a href="https://nick-liu.com/posts/herdr-trial-agent-multiplexer/" &gt;a post on this blog about trialling herdr&lt;/a&gt;, with exit conditions written down before the trial started and a verdict due on August 16.&lt;/p&gt;&#10;&lt;p&gt;HerdDeck was built between August 6 and August 9.&lt;/p&gt;&#10;&lt;p&gt;So I deleted a working codebase and rebuilt my hardware controller on a substrate that was still on probation, a week before the trial I had written exit conditions for was due to conclude. If the verdict had gone the other way, the sunk cost would have been the whole rebuild plus the ClaudeDeck code I had already thrown away.&lt;/p&gt;&#10;&lt;p&gt;The verdict has since landed and it went my way. herdr graduated, which is the least interesting thing about it. It graduated on two of its three conditions, because the third turned out to be unanswerable from inside the window: a month of deliberately using one tool makes that tool look load-bearing whichever way the comparison would actually have gone. The trial is the data.&lt;/p&gt;&#10;&lt;p&gt;That is the same problem I had already created, one layer down and worse. Building HerdDeck did not merely make herdr look useful. It made herdr useful, to me, on hardware I reach for every day. A trial gets harder to fail once you have built something on the thing being trialled, and I built four days of work on it before the verdict was in.&lt;/p&gt;&#10;&lt;p&gt;A favourable answer does not make the sequence defensible and I am not going to dress it up as one. What makes it survivable rather than reckless is narrow: the deletion is reversible in the only sense that matters, because ClaudeDeck is still a repository and still works. What it cost is a real option, the ability to evaluate herdr without also evaluating four days of my own work sitting on top of it.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;What the protocol charged&#10; &lt;div id="what-the-protocol-charged" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#what-the-protocol-charged" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;These are the things you cannot learn by reading a schema, and they are the actual price of the substrate.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;One request per connection.&lt;/strong&gt; herdr answers the first NDJSON line on a connection and closes it. &lt;code&gt;events.subscribe&lt;/code&gt; is the exception: it converts its connection into a long-lived stream with a fixed subscription set. A client that wants to change what it is subscribed to has to open a new stream, which turns every subscription change into a make-before-break problem rather than a mutation.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Event names are inconsistent.&lt;/strong&gt; Lifecycle pushes use underscores, like &lt;code&gt;pane_created&lt;/code&gt;, with &lt;code&gt;data.type&lt;/code&gt; repeating the name. Status pushes use dots, like &lt;code&gt;pane.agent_status_changed&lt;/code&gt;. The cache accepts both spellings so no caller has to normalise first, which is a workaround rather than a fix.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Container closes do not cascade into pane events.&lt;/strong&gt; Closing a workspace or a tab emits &lt;code&gt;workspace_closed&lt;/code&gt; or &lt;code&gt;tab_closed&lt;/code&gt; and nothing else. No &lt;code&gt;pane_closed&lt;/code&gt; for the panes inside. A cache that only listens for pane events keeps zombie entries forever, which is exactly what mine did until I noticed.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;code&gt;workspace.close&lt;/code&gt; is asynchronous.&lt;/strong&gt; The &lt;code&gt;ok&lt;/code&gt; response returns immediately. The pane processes take one to two seconds to wind down before &lt;code&gt;workspace_closed&lt;/code&gt; fires.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;New subscribers get synthetic replay.&lt;/strong&gt; A fresh &lt;code&gt;events.subscribe&lt;/code&gt; stream receives &lt;code&gt;pane_created&lt;/code&gt; for panes that already existed. This is harmless under the ordering below, and it looks exactly like corruption if you are not expecting it.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Per-pane subscriptions are all-or-nothing.&lt;/strong&gt; &lt;code&gt;pane.agent_status_changed&lt;/code&gt; requires a &lt;code&gt;pane_id&lt;/code&gt; and there is no wildcard. One stale id fails the entire batch. That one produced the most instructive bug in the project, and it is the rest of this post.&lt;/p&gt;&#10;&lt;p&gt;None of the above is a criticism of herdr, which is a good substrate and the reason the rebuild was worth attempting. It is the answer to the question &amp;ldquo;what did it cost&amp;rdquo;, which is the question a post like this usually skips.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;The ordering that took three tries&#10; &lt;div id="the-ordering-that-took-three-tries" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#the-ordering-that-took-three-tries" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;The naive connect sequence is: snapshot the state, then subscribe to changes. That loses every transition landing in the gap between the two. The reverse, subscribe then snapshot, double-counts.&lt;/p&gt;&#10;&lt;p&gt;What actually works has five steps, and step four is the load-bearing one.&lt;/p&gt;&#10;&lt;div class="not-prose diagram diagram-light"&gt;&lt;svg id="dcd14d06924d1858alight" width="100%" xmlns="http://www.w3.org/2000/svg" style="max-width: 542.5px;" viewBox="-81.5 -10 542.5 579" role="graphics-document document" aria-roledescription="sequence"&gt;&lt;g&gt;&lt;rect x="261" y="493" fill="#eaeaea" stroke="#666" width="150" height="65" name="H" rx="3" ry="3" class="actor actor-bottom"&gt;&lt;/rect&gt;&lt;text x="336" y="525.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"&gt;&lt;tspan x="336" dy="0"&gt;herdr&lt;/tspan&gt;&lt;/text&gt;&lt;/g&gt;&lt;g&gt;&lt;rect x="0" y="493" fill="#eaeaea" stroke="#666" width="150" height="65" name="D" rx="3" ry="3" class="actor actor-bottom"&gt;&lt;/rect&gt;&lt;text x="75" y="525.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"&gt;&lt;tspan x="75" dy="0"&gt;daemon&lt;/tspan&gt;&lt;/text&gt;&lt;/g&gt;&lt;g&gt;&lt;line id="actor7" x1="336" y1="65" x2="336" y2="493" class="actor-line 200" stroke-width="0.5px" stroke="#999" name="H" data-et="life-line" data-id="H"&gt;&lt;/line&gt;&lt;g id="root-7" data-et="participant" data-type="participant" data-id="H"&gt;&lt;rect x="261" y="0" fill="#eaeaea" stroke="#666" width="150" height="65" name="H" rx="3" ry="3" class="actor actor-top"&gt;&lt;/rect&gt;&lt;text x="336" y="32.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"&gt;&lt;tspan x="336" dy="0"&gt;herdr&lt;/tspan&gt;&lt;/text&gt;&lt;/g&gt;&lt;/g&gt;&lt;g&gt;&lt;line id="actor6" x1="75" y1="65" x2="75" y2="493" class="actor-line 200" stroke-width="0.5px" stroke="#999" name="D" data-et="life-line" data-id="D"&gt;&lt;/line&gt;&lt;g id="root-6" data-et="participant" data-type="participant" data-id="D"&gt;&lt;rect x="0" y="0" fill="#eaeaea" stroke="#666" width="150" height="65" name="D" rx="3" ry="3" class="actor actor-top"&gt;&lt;/rect&gt;&lt;text x="75" y="32.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"&gt;&lt;tspan x="75" dy="0"&gt;daemon&lt;/tspan&gt;&lt;/text&gt;&lt;/g&gt;&lt;/g&gt;&lt;style&gt;#dcd14d06924d1858alight{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,noto sans,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#dcd14d06924d1858alight .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#dcd14d06924d1858alight .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#dcd14d06924d1858alight .error-icon{fill:rgb(255, 255, 255);}#dcd14d06924d1858alight .error-text{fill:#000000;stroke:#000000;}#dcd14d06924d1858alight .edge-thickness-normal{stroke-width:1px;}#dcd14d06924d1858alight .edge-thickness-thick{stroke-width:3.5px;}#dcd14d06924d1858alight .edge-pattern-solid{stroke-dasharray:0;}#dcd14d06924d1858alight .edge-thickness-invisible{stroke-width:0;fill:none;}#dcd14d06924d1858alight .edge-pattern-dashed{stroke-dasharray:3;}#dcd14d06924d1858alight .edge-pattern-dotted{stroke-dasharray:2;}#dcd14d06924d1858alight .marker{fill:rgb(74, 86, 92);stroke:rgb(74, 86, 92);}#dcd14d06924d1858alight .marker.cross{stroke:rgb(74, 86, 92);}#dcd14d06924d1858alight svg{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,noto sans,sans-serif;font-size:16px;}#dcd14d06924d1858alight p{margin:0;}#dcd14d06924d1858alight .actor{stroke:rgb(204, 216, 222);fill:rgb(255, 255, 255);stroke-width:1;}#dcd14d06924d1858alight rect.actor.outer-path[data-look="neo"]{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#dcd14d06924d1858alight rect.note[data-look="neo"]{stroke:hsl(52.6829268293, 60%, 73.9215686275%);fill:#fff5ad;filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#dcd14d06924d1858alight text.actor&amp;gt;tspan{fill:#333;stroke:none;}#dcd14d06924d1858alight .actor-line{stroke:rgb(204, 216, 222);}#dcd14d06924d1858alight .innerArc{stroke-width:1.5;stroke-dasharray:none;}#dcd14d06924d1858alight .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#dcd14d06924d1858alight .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#dcd14d06924d1858alight [id$="-arrowhead"] path{fill:#333;stroke:#333;}#dcd14d06924d1858alight .sequenceNumber{fill:#b5a9a3;}#dcd14d06924d1858alight [id$="-sequencenumber"]{fill:#333;}#dcd14d06924d1858alight [id$="-crosshead"] path{fill:#333;stroke:#333;}#dcd14d06924d1858alight .messageText{fill:#333;stroke:none;}#dcd14d06924d1858alight .labelBox{stroke:rgb(204, 216, 222);fill:rgb(255, 255, 255);filter:none;}#dcd14d06924d1858alight .labelText,#dcd14d06924d1858alight .labelText&amp;gt;tspan{fill:#333;stroke:none;}#dcd14d06924d1858alight .loopText,#dcd14d06924d1858alight .loopText&amp;gt;tspan{fill:#333;stroke:none;}#dcd14d06924d1858alight .sectionTitle,#dcd14d06924d1858alight .sectionTitle&amp;gt;tspan{fill:#333;stroke:none;}#dcd14d06924d1858alight .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:rgb(204, 216, 222);fill:rgb(204, 216, 222);}#dcd14d06924d1858alight .note{stroke:hsl(52.6829268293, 60%, 73.9215686275%);fill:#fff5ad;}#dcd14d06924d1858alight .noteText,#dcd14d06924d1858alight .noteText&amp;gt;tspan{fill:#333;stroke:none;font-weight:normal;}#dcd14d06924d1858alight .activation0{fill:rgb(182, 240, 255);stroke:hsl(192.3287671233, 100%, 75.6862745098%);}#dcd14d06924d1858alight .activation1{fill:rgb(182, 240, 255);stroke:hsl(192.3287671233, 100%, 75.6862745098%);}#dcd14d06924d1858alight .activation2{fill:rgb(182, 240, 255);stroke:hsl(192.3287671233, 100%, 75.6862745098%);}#dcd14d06924d1858alight .actorPopupMenu{position:absolute;}#dcd14d06924d1858alight .actorPopupMenuPanel{position:absolute;fill:rgb(255, 255, 255);box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#dcd14d06924d1858alight .actor-man circle,#dcd14d06924d1858alight line{fill:rgb(255, 255, 255);stroke-width:2px;}#dcd14d06924d1858alight g rect.rect{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));stroke:rgb(204, 216, 222);}#dcd14d06924d1858alight .node .neo-node{stroke:rgb(204, 216, 222);}#dcd14d06924d1858alight [data-look="neo"].node rect,#dcd14d06924d1858alight [data-look="neo"].cluster rect,#dcd14d06924d1858alight [data-look="neo"].node polygon{stroke:url(#dcd14d06924d1858alight-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#dcd14d06924d1858alight [data-look="neo"].swimlane.cluster rect{filter:none;}#dcd14d06924d1858alight [data-look="neo"].node path{stroke:url(#dcd14d06924d1858alight-gradient);stroke-width:1px;}#dcd14d06924d1858alight [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#dcd14d06924d1858alight [data-look="neo"].node .neo-line path{stroke:rgb(204, 216, 222);filter:none;}#dcd14d06924d1858alight [data-look="neo"].node circle{stroke:url(#dcd14d06924d1858alight-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#dcd14d06924d1858alight [data-look="neo"].node circle .state-start{fill:#000000;}#dcd14d06924d1858alight [data-look="neo"].icon-shape .icon{fill:url(#dcd14d06924d1858alight-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#dcd14d06924d1858alight [data-look="neo"].icon-shape .icon-neo path{stroke:url(#dcd14d06924d1858alight-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#dcd14d06924d1858alight :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}&lt;/style&gt;&lt;g&gt;&lt;/g&gt;&lt;defs&gt;&lt;symbol id="dcd14d06924d1858alight-computer" width="24" height="24"&gt;&lt;path transform="scale(.5)" d="M2 2v13h20v-13h-20zm18 11h-16v-9h16v9zm-10.228 6l.466-1h3.524l.467 1h-4.457zm14.228 3h-24l2-6h2.104l-1.33 4h18.45l-1.297-4h2.073l2 6zm-5-10h-14v-7h14v7z"&gt;&lt;/path&gt;&lt;/symbol&gt;&lt;/defs&gt;&lt;defs&gt;&lt;symbol id="dcd14d06924d1858alight-database" fill-rule="evenodd" clip-rule="evenodd"&gt;&lt;path transform="scale(.5)" d="M12.258.001l.256.004.255.005.253.008.251.01.249.012.247.015.246.016.242.019.241.02.239.023.236.024.233.027.231.028.229.031.225.032.223.034.22.036.217.038.214.04.211.041.208.043.205.045.201.046.198.048.194.05.191.051.187.053.183.054.18.056.175.057.172.059.168.06.163.061.16.063.155.064.15.066.074.033.073.033.071.034.07.034.069.035.068.035.067.035.066.035.064.036.064.036.062.036.06.036.06.037.058.037.058.037.055.038.055.038.053.038.052.038.051.039.05.039.048.039.047.039.045.04.044.04.043.04.041.04.04.041.039.041.037.041.036.041.034.041.033.042.032.042.03.042.029.042.027.042.026.043.024.043.023.043.021.043.02.043.018.044.017.043.015.044.013.044.012.044.011.045.009.044.007.045.006.045.004.045.002.045.001.045v17l-.001.045-.002.045-.004.045-.006.045-.007.045-.009.044-.011.045-.012.044-.013.044-.015.044-.017.043-.018.044-.02.043-.021.043-.023.043-.024.043-.026.043-.027.042-.029.042-.03.042-.032.042-.033.042-.034.041-.036.041-.037.041-.039.041-.04.041-.041.04-.043.04-.044.04-.045.04-.047.039-.048.039-.05.039-.051.039-.052.038-.053.038-.055.038-.055.038-.058.037-.058.037-.06.037-.06.036-.062.036-.064.036-.064.036-.066.035-.067.035-.068.035-.069.035-.07.034-.071.034-.073.033-.074.033-.15.066-.155.064-.16.063-.163.061-.168.06-.172.059-.175.057-.18.056-.183.054-.187.053-.191.051-.194.05-.198.048-.201.046-.205.045-.208.043-.211.041-.214.04-.217.038-.22.036-.223.034-.225.032-.229.031-.231.028-.233.027-.236.024-.239.023-.241.02-.242.019-.246.016-.247.015-.249.012-.251.01-.253.008-.255.005-.256.004-.258.001-.258-.001-.256-.004-.255-.005-.253-.008-.251-.01-.249-.012-.247-.015-.245-.016-.243-.019-.241-.02-.238-.023-.236-.024-.234-.027-.231-.028-.228-.031-.226-.032-.223-.034-.22-.036-.217-.038-.214-.04-.211-.041-.208-.043-.204-.045-.201-.046-.198-.048-.195-.05-.19-.051-.187-.053-.184-.054-.179-.056-.176-.057-.172-.059-.167-.06-.164-.061-.159-.063-.155-.064-.151-.066-.074-.033-.072-.033-.072-.034-.07-.034-.069-.035-.068-.035-.067-.035-.066-.035-.064-.036-.063-.036-.062-.036-.061-.036-.06-.037-.058-.037-.057-.037-.056-.038-.055-.038-.053-.038-.052-.038-.051-.039-.049-.039-.049-.039-.046-.039-.046-.04-.044-.04-.043-.04-.041-.04-.04-.041-.039-.041-.037-.041-.036-.041-.034-.041-.033-.042-.032-.042-.03-.042-.029-.042-.027-.042-.026-.043-.024-.043-.023-.043-.021-.043-.02-.043-.018-.044-.017-.043-.015-.044-.013-.044-.012-.044-.011-.045-.009-.044-.007-.045-.006-.045-.004-.045-.002-.045-.001-.045v-17l.001-.045.002-.045.004-.045.006-.045.007-.045.009-.044.011-.045.012-.044.013-.044.015-.044.017-.043.018-.044.02-.043.021-.043.023-.043.024-.043.026-.043.027-.042.029-.042.03-.042.032-.042.033-.042.034-.041.036-.041.037-.041.039-.041.04-.041.041-.04.043-.04.044-.04.046-.04.046-.039.049-.039.049-.039.051-.039.052-.038.053-.038.055-.038.056-.038.057-.037.058-.037.06-.037.061-.036.062-.036.063-.036.064-.036.066-.035.067-.035.068-.035.069-.035.07-.034.072-.034.072-.033.074-.033.151-.066.155-.064.159-.063.164-.061.167-.06.172-.059.176-.057.179-.056.184-.054.187-.053.19-.051.195-.05.198-.048.201-.046.204-.045.208-.043.211-.041.214-.04.217-.038.22-.036.223-.034.226-.032.228-.031.231-.028.234-.027.236-.024.238-.023.241-.02.243-.019.245-.016.247-.015.249-.012.251-.01.253-.008.255-.005.256-.004.258-.001.258.001zm-9.258 20.499v.01l.001.021.003.021.004.022.005.021.006.022.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.023.018.024.019.024.021.024.022.025.023.024.024.025.052.049.056.05.061.051.066.051.07.051.075.051.079.052.084.052.088.052.092.052.097.052.102.051.105.052.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.048.144.049.147.047.152.047.155.047.16.045.163.045.167.043.171.043.176.041.178.041.183.039.187.039.19.037.194.035.197.035.202.033.204.031.209.03.212.029.216.027.219.025.222.024.226.021.23.02.233.018.236.016.24.015.243.012.246.01.249.008.253.005.256.004.259.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.021.224-.024.22-.026.216-.027.212-.028.21-.031.205-.031.202-.034.198-.034.194-.036.191-.037.187-.039.183-.04.179-.04.175-.042.172-.043.168-.044.163-.045.16-.046.155-.046.152-.047.148-.048.143-.049.139-.049.136-.05.131-.05.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.053.083-.051.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.05.023-.024.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.023.01-.022.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.127l-.077.055-.08.053-.083.054-.085.053-.087.052-.09.052-.093.051-.095.05-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.045-.118.044-.12.043-.122.042-.124.042-.126.041-.128.04-.13.04-.132.038-.134.038-.135.037-.138.037-.139.035-.142.035-.143.034-.144.033-.147.032-.148.031-.15.03-.151.03-.153.029-.154.027-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.01-.179.008-.179.008-.181.006-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.006-.179-.008-.179-.008-.178-.01-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.027-.153-.029-.151-.03-.15-.03-.148-.031-.146-.032-.145-.033-.143-.034-.141-.035-.14-.035-.137-.037-.136-.037-.134-.038-.132-.038-.13-.04-.128-.04-.126-.041-.124-.042-.122-.042-.12-.044-.117-.043-.116-.045-.113-.045-.112-.046-.109-.047-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.05-.093-.052-.09-.051-.087-.052-.085-.053-.083-.054-.08-.054-.077-.054v4.127zm0-5.654v.011l.001.021.003.021.004.021.005.022.006.022.007.022.009.022.01.022.011.023.012.023.013.023.015.024.016.023.017.024.018.024.019.024.021.024.022.024.023.025.024.024.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.052.11.051.114.051.119.052.123.05.127.051.131.05.135.049.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.044.171.042.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.022.23.02.233.018.236.016.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.012.241-.015.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.048.139-.05.136-.049.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.051.051-.049.023-.025.023-.024.021-.025.02-.024.019-.024.018-.024.017-.024.015-.023.014-.023.013-.024.012-.022.01-.023.01-.023.008-.022.006-.022.006-.022.004-.021.004-.022.001-.021.001-.021v-4.139l-.077.054-.08.054-.083.054-.085.052-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.044-.118.044-.12.044-.122.042-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.035-.143.033-.144.033-.147.033-.148.031-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.009-.179.009-.179.007-.181.007-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.007-.179-.007-.179-.009-.178-.009-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.031-.146-.033-.145-.033-.143-.033-.141-.035-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.04-.126-.041-.124-.042-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.051-.093-.051-.09-.051-.087-.053-.085-.052-.083-.054-.08-.054-.077-.054v4.139zm0-5.666v.011l.001.02.003.022.004.021.005.022.006.021.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.024.018.023.019.024.021.025.022.024.023.024.024.025.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.051.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.043.171.043.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.021.23.02.233.018.236.017.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.013.241-.014.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.049.139-.049.136-.049.131-.051.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.049.023-.025.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.022.01-.023.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.153l-.077.054-.08.054-.083.053-.085.053-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.048-.105.048-.106.048-.109.046-.111.046-.114.046-.115.044-.118.044-.12.043-.122.043-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.034-.143.034-.144.033-.147.032-.148.032-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.024-.161.024-.162.023-.163.023-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.01-.178.01-.179.009-.179.007-.181.006-.182.006-.182.004-.184.003-.184.001-.185.001-.185-.001-.184-.001-.184-.003-.182-.004-.182-.006-.181-.006-.179-.007-.179-.009-.178-.01-.176-.01-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.023-.162-.023-.161-.024-.159-.024-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.032-.146-.032-.145-.033-.143-.034-.141-.034-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.041-.126-.041-.124-.041-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.048-.105-.048-.102-.048-.1-.05-.097-.049-.095-.051-.093-.051-.09-.052-.087-.052-.085-.053-.083-.053-.08-.054-.077-.054v4.153zm8.74-8.179l-.257.004-.254.005-.25.008-.247.011-.244.012-.241.014-.237.016-.233.018-.231.021-.226.022-.224.023-.22.026-.216.027-.212.028-.21.031-.205.032-.202.033-.198.034-.194.036-.191.038-.187.038-.183.04-.179.041-.175.042-.172.043-.168.043-.163.045-.16.046-.155.046-.152.048-.148.048-.143.048-.139.049-.136.05-.131.05-.126.051-.123.051-.118.051-.114.052-.11.052-.106.052-.101.052-.096.052-.092.052-.088.052-.083.052-.079.052-.074.051-.07.052-.065.051-.06.05-.056.05-.051.05-.023.025-.023.024-.021.024-.02.025-.019.024-.018.024-.017.023-.015.024-.014.023-.013.023-.012.023-.01.023-.01.022-.008.022-.006.023-.006.021-.004.022-.004.021-.001.021-.001.021.001.021.001.021.004.021.004.022.006.021.006.023.008.022.01.022.01.023.012.023.013.023.014.023.015.024.017.023.018.024.019.024.02.025.021.024.023.024.023.025.051.05.056.05.06.05.065.051.07.052.074.051.079.052.083.052.088.052.092.052.096.052.101.052.106.052.11.052.114.052.118.051.123.051.126.051.131.05.136.05.139.049.143.048.148.048.152.048.155.046.16.046.163.045.168.043.172.043.175.042.179.041.183.04.187.038.191.038.194.036.198.034.202.033.205.032.21.031.212.028.216.027.22.026.224.023.226.022.231.021.233.018.237.016.241.014.244.012.247.011.25.008.254.005.257.004.26.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.022.224-.023.22-.026.216-.027.212-.028.21-.031.205-.032.202-.033.198-.034.194-.036.191-.038.187-.038.183-.04.179-.041.175-.042.172-.043.168-.043.163-.045.16-.046.155-.046.152-.048.148-.048.143-.048.139-.049.136-.05.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.05.051-.05.023-.025.023-.024.021-.024.02-.025.019-.024.018-.024.017-.023.015-.024.014-.023.013-.023.012-.023.01-.023.01-.022.008-.022.006-.023.006-.021.004-.022.004-.021.001-.021.001-.021-.001-.021-.001-.021-.004-.021-.004-.022-.006-.021-.006-.023-.008-.022-.01-.022-.01-.023-.012-.023-.013-.023-.014-.023-.015-.024-.017-.023-.018-.024-.019-.024-.02-.025-.021-.024-.023-.024-.023-.025-.051-.05-.056-.05-.06-.05-.065-.051-.07-.052-.074-.051-.079-.052-.083-.052-.088-.052-.092-.052-.096-.052-.101-.052-.106-.052-.11-.052-.114-.052-.118-.051-.123-.051-.126-.051-.131-.05-.136-.05-.139-.049-.143-.048-.148-.048-.152-.048-.155-.046-.16-.046-.163-.045-.168-.043-.172-.043-.175-.042-.179-.041-.183-.04-.187-.038-.191-.038-.194-.036-.198-.034-.202-.033-.205-.032-.21-.031-.212-.028-.216-.027-.22-.026-.224-.023-.226-.022-.231-.021-.233-.018-.237-.016-.241-.014-.244-.012-.247-.011-.25-.008-.254-.005-.257-.004-.26-.001-.26.001z"&gt;&lt;/path&gt;&lt;/symbol&gt;&lt;/defs&gt;&lt;defs&gt;&lt;symbol id="dcd14d06924d1858alight-clock" width="24" height="24"&gt;&lt;path transform="scale(.5)" d="M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm5.848 12.459c.202.038.202.333.001.372-1.907.361-6.045 1.111-6.547 1.111-.719 0-1.301-.582-1.301-1.301 0-.512.77-5.447 1.125-7.445.034-.192.312-.181.343.014l.985 6.238 5.394 1.011z"&gt;&lt;/path&gt;&lt;/symbol&gt;&lt;/defs&gt;&lt;defs&gt;&lt;marker id="dcd14d06924d1858alight-arrowhead" refX="7.9" refY="5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto-start-reverse"&gt;&lt;path d="M -1 0 L 10 5 L 0 10 z"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;defs&gt;&lt;marker id="dcd14d06924d1858alight-crosshead" markerWidth="15" markerHeight="8" orient="auto" refX="4" refY="4.5"&gt;&lt;path fill="none" stroke="#000000" stroke-width="1pt" d="M 1,2 L 6,7 M 6,2 L 1,7" style="stroke-dasharray: 0, 0;"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;defs&gt;&lt;marker id="dcd14d06924d1858alight-filled-head" refX="15.5" refY="7" markerWidth="20" markerHeight="28" orient="auto"&gt;&lt;path d="M 18,7 L9,13 L14,7 L9,1 Z"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;defs&gt;&lt;marker id="dcd14d06924d1858alight-sequencenumber" refX="15" refY="15" markerWidth="60" markerHeight="40" orient="auto"&gt;&lt;circle cx="15" cy="15" r="6"&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;defs&gt;&lt;marker id="dcd14d06924d1858alight-solidTopArrowHead" refX="7.9" refY="7.25" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto-start-reverse"&gt;&lt;path d="M 0 0 L 10 8 L 0 8 z"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;defs&gt;&lt;marker id="dcd14d06924d1858alight-solidBottomArrowHead" refX="7.9" refY="0.75" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto-start-reverse"&gt;&lt;path d="M 0 0 L 10 0 L 0 8 z"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;defs&gt;&lt;marker id="dcd14d06924d1858alight-stickTopArrowHead" refX="7.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto-start-reverse"&gt;&lt;path d="M 0 0 L 7 7" stroke="black" stroke-width="1.5" fill="none"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;defs&gt;&lt;marker id="dcd14d06924d1858alight-stickBottomArrowHead" refX="7.5" refY="0" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto-start-reverse"&gt;&lt;path d="M 0 7 L 7 0" stroke="black" stroke-width="1.5" fill="none"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;g data-et="note" data-id="i3"&gt;&lt;rect x="0" y="213" fill="#EDF2AE" stroke="#666" width="150" height="56" class="note"&gt;&lt;/rect&gt;&lt;text x="75" y="218" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="noteText" dy="1em" style="font-size: 16px; font-weight: 400;"&gt;&lt;tspan x="75"&gt;buffer everything&lt;/tspan&gt;&lt;/text&gt;&lt;text x="75" y="236" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="noteText" dy="1em" style="font-size: 16px; font-weight: 400;"&gt;&lt;tspan x="75"&gt;it delivers&lt;/tspan&gt;&lt;/text&gt;&lt;/g&gt;&lt;g data-et="note" data-id="i6"&gt;&lt;rect x="-31.5" y="371" fill="#EDF2AE" stroke="#666" width="213" height="56" class="note"&gt;&lt;/rect&gt;&lt;text x="75" y="376" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="noteText" dy="1em" style="font-size: 16px; font-weight: 400;"&gt;&lt;tspan x="75"&gt;replay buffer, drop&lt;/tspan&gt;&lt;/text&gt;&lt;text x="75" y="394" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="noteText" dy="1em" style="font-size: 16px; font-weight: 400;"&gt;&lt;tspan x="75"&gt;what snapshot already has&lt;/tspan&gt;&lt;/text&gt;&lt;/g&gt;&lt;text x="204" y="80" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;"&gt;ping&lt;/text&gt;&lt;line x1="76" y1="111" x2="332" y2="111" class="messageLine0" data-et="message" data-id="i0" data-from="D" data-to="H" stroke-width="2" stroke="none" marker-end="url(#dcd14d06924d1858alight-arrowhead)" style="fill: none;"&gt;&lt;/line&gt;&lt;text x="207" y="126" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;"&gt;protocol 19&lt;/text&gt;&lt;line x1="335" y1="157" x2="79" y2="157" class="messageLine1" data-et="message" data-id="i1" data-from="H" data-to="D" stroke-width="2" stroke="none" marker-end="url(#dcd14d06924d1858alight-arrowhead)" style="stroke-dasharray: 3, 3; fill: none;"&gt;&lt;/line&gt;&lt;text x="204" y="172" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;"&gt;events.subscribe&lt;/text&gt;&lt;line x1="76" y1="203" x2="332" y2="203" class="messageLine0" data-et="message" data-id="i2" data-from="D" data-to="H" stroke-width="2" stroke="none" marker-end="url(#dcd14d06924d1858alight-arrowhead)" style="fill: none;"&gt;&lt;/line&gt;&lt;text x="204" y="284" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;"&gt;session.snapshot&lt;/text&gt;&lt;line x1="76" y1="315" x2="332" y2="315" class="messageLine0" data-et="message" data-id="i4" data-from="D" data-to="H" stroke-width="2" stroke="none" marker-end="url(#dcd14d06924d1858alight-arrowhead)" style="fill: none;"&gt;&lt;/line&gt;&lt;text x="207" y="330" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;"&gt;panes + seq numbers&lt;/text&gt;&lt;line x1="335" y1="361" x2="79" y2="361" class="messageLine1" data-et="message" data-id="i5" data-from="H" data-to="D" stroke-width="2" stroke="none" marker-end="url(#dcd14d06924d1858alight-arrowhead)" style="stroke-dasharray: 3, 3; fill: none;"&gt;&lt;/line&gt;&lt;text x="204" y="442" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;"&gt;subscribe per-pane status&lt;/text&gt;&lt;line x1="76" y1="473" x2="332" y2="473" class="messageLine0" data-et="message" data-id="i7" data-from="D" data-to="H" stroke-width="2" stroke="none" marker-end="url(#dcd14d06924d1858alight-arrowhead)" style="fill: none;"&gt;&lt;/line&gt;&lt;/svg&gt;&lt;/div&gt;&#10; &lt;div class="not-prose diagram diagram-dark"&gt;&lt;svg id="dcd14d06924d1858adark" width="100%" xmlns="http://www.w3.org/2000/svg" style="max-width: 542.5px;" viewBox="-81.5 -10 542.5 579" role="graphics-document document" aria-roledescription="sequence"&gt;&lt;g&gt;&lt;rect x="261" y="493" fill="#eaeaea" stroke="#666" width="150" height="65" name="H" rx="3" ry="3" class="actor actor-bottom"&gt;&lt;/rect&gt;&lt;text x="336" y="525.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"&gt;&lt;tspan x="336" dy="0"&gt;herdr&lt;/tspan&gt;&lt;/text&gt;&lt;/g&gt;&lt;g&gt;&lt;rect x="0" y="493" fill="#eaeaea" stroke="#666" width="150" height="65" name="D" rx="3" ry="3" class="actor actor-bottom"&gt;&lt;/rect&gt;&lt;text x="75" y="525.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"&gt;&lt;tspan x="75" dy="0"&gt;daemon&lt;/tspan&gt;&lt;/text&gt;&lt;/g&gt;&lt;g&gt;&lt;line id="actor9" x1="336" y1="65" x2="336" y2="493" class="actor-line 200" stroke-width="0.5px" stroke="#999" name="H" data-et="life-line" data-id="H"&gt;&lt;/line&gt;&lt;g id="root-9" data-et="participant" data-type="participant" data-id="H"&gt;&lt;rect x="261" y="0" fill="#eaeaea" stroke="#666" width="150" height="65" name="H" rx="3" ry="3" class="actor actor-top"&gt;&lt;/rect&gt;&lt;text x="336" y="32.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"&gt;&lt;tspan x="336" dy="0"&gt;herdr&lt;/tspan&gt;&lt;/text&gt;&lt;/g&gt;&lt;/g&gt;&lt;g&gt;&lt;line id="actor8" x1="75" y1="65" x2="75" y2="493" class="actor-line 200" stroke-width="0.5px" stroke="#999" name="D" data-et="life-line" data-id="D"&gt;&lt;/line&gt;&lt;g id="root-8" data-et="participant" data-type="participant" data-id="D"&gt;&lt;rect x="0" y="0" fill="#eaeaea" stroke="#666" width="150" height="65" name="D" rx="3" ry="3" class="actor actor-top"&gt;&lt;/rect&gt;&lt;text x="75" y="32.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"&gt;&lt;tspan x="75" dy="0"&gt;daemon&lt;/tspan&gt;&lt;/text&gt;&lt;/g&gt;&lt;/g&gt;&lt;style&gt;#dcd14d06924d1858adark{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,noto sans,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#dcd14d06924d1858adark .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#dcd14d06924d1858adark .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#dcd14d06924d1858adark .error-icon{fill:#a44141;}#dcd14d06924d1858adark .error-text{fill:#ddd;stroke:#ddd;}#dcd14d06924d1858adark .edge-thickness-normal{stroke-width:1px;}#dcd14d06924d1858adark .edge-thickness-thick{stroke-width:3.5px;}#dcd14d06924d1858adark .edge-pattern-solid{stroke-dasharray:0;}#dcd14d06924d1858adark .edge-thickness-invisible{stroke-width:0;fill:none;}#dcd14d06924d1858adark .edge-pattern-dashed{stroke-dasharray:3;}#dcd14d06924d1858adark .edge-pattern-dotted{stroke-dasharray:2;}#dcd14d06924d1858adark .marker{fill:lightgrey;stroke:lightgrey;}#dcd14d06924d1858adark .marker.cross{stroke:lightgrey;}#dcd14d06924d1858adark svg{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,noto sans,sans-serif;font-size:16px;}#dcd14d06924d1858adark p{margin:0;}#dcd14d06924d1858adark .actor{stroke:#ccc;fill:#1f2020;stroke-width:1;}#dcd14d06924d1858adark rect.actor.outer-path[data-look="neo"]{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#dcd14d06924d1858adark rect.note[data-look="neo"]{stroke:hsl(180, 0%, 18.3529411765%);fill:hsl(180, 1.5873015873%, 28.3529411765%);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#dcd14d06924d1858adark text.actor&amp;gt;tspan{fill:lightgrey;stroke:none;}#dcd14d06924d1858adark .actor-line{stroke:#ccc;}#dcd14d06924d1858adark .innerArc{stroke-width:1.5;stroke-dasharray:none;}#dcd14d06924d1858adark .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:lightgrey;}#dcd14d06924d1858adark .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:lightgrey;}#dcd14d06924d1858adark [id$="-arrowhead"] path{fill:lightgrey;stroke:lightgrey;}#dcd14d06924d1858adark .sequenceNumber{fill:black;}#dcd14d06924d1858adark [id$="-sequencenumber"]{fill:lightgrey;}#dcd14d06924d1858adark [id$="-crosshead"] path{fill:lightgrey;stroke:lightgrey;}#dcd14d06924d1858adark .messageText{fill:lightgrey;stroke:none;}#dcd14d06924d1858adark .labelBox{stroke:#ccc;fill:#1f2020;filter:none;}#dcd14d06924d1858adark .labelText,#dcd14d06924d1858adark .labelText&amp;gt;tspan{fill:lightgrey;stroke:none;}#dcd14d06924d1858adark .loopText,#dcd14d06924d1858adark .loopText&amp;gt;tspan{fill:lightgrey;stroke:none;}#dcd14d06924d1858adark .sectionTitle,#dcd14d06924d1858adark .sectionTitle&amp;gt;tspan{fill:lightgrey;stroke:none;}#dcd14d06924d1858adark .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:#ccc;fill:#ccc;}#dcd14d06924d1858adark .note{stroke:hsl(180, 0%, 18.3529411765%);fill:hsl(180, 1.5873015873%, 28.3529411765%);}#dcd14d06924d1858adark .noteText,#dcd14d06924d1858adark .noteText&amp;gt;tspan{fill:rgb(183.8476190475, 181.5523809523, 181.5523809523);stroke:none;font-weight:normal;}#dcd14d06924d1858adark .activation0{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:#ccc;}#dcd14d06924d1858adark .activation1{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:#ccc;}#dcd14d06924d1858adark .activation2{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:#ccc;}#dcd14d06924d1858adark .actorPopupMenu{position:absolute;}#dcd14d06924d1858adark .actorPopupMenuPanel{position:absolute;fill:#1f2020;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#dcd14d06924d1858adark .actor-man circle,#dcd14d06924d1858adark line{fill:#1f2020;stroke-width:2px;}#dcd14d06924d1858adark g rect.rect{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));stroke:#ccc;}#dcd14d06924d1858adark .node .neo-node{stroke:#ccc;}#dcd14d06924d1858adark [data-look="neo"].node rect,#dcd14d06924d1858adark [data-look="neo"].cluster rect,#dcd14d06924d1858adark [data-look="neo"].node polygon{stroke:url(#dcd14d06924d1858adark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#dcd14d06924d1858adark [data-look="neo"].swimlane.cluster rect{filter:none;}#dcd14d06924d1858adark [data-look="neo"].node path{stroke:url(#dcd14d06924d1858adark-gradient);stroke-width:1px;}#dcd14d06924d1858adark [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#dcd14d06924d1858adark [data-look="neo"].node .neo-line path{stroke:#ccc;filter:none;}#dcd14d06924d1858adark [data-look="neo"].node circle{stroke:url(#dcd14d06924d1858adark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#dcd14d06924d1858adark [data-look="neo"].node circle .state-start{fill:#000000;}#dcd14d06924d1858adark [data-look="neo"].icon-shape .icon{fill:url(#dcd14d06924d1858adark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#dcd14d06924d1858adark [data-look="neo"].icon-shape .icon-neo path{stroke:url(#dcd14d06924d1858adark-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#dcd14d06924d1858adark :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}&lt;/style&gt;&lt;g&gt;&lt;/g&gt;&lt;defs&gt;&lt;symbol id="dcd14d06924d1858adark-computer" width="24" height="24"&gt;&lt;path transform="scale(.5)" d="M2 2v13h20v-13h-20zm18 11h-16v-9h16v9zm-10.228 6l.466-1h3.524l.467 1h-4.457zm14.228 3h-24l2-6h2.104l-1.33 4h18.45l-1.297-4h2.073l2 6zm-5-10h-14v-7h14v7z"&gt;&lt;/path&gt;&lt;/symbol&gt;&lt;/defs&gt;&lt;defs&gt;&lt;symbol id="dcd14d06924d1858adark-database" fill-rule="evenodd" clip-rule="evenodd"&gt;&lt;path transform="scale(.5)" d="M12.258.001l.256.004.255.005.253.008.251.01.249.012.247.015.246.016.242.019.241.02.239.023.236.024.233.027.231.028.229.031.225.032.223.034.22.036.217.038.214.04.211.041.208.043.205.045.201.046.198.048.194.05.191.051.187.053.183.054.18.056.175.057.172.059.168.06.163.061.16.063.155.064.15.066.074.033.073.033.071.034.07.034.069.035.068.035.067.035.066.035.064.036.064.036.062.036.06.036.06.037.058.037.058.037.055.038.055.038.053.038.052.038.051.039.05.039.048.039.047.039.045.04.044.04.043.04.041.04.04.041.039.041.037.041.036.041.034.041.033.042.032.042.03.042.029.042.027.042.026.043.024.043.023.043.021.043.02.043.018.044.017.043.015.044.013.044.012.044.011.045.009.044.007.045.006.045.004.045.002.045.001.045v17l-.001.045-.002.045-.004.045-.006.045-.007.045-.009.044-.011.045-.012.044-.013.044-.015.044-.017.043-.018.044-.02.043-.021.043-.023.043-.024.043-.026.043-.027.042-.029.042-.03.042-.032.042-.033.042-.034.041-.036.041-.037.041-.039.041-.04.041-.041.04-.043.04-.044.04-.045.04-.047.039-.048.039-.05.039-.051.039-.052.038-.053.038-.055.038-.055.038-.058.037-.058.037-.06.037-.06.036-.062.036-.064.036-.064.036-.066.035-.067.035-.068.035-.069.035-.07.034-.071.034-.073.033-.074.033-.15.066-.155.064-.16.063-.163.061-.168.06-.172.059-.175.057-.18.056-.183.054-.187.053-.191.051-.194.05-.198.048-.201.046-.205.045-.208.043-.211.041-.214.04-.217.038-.22.036-.223.034-.225.032-.229.031-.231.028-.233.027-.236.024-.239.023-.241.02-.242.019-.246.016-.247.015-.249.012-.251.01-.253.008-.255.005-.256.004-.258.001-.258-.001-.256-.004-.255-.005-.253-.008-.251-.01-.249-.012-.247-.015-.245-.016-.243-.019-.241-.02-.238-.023-.236-.024-.234-.027-.231-.028-.228-.031-.226-.032-.223-.034-.22-.036-.217-.038-.214-.04-.211-.041-.208-.043-.204-.045-.201-.046-.198-.048-.195-.05-.19-.051-.187-.053-.184-.054-.179-.056-.176-.057-.172-.059-.167-.06-.164-.061-.159-.063-.155-.064-.151-.066-.074-.033-.072-.033-.072-.034-.07-.034-.069-.035-.068-.035-.067-.035-.066-.035-.064-.036-.063-.036-.062-.036-.061-.036-.06-.037-.058-.037-.057-.037-.056-.038-.055-.038-.053-.038-.052-.038-.051-.039-.049-.039-.049-.039-.046-.039-.046-.04-.044-.04-.043-.04-.041-.04-.04-.041-.039-.041-.037-.041-.036-.041-.034-.041-.033-.042-.032-.042-.03-.042-.029-.042-.027-.042-.026-.043-.024-.043-.023-.043-.021-.043-.02-.043-.018-.044-.017-.043-.015-.044-.013-.044-.012-.044-.011-.045-.009-.044-.007-.045-.006-.045-.004-.045-.002-.045-.001-.045v-17l.001-.045.002-.045.004-.045.006-.045.007-.045.009-.044.011-.045.012-.044.013-.044.015-.044.017-.043.018-.044.02-.043.021-.043.023-.043.024-.043.026-.043.027-.042.029-.042.03-.042.032-.042.033-.042.034-.041.036-.041.037-.041.039-.041.04-.041.041-.04.043-.04.044-.04.046-.04.046-.039.049-.039.049-.039.051-.039.052-.038.053-.038.055-.038.056-.038.057-.037.058-.037.06-.037.061-.036.062-.036.063-.036.064-.036.066-.035.067-.035.068-.035.069-.035.07-.034.072-.034.072-.033.074-.033.151-.066.155-.064.159-.063.164-.061.167-.06.172-.059.176-.057.179-.056.184-.054.187-.053.19-.051.195-.05.198-.048.201-.046.204-.045.208-.043.211-.041.214-.04.217-.038.22-.036.223-.034.226-.032.228-.031.231-.028.234-.027.236-.024.238-.023.241-.02.243-.019.245-.016.247-.015.249-.012.251-.01.253-.008.255-.005.256-.004.258-.001.258.001zm-9.258 20.499v.01l.001.021.003.021.004.022.005.021.006.022.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.023.018.024.019.024.021.024.022.025.023.024.024.025.052.049.056.05.061.051.066.051.07.051.075.051.079.052.084.052.088.052.092.052.097.052.102.051.105.052.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.048.144.049.147.047.152.047.155.047.16.045.163.045.167.043.171.043.176.041.178.041.183.039.187.039.19.037.194.035.197.035.202.033.204.031.209.03.212.029.216.027.219.025.222.024.226.021.23.02.233.018.236.016.24.015.243.012.246.01.249.008.253.005.256.004.259.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.021.224-.024.22-.026.216-.027.212-.028.21-.031.205-.031.202-.034.198-.034.194-.036.191-.037.187-.039.183-.04.179-.04.175-.042.172-.043.168-.044.163-.045.16-.046.155-.046.152-.047.148-.048.143-.049.139-.049.136-.05.131-.05.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.053.083-.051.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.05.023-.024.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.023.01-.022.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.127l-.077.055-.08.053-.083.054-.085.053-.087.052-.09.052-.093.051-.095.05-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.045-.118.044-.12.043-.122.042-.124.042-.126.041-.128.04-.13.04-.132.038-.134.038-.135.037-.138.037-.139.035-.142.035-.143.034-.144.033-.147.032-.148.031-.15.03-.151.03-.153.029-.154.027-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.01-.179.008-.179.008-.181.006-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.006-.179-.008-.179-.008-.178-.01-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.027-.153-.029-.151-.03-.15-.03-.148-.031-.146-.032-.145-.033-.143-.034-.141-.035-.14-.035-.137-.037-.136-.037-.134-.038-.132-.038-.13-.04-.128-.04-.126-.041-.124-.042-.122-.042-.12-.044-.117-.043-.116-.045-.113-.045-.112-.046-.109-.047-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.05-.093-.052-.09-.051-.087-.052-.085-.053-.083-.054-.08-.054-.077-.054v4.127zm0-5.654v.011l.001.021.003.021.004.021.005.022.006.022.007.022.009.022.01.022.011.023.012.023.013.023.015.024.016.023.017.024.018.024.019.024.021.024.022.024.023.025.024.024.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.052.11.051.114.051.119.052.123.05.127.051.131.05.135.049.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.044.171.042.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.022.23.02.233.018.236.016.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.012.241-.015.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.048.139-.05.136-.049.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.051.051-.049.023-.025.023-.024.021-.025.02-.024.019-.024.018-.024.017-.024.015-.023.014-.023.013-.024.012-.022.01-.023.01-.023.008-.022.006-.022.006-.022.004-.021.004-.022.001-.021.001-.021v-4.139l-.077.054-.08.054-.083.054-.085.052-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.044-.118.044-.12.044-.122.042-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.035-.143.033-.144.033-.147.033-.148.031-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.009-.179.009-.179.007-.181.007-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.007-.179-.007-.179-.009-.178-.009-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.031-.146-.033-.145-.033-.143-.033-.141-.035-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.04-.126-.041-.124-.042-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.051-.093-.051-.09-.051-.087-.053-.085-.052-.083-.054-.08-.054-.077-.054v4.139zm0-5.666v.011l.001.02.003.022.004.021.005.022.006.021.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.024.018.023.019.024.021.025.022.024.023.024.024.025.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.051.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.043.171.043.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.021.23.02.233.018.236.017.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.013.241-.014.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.049.139-.049.136-.049.131-.051.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.049.023-.025.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.022.01-.023.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.153l-.077.054-.08.054-.083.053-.085.053-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.048-.105.048-.106.048-.109.046-.111.046-.114.046-.115.044-.118.044-.12.043-.122.043-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.034-.143.034-.144.033-.147.032-.148.032-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.024-.161.024-.162.023-.163.023-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.01-.178.01-.179.009-.179.007-.181.006-.182.006-.182.004-.184.003-.184.001-.185.001-.185-.001-.184-.001-.184-.003-.182-.004-.182-.006-.181-.006-.179-.007-.179-.009-.178-.01-.176-.01-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.023-.162-.023-.161-.024-.159-.024-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.032-.146-.032-.145-.033-.143-.034-.141-.034-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.041-.126-.041-.124-.041-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.048-.105-.048-.102-.048-.1-.05-.097-.049-.095-.051-.093-.051-.09-.052-.087-.052-.085-.053-.083-.053-.08-.054-.077-.054v4.153zm8.74-8.179l-.257.004-.254.005-.25.008-.247.011-.244.012-.241.014-.237.016-.233.018-.231.021-.226.022-.224.023-.22.026-.216.027-.212.028-.21.031-.205.032-.202.033-.198.034-.194.036-.191.038-.187.038-.183.04-.179.041-.175.042-.172.043-.168.043-.163.045-.16.046-.155.046-.152.048-.148.048-.143.048-.139.049-.136.05-.131.05-.126.051-.123.051-.118.051-.114.052-.11.052-.106.052-.101.052-.096.052-.092.052-.088.052-.083.052-.079.052-.074.051-.07.052-.065.051-.06.05-.056.05-.051.05-.023.025-.023.024-.021.024-.02.025-.019.024-.018.024-.017.023-.015.024-.014.023-.013.023-.012.023-.01.023-.01.022-.008.022-.006.023-.006.021-.004.022-.004.021-.001.021-.001.021.001.021.001.021.004.021.004.022.006.021.006.023.008.022.01.022.01.023.012.023.013.023.014.023.015.024.017.023.018.024.019.024.02.025.021.024.023.024.023.025.051.05.056.05.06.05.065.051.07.052.074.051.079.052.083.052.088.052.092.052.096.052.101.052.106.052.11.052.114.052.118.051.123.051.126.051.131.05.136.05.139.049.143.048.148.048.152.048.155.046.16.046.163.045.168.043.172.043.175.042.179.041.183.04.187.038.191.038.194.036.198.034.202.033.205.032.21.031.212.028.216.027.22.026.224.023.226.022.231.021.233.018.237.016.241.014.244.012.247.011.25.008.254.005.257.004.26.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.022.224-.023.22-.026.216-.027.212-.028.21-.031.205-.032.202-.033.198-.034.194-.036.191-.038.187-.038.183-.04.179-.041.175-.042.172-.043.168-.043.163-.045.16-.046.155-.046.152-.048.148-.048.143-.048.139-.049.136-.05.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.05.051-.05.023-.025.023-.024.021-.024.02-.025.019-.024.018-.024.017-.023.015-.024.014-.023.013-.023.012-.023.01-.023.01-.022.008-.022.006-.023.006-.021.004-.022.004-.021.001-.021.001-.021-.001-.021-.001-.021-.004-.021-.004-.022-.006-.021-.006-.023-.008-.022-.01-.022-.01-.023-.012-.023-.013-.023-.014-.023-.015-.024-.017-.023-.018-.024-.019-.024-.02-.025-.021-.024-.023-.024-.023-.025-.051-.05-.056-.05-.06-.05-.065-.051-.07-.052-.074-.051-.079-.052-.083-.052-.088-.052-.092-.052-.096-.052-.101-.052-.106-.052-.11-.052-.114-.052-.118-.051-.123-.051-.126-.051-.131-.05-.136-.05-.139-.049-.143-.048-.148-.048-.152-.048-.155-.046-.16-.046-.163-.045-.168-.043-.172-.043-.175-.042-.179-.041-.183-.04-.187-.038-.191-.038-.194-.036-.198-.034-.202-.033-.205-.032-.21-.031-.212-.028-.216-.027-.22-.026-.224-.023-.226-.022-.231-.021-.233-.018-.237-.016-.241-.014-.244-.012-.247-.011-.25-.008-.254-.005-.257-.004-.26-.001-.26.001z"&gt;&lt;/path&gt;&lt;/symbol&gt;&lt;/defs&gt;&lt;defs&gt;&lt;symbol id="dcd14d06924d1858adark-clock" width="24" height="24"&gt;&lt;path transform="scale(.5)" d="M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm5.848 12.459c.202.038.202.333.001.372-1.907.361-6.045 1.111-6.547 1.111-.719 0-1.301-.582-1.301-1.301 0-.512.77-5.447 1.125-7.445.034-.192.312-.181.343.014l.985 6.238 5.394 1.011z"&gt;&lt;/path&gt;&lt;/symbol&gt;&lt;/defs&gt;&lt;defs&gt;&lt;marker id="dcd14d06924d1858adark-arrowhead" refX="7.9" refY="5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto-start-reverse"&gt;&lt;path d="M -1 0 L 10 5 L 0 10 z"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;defs&gt;&lt;marker id="dcd14d06924d1858adark-crosshead" markerWidth="15" markerHeight="8" orient="auto" refX="4" refY="4.5"&gt;&lt;path fill="none" stroke="#000000" stroke-width="1pt" d="M 1,2 L 6,7 M 6,2 L 1,7" style="stroke-dasharray: 0, 0;"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;defs&gt;&lt;marker id="dcd14d06924d1858adark-filled-head" refX="15.5" refY="7" markerWidth="20" markerHeight="28" orient="auto"&gt;&lt;path d="M 18,7 L9,13 L14,7 L9,1 Z"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;defs&gt;&lt;marker id="dcd14d06924d1858adark-sequencenumber" refX="15" refY="15" markerWidth="60" markerHeight="40" orient="auto"&gt;&lt;circle cx="15" cy="15" r="6"&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;defs&gt;&lt;marker id="dcd14d06924d1858adark-solidTopArrowHead" refX="7.9" refY="7.25" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto-start-reverse"&gt;&lt;path d="M 0 0 L 10 8 L 0 8 z"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;defs&gt;&lt;marker id="dcd14d06924d1858adark-solidBottomArrowHead" refX="7.9" refY="0.75" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto-start-reverse"&gt;&lt;path d="M 0 0 L 10 0 L 0 8 z"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;defs&gt;&lt;marker id="dcd14d06924d1858adark-stickTopArrowHead" refX="7.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto-start-reverse"&gt;&lt;path d="M 0 0 L 7 7" stroke="black" stroke-width="1.5" fill="none"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;defs&gt;&lt;marker id="dcd14d06924d1858adark-stickBottomArrowHead" refX="7.5" refY="0" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto-start-reverse"&gt;&lt;path d="M 0 7 L 7 0" stroke="black" stroke-width="1.5" fill="none"&gt;&lt;/path&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;g data-et="note" data-id="i3"&gt;&lt;rect x="0" y="213" fill="#EDF2AE" stroke="#666" width="150" height="56" class="note"&gt;&lt;/rect&gt;&lt;text x="75" y="218" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="noteText" dy="1em" style="font-size: 16px; font-weight: 400;"&gt;&lt;tspan x="75"&gt;buffer everything&lt;/tspan&gt;&lt;/text&gt;&lt;text x="75" y="236" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="noteText" dy="1em" style="font-size: 16px; font-weight: 400;"&gt;&lt;tspan x="75"&gt;it delivers&lt;/tspan&gt;&lt;/text&gt;&lt;/g&gt;&lt;g data-et="note" data-id="i6"&gt;&lt;rect x="-31.5" y="371" fill="#EDF2AE" stroke="#666" width="213" height="56" class="note"&gt;&lt;/rect&gt;&lt;text x="75" y="376" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="noteText" dy="1em" style="font-size: 16px; font-weight: 400;"&gt;&lt;tspan x="75"&gt;replay buffer, drop&lt;/tspan&gt;&lt;/text&gt;&lt;text x="75" y="394" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="noteText" dy="1em" style="font-size: 16px; font-weight: 400;"&gt;&lt;tspan x="75"&gt;what snapshot already has&lt;/tspan&gt;&lt;/text&gt;&lt;/g&gt;&lt;text x="204" y="80" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;"&gt;ping&lt;/text&gt;&lt;line x1="76" y1="111" x2="332" y2="111" class="messageLine0" data-et="message" data-id="i0" data-from="D" data-to="H" stroke-width="2" stroke="none" marker-end="url(#dcd14d06924d1858adark-arrowhead)" style="fill: none;"&gt;&lt;/line&gt;&lt;text x="207" y="126" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;"&gt;protocol 19&lt;/text&gt;&lt;line x1="335" y1="157" x2="79" y2="157" class="messageLine1" data-et="message" data-id="i1" data-from="H" data-to="D" stroke-width="2" stroke="none" marker-end="url(#dcd14d06924d1858adark-arrowhead)" style="stroke-dasharray: 3, 3; fill: none;"&gt;&lt;/line&gt;&lt;text x="204" y="172" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;"&gt;events.subscribe&lt;/text&gt;&lt;line x1="76" y1="203" x2="332" y2="203" class="messageLine0" data-et="message" data-id="i2" data-from="D" data-to="H" stroke-width="2" stroke="none" marker-end="url(#dcd14d06924d1858adark-arrowhead)" style="fill: none;"&gt;&lt;/line&gt;&lt;text x="204" y="284" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;"&gt;session.snapshot&lt;/text&gt;&lt;line x1="76" y1="315" x2="332" y2="315" class="messageLine0" data-et="message" data-id="i4" data-from="D" data-to="H" stroke-width="2" stroke="none" marker-end="url(#dcd14d06924d1858adark-arrowhead)" style="fill: none;"&gt;&lt;/line&gt;&lt;text x="207" y="330" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;"&gt;panes + seq numbers&lt;/text&gt;&lt;line x1="335" y1="361" x2="79" y2="361" class="messageLine1" data-et="message" data-id="i5" data-from="H" data-to="D" stroke-width="2" stroke="none" marker-end="url(#dcd14d06924d1858adark-arrowhead)" style="stroke-dasharray: 3, 3; fill: none;"&gt;&lt;/line&gt;&lt;text x="204" y="442" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;"&gt;subscribe per-pane status&lt;/text&gt;&lt;line x1="76" y1="473" x2="332" y2="473" class="messageLine0" data-et="message" data-id="i7" data-from="D" data-to="H" stroke-width="2" stroke="none" marker-end="url(#dcd14d06924d1858adark-arrowhead)" style="fill: none;"&gt;&lt;/line&gt;&lt;/svg&gt;&lt;/div&gt;&#10;&lt;p&gt;Buffered events are either already reflected in the snapshot or strictly newer than it, and &lt;code&gt;state_change_seq&lt;/code&gt; tells you which. Replayed events carrying no sequence number get dropped whenever the pane is already cached, and applied only when they describe something the snapshot missed, such as a pane created after it was taken.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;When the recovery mechanism prevents recovery&#10; &lt;div id="when-the-recovery-mechanism-prevents-recovery" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#when-the-recovery-mechanism-prevents-recovery" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;On a busy session the daemon reconnected 24 times in 12 seconds.&lt;/p&gt;&#10;&lt;p&gt;The cause is the all-or-nothing subscription rule meeting reality. Short-lived panes, popups and plugin panes, routinely vanish between their &lt;code&gt;pane_created&lt;/code&gt; event and the resubscribe that event triggers. herdr fails the entire subscribe batch when one &lt;code&gt;pane_id&lt;/code&gt; in it is stale. Tearing down the connection on that failure and reconnecting rebuilds the identical doomed batch, which fails identically, which tears down the connection.&lt;/p&gt;&#10;&lt;p&gt;An endless &lt;code&gt;online&lt;/code&gt; to &lt;code&gt;connecting&lt;/code&gt; flap, in which the recovery mechanism was the only thing preventing recovery.&lt;/p&gt;&#10;&lt;p&gt;The fix prunes the vanished pane out of the cache and retries, bounded:&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/** Bound on per-open prune retries, so a pathological server can&amp;#39;t spin&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * this loop forever. */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MAX_STALE_PANE_PRUNES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;stalePaneId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;: &lt;span class="kt"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;HerdrApiError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;pane_not_found&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sr"&gt;/pane (\S+) not found/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Reconnects went from 24 in 12 seconds to one.&lt;/p&gt;&#10;&lt;p&gt;The bound matters more than the prune. Retry-until-it-works against a server that will never agree is the same flap with extra steps, so the loop gives up after eight prunes and throws with a message naming the count. A recovery path that cannot fail is not a recovery path.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;What it came to&#10; &lt;div id="what-it-came-to" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#what-it-came-to" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;Four days, 36 commits on &lt;code&gt;main&lt;/code&gt;, 35 of them merged through pull requests behind seven required checks. Four packages, 504 tests across 32 files, and close to one line of test for every line of source, which was not a target so much as a description of where the difficulty lived.&lt;/p&gt;&#10;&lt;p&gt;The difficulty did not live in the Stream Deck. It lived in the seam.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Lessons&#10; &lt;div id="lessons" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#lessons" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Changing the substrate is a deletion strategy. If a dependency already tracks the thing you are inferring, the win is measured in subsystems removed, not features added.&lt;/li&gt;&#10;&lt;li&gt;Ask what a protocol costs before you claim it saved you something. Event naming, connection lifetime and subscription granularity are the parts no schema documents and the parts you will actually pay for.&lt;/li&gt;&#10;&lt;li&gt;Subscribe first and buffer, then snapshot, then replay against the sequence numbers. Snapshot-then-subscribe drops transitions and subscribe-then-snapshot double counts.&lt;/li&gt;&#10;&lt;li&gt;If one bad id fails a whole batch, reconnecting rebuilds the same bad batch. Prune the offending item and retry, bounded, or the recovery path becomes the outage.&lt;/li&gt;&#10;&lt;li&gt;Building on a tool you are still evaluating makes the evaluation harder to fail. Write down that you did it, because sunk cost will not remind you later.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&#10;&lt;h2 class="relative group"&gt;References&#10; &lt;div id="references" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#references" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;herdr: &lt;a href="https://herdr.dev" target="_blank" rel="noreferrer"&gt;https://herdr.dev&lt;/a&gt; (source: &lt;a href="https://github.com/herdrdev/herdr" target="_blank" rel="noreferrer"&gt;https://github.com/herdrdev/herdr&lt;/a&gt;)&lt;/li&gt;&#10;&lt;li&gt;HerdDeck: &lt;a href="https://github.com/nickboy/herddeck" target="_blank" rel="noreferrer"&gt;https://github.com/nickboy/herddeck&lt;/a&gt;. Engineering notes, including the protocol behaviour above, in &lt;a href="https://github.com/nickboy/herddeck/blob/main/docs/engineering-notes.md" target="_blank" rel="noreferrer"&gt;&lt;code&gt;docs/engineering-notes.md&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;ClaudeDeck, the predecessor: &lt;a href="https://github.com/nickboy/claudedeck" target="_blank" rel="noreferrer"&gt;https://github.com/nickboy/claudedeck&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;The herdr trial this rebuild jumped ahead of: &lt;a href="https://nick-liu.com/posts/herdr-trial-agent-multiplexer/" &gt;Running six agents made tab patrol my biggest time sink. So: a herdr trial.&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;The hook layer HerdDeck deleted: &lt;a href="https://nick-liu.com/posts/claude-code-hooks-reality/" &gt;The Claude Code hooks docs are wrong. Here&amp;rsquo;s what&amp;rsquo;s actually on the wire.&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;The PTY runner HerdDeck deleted: &lt;a href="https://nick-liu.com/posts/pty-wrap-migration/" &gt;I split my daemon in two so a Node subprocess could own the PTY&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;The codesigning and TCC path HerdDeck deleted: &lt;a href="https://nick-liu.com/posts/tcc-cdhash-trap/" &gt;TCC pins your Accessibility grant to a cdhash. Every rebuild breaks it.&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</content:encoded></item></channel></rss>