//! Cross-runtime parity helper for `SessionRecord` JSON shape. //! //! Reads a fixture JSON on stdin, builds a `SessionRecord`, emits //! one JSONL row on stdout. Used by //! `golangLAKEHOUSE/scripts/cutover/parity/session_log_parity.sh` //! to verify the Rust gateway's session log shape stays byte-equal //! to the Go-side validatord's `validator.SessionRecord` (commit //! 1a3a82a in golangLAKEHOUSE). use gateway::v1::session_log::{SessionAttemptRecord, SessionRecord, SESSION_RECORD_SCHEMA}; use serde::Deserialize; use std::io::Read; #[derive(Deserialize)] struct FixtureInput { session_id: String, kind: String, model: String, provider: String, prompt: String, iterations: u32, max_iterations: u32, final_verdict: String, attempts: Vec, #[serde(default)] artifact: Option, #[serde(default)] grounded_in_roster: Option, duration_ms: u64, } fn main() { let mut buf = String::new(); if let Err(e) = std::io::stdin().read_to_string(&mut buf) { eprintln!("read stdin: {e}"); std::process::exit(1); } let input: FixtureInput = match serde_json::from_str(&buf) { Ok(v) => v, Err(e) => { eprintln!("parse stdin: {e}"); std::process::exit(1); } }; let rec = SessionRecord { schema: SESSION_RECORD_SCHEMA.to_string(), session_id: input.session_id, // Pinned timestamp so both runtimes' rows compare byte-equal // when the test wrapper normalizes on `daemon` only. timestamp: "2026-01-01T00:00:00+00:00".to_string(), daemon: "gateway".to_string(), kind: input.kind, model: input.model, provider: input.provider, prompt: input.prompt, iterations: input.iterations, max_iterations: input.max_iterations, final_verdict: input.final_verdict, attempts: input.attempts, artifact: input.artifact, grounded_in_roster: input.grounded_in_roster, duration_ms: input.duration_ms, }; match serde_json::to_string(&rec) { Ok(s) => println!("{s}"), Err(e) => { eprintln!("marshal: {e}"); std::process::exit(1); } } }