<div class="xvor">
<p class="xvor-lede">An agent decides its own next step. Nothing in that sentence decides which agents exist, what runs first, what one of them learned that the others don't know, or whether the finished answer is true. That gap is orchestration.</p>
<p>Agent projects rarely fail because the model was too weak. They fail because three agents were pointed at one goal, two did the same scrape, one quietly died, and the report was written from two thirds of the evidence in a confident voice — with nothing in the logs, because nothing errored.</p>
<div class="xvor-answer">
<p class="xvor-answer-label">The short answer</p>
<p class="xvor-answer-body"><strong>Orchestration is the layer that turns agents into a system.</strong> It decides which agents exist, what runs concurrently, what they share, what happens when one crashes, what gets verified before anything leaves, and when to stop. An agent can only reason about its own context, so every one of those decisions is invisible to it. <strong>The orchestrator is not a smarter agent. It is the only thing that can see the run.</strong></p>
</div>
<nav class="xvor-toc" aria-label="Contents">
<p class="xvor-toc-label">Contents</p>
<ol>
<li><a href="#what-is-orchestration">What orchestration actually is</a></li>
<li><a href="#the-blind-spot">The blind spot</a></li>
<li><a href="#six-jobs">The six jobs of an orchestrator</a></li>
<li><a href="#shared-state">What a blackboard changes</a></li>
<li><a href="#the-run">The same mission, run twice</a></li>
<li><a href="#not-orchestration">Three things that aren't orchestration</a></li>
<li><a href="#one-agent">Even one agent needs it</a></li>
<li><a href="#checklist">Is it a real orchestrator?</a></li>
<li><a href="#how-xorviex-works">How Xorviex orchestrates</a></li>
<li><a href="#faq">Frequently asked questions</a></li>
</ol>
</nav>
<div class="xvor-chapter xvor-reveal">
<p class="xvor-eyebrow">The Definition</p>
<h2 class="xvor-statement" id="what-is-orchestration">Agents decide steps.<br>Something decides the <em>run</em>.</h2>
<p>An agent's competence lives in one loop: look at my context, pick a tool, see the real result, pick again. That loop has exactly one horizon — the agent's own transcript.</p>
<p>Real work doesn't fit in that horizon. It has parts that could run at once, parts that must wait, evidence one worker gathers and another needs, and a definition of done no single worker can declare.</p>
<blockquote class="xvor-quote">A group of agents is not a system. It's a group. The difference between the two is the whole job.</blockquote>
<p>Orchestration is not a bigger prompt, a framework you import, or one agent told to be the manager. It is a control layer that holds state the agents can't hold and enforces limits they have no incentive to respect.</p>
</div>
<div class="xvor-chapter xvor-reveal">
<p class="xvor-eyebrow">The Reason</p>
<h2 class="xvor-statement" id="the-blind-spot">It cannot see<br>the thing it's <em>in</em>.</h2>
<p>The temptation is to solve this with the model: a better prompt, told to plan carefully and check itself. It fails for a structural reason no prompt reaches.</p>
<div class="xvor-split">
<div class="xvor-split-col">
<p class="xvor-split-label">What an agent can see</p>
<p class="xvor-stag">Its goal, as written.</p>
<p class="xvor-stag">Its own transcript, so far.</p>
<p class="xvor-stag">The result of the tool it just called.</p>
</div>
<div class="xvor-split-divider"></div>
<div class="xvor-split-col xvor-split-col--other">
<p class="xvor-split-label">What only the orchestrator can see</p>
<p class="xvor-stag">Which agents exist, and why.</p>
<p class="xvor-stag">What every peer has already found.</p>
<p class="xvor-stag">That an agent stopped producing turns.</p>
<p class="xvor-stag">Total time, total spend, total turns.</p>
<p class="xvor-stag">Whether the result answers the goal.</p>
</div>
</div>
<p>An agent is also the worst judge of its own output — it has already rationalized what it guessed at, so self-review returns agreement. A stronger model makes better <em>steps</em>; it does not gain sight of a run it is one participant in.</p>
</div>
<div class="xvor-chapter xvor-reveal">
<p class="xvor-eyebrow">Anatomy</p>
<h2 class="xvor-statement" id="six-jobs">Six jobs.<br>Skip one and it <em>shows</em>.</h2>
<p>Six responsibilities get bundled under one word. Every production incident with agents traces back to one of them being absent.</p>
<div class="xvor-jobs-wrap" id="xvor-jobs">
<div class="xvor-rail"><div class="xvor-rail-fill" id="xvor-rail-fill"></div></div>
<ol class="xvor-jobs">
<li class="xvor-job">
<span class="xvor-job-dot">01</span>
<h3 class="xvor-job-name">Planning — who exists at all</h3>
<p>How many agents this goal needs, and what each is for. A shape derived from the job, not a cast picked in advance.</p>
<p class="xvor-job-miss"><span class="xvor-miss-label">With nothing doing it</span>The team fits the last job you had — four agents on work that needed one.</p>
</li>
<li class="xvor-job">
<span class="xvor-job-dot">02</span>
<h3 class="xvor-job-name">Dispatch — who runs, and when</h3>
<p>Starting what can start, holding what depends on a result, running independent work concurrently.</p>
<p class="xvor-job-miss"><span class="xvor-miss-label">With nothing doing it</span>Six slow lookups that could have overlapped are paid end to end, and the run times out mid-way.</p>
</li>
<li class="xvor-job">
<span class="xvor-job-dot">03</span>
<h3 class="xvor-job-name">Shared state — what one knows, all use</h3>
<p>A place agents read and write during the run, so a peer's finding is there when another needs it.</p>
<p class="xvor-job-miss"><span class="xvor-miss-label">With nothing doing it</span>Two agents repeat the same lookup, or reach different conclusions from one source and nothing reconciles them.</p>
</li>
<li class="xvor-job">
<span class="xvor-job-dot">04</span>
<h3 class="xvor-job-name">Failure handling — noticing what stopped</h3>
<p>Watching for crashes, stalls and silence, then choosing between retry, alert and escalate.</p>
<p class="xvor-job-miss"><span class="xvor-miss-label">With nothing doing it</span>An agent exits at turn nine. Nothing errors, so nothing alerts, and the mission is marked finished with a hole in it.</p>
</li>
<li class="xvor-job">
<span class="xvor-job-dot">05</span>
<h3 class="xvor-job-name">Verification — checking before it leaves</h3>
<p>An independent model that did not do the work judging the result against the goal, with a real path back.</p>
<p class="xvor-job-miss"><span class="xvor-miss-label">With nothing doing it</span>The only reviewer is the author. Partial answers go out reading like complete ones.</p>
</li>
<li class="xvor-job">
<span class="xvor-job-dot">06</span>
<h3 class="xvor-job-name">Limits — knowing when to stop</h3>
<p>Caps on turns, time and spend, plus metering, so a run's cost is a number instead of a surprise.</p>
<p class="xvor-job-miss"><span class="xvor-miss-label">With nothing doing it</span>A retry loop is the cheapest way to spend a lot of money slowly. The stopping condition becomes the invoice.</p>
</li>
</ol>
</div>
<p>Two are assumed to be free and aren't. <strong>Failure handling means noticing</strong> — agents rarely crash loudly, they go quiet, and something outside has to watch for the absence. And <strong>shared state is not the transcript</strong>, which is the next section.</p>
</div>
<div class="xvor-chapter xvor-reveal">
<p class="xvor-eyebrow">The Blackboard</p>
<h2 class="xvor-statement" id="shared-state">A hand-off is not<br><em>memory</em>.</h2>
<p>Pasting agent A's final message into agent B's prompt feels like sharing. It is one-directional, happens once, and carries what A chose to summarize rather than what A found. Every hop loses the detail the last step didn't mention.</p>
<figure class="xvor-fig">
<p class="xvor-fig-label">Chain — findings thin out at every hop</p>
<svg class="xvor-svg" viewBox="0 0 700 104" role="img" aria-label="Three agents in a chain, each passing a shorter summary to the next, ending in a thin result">
<g class="xvor-node"><rect x="2" y="26" width="122" height="52" rx="6"/><text x="63" y="49">a1</text><text x="63" y="66" class="xvor-sub">full findings</text></g>
<g class="xvor-node"><rect x="222" y="26" width="122" height="52" rx="6"/><text x="283" y="49">a2</text><text x="283" y="66" class="xvor-sub">a1's summary</text></g>
<g class="xvor-node"><rect x="442" y="26" width="122" height="52" rx="6"/><text x="503" y="49">a3</text><text x="503" y="66" class="xvor-sub">a summary of that</text></g>
<path class="xvor-flow xvor-flow--lossy" d="M124 52 H222"/>
<path class="xvor-flow xvor-flow--lossy" d="M344 52 H442"/>
<path class="xvor-flow xvor-flow--lossy" d="M564 52 H648"/>
<text x="698" y="56" class="xvor-lossy-out">result</text>
</svg>
</figure>
<p>Real shared state is a place both read and write <em>while the run is going</em>, so B sees A's finding as evidence rather than a paragraph about the evidence. Nothing is re-derived, nothing arrives pre-flattened.</p>
<figure class="xvor-fig">
<p class="xvor-fig-label">Blackboard — everyone writes, everyone reads</p>
<svg class="xvor-svg" viewBox="0 0 700 230" role="img" aria-label="Three agents writing findings into a shared mission memory that an analyst reads from">
<g class="xvor-node"><rect x="2" y="14" width="120" height="44" rx="6"/><text x="62" y="41">a1</text></g>
<g class="xvor-node"><rect x="2" y="93" width="120" height="44" rx="6"/><text x="62" y="120">a2</text></g>
<g class="xvor-node"><rect x="2" y="172" width="120" height="44" rx="6"/><text x="62" y="199">a3</text></g>
<path class="xvor-flow xvor-flow--in" d="M122 36 C 200 36, 210 96, 278 108"/>
<path class="xvor-flow xvor-flow--in" d="M122 115 H278"/>
<path class="xvor-flow xvor-flow--in" d="M122 194 C 200 194, 210 134, 278 122"/>
<g class="xvor-board"><rect x="278" y="79" width="152" height="72" rx="8"/><text x="354" y="110">shared</text><text x="354" y="128">mission memory</text></g>
<path class="xvor-flow xvor-flow--out" d="M430 115 H556"/>
<g class="xvor-node xvor-node--good"><rect x="556" y="93" width="142" height="44" rx="6"/><text x="627" y="120">analyst</text></g>
</svg>
<figcaption>Peers write findings as they land; anything that needs them reads the real payload rather than a retelling.</figcaption>
</figure>
</div>
<div class="xvor-chapter xvor-reveal">
<p class="xvor-eyebrow">The Mechanism</p>
<h2 class="xvor-statement" id="the-run">Same goal.<br>Same models. Two <em>results</em>.</h2>
<p>One mission — compare three competitors' pricing and produce a table — given to the same three agents, the same loop, the same model. The only variable is whether anything is orchestrating them.</p>
<div class="xvor-runs" id="xvor-runs">
<div class="xvor-run-col">
<p class="xvor-run-head">Without an orchestrator</p>
<ul class="xvor-trace-list" id="xvor-trace-0"></ul>
<p class="xvor-trace-status" id="xvor-status-0">running…</p>
</div>
<div class="xvor-run-col xvor-run-col--good">
<p class="xvor-run-head">The same agents, orchestrated</p>
<ul class="xvor-trace-list" id="xvor-trace-1"></ul>
<p class="xvor-trace-status" id="xvor-status-1">running…</p>
</div>
</div>
<p><strong>Nothing in the left column is a bug.</strong> Every agent behaved correctly given what it could see. <span class="xvor-inline-code">a2</span> repeated <span class="xvor-inline-code">a1</span>'s search because it couldn't know it had been done; <span class="xvor-inline-code">a3</span> stopped because nothing watched for its silence; the report covered two of three competitors and said so nowhere.</p>
<p>It costs more, takes longer, and is wrong in a way you can't detect by reading it. The right-hand run differs in four places: the team came from the goal, two agents ran at once, findings landed where peers could read them, and the deliverable was judged by something that hadn't produced it — the only reason the gap was caught.</p>
</div>
<div class="xvor-chapter xvor-reveal">
<p class="xvor-eyebrow">The Confusion</p>
<h2 class="xvor-statement" id="not-orchestration">Three things<br>wearing the <em>word</em>.</h2>
<p>Most systems called orchestrated are one of the first three. Each is useful, and each is missing a specific job — which tells you what will go wrong.</p>
<div class="xvor-cards">
<div class="xvor-card">
<p class="xvor-card-kind">Prompt chain</p>
<p class="xvor-card-verdict">Output A becomes prompt B</p>
<p>A pipeline of summaries. Every hand-off loses what the previous step didn't think to mention, and the loss compounds silently.</p>
<p class="xvor-card-miss"><span class="xvor-miss-label">Missing</span>Shared state, failure handling, verification. A failed step still produces text, and the text flows onward as a finding.</p>
</div>
<div class="xvor-card">
<p class="xvor-card-kind">Fixed DAG / workflow</p>
<p class="xvor-card-verdict">A graph someone drew</p>
<p>Good engineering, and the right answer whenever the procedure is genuinely known in advance. The shape was decided before the run, by a person.</p>
<p class="xvor-card-miss"><span class="xvor-miss-label">Missing</span>Planning. Every job gets the shape you drew last quarter.</p>
</div>
<div class="xvor-card">
<p class="xvor-card-kind">A "manager" agent</p>
<p class="xvor-card-verdict">An agent reading self-reports</p>
<p>It feels like orchestration and inherits the blind spot: its view of its workers is whatever the workers said about themselves.</p>
<p class="xvor-card-miss"><span class="xvor-miss-label">Missing</span>Failure handling, limits, verification. A silent worker reports nothing, a fabricating one reports confidently, and the manager summarizes both into a clean status.</p>
</div>
<div class="xvor-card xvor-card--good">
<p class="xvor-card-kind">An orchestrator</p>
<p class="xvor-card-verdict">Trusted code holding the run</p>
<p>State the agents can't hold, a view of workers that doesn't rely on self-reports, an audit by something that didn't do the work, and caps that need nobody's cooperation. A model decides the plan — as one input, not as the thing in charge.</p>
<p class="xvor-card-miss xvor-card-miss--good"><span class="xvor-miss-label">Costs</span>Overhead, bought back as a result you can trust without reading every turn.</p>
</div>
</div>
<p>A model can help orchestrate — deciding the team is a good use of one. But it has to be called by trusted code that holds the state and enforces the caps, not the other way around.</p>
</div>
<div class="xvor-chapter xvor-reveal">
<p class="xvor-eyebrow">The Surprise</p>
<h2 class="xvor-statement" id="one-agent">One agent needs<br>this <em>too</em>.</h2>
<p>Four of the six jobs apply just as hard to a single agent. Skipping them is why solo deployments fail in production after passing every demo.</p>
<ul class="xvor-list">
<li><strong>Failure handling.</strong> One agent can stall or exit at turn nine. If nothing notices, the mission is marked finished with a partial answer.</li>
<li><strong>Verification.</strong> One agent grading itself is the same non-check it is with ten.</li>
<li><strong>Limits.</strong> A solo agent in a retry loop is the cheapest way to spend a lot of money slowly.</li>
<li><strong>Durable state.</strong> Even alone, its context degrades as tool results pile up. Notes it can re-read outlive what gets crowded out.</li>
</ul>
<p>Only planning and dispatch are genuinely about having more than one agent. <a href="/blog/single-agent-vs-multi-agent">Agent count</a> is a separate decision — you need orchestration either way.</p>
</div>
<div class="xvor-chapter xvor-reveal">
<p class="xvor-eyebrow">In Practice</p>
<h2 class="xvor-statement" id="checklist">Six questions<br>worth <em>asking</em>.</h2>
<p>Whatever you're building or buying, these answers tell you which jobs are covered. Vague answers are answers.</p>
<div class="xvor-parts">
<div class="xvor-part">
<p class="xvor-part-name">Who decided there would be four agents?</p>
<p>"We designed it that way" means the team is fixed. "The goal did" means planning exists.</p>
</div>
<div class="xvor-part">
<p class="xvor-part-name">Can two of them run at the same time?</p>
<p>If everything is a line, every slow wait is paid end to end — often the difference between finishing and timing out.</p>
</div>
<div class="xvor-part">
<p class="xvor-part-name">Where does agent A's finding live?</p>
<p>"In agent B's prompt" is a hand-off. The useful answer names a place both of them read and write.</p>
</div>
<div class="xvor-part">
<p class="xvor-part-name">What happens if one stops responding?</p>
<p>If someone reads logs later, there is no failure handling. Look for the crash recorded as a fact, and a rule that acts on it.</p>
</div>
<div class="xvor-part">
<p class="xvor-part-name">Who checks the output — and did they do the work?</p>
<p>Self-review is not review. The check must come from something that didn't produce the thing.</p>
</div>
<div class="xvor-part">
<p class="xvor-part-name">What does one run cost, and what stops it?</p>
<p>If neither number exists, the stopping condition is "someone notices" — the most expensive failure mode here.</p>
</div>
</div>
</div>
<div class="xvor-chapter xvor-reveal">
<p class="xvor-eyebrow">Ours</p>
<h2 class="xvor-statement" id="how-xorviex-works">The orchestrator<br>is the <em>product</em>.</h2>
<p><a href="/">Xorviex</a> is built on that position: the agents are the easy part. The six jobs map onto six real pieces of the platform.</p>
<ul class="xvor-list">
<li><strong>Planning.</strong> You write a goal in plain language. A planner decides how many agents it needs and what each is for — no fixed cast, no default count.</li>
<li><strong>Dispatch.</strong> Agents spawn as background work with a real lifecycle, so concurrent agents genuinely run concurrently.</li>
<li><strong>Shared state.</strong> The blackboard above: each agent writes its payload into shared mission memory and opens with its peers' real findings, plus notes it can write and read mid-run.</li>
<li><strong>Failure handling.</strong> Every crash becomes a deduplicated incident, and a rule matrix decides: alert, re-run the agent, or escalate to a human instead of burning budget.</li>
<li><strong>Verification.</strong> An independent Supervisor that did not do the work audits every output against the goal. Rejection returns it with feedback; repeated rejection escalates.</li>
<li><strong>Limits.</strong> Every atomic task is metered as one Operation Unit against the launcher's quota, and retry caps are configurable per workspace.</li>
</ul>
<p>Underneath, agents run the ordinary loop from <a href="/blog/what-are-ai-agents">what AI agents actually are</a>, and nothing model-written is ever executed. The engineering is in what decides which loops exist and what is allowed out of them.</p>
</div>
<div class="xvor-chapter xvor-reveal" id="faq">
<p class="xvor-eyebrow">Questions</p>
<h2 class="xvor-statement">The short<br>versions.</h2>
<h3 class="xvor-q">What is agent orchestration?</h3>
<p>The control layer that decides what an individual agent cannot see: which agents exist, what runs concurrently, how findings are shared, what happens when one fails, what gets verified before anything leaves, and what limits stop the run. An agent decides its next step; the orchestrator decides the shape of the run.</p>
<h3 class="xvor-q">Why can't the agent orchestrate itself?</h3>
<p>Its entire view of the world is its own context window. It cannot see what a peer is doing or already found, that a peer has gone silent, how much the run has cost, or whether its own output is correct. It also can't audit its own work, having already rationalized every part of it.</p>
<h3 class="xvor-q">Is a manager agent the same as an orchestrator?</h3>
<p>No. A manager agent sees only what its workers reported about themselves — a silent worker reports nothing, a fabricating one reports confidently. Real orchestration sits in trusted code that holds the state, observes the workers directly, enforces caps, and calls a model as one input rather than handing it control.</p>
<h3 class="xvor-q">Do I need orchestration for a single agent?</h3>
<p>Yes, for four of the six jobs. A solo agent can stall or exit early with nothing noticing, can't grade its own output, can burn money in a retry loop, and degrades as tool results fill its context. Only planning a team and dispatching one are multi-agent concerns.</p>
<h3 class="xvor-q">How is it different from a workflow engine?</h3>
<p>A workflow engine executes a graph a person drew in advance — right when the procedure is known. Orchestration derives the shape of the run from the goal at runtime, including how many workers there are, and manages workers whose steps nobody wrote.</p>
<h3 class="xvor-q">What breaks first without orchestration?</h3>
<p>Duplicated work, usually. The expensive failure comes next: an agent stops producing turns, nothing notices, and the report is written from partial evidence in a confident voice. Nothing errors, so nothing alerts.</p>
<h3 class="xvor-q">Does orchestration make agents slower?</h3>
<p>Usually the opposite. Most of a real run is waiting on slow external work, and orchestration is what lets independent waits overlap. The overhead it adds is small next to a re-run caused by a partial answer nobody caught.</p>
</div>
<div class="xvor-chapter xvor-reveal">
<p class="xvor-eyebrow">The Difference</p>
<h2 class="xvor-statement" id="the-difference">A pile of agents,<br>or a <em>system</em>.</h2>
<div class="xvor-vs">
<div class="xvor-vs-col">
<p class="xvor-vs-label">Agents in a pile</p>
<p class="xvor-stag">A team designed by hand, months ago.</p>
<p class="xvor-stag">Hand-offs of summaries, in a straight line.</p>
<p class="xvor-stag">A crash discovered in the logs, later.</p>
<p class="xvor-stag">Output reviewed by whoever wrote it.</p>
<p class="xvor-stag">Stops when someone notices the spend.</p>
</div>
<div class="xvor-vs-divider"></div>
<div class="xvor-vs-col xvor-vs-col--for">
<p class="xvor-vs-label">Agents in a system</p>
<p class="xvor-stag">A team derived from this goal, this run.</p>
<p class="xvor-stag">Shared findings, read while the work is live.</p>
<p class="xvor-stag">A crash recorded as a fact, and acted on.</p>
<p class="xvor-stag">Output audited by something that didn't produce it.</p>
<p class="xvor-stag">Stops at a defined limit, with a visible bill.</p>
</div>
</div>
<p class="xvor-outro">The right-hand column isn't a maturity model you grow into — it's a layer you either built or didn't. <a href="/">Xorviex</a> is that layer, shipped: a team planned from your goal, agents running concurrently against a shared blackboard, every crash an incident with a rule attached, every output audited by a Supervisor that didn't do the work, every task metered. You write one sentence. <a href="/signup">Start a mission</a> and watch the run, not the turns.</p>
</div>
<p class="xvor-close">The agent decides the next step.<br>Orchestration decides everything else.</p>
</div>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "What is agent orchestration?",
"acceptedAnswer": {
"@type": "Answer",
"text": "The control layer that decides what an individual agent cannot see: which agents exist, what runs concurrently, how findings are shared, what happens when one fails, what gets verified before anything leaves, and what limits stop the run. An agent decides its next step; the orchestrator decides the shape of the run."
}
},
{
"@type": "Question",
"name": "Why can't the agent orchestrate itself?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Its entire view of the world is its own context window. It cannot see what a peer is doing or already found, that a peer has gone silent, how much the run has cost, or whether its own output is correct. It also can't audit its own work, having already rationalized every part of it."
}
},
{
"@type": "Question",
"name": "Is a manager agent the same as an orchestrator?",
"acceptedAnswer": {
"@type": "Answer",
"text": "No. A manager agent sees only what its workers reported about themselves — a silent worker reports nothing, a fabricating one reports confidently. Real orchestration sits in trusted code that holds the state, observes the workers directly, enforces caps, and calls a model as one input rather than handing it control."
}
},
{
"@type": "Question",
"name": "Do I need orchestration for a single agent?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes, for four of the six jobs. A solo agent can stall or exit early with nothing noticing, can't grade its own output, can burn money in a retry loop, and degrades as tool results fill its context. Only planning a team and dispatching one are multi-agent concerns."
}
},
{
"@type": "Question",
"name": "How is it different from a workflow engine?",
"acceptedAnswer": {
"@type": "Answer",
"text": "A workflow engine executes a graph a person drew in advance — right when the procedure is known. Orchestration derives the shape of the run from the goal at runtime, including how many workers there are, and manages workers whose steps nobody wrote."
}
},
{
"@type": "Question",
"name": "What breaks first without orchestration?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Duplicated work, usually. The expensive failure comes next: an agent stops producing turns, nothing notices, and the report is written from partial evidence in a confident voice. Nothing errors, so nothing alerts."
}
},
{
"@type": "Question",
"name": "Does orchestration make agents slower?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Usually the opposite. Most of a real run is waiting on slow external work, and orchestration is what lets independent waits overlap. The overhead it adds is small next to a re-run caused by a partial answer nobody caught."
}
}
]
}
</script>
<style>
.xvor {
--ink: #0a0a0a;
--muted: rgba(10,10,10,0.42);
--faint: rgba(10,10,10,0.24);
--hair: rgba(10,10,10,0.08);
--indigo: #6366f1;
--emerald: #10b981;
--amber: #d97706;
--red: #ef4444;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
color: var(--ink);
/* Self-sufficient base type so this fragment also previews correctly when
opened on its own, not only inside the blog page's .blog-article styles.
Inside the blog these are no-ops: that container is already 720px wide. */
font-size: 15px;
line-height: 1.9;
max-width: 720px;
margin: 0 auto;
}
/* Margin/colour reset for running text only. Deliberately NOT a stronger
descendant selector: .xvor p is (0,1,1) and anything heavier would
out-specify every single-class component rule below. The component rules
that must win over the blog page's own .blog-article p therefore carry
!important on color, same as the sibling posts. */
.xvor p { margin: 0 0 1.35rem; color: var(--muted); }
.xvor strong { color: var(--ink); font-weight: 600; }
/* Emerald is reserved for the display statements — in running body text an
<em> stays ordinary italic emphasis, or paragraphs pick up stray green
words that read as links. */
.xvor p em { font-style: italic; color: inherit; }
.xvor-lede { font-size: 19px; line-height: 1.65; color: var(--ink) !important; letter-spacing: -0.005em; margin-bottom: 1.6rem !important; }
.xvor-lede:first-child { margin-top: 0; }
.xvor-inline-code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.86em; background: rgba(10,10,10,0.05); border-radius: 4px; padding: 0.1em 0.4em; color: rgba(10,10,10,0.62); }
/* ── motion ─────────────────────────────────────────────────────────────────
Everything here is scroll-driven or self-playing. Nothing on this page is
hidden behind a control the reader has to press: the full text is in the
document, and the animation only affects how it arrives. */
.xvor-reveal { opacity: 0; transform: translateY(30px); transition: opacity 1s cubic-bezier(0.22,1,0.36,1), transform 1s cubic-bezier(0.22,1,0.36,1); }
.xvor-reveal.xvor-on { opacity: 1; transform: none; }
/* staggered lines — index set inline as --i by the script */
.xvor-stag { opacity: 0; transform: translateY(14px); transition: opacity 0.7s cubic-bezier(0.22,1,0.36,1), transform 0.7s cubic-bezier(0.22,1,0.36,1); transition-delay: calc(var(--i, 0) * 90ms); }
.xvor-stag.xvor-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
.xvor-reveal, .xvor-stag { transition: none !important; opacity: 1 !important; transform: none !important; }
/* the traces still render in full under reduced motion — they just arrive
all at once instead of one row at a time */
.xvor-trace-row { animation: none !important; opacity: 1 !important; transform: none !important; }
.xvor-flow { animation: none !important; }
}
.xvor-chapter { padding: 5rem 0; border-top: 1px solid var(--hair); }
.xvor-eyebrow { font-size: 10px; letter-spacing: 0.5em; text-transform: uppercase; color: rgba(10,10,10,0.55) !important; margin: 0 0 1.6rem !important; }
/* The display headings are real h2 elements — the blog page's own
.blog-article h2 rule is (0,1,1), so this is written as
.xvor h2.xvor-statement (0,2,1) to win outright rather than relying on
source order, and it resets the margins that rule sets. */
.xvor h2.xvor-statement { font-weight: 300; font-size: clamp(2rem, 5.2vw, 3.1rem); line-height: 0.98; letter-spacing: -0.02em; margin: 0 0 2rem !important; color: var(--ink) !important; scroll-margin-top: 7rem; }
.xvor h2.xvor-statement em { font-style: normal; color: var(--emerald); position: relative; }
/* the emerald word draws its own underline as the chapter arrives */
.xvor h2.xvor-statement em::after { content: ""; position: absolute; left: 0; right: 100%; bottom: 0.06em; height: 2px; background: var(--emerald); opacity: 0.3; transition: right 0.9s cubic-bezier(0.22,1,0.36,1) 0.35s; }
.xvor-chapter.xvor-on h2.xvor-statement em::after { right: 0; }
@media (prefers-reduced-motion: reduce) { .xvor h2.xvor-statement em::after { display: none; } }
/* answer-first block — the paragraph a snippet or an assistant can lift whole */
.xvor-answer { margin: 2.5rem 0; padding: 1.6rem 1.75rem; border: 1px solid var(--hair); border-left: 2px solid var(--ink); border-radius: 4px; background: rgba(10,10,10,0.015); }
.xvor-answer-label { font-size: 10px !important; letter-spacing: 0.4em; text-transform: uppercase; color: var(--faint) !important; margin: 0 0 0.9rem !important; }
.xvor-answer-body { margin: 0 !important; font-size: 16px; line-height: 1.7; color: var(--ink) !important; }
/* contents */
.xvor-toc { margin: 2.5rem 0 0; padding: 0 0 0 1.5rem; border-left: 1px solid var(--hair); }
.xvor-toc-label { font-size: 10px !important; letter-spacing: 0.4em; text-transform: uppercase; color: var(--faint) !important; margin: 0 0 0.9rem !important; }
.xvor-toc ol { margin: 0; padding: 0 0 0 1.1rem; }
.xvor-toc li { margin-bottom: 0.45rem; color: var(--faint); font-size: 14px; }
.xvor-toc a { color: var(--muted); text-decoration: none; border-bottom: 1px solid transparent; transition: color 0.2s ease, border-color 0.2s ease; }
.xvor-toc a:hover { color: var(--ink); border-bottom-color: rgba(10,10,10,0.25); }
/* body links */
.xvor p a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: rgba(10,10,10,0.3); transition: text-decoration-color 0.2s ease; }
.xvor p a:hover { text-decoration-color: var(--ink); }
/* FAQ — real h3 elements, same specificity fight as the h2 rule above. */
.xvor h3.xvor-q { font-family: inherit; font-weight: 500; font-size: 17px !important; line-height: 1.35; letter-spacing: -0.005em; margin: 2.25rem 0 0.7rem !important; color: var(--ink) !important; scroll-margin-top: 7rem; }
.xvor-quote { margin: 2.25rem 0; padding: 0 0 0 1.5rem; border-left: 2px solid var(--ink); font-size: 17px; line-height: 1.6; color: var(--ink); font-weight: 400; }
/* Written as .xvor ul.xvor-list (0,2,1) because the blog page's own
.blog-article ul rule is (0,1,1) and would otherwise win on padding-left
and put the reset bullets back out of alignment. Same for the jobs list. */
.xvor ul.xvor-list { margin: 2rem 0; padding: 0; list-style: none; }
.xvor ul.xvor-list li { position: relative; padding: 0 0 0 1.5rem; margin-bottom: 1.1rem; color: var(--muted); }
.xvor-list li::before { content: ""; position: absolute; left: 0; top: 0.85em; width: 6px; height: 1px; background: var(--faint); }
.xvor-miss-label { display: block; font-size: 10px; letter-spacing: 0.28em; text-transform: uppercase; color: var(--faint); margin-bottom: 0.3rem; }
/* ── the blind spot: two columns ────────────────────────────────────────── */
.xvor-split { display: grid; grid-template-columns: 1fr 1px 1fr; gap: 2rem; margin: 2.5rem 0; }
@media (max-width: 620px) { .xvor-split { grid-template-columns: 1fr; gap: 2.25rem; } .xvor-split-divider { display: none; } }
.xvor-split-divider { background: var(--hair); }
.xvor-split-col p { font-size: 14px; margin-bottom: 0.85rem; }
.xvor-split-col p:last-child { margin-bottom: 0; }
.xvor-split-label { font-size: 10px !important; letter-spacing: 0.28em; text-transform: uppercase; color: var(--faint) !important; margin-bottom: 1.3rem !important; }
.xvor-split-col--other p { color: var(--ink); }
.xvor-split-col--other .xvor-split-label { color: var(--indigo) !important; }
/* ── the six jobs — a rail the reader's own scrolling draws ─────────────── */
.xvor-jobs-wrap { position: relative; margin: 2.75rem 0; }
.xvor ol.xvor-jobs { margin: 0; padding: 0 0 0 4.1rem; list-style: none; }
.xvor-rail { position: absolute; left: 6px; top: 10px; bottom: 10px; width: 1px; background: var(--hair); }
.xvor-rail-fill { width: 100%; height: 0%; background: var(--emerald); opacity: 0.45; }
.xvor-job { position: relative; margin-bottom: 2.4rem; }
.xvor-job:last-child { margin-bottom: 0; }
.xvor-job-dot { position: absolute; left: -2.85rem; top: 0.05rem; width: 31px; height: 31px; border-radius: 999px; border: 1px solid var(--hair); background: transparent; color: var(--faint); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10px; display: flex; align-items: center; justify-content: center; transition: border-color 0.45s ease, color 0.45s ease, background-color 0.45s ease; }
.xvor-job.is-lit .xvor-job-dot { border-color: rgba(16,185,129,0.55); color: #0f9d76; background: rgba(16,185,129,0.05); }
.xvor h3.xvor-job-name { font-family: inherit; font-weight: 500; font-size: 16px !important; line-height: 1.4; letter-spacing: -0.005em; margin: 0 0 0.6rem !important; color: var(--ink) !important; }
.xvor-job p { font-size: 14px; margin-bottom: 0.7rem; }
.xvor-job p:last-child { margin-bottom: 0; }
.xvor-job-miss { color: var(--red) !important; }
@media (max-width: 620px) {
.xvor ol.xvor-jobs { padding-left: 3.5rem; }
.xvor-rail { left: 5px; }
.xvor-job-dot { left: -2.5rem; width: 26px; height: 26px; font-size: 9px; }
}
/* ── the two diagrams ───────────────────────────────────────────────────── */
.xvor-fig { margin: 2.5rem 0; padding: 1.5rem 1.5rem 1.25rem; border: 1px solid var(--hair); border-radius: 6px; background: rgba(10,10,10,0.015); }
.xvor-fig-label { font-size: 10px !important; letter-spacing: 0.4em; text-transform: uppercase; color: var(--faint) !important; margin: 0 0 1.1rem !important; }
.xvor-fig figcaption { font-size: 13px; line-height: 1.6; color: var(--muted); margin-top: 1rem; }
.xvor-svg { display: block; width: 100%; height: auto; }
.xvor-node rect { fill: none; stroke: rgba(10,10,10,0.18); stroke-width: 1; }
.xvor-node text { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; fill: rgba(10,10,10,0.72); text-anchor: middle; }
.xvor-node .xvor-sub { font-family: inherit; font-size: 10px; fill: rgba(10,10,10,0.32); }
.xvor-node--good rect { stroke: rgba(16,185,129,0.45); }
.xvor-node--good text { fill: #0f9d76; }
.xvor-board rect { fill: rgba(99,102,241,0.06); stroke: rgba(99,102,241,0.4); stroke-width: 1; }
.xvor-board text { font-family: inherit; font-size: 12px; fill: var(--indigo); text-anchor: middle; }
.xvor-lossy-out { font-family: inherit; font-size: 11px; fill: var(--red); text-anchor: end; }
.xvor-flow { fill: none; stroke-width: 1.4; stroke-dasharray: 3 7; stroke-linecap: round; }
.xvor-flow--in { stroke: rgba(99,102,241,0.75); animation: xvor-dash 1.5s linear infinite; }
.xvor-flow--out { stroke: rgba(16,185,129,0.8); animation: xvor-dash 1.5s linear infinite; }
.xvor-flow--lossy { stroke: rgba(239,68,68,0.6); animation: xvor-dash 2.2s linear infinite; }
@keyframes xvor-dash { to { stroke-dashoffset: -20; } }
/* ── the two live traces, side by side ──────────────────────────────────── */
.xvor-runs { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin: 2.5rem 0; }
@media (max-width: 700px) { .xvor-runs { grid-template-columns: 1fr; } }
.xvor-run-col { border: 1px solid var(--hair); border-radius: 6px; padding: 1.2rem 1.15rem; background: rgba(10,10,10,0.015); }
.xvor-run-col--good { border-color: rgba(16,185,129,0.28); background: rgba(16,185,129,0.03); }
.xvor-run-head { font-size: 10px !important; letter-spacing: 0.24em; text-transform: uppercase; color: var(--faint) !important; margin: 0 0 1rem !important; }
.xvor-run-col--good .xvor-run-head { color: #0f9d76 !important; }
.xvor ul.xvor-trace-list { margin: 0; padding: 0; list-style: none; min-height: 19rem; }
.xvor-trace-row { font-size: 12.5px; line-height: 1.5; margin-bottom: 0.75rem; opacity: 0; transform: translateY(8px); animation: xvor-in 0.5s cubic-bezier(0.22,1,0.36,1) forwards; }
@keyframes xvor-in { to { opacity: 1; transform: none; } }
.xvor-trace-head { display: flex; gap: 0.5rem; align-items: baseline; }
.xvor-trace-who { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10.5px; color: var(--faint); flex: none; }
.xvor-trace-tool { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px; color: var(--ink); background: rgba(10,10,10,0.05); border-radius: 4px; padding: 0.05em 0.4em; }
.xvor-trace-out { display: block; color: var(--muted); }
.xvor-trace-row.is-bad .xvor-trace-tool { background: rgba(239,68,68,0.1); color: var(--red); }
.xvor-trace-row.is-bad .xvor-trace-out { color: var(--red); }
.xvor-trace-row.is-warn .xvor-trace-tool { background: rgba(217,119,6,0.12); color: var(--amber); }
.xvor-trace-row.is-warn .xvor-trace-out { color: var(--amber); }
.xvor-trace-row.is-good .xvor-trace-tool { background: rgba(16,185,129,0.12); color: #0f9d76; }
.xvor-trace-row.is-sys .xvor-trace-tool { background: rgba(99,102,241,0.1); color: var(--indigo); }
.xvor-trace-status { margin: 1rem 0 0 !important; font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--faint) !important; transition: color 0.4s ease; }
.xvor-trace-status.is-done { color: #0f9d76 !important; }
.xvor-trace-status.is-bad { color: var(--red) !important; }
@media (max-width: 700px) { .xvor ul.xvor-trace-list { min-height: 0; } }
/* ── the four cards ─────────────────────────────────────────────────────── */
.xvor-cards { margin: 2.5rem 0; border: 1px solid var(--hair); border-radius: 6px; }
.xvor-card { padding: 1.5rem 1.6rem; position: relative; border-top: 1px solid var(--hair); }
.xvor-card:first-child { border-top: 0; }
.xvor-card::before { content: ""; position: absolute; left: 0; top: 0; height: 2px; width: 0; background: var(--red); opacity: 0.45; transition: width 0.9s cubic-bezier(0.22,1,0.36,1); }
.xvor-card--good::before { background: var(--emerald); opacity: 0.7; }
.xvor-chapter.xvor-on .xvor-card::before { width: 100%; }
@media (prefers-reduced-motion: reduce) { .xvor-card::before { display: none; } }
.xvor-card p { font-size: 14px; margin-bottom: 0.7rem; }
.xvor-card p:last-child { margin-bottom: 0; }
.xvor-card-kind { font-size: 10px !important; letter-spacing: 0.28em; text-transform: uppercase; color: var(--faint) !important; margin-bottom: 0.7rem !important; }
.xvor-card-verdict { font-weight: 300; font-size: clamp(1.3rem, 3.4vw, 1.75rem) !important; line-height: 1.1; letter-spacing: -0.015em; color: var(--ink) !important; margin-bottom: 0.9rem !important; }
.xvor-card--good .xvor-card-verdict { color: #0f9d76 !important; }
.xvor-card-miss { color: var(--red) !important; }
.xvor-card-miss--good { color: #0f9d76 !important; }
/* ── checklist cards ────────────────────────────────────────────────────── */
.xvor-parts { margin: 2.5rem 0; border: 1px solid var(--hair); border-radius: 6px; }
.xvor-part { padding: 1.4rem 1.5rem; border-top: 1px solid var(--hair); }
.xvor-part:first-child { border-top: 0; }
.xvor-part p { font-size: 14px; margin-bottom: 0.6rem; }
.xvor-part p:last-child { margin-bottom: 0; }
.xvor-part-name { font-size: 11px !important; letter-spacing: 0.24em; text-transform: uppercase; color: var(--ink) !important; margin-bottom: 0.8rem !important; line-height: 1.6; }
/* ── vs ─────────────────────────────────────────────────────────────────── */
.xvor-vs { display: grid; grid-template-columns: 1fr 1px 1fr; gap: 2rem; margin: 1rem 0 0; }
@media (max-width: 620px) { .xvor-vs { grid-template-columns: 1fr; } .xvor-vs-divider { display: none; } }
.xvor-vs-divider { background: var(--hair); }
.xvor-vs-col p { font-size: 14px; margin-bottom: 0.9rem; }
.xvor-vs-label { font-size: 10px !important; letter-spacing: 0.28em; text-transform: uppercase; color: var(--faint) !important; margin-bottom: 1.3rem !important; }
.xvor-vs-col--for p { color: var(--ink); }
.xvor-vs-col--for .xvor-vs-label { color: #0f9d76 !important; }
.xvor-outro { margin: 2.75rem 0 0 !important; font-size: 15px; }
.xvor-close { margin-top: 4rem !important; padding-top: 3rem; border-top: 1px solid var(--hair); font-weight: 300; font-size: clamp(1.4rem, 3.6vw, 2rem); line-height: 1.25; letter-spacing: -0.015em; color: var(--ink) !important; }
</style>
<script>
(function () {
// This <script> is a SIBLING of .xvor (it sits after the closing </div>), so
// closest() finds nothing — fall back to a plain lookup rather than bailing.
var root = (document.currentScript && document.currentScript.closest(".xvor")) || document.querySelector(".xvor");
if (!root) return;
var reduced = window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
var hasIO = "IntersectionObserver" in window;
/* ── chapter reveal ───────────────────────────────────────────────────── */
var reveals = root.querySelectorAll(".xvor-reveal");
if (hasIO && !reduced) {
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) { entry.target.classList.add("xvor-on"); io.unobserve(entry.target); }
});
}, { threshold: 0.12, rootMargin: "0px 0px -80px 0px" });
reveals.forEach(function (el) { io.observe(el); });
} else {
reveals.forEach(function (el) { el.classList.add("xvor-on"); });
}
/* ── staggered lines ──────────────────────────────────────────────────────
Each group animates in as a unit, one line after another, when its own
column scrolls into view. */
var seen = [];
root.querySelectorAll(".xvor-stag").forEach(function (el) {
if (seen.indexOf(el.parentNode) === -1) { seen.push(el.parentNode); }
});
seen.forEach(function (parent) {
var kids = parent.querySelectorAll(".xvor-stag");
kids.forEach(function (el, i) { el.style.setProperty("--i", i); });
if (!hasIO || reduced) {
kids.forEach(function (el) { el.classList.add("xvor-in"); });
return;
}
var so = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (!entry.isIntersecting) return;
so.unobserve(entry.target);
kids.forEach(function (el) { el.classList.add("xvor-in"); });
});
}, { threshold: 0.25 });
so.observe(parent);
});
/* ── the six jobs: a rail that draws itself as the section passes ────────
Scroll-linked rather than a one-shot transition — the reader's own
scrolling advances it, and each numbered dot lights as its job crosses
the middle of the viewport. All six jobs are plain text in the document;
the animation only decorates the order they are met in. */
var jobsList = root.querySelector("#xvor-jobs");
var railFill = root.querySelector("#xvor-rail-fill");
var jobItems = root.querySelectorAll(".xvor-job");
if (jobsList && railFill) {
if (reduced) {
railFill.style.height = "100%";
jobItems.forEach(function (el) { el.classList.add("is-lit"); });
} else {
var ticking = false;
var drawRail = function () {
ticking = false;
var box = jobsList.getBoundingClientRect();
var mark = window.innerHeight * 0.62;
var progress = (mark - box.top) / Math.max(box.height, 1);
progress = Math.min(1, Math.max(0, progress));
railFill.style.height = (progress * 100).toFixed(2) + "%";
jobItems.forEach(function (el) {
el.classList.toggle("is-lit", el.getBoundingClientRect().top < mark);
});
};
var onScroll = function () {
if (ticking) return;
ticking = true;
window.requestAnimationFrame(drawRail);
};
window.addEventListener("scroll", onScroll, { passive: true });
window.addEventListener("resize", onScroll);
drawRail();
}
}
/* ── the same mission, run twice ──────────────────────────────────────────
Both traces are on screen at once and play in lockstep, so the comparison
is read rather than chosen. No row in the left trace is a mistake by an
agent — each one is correct given what that agent could see, which is the
entire point of the section. */
var RUNS = [
{
status: "finished · nobody checked · reads fine",
bad: true,
rows: [
{ who: "a1", tool: "web-search", out: "12 results for competitor pricing" },
{ who: "a2", tool: "web-search", out: "the same 12 — no way to know a1 ran it", warn: true },
{ who: "a1", tool: "scrape", out: "acme.com/pricing — 3 tiers" },
{ who: "a2", tool: "scrape", out: "acme.com again — scraped twice, billed twice", warn: true },
{ who: "a3", tool: "scrape", out: "403 blocked" },
{ who: "a3", tool: "—", out: "stops producing turns · nothing is watching", bad: true },
{ who: "a1", tool: "report", out: "2 of 3 competitors, written as if complete", bad: true },
{ who: "—", tool: "delivered", out: "no audit — the missing competitor is invisible", bad: true }
]
},
{
status: "goal reached · 3 sources verified · 41 OU",
bad: false,
rows: [
{ who: "plan", tool: "spawn", out: "this goal needs 3 agents: 2 subjects + 1 analyst", sys: true },
{ who: "a1", tool: "scrape", out: "acme.com — 3 tiers → written to shared memory" },
{ who: "a2", tool: "scrape", out: "vertexlabs.io — 4 tiers, running concurrently" },
{ who: "a2", tool: "—", out: "crash at turn 9 → incident recorded, agent re-run", sys: true },
{ who: "a3", tool: "read-notes", out: "reads both peers' real findings, re-derives nothing" },
{ who: "a3", tool: "save-deliverable", out: "comparison table — 3 competitors, 10 tiers" },
{ who: "sup", tool: "audit", out: "one figure unsourced → returned with feedback", warn: true },
{ who: "a3", tool: "save-deliverable", out: "source added → audit passed", good: true }
]
}
];
var lists = [root.querySelector("#xvor-trace-0"), root.querySelector("#xvor-trace-1")];
var statuses = [root.querySelector("#xvor-status-0"), root.querySelector("#xvor-status-1")];
var runTimer = null;
function renderRow(r) {
var li = document.createElement("li");
li.className = "xvor-trace-row"
+ (r.bad ? " is-bad" : "")
+ (r.warn ? " is-warn" : "")
+ (r.good ? " is-good" : "")
+ (r.sys ? " is-sys" : "");
var head = document.createElement("span");
head.className = "xvor-trace-head";
var who = document.createElement("span");
who.className = "xvor-trace-who";
who.textContent = r.who;
var tool = document.createElement("span");
tool.className = "xvor-trace-tool";
tool.textContent = r.tool;
head.appendChild(who); head.appendChild(tool);
var out = document.createElement("span");
out.className = "xvor-trace-out";
out.textContent = r.out;
li.appendChild(head); li.appendChild(out);
return li;
}
function finish(i) {
statuses[i].textContent = RUNS[i].status;
statuses[i].classList.add(RUNS[i].bad ? "is-bad" : "is-done");
}
function playRuns() {
window.clearTimeout(runTimer);
lists.forEach(function (ul) { ul.innerHTML = ""; });
statuses.forEach(function (el) {
el.textContent = "running…";
el.classList.remove("is-done", "is-bad");
});
if (reduced) {
RUNS.forEach(function (run, i) {
run.rows.forEach(function (r) { lists[i].appendChild(renderRow(r)); });
finish(i);
});
return;
}
var n = 0;
var total = Math.max(RUNS[0].rows.length, RUNS[1].rows.length);
(function step() {
if (n >= total) {
RUNS.forEach(function (run, i) { finish(i); });
// Loop, so a reader arriving late still sees it play.
runTimer = window.setTimeout(playRuns, 5600);
return;
}
RUNS.forEach(function (run, i) {
if (n < run.rows.length) { lists[i].appendChild(renderRow(run.rows[n])); }
});
n += 1;
runTimer = window.setTimeout(step, 760);
})();
}
/* Start only once the traces are actually on screen — an animation that has
already finished by the time the reader scrolls to it isn't an animation,
and running it from page load burns work nobody sees. */
var runsEl = root.querySelector("#xvor-runs");
if (!runsEl) return;
if (!hasIO || reduced) { playRuns(); return; }
var once = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) { once.unobserve(entry.target); playRuns(); }
});
}, { threshold: 0.25 });
once.observe(runsEl);
})();
</script>