refactor(evidence_probe): Phase B language-advantage pass — dichotomy wave
CI Pipeline / best-practices (push) Successful in 8s
CI Pipeline / documentation (push) Successful in 4s
CI Pipeline / rust-surface (push) Failing after 13s
CI Pipeline / go-surface (push) Failing after 20s
CI Pipeline / required-checks (push) Canceled after 0s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Canceled after 0s
CI Pipeline / type-check (push) Canceled after 11s
CI Pipeline / gitea-offline (push) Canceled after 11s
Auto-version and Release / release (push) Canceled after 32s
CI Pipeline / lint (push) Canceled after 25s
CI Pipeline / unit-tests (push) Canceled after 25s
CI Pipeline / canary (push) Canceled after 26s
deploy / deploy (push) Canceled after 35s
CI Pipeline / best-practices (push) Successful in 8s
CI Pipeline / documentation (push) Successful in 4s
CI Pipeline / rust-surface (push) Failing after 13s
CI Pipeline / go-surface (push) Failing after 20s
CI Pipeline / required-checks (push) Canceled after 0s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Canceled after 0s
CI Pipeline / type-check (push) Canceled after 11s
CI Pipeline / gitea-offline (push) Canceled after 11s
Auto-version and Release / release (push) Canceled after 32s
CI Pipeline / lint (push) Canceled after 25s
CI Pipeline / unit-tests (push) Canceled after 25s
CI Pipeline / canary (push) Canceled after 26s
deploy / deploy (push) Canceled after 35s
This commit is contained in:
1 parent
9ba51ba5e8
commit
25f7cb6db4
3 files changed
+238
-15
No files matched your search
@@ -30,6 +30,7 @@ import (
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -284,26 +285,53 @@ func CheckBudget(artifactDir string) error {
|
||||
// ── record_probe ────────────────────────────────────────────────────────────
|
||||
|
||||
// RecordProbe — persist the probe: probe.json (indent=2 artifact) and
|
||||
// probe.jsonl (append-only compact line). Returns the artifact path.
|
||||
// probe.jsonl (append-only compact line). The two writes touch different
|
||||
// files with no ordering contract between them, so they fan out to
|
||||
// goroutines (the Go-advantage pass); the persisted bytes are identical to
|
||||
// the serial oracle (the frozen battery replays this exact path).
|
||||
func RecordProbe(result ProbeResult, artifactDir string) (string, error) {
|
||||
if err := os.MkdirAll(artifactDir, 0o777); err != nil {
|
||||
return "", err
|
||||
}
|
||||
doc := PyDumpsIndent2(result.ToDict())
|
||||
if err := os.WriteFile(filepath.Join(artifactDir, "probe.json"), []byte(doc), 0o666); err != nil {
|
||||
return "", err
|
||||
var (
|
||||
wg sync.WaitGroup
|
||||
mu sync.Mutex
|
||||
firstErr error
|
||||
jsonBytes = []byte(PyDumpsIndent2(result.ToDict()))
|
||||
jsonlBytes = []byte(PyDumpsCompact(result.ToDict()) + "\n")
|
||||
jsonPath = filepath.Join(artifactDir, "probe.json")
|
||||
jsonlPath = filepath.Join(artifactDir, "probe.jsonl")
|
||||
)
|
||||
fail := func(err error) {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
}
|
||||
line := PyDumpsCompact(result.ToDict()) + "\n"
|
||||
f, err := os.OpenFile(filepath.Join(artifactDir, "probe.jsonl"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o666)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if _, err := f.WriteString(line); err != nil {
|
||||
f.Close()
|
||||
return "", err
|
||||
}
|
||||
if err := f.Close(); err != nil {
|
||||
return "", err
|
||||
|
||||
wg.Add(2)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
fail(os.WriteFile(jsonPath, jsonBytes, 0o666))
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
f, err := os.OpenFile(jsonlPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o666)
|
||||
if err != nil {
|
||||
fail(err)
|
||||
return
|
||||
}
|
||||
_, err = f.Write(jsonlBytes)
|
||||
fail(err)
|
||||
fail(f.Close())
|
||||
}()
|
||||
wg.Wait()
|
||||
if firstErr != nil {
|
||||
return "", firstErr
|
||||
}
|
||||
return artifactDir + "/probe.json", nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// phaseb.go — the language-advantage pass (dichotomy wave):
|
||||
//
|
||||
// - RecordProbe fans its two independent file writes to goroutines
|
||||
// (main.go) — the serial oracle's only IO seam where parallelism is
|
||||
// honest; the frozen battery replays bytes through the parallel path.
|
||||
// - Every IO seam is a named interface with a Func adapter and a
|
||||
// compile-time assertion, so a seam breaking its contract fails the
|
||||
// build, not a probe run.
|
||||
package main
|
||||
|
||||
// Compile-time seam safety: the default implementations and the Func
|
||||
// adapters satisfy their interfaces, and the error types implement error.
|
||||
// A seam drifting from its contract fails the build, not a probe run.
|
||||
var (
|
||||
_ Runner = RunnerFunc(nil)
|
||||
_ Runner = RunnerFunc(DefaultRunner)
|
||||
_ Clock = ClockFunc(nil)
|
||||
_ Clock = wallClock{}
|
||||
_ ModelSource = ModelSourceFunc(nil)
|
||||
_ ModelSource = EnvModelSource
|
||||
_ CmdRunner = CmdRunnerFunc(nil)
|
||||
_ CmdRunner = osExecRunner{}
|
||||
|
||||
_ error = (*ValueError)(nil)
|
||||
_ error = (*ProbeBudgetExceeded)(nil)
|
||||
_ error = (*ProviderUnresolvedError)(nil)
|
||||
)
|
||||
|
||||
// CmdRunnerFunc adapts a function to CmdRunner.
|
||||
type CmdRunnerFunc func(bin string, args []string) ([]byte, error)
|
||||
|
||||
func (f CmdRunnerFunc) Run(bin string, args []string) ([]byte, error) {
|
||||
return f(bin, args)
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package main
|
||||
|
||||
// Phase B battery — the language-advantage pass. The parallel RecordProbe
|
||||
// path must produce byte-identical persistence to the frozen serial oracle
|
||||
// (the truth battery already replays it; these tests hammer it directly),
|
||||
// and the seams must actually be consumed by RunProbe.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// exitErrOf — a real *exec.ExitError with the given exit code.
|
||||
func exitErrOf(code int) error {
|
||||
_, err := exec.Command("sh", "-c", fmt.Sprintf("exit %d", code)).Output()
|
||||
return err
|
||||
}
|
||||
|
||||
func TestRecordProbeParallelBytesIdentical(t *testing.T) {
|
||||
result := ProbeResult{
|
||||
Question: "q",
|
||||
Source: "https://example.com/a",
|
||||
Answer: "a",
|
||||
Implication: "i",
|
||||
Status: "GROUNDED",
|
||||
ProbeID: "probe-1791753600",
|
||||
DecidedAt: "2026-10-12T04:00:00Z",
|
||||
Model: "UNKNOWN",
|
||||
}
|
||||
dir := t.TempDir()
|
||||
path, err := RecordProbe(result, dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if path != filepath.Join(dir, "probe.json") {
|
||||
t.Fatalf("returned path drifted: %q", path)
|
||||
}
|
||||
pj, err := os.ReadFile(filepath.Join(dir, "probe.json"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
pjl, err := os.ReadFile(filepath.Join(dir, "probe.jsonl"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// The expected bytes come from the Python-faithful serializers, the
|
||||
// same renderers the frozen truth pins byte-for-byte.
|
||||
wantJSON := PyDumpsIndent2(result.ToDict())
|
||||
wantJSONL := PyDumpsCompact(result.ToDict()) + "\n"
|
||||
if string(pj) != wantJSON {
|
||||
t.Fatalf("probe.json bytes drifted:\n got %q\n want %q", pj, wantJSON)
|
||||
}
|
||||
if string(pjl) != wantJSONL {
|
||||
t.Fatalf("probe.jsonl bytes drifted:\n got %q\n want %q", pjl, wantJSONL)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecordProbeConcurrentHammer(t *testing.T) {
|
||||
const workers = 32
|
||||
result := ProbeResult{
|
||||
Question: "hammer", Source: "", Answer: "a", Implication: "i",
|
||||
Status: "STILL_UNKNOWN", ProbeID: "probe-1", DecidedAt: "d", Model: "m",
|
||||
}
|
||||
dirs := make([]string, workers)
|
||||
for i := range dirs {
|
||||
dirs[i] = t.TempDir()
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
errs := make([]error, workers)
|
||||
for i := 0; i < workers; i++ {
|
||||
wg.Add(1)
|
||||
go func(i int) {
|
||||
defer wg.Done()
|
||||
_, errs[i] = RecordProbe(result, dirs[i])
|
||||
}(i)
|
||||
}
|
||||
wg.Wait()
|
||||
for i, err := range errs {
|
||||
if err != nil {
|
||||
t.Fatalf("worker %d: %v", i, err)
|
||||
}
|
||||
}
|
||||
want := PyDumpsIndent2(result.ToDict())
|
||||
for i, dir := range dirs {
|
||||
pj, err := os.ReadFile(filepath.Join(dir, "probe.json"))
|
||||
if err != nil || string(pj) != want {
|
||||
t.Fatalf("worker %d bytes diverged: %v", i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunProbeConsumesSeams(t *testing.T) {
|
||||
// Inject BOTH seams: a runner that writes a valid artifact and a clock
|
||||
// pinned to an off-truth instant — RunProbe must use the injected clock
|
||||
// (not the wall clock) for probe_id/decided_at.
|
||||
dir := t.TempDir()
|
||||
pinned := time.Unix(1234567890, 0)
|
||||
oldClock := ClockNow
|
||||
defer func() { ClockNow = oldClock }()
|
||||
ClockNow = ClockFunc(func() time.Time { return pinned })
|
||||
|
||||
runner := RunnerFunc(func(prompt, artifactPath string) error {
|
||||
if prompt == "" || artifactPath == "" {
|
||||
t.Fatal("seam received empty prompt/path")
|
||||
}
|
||||
return os.WriteFile(artifactPath, []byte(
|
||||
`{"question": "q", "source": "", "answer": "a", "implication": "i", "status": "STILL_UNKNOWN"}`), 0o666)
|
||||
})
|
||||
result, err := RunProbe("q", dir, runner, "seam-model")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if result.ProbeID != "probe-1234567890" {
|
||||
t.Fatalf("clock seam ignored: probe_id %q", result.ProbeID)
|
||||
}
|
||||
if result.DecidedAt != pinned.UTC().Format("2006-01-02T15:04:05Z") {
|
||||
t.Fatalf("clock seam ignored: decided_at %q", result.DecidedAt)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultRunnerConsumesExecSeam(t *testing.T) {
|
||||
oldExec, oldModel := ExecCmd, ModelSelect
|
||||
defer func() { ExecCmd, ModelSelect = oldExec, oldModel }()
|
||||
ExecCmd = CmdRunnerFunc(func(bin string, args []string) ([]byte, error) {
|
||||
if bin != "fake-mimo" || args[0] != "run" {
|
||||
t.Fatalf("exec seam got bin=%q args=%v", bin, args)
|
||||
}
|
||||
return []byte("ok"), nil
|
||||
})
|
||||
ModelSelect = ModelSourceFunc(func() (string, error) { return "seam-m", nil })
|
||||
|
||||
dir := t.TempDir()
|
||||
t.Setenv("MIMO_BIN", "fake-mimo")
|
||||
t.Setenv("MIMO_AGENT", "seam-agent")
|
||||
if err := DefaultRunner("P", filepath.Join(dir, "evidence_probe.json")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
log, err := os.ReadFile(filepath.Join(dir, "evidence_probe.stdout.log"))
|
||||
if err != nil || string(log) != "ok" {
|
||||
t.Fatalf("stdout log drifted: %q %v", log, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExitCodeErrorMapping(t *testing.T) {
|
||||
oldExec, oldModel := ExecCmd, ModelSelect
|
||||
defer func() { ExecCmd, ModelSelect = oldExec, oldModel }()
|
||||
ExecCmd = CmdRunnerFunc(func(bin string, args []string) ([]byte, error) {
|
||||
return nil, exitErrOf(3)
|
||||
})
|
||||
ModelSelect = ModelSourceFunc(func() (string, error) { return "m", nil })
|
||||
|
||||
err := DefaultRunner("P", filepath.Join(t.TempDir(), "evidence_probe.json"))
|
||||
if err == nil || err.Error() != "probe worker exited 3" {
|
||||
t.Fatalf("exit-code mapping drifted: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user