feat(tabs): draw lineage lines as one tree for the selected tab's family

Lineage lines used to draw one glowing dashed bezier per parent/child pair,
hanging below the tab strip, for every family at once. With a parent on row 3
of a wrapped strip and ten children below it, the curves crossed every lower
row's tab names and ran through the terminal text.

- One rounded orthogonal tree per spawning tab: every route starts at the
  parent, so siblings share a trunk. 1.5px, solid, 1px dark outline; only a
  working child's branch is dashed.
- Routes run only through the gaps between tab rows, joined by a spine left of
  every row (computeLineageTree/computeLineageRows in constants.js), so they
  never cross a tab or reach the terminal. The vertical rail gets the same tree
  on its existing left track.
- Only the selected tab's family is drawn (what it spawned, plus its parent and
  siblings). Selection redraws, and the strip's size transitionend redraws once
  more, since the active tab widens for ~150ms after the selection redraw.
- The routing room is reserved by .session-tabs.lineage-tree, keyed on whether
  any lineage exists, never on the selection, so a tab switch never resizes the
  header or the PTY.
- Colours stay per spawning tab, now claimed in strip order for every family so
  selection order never decides who gets the skin blue.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer
2026-10-07 00:03:37 +02:00
parent ac94f339ac
commit 09daf0fe49
14 changed files with 1123 additions and 619 deletions
+1 -1
View File
@@ -189,7 +189,7 @@ followed by a wait races, and reports the previous turn's state.
## Lineage
A create request can name the session that spawned it, through a body field or a header, and
the dashboard then draws a lineage arc from parent to child. The skill sets it automatically.
the dashboard then draws a lineage line from parent to child. The skill sets it automatically.
It is resolved rather than trusted: an unresolvable parent is dropped silently rather than
failing the spawn, because a cosmetic field must never break a worker.
+1 -1
View File
@@ -158,7 +158,7 @@ enough to fix a typo an agent introduced while you are away from your desk.
enforces it.
- The Approvals bell. Phones get the NEEDS YOU strips on the home screen instead.
- The desktop home tab rail, which needs a wide window.
- Lineage arcs, which are a desktop overlay.
- Lineage lines, which are a desktop overlay.
## Gotchas
+1 -1
View File
@@ -89,7 +89,7 @@ every session or only the active tab.
| Vertical Rail Order | *By activity* (default) sorts the rail the way the home screens are sorted; *Manual* keeps your tab order and drag-reordering. |
| Tall Tabs | Taller tab strip. |
| Pop-out Button on Tabs | Adds the detach control to tabs, with a per-tab override. |
| Spawn Lineage Lines | Arcs from a parent tab to sessions it spawned. Desktop only, on by default. |
| Spawn Lineage Lines | Lines from the selected tab to the sessions it spawned, and to the one that spawned it. Desktop only, on by default. |
| Auto-name Sessions | Titles a new tab after its first prompt, keeping the case prefix (`w3-myapp: fix the login redirect`). Synced, off by default. See [The Dashboard](The-Dashboard#automatic-session-names). |
| Overview Home Screen | The phone home screen. On by default. |
+9 -5
View File
@@ -84,13 +84,17 @@ title is derived locally from the prompt's first sentence; no text leaves the ma
On phones the strip scrolls horizontally instead of wrapping, and the active tab is always
scrolled into view. It is not reordered to the front, so the `Alt+N` numbering stays stable.
### Lineage arcs
### Lineage lines
When one session spawns another (an agent starting a worker through the API), Codeman draws
a coloured arc under the strip connecting parent to child, with one colour per child. It is
how a fan-out of eight workers stays readable.
When one session spawns another (an agent starting a worker through the API), selecting
either tab draws its family: lines from the parent to each child, in the parent's colour,
routed through the gaps between tab rows so they never cover a tab or the terminal. A dashed
branch means that child is working. It is how a fan-out of eight workers stays readable.
Desktop only, and on by default. Turn it off in **App Settings → Appearance**. Arcs are
While any tab has spawned another, the strip keeps a little extra room between rows for the
lines, so switching tabs never changes the header height.
Desktop only, and on by default. Turn it off in **App Settings → Appearance**. Lines are
skipped for tabs scrolled out of the strip.
## Header controls
+9 -5
View File
@@ -22,13 +22,17 @@ transcript: what it was asked to do, what it is doing, and what it returned.
This is the feature that makes a fan-out legible. Without it, a lead session that spawned
eight workers looks like a stalled terminal for several minutes.
## Session lineage arcs
## Session lineage lines
The tab strip draws a coloured arc from a parent tab to any tab it spawned, one colour per
child. That covers the other direction of fan-out: not subagents inside one session, but
whole sessions started by an agent through the API.
Select a tab and the tab strip draws lines from it to every tab it spawned, and to the tab
that spawned it (with its siblings). That covers the other direction of fan-out: not
subagents inside one session, but whole sessions started by an agent through the API.
Desktop only, on by default, and toggled in **App Settings → Appearance**. Arcs are skipped
The lines form one tree per spawning tab, in that tab's colour, and run only through the
gaps between tab rows, so they never cover a tab name or the terminal. A dashed branch
means that child is working. Tabs with no lineage draw nothing.
Desktop only, on by default, and toggled in **App Settings → Appearance**. Lines are skipped
for tabs scrolled out of view.
See [Driving Codeman From An Agent](Driving-Codeman-From-An-Agent) for the spawning side.