root fa4e1b4e16 parity: session_log probe + Rust observability parity recorded
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>
2026-05-02 05:39:49 -05:00

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))
}