fn fork_lineage_root_id(defs: &[AgentDefinition], start_id: &str) -> StringExpand description
Resolve a definition’s fork-lineage root by walking parent_id.
parent_id is overloaded in this schema: agentdefcreatefromtemplate
sets it to the template’s id for every freshly-instantiated user
agent (see that handler below), not just forkagentdefinition’s actual
forks — so two unrelated agents both created fresh from the same
template share a parent_id, but are not forks of each other. The one
field that reliably distinguishes an actual fork is branch_label:
forkagentdefinition always sets it (non-empty); agentdefcreatefromtemplate
always leaves it empty. Walk upward only while the current node is
itself a fork (non-empty branch_label); stop at the first non-fork
ancestor (a template, or a first-generation user agent) — that’s the
lineage’s root for fork-counting purposes. Confirmed bug this fixes
(Codex’s review of PR #2721, docs/specs/SPEC_AGENT_QUICK_FORK_NEW_TAB_2026_08_21.md
§2): the naming rule requires a flat, lineage-wide counter (“AgentX #2”
→ “AgentX #3”), but the previous parent_id == source_id filter only
counted immediate children, so forking a fork produced “AgentX #2 #2”.