Skip to content

Propagate nested rollout trace lineage - #640

Open
jdchawla29 wants to merge 1 commit into
hud-evals:mainfrom
jdchawla29:codex/nested-trace-lineage
Open

Propagate nested rollout trace lineage#640
jdchawla29 wants to merge 1 commit into
hud-evals:mainfrom
jdchawla29:codex/nested-trace-lineage

Conversation

@jdchawla29

@jdchawla29 jdchawla29 commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • keep trace context to current and immediate-parent IDs; nesting derives lineage automatically
  • keep nested rollouts on distinct child traces while reporting the immediate parent for local and hosted execution
  • propagate only the active trace across MCP, then attach child and parent headers at the inference gateway boundary
  • prevent self-parenting across equivalent UUID forms and omit invalid parent IDs from hosted submissions

Verification

  • UV_CACHE_DIR=/private/tmp/hud-python-uv-cache uv run --extra dev pytest -q hud/agents/tests/test_tool_agent.py hud/agents/tests/test_claude_sdk_agent.py hud/utils/tests/test_gateway.py hud/eval/tests/test_job.py hud/eval/tests/test_rollout.py hud/eval/tests/test_hosted.py (136 passed)
  • UV_CACHE_DIR=/private/tmp/hud-python-uv-cache uv run --extra dev pytest -q hud/telemetry/tests/test_instrument.py hud/tests/test_trace.py hud/agents/tests/test_trace.py hud/eval/tests/test_file_tracking_observer.py (63 passed)
  • UV_CACHE_DIR=/private/tmp/hud-python-uv-cache uv run --extra dev --extra train ty check on changed source files
  • UV_CACHE_DIR=/private/tmp/hud-python-uv-cache uv run ruff format and ruff check on all changed files

Note

Medium Risk
Changes trace attribution across eval reporting, gateway inference, and MCP boundaries; incorrect parent handling could mis-link nested rollouts on the platform, but behavior is guarded by normalization and extensive tests.

Overview
Nested rollouts now keep a child trace as the active context while recording the immediate parent separately, so platform reporting and downstream calls can stitch lineage without collapsing nested work into one id.

Trace context replaces header-only storage with current and parent context variables. set_trace_context yields the prior active trace as the parent and drops self-parenting when ids are equivalent UUID forms. get_current_trace_id can also resolve inbound MCP tool metadata (hud/trace-id) or a trace-id HTTP header when no local context is bound.

Rollout reporting: local rollout passes parent_trace_id into trace_enter; hosted submit includes a canonical parent_trace_id when the ambient parent is usable (omitted for self-parent or non-platform ids).

Propagation paths align on the same lineage: gateway HTTP adds Trace-Id and X-HUD-Parent-Trace-Id; MCPClient.call_tool sends hud/trace-id in call meta; Claude SDK remote MCP configs add a Trace-Id header alongside auth.

Reviewed by Cursor Bugbot for commit 599dd8a. Bugbot is set up for automated code reviews on this repo. Configure here.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-02T14:50:23.678550Z 599dd8a New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 713cc3d5d5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread hud/eval/run.py Outdated
if job_id is None: # no standalone traces: a lone rollout is a job of one
job_id = uuid.uuid4().hex
await job_enter(job_id, name=task.id, group=1)
parent_trace_id = get_current_trace_id()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Propagate lineage through hosted rollouts

When a nested task selects HostedRuntime, Taskset._run calls HostedRuntime.run directly, bypassing this new parent capture, and the hosted submission payload includes only trace_id and job_id. Consequently, nested hosted rollouts still create an unparented trace and their remote gateway requests cannot carry the immediate parent; capture and submit parent_trace_id in the hosted path as well.

AGENTS.md reference: AGENTS.md:L153-L154

Useful? React with 👍 / 👎.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 713cc3d. Configure here.

