The 5-loop substrate's load-bearing gate is verified — playbook +
matrix indexer give the results we're looking for. Per the report's
rubric, lift ≥ 50% of discoveries means matrix is doing real work;
7/8 = 87.5% blew through that.
Harness was structurally hiding bugs behind a 5-daemon stripped boot.
Expanding to the full 10-daemon prod stack surfaced 7 fixes in cascade:
1. driver→matrixd: {"query": ...} → {"query_text": ...} field name
2. harness temp toml missing [s3] → wrong default bucket → catalogd
rehydrate 500 on first call
3. harness→queryd SQL probe: {"q": ...} → {"sql": ...} field name
4. expand boot from 5 → 10 daemons in dep-ordered launch
5. add SQL surface probe (3-row CSV ingest → COUNT(*)=3 assertion)
6. candidates corpus was synthetic SWE-tech (Swift/iOS, Scala/Spark) —
wrong domain for staffing queries; replaced with ethereal_workers
(10K rows, real staffing schema, "e-" id prefix to avoid collision
with workers' "w-"). staffing_workers driver gains -index-name +
-id-prefix flags so the same binary serves both corpora
7. local_judge qwen3.5:latest is a vision-SSM 256K-ctx build running
~30s per judge call against the lift loop; reverted to
qwen2.5:latest (~1s/call, 30× faster, held lift theory)
Each contract drift (1, 3) is now locked into a cmd/<bin>/main_test.go
so future drift fires in `go test`, not in a reality run. R-005 closed:
- cmd/matrixd/main_test.go (new) — playbook record drift detector +
score bounds + 6 routes mounted
- cmd/queryd/main_test.go — wrong-field-name drift detector
- cmd/pathwayd/main_test.go (new) — 9 routes + add round-trip + retire
- cmd/observerd/main_test.go (new) — 4 routes + invalid-op + unknown-mode
`go test ./cmd/{matrixd,queryd,pathwayd,observerd}` all green.
Reality test results (reports/reality-tests/playbook_lift_001.{json,md}):
Queries 21 (staffing-domain, 7 categories)
Discoveries 8 (judge ≠ cosine top-1)
Lifts 7/8 (87.5%)
Boosts triggered 9
Mean Δ distance -0.053 (warm closer than cold)
OOD honesty dental/RN/SWE rated 1, no fake matches
Cross-corpus boosts confirmed (e- ↔ w- swaps in lifts)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
155 lines
4.6 KiB
Go
155 lines
4.6 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
)
|
|
|
|
// Closes R-005 for queryd: cmd-level tests for the /sql handler's
|
|
// pre-DB paths (decode, body cap, empty SQL). The actual SQL execution
|
|
// path needs DuckDB so it lives in the smoke chain + proof harness.
|
|
//
|
|
// We construct handlers with a nil *sql.DB — the tests only exercise
|
|
// paths that return early before db.QueryContext. Tests that would
|
|
// reach the db are covered by GOLAKE-040 in the proof harness.
|
|
|
|
func mountedRouter() chi.Router {
|
|
h := &handlers{db: nil}
|
|
r := chi.NewRouter()
|
|
h.register(r)
|
|
return r
|
|
}
|
|
|
|
func TestRoutesMounted(t *testing.T) {
|
|
r := mountedRouter()
|
|
found := false
|
|
chi.Walk(r, func(method, route string, _ http.Handler, _ ...func(http.Handler) http.Handler) error {
|
|
if method == "POST" && route == "/sql" {
|
|
found = true
|
|
}
|
|
return nil
|
|
})
|
|
if !found {
|
|
t.Error("POST /sql not mounted")
|
|
}
|
|
}
|
|
|
|
func TestHandleSQL_BodyTooLarge(t *testing.T) {
|
|
// 4xx range — see embedd's TestHandleEmbed_BodyTooLarge for the
|
|
// 413-vs-400 detail. The contract is "client error, fails loud."
|
|
r := mountedRouter()
|
|
srv := httptest.NewServer(r)
|
|
defer srv.Close()
|
|
|
|
big := bytes.Repeat([]byte("x"), maxSQLBodyBytes+1024)
|
|
resp, err := http.Post(srv.URL+"/sql", "application/json", bytes.NewReader(big))
|
|
if err != nil {
|
|
t.Fatalf("POST: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
if resp.StatusCode < 400 || resp.StatusCode >= 500 {
|
|
t.Errorf("expected 4xx on oversize, got %d", resp.StatusCode)
|
|
}
|
|
}
|
|
|
|
func TestHandleSQL_MalformedJSON_400(t *testing.T) {
|
|
r := mountedRouter()
|
|
srv := httptest.NewServer(r)
|
|
defer srv.Close()
|
|
|
|
resp, err := http.Post(srv.URL+"/sql", "application/json", strings.NewReader("not json"))
|
|
if err != nil {
|
|
t.Fatalf("POST: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
if resp.StatusCode != http.StatusBadRequest {
|
|
t.Errorf("expected 400 on malformed, got %d", resp.StatusCode)
|
|
}
|
|
}
|
|
|
|
// TestHandleSQL_WrongFieldName_400 locks the JSON tag on sqlRequest.SQL
|
|
// against drift. The 2026-04-30 playbook_lift harness sent {"q": "..."}
|
|
// — the Go decoder ignores unknown fields by default, so req.SQL stays
|
|
// empty and the empty-check fires with "sql is empty". If anyone renames
|
|
// the JSON tag, callers POSTing the new (wrong) shape would hit this
|
|
// same path; this test makes the contract explicit so the failure mode
|
|
// is documented rather than discovered during a reality run.
|
|
func TestHandleSQL_WrongFieldName_400(t *testing.T) {
|
|
r := mountedRouter()
|
|
srv := httptest.NewServer(r)
|
|
defer srv.Close()
|
|
|
|
cases := []string{
|
|
`{"q":"SELECT 1"}`, // the actual 2026-04-30 harness shape
|
|
`{"query":"SELECT 1"}`, // matrixd-style drift in the other direction
|
|
`{"statement":"SELECT 1"}`,
|
|
}
|
|
for _, body := range cases {
|
|
t.Run(body, func(t *testing.T) {
|
|
resp, err := http.Post(srv.URL+"/sql", "application/json", strings.NewReader(body))
|
|
if err != nil {
|
|
t.Fatalf("POST: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
if resp.StatusCode != http.StatusBadRequest {
|
|
t.Errorf("expected 400 on wrong field name, got %d", resp.StatusCode)
|
|
}
|
|
rb, _ := io.ReadAll(resp.Body)
|
|
if !strings.Contains(string(rb), "sql is empty") {
|
|
t.Errorf("expected 'sql is empty' to anchor the contract, got %q", string(rb))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestHandleSQL_EmptySQL_400(t *testing.T) {
|
|
r := mountedRouter()
|
|
srv := httptest.NewServer(r)
|
|
defer srv.Close()
|
|
|
|
cases := []string{
|
|
`{"sql":""}`,
|
|
`{"sql":" "}`,
|
|
`{"sql":"\n\t \n"}`,
|
|
}
|
|
for _, body := range cases {
|
|
t.Run(body, func(t *testing.T) {
|
|
resp, err := http.Post(srv.URL+"/sql", "application/json", strings.NewReader(body))
|
|
if err != nil {
|
|
t.Fatalf("POST: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
if resp.StatusCode != http.StatusBadRequest {
|
|
t.Errorf("expected 400 on empty/whitespace SQL, got %d", resp.StatusCode)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMaxSQLBodyBytes_Reasonable(t *testing.T) {
|
|
// SQL strings shouldn't be huge — 64 KiB is generous for queryd
|
|
// (DuckDB statements above 64 KiB are pathological). Locking the
|
|
// constant prevents an accidental refactor from blowing this open.
|
|
if maxSQLBodyBytes < 16<<10 {
|
|
t.Errorf("maxSQLBodyBytes=%d below sane SQL minimum (16 KiB)", maxSQLBodyBytes)
|
|
}
|
|
if maxSQLBodyBytes > 1<<20 {
|
|
t.Errorf("maxSQLBodyBytes=%d above sane SQL maximum (1 MiB)", maxSQLBodyBytes)
|
|
}
|
|
}
|
|
|
|
func TestPrimaryBucket_Constant(t *testing.T) {
|
|
// Locks the logical bucket name — secrets provider lookup keys
|
|
// against this. Refactor that flips this would silently fail
|
|
// secret resolution for queryd at startup.
|
|
if primaryBucket != "primary" {
|
|
t.Errorf("primaryBucket = %q, want %q", primaryBucket, "primary")
|
|
}
|
|
}
|