Avoid copying output during basic validation

This commit is contained in:
2026-10-09 00:13:23 +00:00
parent 05fe13d80b
commit ed7c27324d
3 changed files with 45 additions and 24 deletions

View File

@@ -151,7 +151,8 @@ control into the rendered prompt. The
`internal/validate` provides validators backed by an operating-system
filesystem or an `fs.FS`. Invalid generated content is returned as a validation
result; inability to load, register, or compile a schema is an operational
error.
error. Basic validation checks body emptiness on the byte slice directly
instead of first making a response-sized string copy.
Every preparation operation creates one operation-local validation plan. None,
basic, and JSON modes retain the effective output contract without source

View File

@@ -188,7 +188,7 @@ func validateArtifact(ctx context.Context, artifact *domain.Artifact, contract d
res.IsValid = true
return res, nil
case domain.ValidationBasic:
empty := strings.TrimSpace(string(artifact.Body)) == ""
empty := len(bytes.TrimSpace(artifact.Body)) == 0
if err := ctx.Err(); err != nil {
return domain.ValidationResult{}, err
}

View File

@@ -36,8 +36,15 @@ func TestStandardValidatorNoneSkipped(t *testing.T) {
func TestStandardValidatorBasicSuccess(t *testing.T) {
v := NewStandardValidator("")
res, err := v.Validate(context.Background(), &domain.Artifact{Body: []byte("hello")}, domain.OutputContract{
for _, tc := range []struct {
name string
body []byte
}{
{name: "text", body: []byte("hello")},
{name: "invalid UTF-8 byte", body: []byte{0xff}},
} {
t.Run(tc.name, func(t *testing.T) {
res, err := v.Validate(context.Background(), &domain.Artifact{Body: tc.body}, domain.OutputContract{
ValidationMode: domain.ValidationBasic,
})
if err != nil {
@@ -46,12 +53,22 @@ func TestStandardValidatorBasicSuccess(t *testing.T) {
if res.Status != domain.ValidationPassed || !res.IsValid {
t.Fatalf("expected passed/valid, got status=%q valid=%v", res.Status, res.IsValid)
}
})
}
}
func TestStandardValidatorBasicFailureEmpty(t *testing.T) {
v := NewStandardValidator("")
res, err := v.Validate(context.Background(), &domain.Artifact{Body: []byte(" \n\t ")}, domain.OutputContract{
for _, tc := range []struct {
name string
body []byte
}{
{name: "empty bytes", body: []byte{}},
{name: "ASCII whitespace", body: []byte(" \n\t ")},
{name: "Unicode whitespace", body: []byte("\u2003\u00a0\u3000")},
} {
t.Run(tc.name, func(t *testing.T) {
res, err := v.Validate(context.Background(), &domain.Artifact{Body: tc.body}, domain.OutputContract{
ValidationMode: domain.ValidationBasic,
})
if err != nil {
@@ -63,6 +80,8 @@ func TestStandardValidatorBasicFailureEmpty(t *testing.T) {
if len(res.Errors) == 0 {
t.Fatal("expected validation errors")
}
})
}
}
func TestStandardValidatorReportsZeroRepairAttempts(t *testing.T) {
@@ -947,7 +966,8 @@ func BenchmarkBasicValidation(b *testing.B) {
}
b.ReportAllocs()
b.SetBytes(int64(len(benchmark.body)))
// Nonempty input can be classified from its boundary bytes without
// scanning the body, so report latency rather than bytes per second.
b.ResetTimer()
for range b.N {
result, err := validator.Validate(ctx, artifact, contract)