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

6.4 KiB
Raw Blame History

Streaming Markdown PR #1920 — Reviewer Takeaways (bolinfest)

DOs

  • Boldly separate unrelated changes: land independent fixes in their own commits/PRs.

    • Why: Keeps review focused and reduces risk. Example: handle a new SSE event in core separately from UI streaming changes.
    • Example:
      // Commit A (core): precise SSE handling
      match event_name.as_str() {
          "response.reasoning_summary_part.added" => { /* intentionally ignored */ }
          "response.reasoning_summary_text.done" => {
              let event = ResponseEvent::ReasoningSummaryDelta("\n\n".to_string());
              if tx_event.send(Ok(event)).await.is_err() { return; }
          }
          other => debug!(other, "sse event"),
      }
      
      // Commit B (tui): markdown streaming mechanics
      // ... all UI-only code here ...
      
  • Be precise about where logic belongs: put new behavior on the exact event arm intended.

    • Why: Avoids accidental logging/no-op paths and makes intent obvious.
    • Example:
      match event_name.as_str() {
          // Correct: “part.added” is handled (ignored) distinctly,
          // so it doesnt fall into `other` logging.
          "response.reasoning_summary_part.added" => { /* ignore */ }
      
          // Correct: the “text.done” terminator emits a separator.
          "response.reasoning_summary_text.done" => {
              let e = ResponseEvent::ReasoningSummaryDelta("\n\n".to_string());
              if tx_event.send(Ok(e)).await.is_err() { return; }
          }
      
          other => debug!(other, "sse event"),
      }
      
  • Implement fenced code parsing per Markdown rules: detect fences of length ≥ 3 and require an exact-length match to close; support both backticks and tildes.

    • Why: Real markdown allows longer fences; closing fence length must equal opening length.
    • Example:
      fn fence_open(line: &str) -> Option<(&'static str, usize, Option<String>)> {
          let t = line.trim_start();
          for token in ["`", "~"] {
              let count = t.chars().take_while(|&c| c.to_string() == token).count();
              if count >= 3 {
                  let rest = &t[count..];
                  let lang = rest.trim().split_whitespace().next()
                      .filter(|s| !s.is_empty()).map(|s| s.to_string());
                  return Some((token, count, lang));
              }
          }
          None
      }
      
      fn fence_close(line: &str, token: &str, len: usize) -> bool {
          let t = line.trim();
          t.chars().take_while(|&c| c.to_string() == token).count() == len
              && t.chars().skip(len).all(char::is_whitespace)
      }
      
  • Guard streaming against partial fences: buffer inside an open fence and emit only after the closing fence arrives.

    • Why: Prevents stray backticks and malformed code in history.
    • Example:
      if in_fence {
          if fence_close(delta_line, fence_token, fence_len) {
              in_fence = false;
              commit(render_code_block(&buffered_code));
              buffered_code.clear();
          } else {
              buffered_code.push_str(delta_line);
          }
          continue;
      }
      
  • Add tight tests for edge cases the spec permits: longer fences, mismatched closers, mixed tildes/backticks, and headings or lists adjacent to code blocks.

    • Example:
      // open with 5 backticks, close with exactly 5
      assert!(fence_open("`````rust").is_some());
      assert!(fence_close("`````", "`", 5));
      assert!(!fence_close("```", "`", 5)); // wrong length
      // support tildes too
      assert!(fence_open("~~~~~").is_some());
      
  • Keep comments crisp and intent-focused: explain “why” (spec/contract) where non-obvious, not “what”.

    • Example:
      // Markdown: closing fence must equal opening fence length (CommonMark).
      if fence_close(line, token, len) { /* ... */ }
      

DONTs

  • Dont couple orthogonal fixes to UI refactors.

    • Anti-pattern:
      // Mixed in the streaming PR:
      // - add new SSE event handling in core
      // - change TUI streaming, animation, and tests
      // Reviewers cant isolate the behavioral change from UI changes.
      
    • Preferred: land the SSE event handling first (or separately), then the TUI work.
  • Dont place new logic on the wrong match arm (or hide it behind “other” logging).

    • Anti-pattern:
      match event_name.as_str() {
          // Oops: both events lumped into the ignored set
          "response.reasoning_summary_part.added"
          | "response.reasoning_summary_text.done" => { /* ignored */ }
          other => debug!(other, "sse event"),
      }
      
    • Fix:
      "response.reasoning_summary_part.added" => { /* ignore */ }
      "response.reasoning_summary_text.done" => { /* emit separator */ }
      
  • Dont assume fences are exactly three backticks; dont allow mismatched closers.

    • Anti-pattern:
      if line.trim_start().starts_with("```") { in_fence = true; }
      // ...
      if line.trim() == "```" { in_fence = false; } // wrong: ignores 4+, mismatch
      
    • Fix:
      if let Some((tok, len, _)) = fence_open(line) {
          fence_token = tok.to_string();
          fence_len = len;
          in_fence = true;
      }
      if fence_close(line, &fence_token, fence_len) { in_fence = false; }
      
  • Dont stream incomplete fenced content or fence markers into history.

    • Anti-pattern:
      history.push(format!("```{}", lang).into()); // shows the opening fence
      history.push(current_partial_code_line.into()); // before fence closes
      
    • Fix:
      if !in_fence { history.extend(committed_lines); }
      // When fence closes:
      history.extend(render_code_block_exact(&buffered_code));
      
  • Dont rely on default logging to signal correctness for ignored events.

    • Anti-pattern:
      // Let it fall into `other => debug!`
      
    • Fix:
      "response.reasoning_summary_part.added" => { /* intentionally ignored */ }
      // Ensures no misleading warnings/logging elsewhere.
      
  • Dont leave tests ambiguous about intent (e.g., “works” without spec reference).

    • Anti-pattern:
      #[test]
      fn fence_parsing_works() { /* vague, brittle */ }
      
    • Fix:
      #[test]
      fn closes_only_with_equal_length_fence() {
          let (tok, n, _) = fence_open("````txt").unwrap();
          assert!(fence_close("````", tok, n));
          assert!(!fence_close("```", tok, n));
      }