Skip to content

Preserve Codex subagent thread.started metadata#1

Merged
ratulsarna merged 2 commits intosubagent-support-codexfrom
rat-117-preserve-codex-thread-started-metadata
Mar 7, 2026
Merged

Preserve Codex subagent thread.started metadata#1
ratulsarna merged 2 commits intosubagent-support-codexfrom
rat-117-preserve-codex-thread-started-metadata

Conversation

@ratulsarna
Copy link
Copy Markdown
Owner

@ratulsarna ratulsarna commented Mar 7, 2026

Summary

  • preserve Codex thread started metadata in the normalized runtime contract
  • map Codex child-thread source metadata through the adapter without changing orchestration semantics
  • fix string-based source normalization when top-level agent metadata is explicitly null

Scope

  • extend the normalized thread.started payload with thread source metadata such as subAgentThreadSpawn, parentProviderThreadId, depth, agentNickname, and agentRole
  • keep RAT-117 as a seam-only change; child-thread materialization is intentionally deferred to follow-up backend work
  • add regression coverage proving richer payloads do not change current lifecycle behavior

Verification

  • bun lint
  • bun typecheck
  • ./node_modules/.bin/vitest run packages/contracts/src/providerRuntime.test.ts apps/server/src/provider/Layers/CodexAdapter.test.ts apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts

Summary by CodeRabbit

  • New Features

    • Enhanced thread event handling to support nested agent spawning with parent-child relationships, depth tracking, and agent metadata.
  • Tests

    • Added comprehensive test coverage for thread event mapping with subagent metadata, including edge cases such as legacy payloads and source variations.
    • Added validation tests for thread metadata parsing and normalization.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 7, 2026

📝 Walkthrough

Walkthrough

The changes extend thread event handling infrastructure to support nested agent thread spawning. New type definitions introduce structured source metadata for thread events, parsing utilities normalize incoming event payloads, and comprehensive tests validate the enhanced functionality across the provider adapter and orchestration layers.

Changes

Cohort / File(s) Summary
Thread Event Type System
packages/contracts/src/providerRuntime.ts, packages/contracts/src/providerRuntime.test.ts
Introduces ThreadStartedSourceKind and ThreadStartedSource types with support for subagent thread spawning (parent thread ID, depth, agent metadata). Extends ThreadStartedPayload with optional name, preview, status, and source fields. Tests validate decoding of varied payload shapes including spawned subagents and legacy formats.
Provider Adapter Enhancement
apps/server/src/provider/Layers/CodexAdapter.ts
Replaces simple providerThreadId extraction with comprehensive parsing logic. Adds utilities (asNonNegativeInt, normalizeNonEmptyString, readThreadStartedPayload, normalizeThreadStartedSource) to normalize and enrich thread-started event payloads, supporting multiple source kinds (cli, vscode, exec, mcp, subagent, thread_spawn) and merging agent metadata.
Adapter Logic Tests
apps/server/src/provider/Layers/CodexAdapter.test.ts
Adds extensive lifecycle tests for thread/started event mapping, validating payload transformation to canonical thread.started events with correct providerThreadId, agent metadata, spawn source details, and fallback behavior for legacy formats and malformed inputs.
Orchestration Test Augmentation
apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts
Augments existing test cases to include providerThread spawn payloads in thread-started events, enabling tracking of sub-agent thread creation with parent, depth, and agent metadata.

Sequence Diagram

sequenceDiagram
    participant Codex as Codex Provider
    participant Adapter as CodexAdapter
    participant Parser as Payload Parser
    participant Runtime as Runtime Layer
    participant Orchestration as Orchestration

    Codex->>Adapter: thread/started event<br/>(raw nested spawn data)
    Adapter->>Parser: readThreadStartedPayload(raw event)
    Parser->>Parser: normalizeThreadStartedSource()<br/>Validate & enrich metadata
    Parser->>Parser: coalesceNullableString()<br/>Merge agent defaults
    Parser-->>Adapter: ThreadStartedPayload<br/>(normalized structure)
    Adapter->>Runtime: emit thread.started<br/>(structured payload)
    Runtime->>Orchestration: thread.started<br/>(with parent/depth/agent info)
    Orchestration->>Orchestration: Track nested thread hierarchy
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

The review requires understanding new type definitions, evaluating multiple parsing/normalization utility functions with edge case handling, verifying comprehensive test coverage across varied payload shapes, and confirming correct integration across three layers (contracts, adapter, orchestration).

Poem

🐰 Threads now spawn with purpose clear,
Parent depths and agents near,
Payloads rich with metadata true,
Nested worlds for work to do!
Hop along, the trees grow deep. 🌳✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Preserve Codex subagent thread.started metadata' directly and clearly summarizes the main change: extending thread.started payload to preserve subagent metadata fields (subAgentThreadSpawn, parentProviderThreadId, depth, agentNickname, agentRole) through the Codex adapter.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch rat-117-preserve-codex-thread-started-metadata

Comment @coderabbitai help to get the list of available commands and usage tips.

@ratulsarna ratulsarna changed the base branch from main to subagent-support-codex March 7, 2026 21:04
@ratulsarna
Copy link
Copy Markdown
Owner Author

@coderabbitai review

@ratulsarna
Copy link
Copy Markdown
Owner Author

@codex review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 7, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

ℹ️ 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".

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
packages/contracts/src/providerRuntime.test.ts (1)

123-154: Assert payload.status in this regression too.

status is part of the new contract surface, but this test never verifies the decoded value. It still passes if the decoder starts dropping or rewriting that field.

Possible assertion
     expect(parsed.payload.providerThreadId).toBe("provider-thread-1");
     expect(parsed.payload.name).toBeNull();
     expect(parsed.payload.preview).toBe("");
+    expect(parsed.payload.status).toEqual({
+      type: "active",
+      activeFlags: [],
+    });
     expect(parsed.payload.source).toEqual({
       kind: "subAgentThreadSpawn",
       parentProviderThreadId: "provider-parent-1",
       depth: 1,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/contracts/src/providerRuntime.test.ts` around lines 123 - 154, The
test for decoding "thread.started" doesn't assert the new payload.status field,
so regressions can drop or change it; update the test in providerRuntime.test.ts
to assert parsed.payload.status equals the expected object (e.g., { type:
"active", activeFlags: [] }) after the existing assertions for
providerThreadId/name/preview/source, referencing the parsed variable and its
payload.status property to ensure the decoder preserves that field.
packages/contracts/src/providerRuntime.ts (1)

285-292: Make ThreadStartedSource kind-specific.

This flat shape accepts impossible combinations like kind: "subAgentOther" without otherKind, or kind: "cli" with depth. A discriminated contract here would keep malformed canonical events out of downstream ingestion instead of pushing that validation to consumers.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/contracts/src/providerRuntime.ts` around lines 285 - 292,
ThreadStartedSource is currently a flat Schema.Struct that allows impossible
field combos (e.g., kind: "subAgentOther" without otherKind or kind: "cli" with
depth); convert it into a discriminated union keyed on kind (use
Schema.Sum/Schema.Discriminated/Schema.Union as available) where each branch
enforces the correct shape: e.g., a "subAgent"/"subAgentOther" branch requiring
parentProviderThreadId and for "subAgentOther" requiring otherKind, a "cli"
branch disallowing depth, and the agentNickname/agentRole fields only present on
the branches that allow them; update ThreadStartedSource to be this
kind-specific summed schema while reusing existing primitives
(ThreadStartedSourceKind, TrimmedNonEmptyStringSchema, NonNegativeInt) so
downstream consumers get proper validation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/contracts/src/providerRuntime.test.ts`:
- Around line 123-154: The test for decoding "thread.started" doesn't assert the
new payload.status field, so regressions can drop or change it; update the test
in providerRuntime.test.ts to assert parsed.payload.status equals the expected
object (e.g., { type: "active", activeFlags: [] }) after the existing assertions
for providerThreadId/name/preview/source, referencing the parsed variable and
its payload.status property to ensure the decoder preserves that field.

In `@packages/contracts/src/providerRuntime.ts`:
- Around line 285-292: ThreadStartedSource is currently a flat Schema.Struct
that allows impossible field combos (e.g., kind: "subAgentOther" without
otherKind or kind: "cli" with depth); convert it into a discriminated union
keyed on kind (use Schema.Sum/Schema.Discriminated/Schema.Union as available)
where each branch enforces the correct shape: e.g., a "subAgent"/"subAgentOther"
branch requiring parentProviderThreadId and for "subAgentOther" requiring
otherKind, a "cli" branch disallowing depth, and the agentNickname/agentRole
fields only present on the branches that allow them; update ThreadStartedSource
to be this kind-specific summed schema while reusing existing primitives
(ThreadStartedSourceKind, TrimmedNonEmptyStringSchema, NonNegativeInt) so
downstream consumers get proper validation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e99a1385-0930-4a37-8110-329569b861c9

📥 Commits

Reviewing files that changed from the base of the PR and between 59b0527 and 7bf804c.

📒 Files selected for processing (5)
  • apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts
  • apps/server/src/provider/Layers/CodexAdapter.test.ts
  • apps/server/src/provider/Layers/CodexAdapter.ts
  • packages/contracts/src/providerRuntime.test.ts
  • packages/contracts/src/providerRuntime.ts

@ratulsarna ratulsarna merged commit 31a7a77 into subagent-support-codex Mar 7, 2026
1 check passed
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