Commit Graph

1 Commits

Author SHA1 Message Date
teamchong f094649831 Rust transform: match Python's body output byte-for-byte (except PNG)
Three bug fixes surfaced by scripts/diff_transform.py harness, which
synthesizes a realistic Claude Code request body and runs it through both
Python transform_request() and Rust transform(), then JSON-structurally
diffs the outputs.

Before these fixes, harness found:
  - 2 structural diffs in the transformed body JSON
  - 4+ TransformInfo divergences

After these fixes, harness finds:
  - 1 structural diff:  $.messages[0].content[1].source.data
    (the base64 PNG, expected to differ — Menlo vs JetBrains Mono fonts)
  - TransformInfo still differs on byte-vs-char counts (telemetry-only)

Fixes:

1. src/rust/src/transform.rs:93 — per-tool markdown header
   was:  '### Tool: {name}\n{desc}'
   now:  '#### Tool: {name}\n{desc}\n'
   Matches proxy.py:230,233. Also restores the trailing newline that
   Python emits between tool entries.

2. src/rust/src/transform.rs:123 — tool section markdown header
   was:  '\n\n# Tool Documentation\n\n'
   now:  '\n\n#### Tool Documentation\n\n'
   Matches proxy.py:248.

3. src/rust/src/transform.rs:265 — preserve system field by default
   was:  always replaced system with billing_line OR remainder
   now:  only replaces if billing_line was stripped, otherwise leaves
         the original system field untouched.
   Matches proxy.py:417 which intentionally leaves system alone in the
   default PLACEMENT="user" path 'so Anthropic still has guardrails'.
   The image lives in messages[].content as a side-channel; system stays
   as original text. This is the behavior our 95+ live Python requests
   have validated against Anthropic's API.

4. src/rust/src/lib.rs — expose 'transform' module so harnesses and the
   transform_only example can call transform() without going through HTTP.

Added:
  - src/rust/examples/transform_only.rs — CLI binary that reads a body
    from a file and writes the transformed body + TransformInfo as JSON.
  - scripts/diff_transform.py — Python harness that calls both Python
    transform_request() and the Rust transform_only binary, then runs a
    structural JSON diff with field-by-field TransformInfo comparison.

Validation:
  python3 scripts/diff_transform.py
  # → 'found 1 structural diff'
  # → $.messages[0].content[1].source.data (the PNG, expected)

Remaining known telemetry-only diffs (not blocking the swap):
  - system_text_chars: Python counts Unicode chars, Rust counts UTF-8 bytes
  - tool_text_added: same UTF-8 issue
  - expected_image_tokens: ~30% higher in Rust due to ab_glyph 4px cell
    vs PIL 3px cell — Rust images are 33% wider for the same text. Rust
    PNG bytes are still smaller overall because of the tight-bound height
    (which Python also has now, after the previous baseline commit).
  - placement, png_sha8 fields missing from Rust TransformInfo
  - min_chars threshold uses bytes (Rust) vs chars (Python)
  These can be addressed later for full telemetry parity but the
  upstream-visible behavior is byte-equivalent.
2026-05-18 13:03:28 -04:00