Skip to content

Call Paths

The execution traces read as five separate call chains. They are not. They are five entry points into one graph, and the places where they meet are where the architecture’s load-bearing claims live.

That is the one thing two ASCII blocks three hundred lines apart structurally cannot show, and it is why this page exists.

Select a hop.

The three primitives — output_key, compute_node, store_output — appear in trace (b) and trace (d), and nowhere else. That is the entire design claim of the streaming implementation: batch and stream execution share their centre.

It is also the entire bug. Everything around those three is written twice, and the copies have drifted — the stream path emits no cache events at all, so RunReader::cache_activity reports zero cache activity for every streamed run. That is D-11, and this page is the shortest way to see why it happened: the shared part is three function calls, and the duplicated part is everything you can see around them in both trees at once.

The other junctions are structural rather than suspicious. execute joins (a) to (b) because a forward is a plan walk. EffectDriver appears in (c) and in the ownership spine because it is the one component a session holds only when the graph contains steps.

BadgeMeaning
P1 P2 P3One of the three shared primitives — output_key, compute_node, store_output
dyn TThe call leaves through a trait object. This is where a static call-graph tool stops and the architecture graph takes over
D-nnThe hop is on the path of a documented problem
→ (x)Control continues in another trace
in N tracesA junction: the same code reached from more than one entry point

docs/data/traces.json is the source. docs/scripts/gen-traces.mjs renders it twice — as the ASCII blocks in execution.md and as the JSON blob behind this page:

Terminal window
cd docs && node scripts/gen-traces.mjs

They are generated from one file rather than written twice on purpose. Keeping two hand-maintained copies of the same call chains is precisely the smell the debt register is about, and writing it into the section that denounces it would be hard to defend.

The traces are hand-authored, not extracted, and that is the point. A static analyser cannot tell you that run_node_inner is the branch distinguishing a filter from a step, or that the Suspend arm’s journal lookup is the whole resume mechanism. What the generator adds is bookkeeping: it expands every short file:line into a repo path, so npm run check verifies the 99 of them that carry one. In their hand-written form the guard could see none.