Companion to lakehouse commit 57bde63 (Rust gateway gains
trace-id propagation + coordinator session JSONL). The
cross-runtime parity probe is the regression gate that prevents
silent schema drift between the two runtimes.
scripts/cutover/parity/session_log_parity.sh:
- 4 fixtures (accepted_grounded, max_iter_exhausted, infra_error,
unicode_in_prompt) feed identical input to both helpers
- jq -e validity gate + non-trivial-equal guard prevents the
"both sides fail identically → spurious match" failure mode
(caught one IFS='||' bug during initial authoring — recorded
in the script comment)
- normalize() strips timestamp + daemon (legitimate per-producer
differences); everything else must be byte-equal
- Result: 4/4 fixtures match, including unicode
scripts/cutover/parity/session_log_helper/main.go:
- Tiny stdin/stdout Go helper that round-trips a fixture
through validator.SessionRecord serde
- Counterpart to crates/gateway/src/bin/parity_session_log.rs
docs/ARCHITECTURE_COMPARISON.md decisions tracker:
- "Rust observability parity" row added (DONE 2026-05-02)
- Cross-runtime probe documented as reusable gate
STATE_OF_PLAY refreshed.
Both observability pieces (trace-id propagation, session JSONL)
now exist on both runtimes. Operators who point Rust gateway and
Go validatord at the same session-log path get a unified
longitudinal stream queryable via DuckDB.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
70 lines
2.3 KiB
Go
70 lines
2.3 KiB
Go
// session_log_helper — Go-side counterpart for the cross-runtime
|
|
// session-log parity probe. Reads a fixture JSON on stdin, builds a
|
|
// SessionRecord, emits one JSONL row to stdout.
|
|
//
|
|
// Used by scripts/cutover/parity/session_log_parity.sh.
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"time"
|
|
|
|
"git.agentview.dev/profit/golangLAKEHOUSE/internal/validator"
|
|
)
|
|
|
|
// fixtureInput shape mirrors the Rust helper's accepted shape so both
|
|
// helpers can read the same stdin payload.
|
|
type fixtureInput struct {
|
|
SessionID string `json:"session_id"`
|
|
Kind string `json:"kind"`
|
|
Model string `json:"model"`
|
|
Provider string `json:"provider"`
|
|
Prompt string `json:"prompt"`
|
|
Iterations int `json:"iterations"`
|
|
MaxIterations int `json:"max_iterations"`
|
|
FinalVerdict string `json:"final_verdict"`
|
|
Attempts []validator.SessionAttemptRecord `json:"attempts"`
|
|
Artifact map[string]any `json:"artifact"`
|
|
GroundedInRoster *bool `json:"grounded_in_roster"`
|
|
DurationMs int64 `json:"duration_ms"`
|
|
}
|
|
|
|
func main() {
|
|
buf, err := io.ReadAll(os.Stdin)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "read stdin: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
var in fixtureInput
|
|
if err := json.Unmarshal(buf, &in); err != nil {
|
|
fmt.Fprintf(os.Stderr, "parse stdin: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
rec := validator.SessionRecord{
|
|
Schema: validator.SessionRecordSchema,
|
|
SessionID: in.SessionID,
|
|
Timestamp: time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC).Format(time.RFC3339),
|
|
Daemon: "validatord",
|
|
Kind: in.Kind,
|
|
Model: in.Model,
|
|
Provider: in.Provider,
|
|
Prompt: in.Prompt,
|
|
Iterations: in.Iterations,
|
|
MaxIterations: in.MaxIterations,
|
|
FinalVerdict: in.FinalVerdict,
|
|
Attempts: in.Attempts,
|
|
Artifact: in.Artifact,
|
|
GroundedInRoster: in.GroundedInRoster,
|
|
DurationMs: in.DurationMs,
|
|
}
|
|
body, err := json.Marshal(rec)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "marshal: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
fmt.Println(string(body))
|
|
}
|