Two threads landing together — the doc edits interleave so they ship in a single commit. 1. **vectord substrate fix verified at original scale** (closes the 2026-05-01 thread). Re-ran multitier 5min @ conc=50: 132,211 scenarios at 438/sec, 6/6 classes at 0% failure (was 4/6 pre-fix). Throughput dropped 1,115 → 438/sec because previously-broken scenarios now do real HNSW Add work — honest cost of correctness. The fix (i.vectors side-store + safeGraphAdd recover wrappers + smallIndexRebuildThreshold=32 + saveTask coalescing) holds at the footprint that originally surfaced the bug. 2. **Materializer port** — internal/materializer + cmd/materializer + scripts/materializer_smoke.sh. Ports scripts/distillation/transforms.ts (12 transforms) + build_evidence_index.ts (idempotency, day-partition, receipt). On-wire JSON shape matches TS so Bun and Go runs are interchangeable. 14 tests green. 3. **Replay port** — internal/replay + cmd/replay + scripts/replay_smoke.sh. Ports scripts/distillation/replay.ts (retrieve → bundle → /v1/chat → validate → log). Closes audit-FULL phase 7 live invocation on the Go side. Both runtimes append to the same data/_kb/replay_runs.jsonl (schema=replay_run.v1). 14 tests green. Side effect on internal/distillation/types.go: EvidenceRecord gained prompt_tokens, completion_tokens, and metadata fields to mirror the TS shape the materializer transforms produce. STATE_OF_PLAY refreshed to 2026-05-02; ARCHITECTURE_COMPARISON decisions tracker moves the materializer + replay items from _open_ to DONE and adds the substrate-fix scale verification row. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
132 lines
4.0 KiB
Go
132 lines
4.0 KiB
Go
package materializer
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
"git.agentview.dev/profit/golangLAKEHOUSE/internal/distillation"
|
|
)
|
|
|
|
// ValidateEvidenceRecord ports validateEvidenceRecord from
|
|
// auditor/schemas/distillation/evidence_record.ts. Returns nil on
|
|
// success or a slice of human-readable error messages — the
|
|
// materializer logs the slice into distillation_skips.jsonl so an
|
|
// operator can see why a row was rejected without diff'ing logic.
|
|
//
|
|
// The validator is intentionally separate from
|
|
// distillation.ValidateScoredRun: scoring runs and evidence records
|
|
// have different shapes and the scorer's validator only covers the
|
|
// scored-run side.
|
|
func ValidateEvidenceRecord(r distillation.EvidenceRecord) []string {
|
|
var errs []string
|
|
|
|
if r.RunID == "" {
|
|
errs = append(errs, "run_id: must be non-empty")
|
|
}
|
|
if r.TaskID == "" {
|
|
errs = append(errs, "task_id: must be non-empty")
|
|
}
|
|
if !validISOTimestamp(r.Timestamp) {
|
|
errs = append(errs, fmt.Sprintf("timestamp: not a valid ISO 8601 timestamp: %s", trim(r.Timestamp, 60)))
|
|
}
|
|
if r.SchemaVersion != distillation.EvidenceSchemaVersion {
|
|
errs = append(errs, fmt.Sprintf("schema_version: expected %d, got %d", distillation.EvidenceSchemaVersion, r.SchemaVersion))
|
|
}
|
|
errs = append(errs, validateProvenanceFields(r.Provenance)...)
|
|
|
|
if r.ModelRole != "" && !isValidModelRole(r.ModelRole) {
|
|
errs = append(errs, fmt.Sprintf("model_role: must be a known role, got %q", r.ModelRole))
|
|
}
|
|
if r.InputHash != "" && !isHexSha256(r.InputHash) {
|
|
errs = append(errs, "input_hash: must be hex sha256 when present")
|
|
}
|
|
if r.OutputHash != "" && !isHexSha256(r.OutputHash) {
|
|
errs = append(errs, "output_hash: must be hex sha256 when present")
|
|
}
|
|
if r.ObserverConfidence < 0 || r.ObserverConfidence > 100 {
|
|
errs = append(errs, "observer_confidence: must be in [0, 100]")
|
|
}
|
|
if r.HumanOverride != nil {
|
|
if r.HumanOverride.Overrider == "" {
|
|
errs = append(errs, "human_override.overrider: must be non-empty")
|
|
}
|
|
if r.HumanOverride.Reason == "" {
|
|
errs = append(errs, "human_override.reason: must be non-empty")
|
|
}
|
|
if !validISOTimestamp(r.HumanOverride.OverriddenAt) {
|
|
errs = append(errs, "human_override.overridden_at: must be ISO 8601")
|
|
}
|
|
switch r.HumanOverride.Decision {
|
|
case "accept", "reject", "needs_review":
|
|
default:
|
|
errs = append(errs, "human_override.decision: must be accept|reject|needs_review")
|
|
}
|
|
}
|
|
|
|
if len(errs) == 0 {
|
|
return nil
|
|
}
|
|
return errs
|
|
}
|
|
|
|
func validateProvenanceFields(p distillation.Provenance) []string {
|
|
var errs []string
|
|
if p.SourceFile == "" {
|
|
errs = append(errs, "provenance.source_file: must be non-empty")
|
|
}
|
|
if !isHexSha256(p.SigHash) {
|
|
errs = append(errs, fmt.Sprintf("provenance.sig_hash: not a valid hex sha256: %s", trim(p.SigHash, 80)))
|
|
}
|
|
if !validISOTimestamp(p.RecordedAt) {
|
|
errs = append(errs, "provenance.recorded_at: must be ISO 8601")
|
|
}
|
|
return errs
|
|
}
|
|
|
|
var (
|
|
// Permissive ISO 8601 (matches TS regex):
|
|
// YYYY-MM-DDTHH:MM:SS(.fraction)?(Z|±HH:MM)?
|
|
isoTimestampRE = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?$`)
|
|
hexSha256RE = regexp.MustCompile(`^[0-9a-f]{64}$`)
|
|
)
|
|
|
|
func validISOTimestamp(s string) bool {
|
|
if s == "" {
|
|
return false
|
|
}
|
|
if !isoTimestampRE.MatchString(s) {
|
|
return false
|
|
}
|
|
// Belt-and-suspenders: confirm it's actually parseable too.
|
|
if _, err := time.Parse(time.RFC3339, s); err == nil {
|
|
return true
|
|
}
|
|
if _, err := time.Parse(time.RFC3339Nano, s); err == nil {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func isHexSha256(s string) bool {
|
|
return hexSha256RE.MatchString(s)
|
|
}
|
|
|
|
func isValidModelRole(role distillation.ModelRole) bool {
|
|
switch role {
|
|
case distillation.RoleExecutor, distillation.RoleReviewer, distillation.RoleExtractor,
|
|
distillation.RoleVerifier, distillation.RoleCategorizer, distillation.RoleTiebreaker,
|
|
distillation.RoleApplier, distillation.RoleEmbedder, distillation.RoleOther:
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func trim(s string, n int) string {
|
|
if len(s) <= n {
|
|
return s
|
|
}
|
|
return strings.ReplaceAll(s[:n], "\n", " ")
|
|
}
|