Files
codex/prs/bolinfest/study/PR-1587-study.md
2025-09-02 15:17:45 -07:00

4.3 KiB
Raw Blame History

DOs

  • Disable Flaky Tests Properly: Use #[ignore] with a clear reason and keep doc comments truthful.
/// Verifies the agent retries when SSE ends before `response.completed`.
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
#[ignore] // flaky: race condition; tracked in GH-1234
async fn retries_on_early_close() {
    // test body...
}
  • Process SSE Incrementally: Handle events as they arrive rather than buffering everything first.
// Good: act on events as they stream in
while let Some(Ok(event)) = stream.next().await {
    match event {
        // handle events...
        _ => {}
    }
}
  • Wire Delta Events EndtoEnd: Add protocol types, parse SSE fields, and forward deltas through the system.
// protocol.rs
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct AgentMessageDeltaEvent { pub delta: String }

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct AgentReasoningDeltaEvent { pub delta: String }

#[derive(Debug, Clone, Deserialize, Serialize)]
pub enum EventMsg {
    AgentMessageDelta(AgentMessageDeltaEvent),
    AgentReasoningDelta(AgentReasoningDeltaEvent),
    // ...
}

// client.rs (SSE -> ResponseEvent)
match event_type.as_str() {
    "response.output_text.delta" => {
        if let Some(delta) = event.delta { tx_event.send(Ok(ResponseEvent::OutputTextDelta(delta))).await.ok(); }
    }
    "response.reasoning_summary_text.delta" => {
        if let Some(delta) = event.delta { tx_event.send(Ok(ResponseEvent::ReasoningSummaryDelta(delta))).await.ok(); }
    }
    _ => {}
}
  • Ignore Deltas During Aggregation: Skip deltas when the consumer expects a final, aggregated output.
match Pin::new(self).poll_next(cx) {
    Poll::Ready(Some(Ok(ResponseEvent::OutputTextDelta(_))))
    | Poll::Ready(Some(Ok(ResponseEvent::ReasoningSummaryDelta(_)))) => {
        // aggregation waits for OutputItemDone
        continue;
    }
    _ => {}
}
  • Write Precise Test Assertions: Assert on exact lines or structured outputs, not naive substring counts.
let hi_lines = stdout.lines().filter(|line| line.trim() == "hi").count();
assert_eq!(hi_lines, 1, "Expected exactly one line with 'hi'");
  • Handle New Variants Explicitly Across Consumers: Update exec, mcp-server, and tui match arms even if only to TODO.
match event.msg {
    EventMsg::AgentMessageDelta(AgentMessageDeltaEvent { delta: _ }) => {
        // TODO: decide CLI streaming UX
    }
    EventMsg::AgentReasoningDelta(AgentReasoningDeltaEvent { delta: _ }) => {
        // TODO: decide CLI streaming UX
    }
    _ => {}
}
  • RightSize Channels (Prefer Constants/Config): Justify capacity changes and make them easy to tune.
const RESPONSE_EVENT_CAP: usize = 1600; // large bursts during delta streaming
let (tx_event, rx_event) = mpsc::channel::<Result<ResponseEvent>>(RESPONSE_EVENT_CAP);

DONTs

  • Dont Commit Large Blocks of CommentedOut Code: Remove or revert; dont leave dead code in the tree.
// BAD: commented-out file contents
// //! Verifies that the agent retries when...
// use std::time::Duration;
// #[tokio::test] async fn ... {}
  • Dont Buffer the Entire Stream Before Acting: This risks timeouts and hides streaming regressions.
// BAD: buffer first, act later
let mut input = Vec::new();
while let Some(event) = stream.next().await {
    input.push(event?);
}
for event in input { /* ... */ }
  • Dont Swallow New Events With CatchAlls: Add explicit variants so future changes arent silently ignored.
// BAD: hides new protocol messages
match event {
    _ => { /* ignored */ }
}

// GOOD: enumerate and handle (or TODO)
match event {
    EventMsg::AgentMessageDelta(_) => { /* TODO */ }
    EventMsg::AgentReasoningDelta(_) => { /* TODO */ }
    _ => {}
}
  • Dont Leave ContextFree TODOs: Include what/why and a tracking reference so cleanup is actionable.
// BAD
// TODO: support this

// GOOD
// TODO(GH-1234): Stream deltas in TUI; buffer per message ID and repaint incrementally.
  • Dont Mix Unrelated or Mistaken Merges: If a file was merged by mistake, revert it instead of commenting it out.
# Revert an unintended file change cleanly
git checkout origin/main -- codex-rs/core/tests/stream_no_completed.rs