feat: native interrupt + Task-subagent goldens (pre-metering)#14
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b905b020be
ℹ️ 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".
| "type": "user", | ||
| "content": "Use the Task tool to launch a subagent that answers this question: what is 7 times 6? Report only the subagent's answer." | ||
| }, | ||
| { "type": "wait_control_request", "timeoutMs": 60000 }, |
There was a problem hiding this comment.
Avoid waiting for a permission request that never arrives
In the recorded task-subagent run, native emits no control_request for this prompt, so this wait_control_request delays the sequence until its 60s timeout; by then the result.success has already been seen, and the following wait_result only waits for a new result, causing the harness to hit its 240s timeout and kill the process (the added report records exit code 143). This makes this golden both slow and contaminated with a SIGTERM exit whenever the ground-truth behavior is actually being reproduced; remove the permission wait/response or start waiting for the result immediately.
Useful? React with 👍 / 👎.
The last irreplaceable native ground truth before claude -p bills at metered API pricing on 2026-06-15. Both sets recorded against native 2.1.170 (sonnet). - 2026-06-10-interrupt/: the 7-case interrupt matrix (cases-interrupt.json): control-protocol interrupt and SIGINT during a long task, double interrupt, and interrupt-then-prompt pipelines. Native answers an interrupted turn with result.error_during_execution; follow-up prompts produce result.success. - 2026-06-10-task-subagent/: new case file for a Task subagent round-trip (tool name "Agent" in 2.1.170). Locks in two facts clarp must match: native emits ZERO sidechain lines on -p stdout, and emits system.task_started / system.task_notification events for the subagent lifecycle. The case waits directly for the result — the Agent tool needs no permission, so a wait_control_request would idle 60s and poison the recorded exit code with the harness's timeout SIGTERM (caught by review on the first capture; re-captured cleanly: exit 0, result at ~36s).
b905b02 to
d3cc6fb
Compare
…pe, thinking signature Closes the consumed-field parity gaps confirmed by replay against the 2026-06-09 goldens (PARITY-GAPS #2/#3/#14/#15/#16), and adds the parity-policy tiers to PARITY-GAPS.md (contract / consumed fields / on-demand / won't-fix). - --max-turns now counts assistant API rounds (SSE message_start) like native, not user prompts — a single prompt chaining tools can exhaust it. On exceeding: interrupt, then report result.error_max_turns (is_error, NO result field, num_turns = rounds) and exit 1, even in stream-json mode, whether or not the interrupt beat the turn's natural completion. The old prompt-count check remains as a fallback for backends without SSE. - Ack initialize (truthful payload: commands from transcript init, output_style, pid) and set_permission_mode (echo mode) using native's nested control_response shape {type, response: {subtype, request_id, response}}; migrated the interrupt ack from clarp's old flat shape. - Turn-level backend API errors report subtype "success" with is_error: true (invalid-model golden), not subtype "error"; emitResult decouples is_error from subtype and can omit the result field (error_max_turns has none). - Assembler accumulates signature_delta; thinking blocks are {type, thinking, signature} like native. - Exit code now reflects the last result's is_error on stdin-drain shutdown (native exits 1 after an invalid-model turn even though the stream ends normally).
d3cc6fb to
3f0d23a
Compare
3f0d23a to
5fe0331
Compare
…pe, thinking signature Closes the consumed-field parity gaps confirmed by replay against the 2026-06-09 goldens (PARITY-GAPS #2/#3/#14/#15/#16), and adds the parity-policy tiers to PARITY-GAPS.md (contract / consumed fields / on-demand / won't-fix). - --max-turns now counts assistant API rounds (SSE message_start) like native, not user prompts — a single prompt chaining tools can exhaust it. On exceeding: interrupt, then report result.error_max_turns (is_error, NO result field, num_turns = rounds) and exit 1, even in stream-json mode, whether or not the interrupt beat the turn's natural completion. The old prompt-count check remains as a fallback for backends without SSE. - Ack initialize (truthful payload: commands from transcript init, output_style, pid) and set_permission_mode (echo mode) using native's nested control_response shape {type, response: {subtype, request_id, response}}; migrated the interrupt ack from clarp's old flat shape. - Turn-level backend API errors report subtype "success" with is_error: true (invalid-model golden), not subtype "error"; emitResult decouples is_error from subtype and can omit the result field (error_max_turns has none). - Assembler accumulates signature_delta; thinking blocks are {type, thinking, signature} like native. - Exit code now reflects the last result's is_error on stdin-drain shutdown (native exits 1 after an invalid-model turn even though the stream ends normally).
…pe, thinking signature Closes the consumed-field parity gaps confirmed by replay against the 2026-06-09 goldens (PARITY-GAPS #2/#3/#14/#15/#16), and adds the parity-policy tiers to PARITY-GAPS.md (contract / consumed fields / on-demand / won't-fix). - --max-turns now counts assistant API rounds (SSE message_start) like native, not user prompts — a single prompt chaining tools can exhaust it. On exceeding: interrupt, then report result.error_max_turns (is_error, NO result field, num_turns = rounds) and exit 1, even in stream-json mode, whether or not the interrupt beat the turn's natural completion. The old prompt-count check remains as a fallback for backends without SSE. - Ack initialize (truthful payload: commands from transcript init, output_style, pid) and set_permission_mode (echo mode) using native's nested control_response shape {type, response: {subtype, request_id, response}}; migrated the interrupt ack from clarp's old flat shape. - Turn-level backend API errors report subtype "success" with is_error: true (invalid-model golden), not subtype "error"; emitResult decouples is_error from subtype and can omit the result field (error_max_turns has none). - Assembler accumulates signature_delta; thinking blocks are {type, thinking, signature} like native. - Exit code now reflects the last result's is_error on stdin-drain shutdown (native exits 1 after an invalid-model turn even though the stream ends normally).
…pe, thinking signature Closes the consumed-field parity gaps confirmed by replay against the 2026-06-09 goldens (PARITY-GAPS #2/#3/#14/#15/#16), and adds the parity-policy tiers to PARITY-GAPS.md (contract / consumed fields / on-demand / won't-fix). - --max-turns now counts assistant API rounds (SSE message_start) like native, not user prompts — a single prompt chaining tools can exhaust it. On exceeding: interrupt, then report result.error_max_turns (is_error, NO result field, num_turns = rounds) and exit 1, even in stream-json mode, whether or not the interrupt beat the turn's natural completion. The old prompt-count check remains as a fallback for backends without SSE. - Ack initialize (truthful payload: commands from transcript init, output_style, pid) and set_permission_mode (echo mode) using native's nested control_response shape {type, response: {subtype, request_id, response}}; migrated the interrupt ack from clarp's old flat shape. - Turn-level backend API errors report subtype "success" with is_error: true (invalid-model golden), not subtype "error"; emitResult decouples is_error from subtype and can omit the result field (error_max_turns has none). - Assembler accumulates signature_delta; thinking blocks are {type, thinking, signature} like native. - Exit code now reflects the last result's is_error on stdin-drain shutdown (native exits 1 after an invalid-model turn even though the stream ends normally).
…pe, thinking signature Closes the consumed-field parity gaps confirmed by replay against the 2026-06-09 goldens (PARITY-GAPS #2/#3/#14/#15/#16), and adds the parity-policy tiers to PARITY-GAPS.md (contract / consumed fields / on-demand / won't-fix). - --max-turns now counts assistant API rounds (SSE message_start) like native, not user prompts — a single prompt chaining tools can exhaust it. On exceeding: interrupt, then report result.error_max_turns (is_error, NO result field, num_turns = rounds) and exit 1, even in stream-json mode, whether or not the interrupt beat the turn's natural completion. The old prompt-count check remains as a fallback for backends without SSE. - Ack initialize (truthful payload: commands from transcript init, output_style, pid) and set_permission_mode (echo mode) using native's nested control_response shape {type, response: {subtype, request_id, response}}; migrated the interrupt ack from clarp's old flat shape. - Turn-level backend API errors report subtype "success" with is_error: true (invalid-model golden), not subtype "error"; emitResult decouples is_error from subtype and can omit the result field (error_max_turns has none). - Assembler accumulates signature_delta; thinking blocks are {type, thinking, signature} like native. - Exit code now reflects the last result's is_error on stdin-drain shutdown (native exits 1 after an invalid-model turn even though the stream ends normally).
The last irreplaceable native ground truth before
claude -pbills at metered API pricing on 2026-06-15. Both sets recorded against native 2.1.170 (sonnet); pure additions, independent of #12/#13.2026-06-10-interrupt/— the 7-case interrupt matrix: control-protocol interrupt and SIGINT during a long task, double interrupt, interrupt-then-prompt pipelines. Native answers an interrupted turn withresult.error_during_execution; follow-up prompts produceresult.success.2026-06-10-task-subagent/— new case file for a Task subagent round-trip (tool nameAgentin 2.1.170). Locks in two facts clarp must match: native emits zero sidechain lines on-pstdout, and emitssystem.task_started/system.task_notificationfor the subagent lifecycle.