Comment thread hud/capabilities/mcp.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7dbad18ab2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread hud/eval/runtime/hosted.py Outdated
if group_id is not None:
payload["group_id"] = group_id
if parent_trace_id is not None:
payload["parent_trace_id"] = str(uuid.UUID(parent_trace_id))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve hosted runs with non-UUID parent trace IDs

When a hosted rollout runs under an ambient trace ID that is not UUID-shaped, this new conversion raises ValueError before submission, and HostedRuntime.run turns the otherwise valid rollout into a failed run. This can occur through supported SDK paths because rollout(trace_id=...) and set_trace_context(...) accept arbitrary strings, and telemetry explicitly normalizes arbitrary run identifiers; previously, the hosted rollout succeeded regardless of the ambient context. Either preserve the parent identifier without UUID parsing or avoid letting an unrepresentable optional lineage value abort the child rollout.

AGENTS.md reference: AGENTS.md:L103-L107

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: afa1c03fc5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread hud/capabilities/mcp.py
Comment on lines +70 to +72
trace_id = get_current_trace_id()
meta = {MCP_TRACE_ID_META_KEY: trace_id} if trace_id is not None else None
raw = await self._client.call_tool_mcp(name=name, arguments=arguments, meta=meta)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Propagate trace metadata through Claude SDK MCP calls

When ClaudeSDKAgent invokes an MCP capability, the Claude process uses the generated server configuration in hud/agents/claude/sdk/agent.py:98-107 and never calls this MCPClient.call_tool wrapper. Consequently, an MCP tool that launches a nested rollout receives no hud/trace-id, so _get_mcp_trace_id() returns None and the child is still recorded as a root trace for this shipped agent path. Extend the propagation mechanism to the Claude SDK MCP route as well.

AGENTS.md reference: AGENTS.md:L149-L150

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 29fdbfe. Claude SDK MCP server configs now include the active trace as a Trace-Id HTTP header, and FastMCP resolves that header when per-call MCP metadata is unavailable. Covered by the Claude SDK and server-context tests.

Comment thread hud/eval/runtime/hosted.py Outdated
Comment on lines +74 to +77
parent_trace_id = get_current_trace_id()
trace_id = trace_id or uuid.uuid4().hex
if parent_trace_id == trace_id:
parent_trace_id = None

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Compare canonical UUIDs before suppressing self-parenting

When the ambient context contains a hyphenated UUID and the explicit trace_id is the same UUID in compact .hex form, this string comparison does not recognize them as equal. _submit_and_await then canonicalizes both values, producing a submission whose parent_trace_id equals its trace_id, which can create or be rejected as a self-referential trace. Normalize valid UUIDs before applying the self-parent guard.

AGENTS.md reference: AGENTS.md:L103-L107

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 29fdbfe. Hosted parent IDs are canonicalized before comparison, so hyphenated and compact forms of the same UUID are treated as self-parenting and omitted. A regression test covers this exact case.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 29fdbfef41

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread hud/eval/run.py Outdated
Comment on lines +492 to +493
if parent_trace_id == trace_id:
parent_trace_id = None

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Canonicalize IDs in the local self-parent guard

When the ambient parent is a hyphenated UUID and the explicit local trace_id is the same UUID in compact form, this raw string comparison misses the match, so trace_enter and gateway requests receive a parent that canonically equals the child and can create or be rejected as a self-referential trace. The hosted guard was corrected to compare canonical UUIDs, but the local rollout path still needs the same normalization before suppressing the parent.

AGENTS.md reference: AGENTS.md:L103-L107

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in fd84a80. Local and hosted rollouts now share UUID-aware trace ID equality, so compact and hyphenated forms cannot produce a self-parent edge. The local rollout lifecycle test covers the exact case.

@jdchawla29
jdchawla29 force-pushed the codex/nested-trace-lineage branch from fd84a80 to 4096d57 Compare September 2, 2026 06:03
@jdchawla29
jdchawla29 force-pushed the codex/nested-trace-lineage branch from 4096d57 to 599dd8a Compare September 2, 2026 14:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant