Skip to content

The span tree and span details in the Console #996

Closed

Description

@JacobStephens2

Parent

#700

What to build

Build #995's design.

  • The span tree grows out of the Waterfall for any Command with Session traces: its Runs, stages, sessions, model calls and tool calls.
  • Span details: selecting a span shows its details in the Peek panel.
  • A CLI command with --json gives the same data, as every Console view has one (ADR 0016).

Acceptance criteria

  • Route and browser tests show the tree for a Command with child Runs, and a selected span's details.
  • It fits a 390 px phone.
  • The same data comes from the CLI with --json.

Design (settled in #995)

Settled with Jacob in #995's prototype: layout E, a tree with a timeline and the slowest calls, and Peek layout 3, a summary card. The prototype is the primary source: src/console/span-tree-prototype/ on the issue-995-prototype branch. Run it with real Session traces as its README says, and open ?variant=E&details=3. It is throwaway code: rebuild it properly, don't copy it.

The span tree

  • One tree below the Waterfall's Command chips: Command › Runs › stages › sessions › model calls, tool calls and sub-agents. A child Run nests under the stage it started in. A sub-agent's calls nest under it. A session that several stages name (the "pull request" stage reuses the implement session's Session trace) sits under the first stage that names it.
  • Each row has a disclosure triangle, a kind tag (cmd, run, stage, sess, model, turn, tool, agent), the name truncated with an ellipsis, a status mark, a duration column, and a bar on one shared time axis. The status mark is ✕ for an error, with its message as the tooltip, or ● for running. The duration gets a * when the time is estimated. The axis ticks are relative: +0 ms, +40m 48s, …
  • Bars distinguish tool calls from model calls, errors, running calls and estimated times. A running call is hatched and extends to now. An estimated time is dotted.
  • Folding: the Command, Runs and stages start open, and sessions start folded. A row of buttons expands to Runs, stages, sessions or every call. A folded parent shows its error count and the ranks of any slowest calls inside it, such as ▸ #1 #2 #3.
  • Keyboard: the ARIA tree pattern. ↑ ↓ (and j k) move; → expands or goes to the first child; ← folds or goes to the parent; Enter or Space opens the Peek.

Slowest calls

  • A foldable list above the tree, open by default: the ten slowest tool and model calls in the timeline's current scope. Codex turn spans span their own tool calls, so they would crowd them out; they are left out, as are sub-agent spans.
  • Each entry has a rank badge, the kind tag, the name, its start → end clock times (→ now while running), the duration, and "N% of its · # · session".
  • The tree marks the same calls: the rank badge on the row and a highlighted bar.
  • Clicking an entry unfolds the tree to the call, selects it, opens its Peek, and brings its row into view.

Zooming the timeline

  • The Peek's button: on a call it reads "Zoom timeline around this call" and shows a window around the call. On a span with children it reads "Zoom timeline to this " and fits the axis to that span.
    // Around a call: show what ran just before and after it.
    const pad = Math.max(call.duration, 1000) * 1.5;
    axis = { start: Math.max(parent.start, call.start - pad), end: Math.min(parent.end ?? now, call.end + pad) };
  • The zoom notice is pinned in the sticky axis header: "Timeline zoomed around : → ()", plus a Zoom out to whole Command button. The name stays on one line. The Peek's button also becomes "Zoom out to whole Command".
  • While zoomed, rows outside the window are dimmed and the slowest list re-ranks within the window.
  • A row brought into view (after zooming or from the slowest list) stays below the sticky header and, on a phone, above the Peek's bottom sheet. Centre it in what's left visible.

Span details in the Peek (summary card)

  1. The path of ancestors, as links that reveal and select that span.
  2. Then: the kind tag and the name as the heading, the status, the start → end clock times, and an "estimated" marker.
  3. Tiles, only those that apply: duration, % of its parent, tokens in / out, cost, model / tool call counts, errors.
  4. Two small bars: where the span sits within its parent, and within the Command.
  5. Actions: the zoom button, Open in conversation (the conversation view at this record), and Copy CLI.
  6. Input, open: a tool call's arguments as pretty JSON, a session's Session prompt, or a sub-agent's description. Output, All attributes and an Overview table (kind, status, times, model, Harness, tokens with the cache split, cost, span ID) are folded below. A model call's span carries no text, so its Peek says the text is in the conversation view.

Phone (390 px) and laptop

  • Laptop: the Peek sits beside the tree, as body.peek-open does today. Tree rows are a grid: label · duration (7ch) · bar.
  • Phone: the label takes a full-width line, with the bar and duration on a line under it. The indent is 8 px per level, and there are three axis ticks. The Peek is today's bottom sheet. A slowest-calls entry wraps to name, then times and duration, then where it ran.

CLI

The tree and one span's details come from the CLI with --json. The prototype showed thirdshift logs <command> --spans --json and --span <id> as a placeholder; name it as ADR 0016 and the existing commands suggest.

What the real data showed

  • Converted Session logs carry estimated times that can overlap. A converted session can start at the Command's start: Find what still makes the macOS test shards slow after #857 #894's Security review session claims 3h 24m in a 40 s stage. A converted model call is estimated to last until the next event, so it absorbs the wait of the tool call it made. The tree tolerates both; mark estimated times with *. A flame chart could not, which is one reason layout C lost.
  • Sub-agent spans that never ended (status "call did not end") stretch to the session's end.
  • Codex sessions have no model-call spans: one turn span carries the usage, and the tool calls sit flat under the session, hundreds of them in Spec: Session traces, OTLP JSON Lines in place of Session logs #700's Runs.
  • Session spans repeat their calls' token totals, so don't add a session's tokens to its children's.
  • Upper levels: use the span IDs computed from the Command record, as Spec: Session traces, OTLP JSON Lines in place of Session logs #700 says. The prototype used stand-in hashes.

What the static prototype didn't show

The prototype was a static page over one snapshot. The build also needs these.

  • The tree replaces today's Waterfall body (each Run's section with its stage and tool bars), as layout E did. It shows the same Runs, stages and calls, and more. The Command chips and the page's CLI line stay.
  • Command details stay reachable. Today a Run's heading opens the Command's Peek, with Stop, the logs and the pull request. The prototype gave Command and Run rows the summary card instead. Keep both: the card for the span, and a link to the Command details.
  • Live updates: the Waterfall refreshes while a Command runs. Folding, zoom, selection and the open Peek survive each refresh, running calls grow to now, and the slowest list may re-rank.
  • Scale: a Run's session can hold hundreds of tool calls (Spec: Session traces, OTLP JSON Lines in place of Session logs #700's Runs total about 2,200). Render a session's calls only once it is unfolded.
  • Commands without Session traces still show their Runs and stages from the Command record, with no sessions under them.
  • Open in conversation links to the conversation view at that span's record. If the view can't anchor a record, link to the session's conversation.

Activity

  1. JacobStephens2 commented on Oct 22, 2026

    @JacobStephens2
    OwnerAuthor

    Closed by #1107, merged into issue-700-branch-2 by a thirdshift Merge run.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    ready-for-agentFully specified, ready for an AFK agent

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions