Repository navigation
Name the spawning call on a Codex subagent's start - #1939
realtonyyoung wants to merge 1 commit into
Conversation
An import posts every start after the parent transcript, so the server can place a subagent's row only by the call; a grandchild names its root-level ancestor's call, since it is imported onto the root Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PR Summary by QodoPlace Codex subagents at their spawning calls
AI Description
Diagram
High-Level Assessment
Files changed (4)
|
Code Review by Qodo
1. JSON type checks bypass shared helpers
|
| if (output.TryGetProperty("output", out var body) && body.ValueKind == JsonValueKind.String) { | ||
| try { |
There was a problem hiding this comment.
1. Json type checks bypass shared helpers 📘 Rule violation ⚙ Maintainability
TaskNameOf compares JsonElement.ValueKind directly for string and object detection instead of using the available JsonElementExtensions helpers. Any future type-checking change must be repeated in these branches, leaving the new Codex rollout parsing path inconsistent with the shared JSON conventions.
Agent Prompt
## Issue description
The new `TaskNameOf` implementation directly compares `JsonElement.ValueKind`, contrary to the shared JSON helper convention.
## Fix Focus Areas
- src/Capacitor.Cli.Core/Harness/Codex/CodexSubagentDiscovery.cs[307-311]
## Recommended Fix
Replace the direct string and object `ValueKind` comparisons with the corresponding `JsonElementExtensions` methods, such as `IsString()` and `IsObject()`, while preserving the existing parsing behavior.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| var day = DayDir(tmp.Path); | ||
| var parent = WriteParent(day); | ||
| File.AppendAllLines(parent, [ | ||
| Item("""{"type":"function_call","name":"spawn_agent","namespace":"collaboration","call_id":"call_spawn","arguments":"{\"task_name\":\"spec_quality\"}"}"""), | ||
| Item("""{"type":"function_call_output","call_id":"call_spawn","output":"{\"task_name\":\"/root/spec_quality\"}"}"""), | ||
| Item("""{"type":"function_call","name":"exec_command","call_id":"call_exec","arguments":"{}"}"""), |
There was a problem hiding this comment.
2. Test writes temp files outside helpers 📘 Rule violation ⚙ Maintainability
The new test appends directly with File.AppendAllLines(parent, ...) after deriving parent from tmp.Path, rather than using the TempDir file helpers for state under the temporary root. This bypasses the helper's path and file-operation abstraction in the new filesystem-writing path, even though disposal still occurs at the end of the test.
Agent Prompt
## Issue description
The new test performs direct filesystem writes under `tmp.Path` instead of using `TempDir` path and file helpers.
## Fix Focus Areas
- test/Capacitor.Cli.Tests.Unit/Harness/Codex/CodexSubagentDiscoveryTests.cs[263-271]
## Recommended Fix
Construct the rollout paths with `TempDir.PathTo` or `CreateDir`, and create or update the parent rollout through `TempDir.CreateFile` or another helper-backed operation rather than calling `File.AppendAllLines` directly under the temporary root.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Part of AI-3070 (no GitHub issue)
What & why
A Codex import posts every subagent's start after the whole parent transcript, so the server puts every Codex agent row under the last turn. The start now carries
spawn_call_id: the parent'sspawn_agentcall whose output names the agent'sagent_pathas itstask_name. A grandchild is imported onto the root, so it names its nearest root-level ancestor's call. The live watcher sends the same field, read once per scan that finds a new childThe server half, which stores the call on the start and places the row by it, is kurrent-io/kcap-server#2673. A server without it ignores the field
Where to look
ReadSpawnCallsreads the whole parent rollout once per import. A spawn whose output is not written yet names no call, and the start keeps its own positionVerification
An_imported_subagent_start_names_the_call_that_spawned_it_or_its_ancestordrivesSessionImporter.ImportSessionAsyncover a rollout tree with a child, a grandchild, an agent whose path only another tool's output carries, and a truncated last line. Red when the importer sends no call, and when a non-spawn output is accepted:Expected to be equivalent to [[019fec44…, call_spawn], …]A_path_takes_its_own_spawning_call_or_its_nearest_ancestorsis red on/root/a/b/cwhen the walk stops at the exact pathtask_nameoutputs match real Codex 0.146 rollouts🤖 Generated with Claude Code
Summary by CodeRabbit