root 0d4f033b34 audit_baselines: round-trip validation against live Rust data
Same shape of proof as embed_parity.sh for the embed endpoint:
take the just-shipped Go port (ca142b9) and validate it against
the actual production data the Rust legacy emits, not just unit-
test fixtures. Locks the cross-runtime parity that operators
running mixed pipelines depend on.

scripts/cutover/audit_baselines_validate.go:
- Reads /home/profit/lakehouse/data/_kb/audit_baselines.jsonl
- Parses every entry via the Go AuditBaseline struct
- Round-trips the last entry: encode → decode → field-by-field
  equality check (catches any silently-dropped JSON keys)
- Calls LoadLastBaseline against the live file (proves the public
  API works on real shapes, not just inline parsing)
- Computes BuildAuditDriftTable(first → last) — full-window
  lineage drift over the captured baselines

Live-data probe results (reports/cutover/audit_baselines_roundtrip.md):
- 7 entries parse without error
- Round-trip is byte-equal on every metric + every header field
- Drift table fires the expected verdicts:
  - p2_evidence_rows 12→82 (+583%) → warn (above 20% threshold)
  - p3_accepted/partial/rejected/human 0→non-zero → warn (the
    zero-baseline edge case TestBuildAuditDriftTable_ZeroBaseline
    was designed to lock — verified now firing on real history)
  - p4_* metrics +0% → ok (stable across the window)

What this does NOT prove (documented in the report): the Go-side
audit-FULL pipeline that PRODUCES baselines doesn't exist yet.
Only the load/append/drift substrate is ported. Operators running
audit-full from Go would still need a metric-collection pass —
that's a separate port deliberately not in this wave.

reports/cutover/SUMMARY.md gains a new row alongside the embed
parity entries; cutover-prep verification log keeps the
discipline of "verified against real data, not just fixtures."

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 00:20:18 -05:00

112 lines
3.5 KiB
Go

// audit_baselines_validate — one-shot proof that
// internal/distillation's audit-baseline port round-trips against
// the live Rust-side data/_kb/audit_baselines.jsonl. Loads every
// entry, computes lineage drift between the first and last
// recorded baseline, dumps the formatted drift table.
//
// Usage:
// go run scripts/cutover/audit_baselines_validate.go \
// [-path /home/profit/lakehouse/data/_kb/audit_baselines.jsonl]
//
// Lives in scripts/cutover/ (the same place as embed_parity.sh) so
// the cross-runtime validation pattern stays grouped. Output is
// captured in reports/cutover/audit_baselines_roundtrip.md as the
// evidence record.
package main
import (
"encoding/json"
"flag"
"fmt"
"log"
"os"
"strings"
"git.agentview.dev/profit/golangLAKEHOUSE/internal/distillation"
)
func main() {
path := flag.String("path", "/home/profit/lakehouse/data/_kb/audit_baselines.jsonl",
"Rust-side audit_baselines.jsonl to round-trip")
flag.Parse()
data, err := os.ReadFile(*path)
if err != nil {
log.Fatalf("read %s: %v", *path, err)
}
lines := strings.Split(string(data), "\n")
all := []distillation.AuditBaseline{}
for i, line := range lines {
s := strings.TrimSpace(line)
if s == "" {
continue
}
var b distillation.AuditBaseline
if err := json.Unmarshal([]byte(s), &b); err != nil {
log.Fatalf("decode line %d: %v", i+1, err)
}
all = append(all, b)
}
fmt.Printf("loaded %d baselines from %s\n\n", len(all), *path)
if len(all) == 0 {
log.Fatal("no entries — file is empty")
}
// Round-trip via the Go port: re-encode then decode the LAST
// entry. Bytes-equal proves field names + types match exactly.
last := all[len(all)-1]
enc, err := json.Marshal(last)
if err != nil {
log.Fatalf("re-encode last: %v", err)
}
var rt distillation.AuditBaseline
if err := json.Unmarshal(enc, &rt); err != nil {
log.Fatalf("re-decode last: %v", err)
}
if rt.RecordedAt != last.RecordedAt || rt.GitCommit != last.GitCommit {
log.Fatalf("round-trip mismatch on header fields:\n got: %+v\n want: %+v", rt, last)
}
for k, v := range last.Metrics {
if rt.Metrics[k] != v {
log.Fatalf("round-trip mismatch on metric %s: got %d, want %d", k, rt.Metrics[k], v)
}
}
fmt.Println("✓ round-trip parity (encode → decode → match)")
// LoadLastBaseline against the same file — proves the public API
// surface works on real-shape data, not just the inline parser.
loaded, err := distillation.LoadLastBaseline(*path)
if err != nil {
log.Fatalf("LoadLastBaseline: %v", err)
}
if loaded == nil || loaded.RecordedAt != last.RecordedAt {
log.Fatalf("LoadLastBaseline disagreement with manual parse: got %+v", loaded)
}
fmt.Println("✓ LoadLastBaseline returns the most recent entry")
// Lineage drift: first vs last. Reflects the full historical
// shift across whatever window the file captures. Concrete
// signal that BuildAuditDriftTable handles real-shape inputs.
first := all[0]
rows := distillation.BuildAuditDriftTable(&first, last.Metrics, distillation.DefaultDriftWarnThreshold)
fmt.Printf("\nLineage drift: first (%s) → last (%s)\n",
first.RecordedAt, last.RecordedAt)
fmt.Printf(" span: %d entries\n\n", len(all))
fmt.Println(distillation.FormatAuditDriftTable(rows))
// Summary counts for the report.
warn := 0
firstRun := 0
for _, r := range rows {
switch r.Flag {
case distillation.AuditDriftFlagWarn:
warn++
case distillation.AuditDriftFlagFirstRun:
firstRun++
}
}
fmt.Printf("verdict: %d/%d metrics flagged warn, %d first-run\n", warn, len(rows), firstRun)
}