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>
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
// 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))
|
||||
}
|
||||
Reference in New Issue
Block a user