Replace validator contracts with raw output validation
This commit is contained in:
@@ -386,6 +386,10 @@ func (validator registryValidator) Name() string {
|
||||
return validator.name
|
||||
}
|
||||
|
||||
func (validator registryValidator) Validate(ctx context.Context, req contracts.ValidationRequest) (contracts.ValidationResult, error) {
|
||||
return contracts.ValidationResult{}, nil
|
||||
func (validator registryValidator) ExecutionClass() contracts.ExecutionClass {
|
||||
return contracts.ExecutionClassDeterministic
|
||||
}
|
||||
|
||||
func (validator registryValidator) Validate(ctx context.Context, req contracts.ValidationRequest) (contracts.ValidationResult, error) {
|
||||
return contracts.ValidationResult{Approved: true}, nil
|
||||
}
|
||||
|
||||
@@ -13,16 +13,16 @@ type rawValidationKey struct {
|
||||
}
|
||||
|
||||
type RawValidationRegistry struct {
|
||||
chains map[rawValidationKey][]contracts.RawValidator
|
||||
chains map[rawValidationKey][]contracts.Validator
|
||||
}
|
||||
|
||||
func NewRawValidationRegistry() *RawValidationRegistry {
|
||||
return &RawValidationRegistry{
|
||||
chains: make(map[rawValidationKey][]contracts.RawValidator),
|
||||
chains: make(map[rawValidationKey][]contracts.Validator),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RawValidationRegistry) Register(stage ModuleStage, module string, validators ...contracts.RawValidator) error {
|
||||
func (r *RawValidationRegistry) Register(stage ModuleStage, module string, validators ...contracts.Validator) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("raw validation registry must not be nil")
|
||||
}
|
||||
@@ -39,7 +39,7 @@ func (r *RawValidationRegistry) Register(stage ModuleStage, module string, valid
|
||||
return fmt.Errorf("raw validation chain for %q %q must not be empty", stage, normalizedModule)
|
||||
}
|
||||
|
||||
chain := make([]contracts.RawValidator, 0, len(validators))
|
||||
chain := make([]contracts.Validator, 0, len(validators))
|
||||
for i, validator := range validators {
|
||||
if validator == nil {
|
||||
return fmt.Errorf("raw validator %d for %q %q must not be nil", i, stage, normalizedModule)
|
||||
@@ -47,21 +47,26 @@ func (r *RawValidationRegistry) Register(stage ModuleStage, module string, valid
|
||||
if strings.TrimSpace(validator.Name()) == "" {
|
||||
return fmt.Errorf("raw validator %d for %q %q must not have an empty name", i, stage, normalizedModule)
|
||||
}
|
||||
switch validator.ExecutionClass() {
|
||||
case contracts.ExecutionClassDeterministic, contracts.ExecutionClassLLMBacked:
|
||||
default:
|
||||
return fmt.Errorf("raw validator %q for %q %q has unsupported execution class %q", validator.Name(), stage, normalizedModule, validator.ExecutionClass())
|
||||
}
|
||||
chain = append(chain, validator)
|
||||
}
|
||||
|
||||
if r.chains == nil {
|
||||
r.chains = make(map[rawValidationKey][]contracts.RawValidator)
|
||||
r.chains = make(map[rawValidationKey][]contracts.Validator)
|
||||
}
|
||||
key := rawValidationKey{stage: stage, module: normalizedModule}
|
||||
if _, exists := r.chains[key]; exists {
|
||||
return fmt.Errorf("raw validation chain for %q %q is already registered", stage, normalizedModule)
|
||||
}
|
||||
r.chains[key] = append([]contracts.RawValidator(nil), chain...)
|
||||
r.chains[key] = append([]contracts.Validator(nil), chain...)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *RawValidationRegistry) Validators(stage ModuleStage, module string) []contracts.RawValidator {
|
||||
func (r *RawValidationRegistry) Validators(stage ModuleStage, module string) []contracts.Validator {
|
||||
if r == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -69,5 +74,5 @@ func (r *RawValidationRegistry) Validators(stage ModuleStage, module string) []c
|
||||
if len(chain) == 0 {
|
||||
return nil
|
||||
}
|
||||
return append([]contracts.RawValidator(nil), chain...)
|
||||
return append([]contracts.Validator(nil), chain...)
|
||||
}
|
||||
|
||||
@@ -461,7 +461,7 @@ func (r *Runner) validateRaw(ctx context.Context, target rawValidationTarget) ([
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
request := contracts.RawValidationRequest{
|
||||
request := contracts.ValidationRequest{
|
||||
Stage: string(target.stage),
|
||||
LaneID: target.laneID,
|
||||
ModuleKey: target.moduleKey,
|
||||
@@ -476,7 +476,7 @@ func (r *Runner) validateRaw(ctx context.Context, target rawValidationTarget) ([
|
||||
|
||||
var warnings []contracts.Warning
|
||||
for _, validator := range validators {
|
||||
result, err := validator.ValidateRaw(ctx, request)
|
||||
result, err := validator.Validate(ctx, request)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("validate raw %s output with validator %q: %w", target.stage, validator.Name(), err)
|
||||
}
|
||||
|
||||
@@ -1796,14 +1796,15 @@ func (normalizer *runnerNormalizer) Normalize(ctx context.Context, req contracts
|
||||
}
|
||||
|
||||
type runnerValidator struct {
|
||||
name string
|
||||
resultName string
|
||||
decisions func([]artifacts.ArtifactCandidate) []contracts.ValidationDecision
|
||||
warnings []contracts.Warning
|
||||
err error
|
||||
order *[]string
|
||||
calls int
|
||||
requests []contracts.ValidationRequest
|
||||
name string
|
||||
approved []bool
|
||||
reason string
|
||||
message string
|
||||
warnings []contracts.Warning
|
||||
err error
|
||||
order *[]string
|
||||
calls int
|
||||
requests []contracts.ValidationRequest
|
||||
}
|
||||
|
||||
type runnerRawValidator struct {
|
||||
@@ -1814,18 +1815,22 @@ type runnerRawValidator struct {
|
||||
warnings []contracts.Warning
|
||||
err error
|
||||
calls int
|
||||
requests []contracts.RawValidationRequest
|
||||
requests []contracts.ValidationRequest
|
||||
}
|
||||
|
||||
func (validator *runnerRawValidator) Name() string {
|
||||
return validator.name
|
||||
}
|
||||
|
||||
func (validator *runnerRawValidator) ValidateRaw(ctx context.Context, req contracts.RawValidationRequest) (contracts.RawValidationResult, error) {
|
||||
func (validator *runnerRawValidator) ExecutionClass() contracts.ExecutionClass {
|
||||
return contracts.ExecutionClassDeterministic
|
||||
}
|
||||
|
||||
func (validator *runnerRawValidator) Validate(ctx context.Context, req contracts.ValidationRequest) (contracts.ValidationResult, error) {
|
||||
validator.calls++
|
||||
validator.requests = append(validator.requests, req)
|
||||
if validator.err != nil {
|
||||
return contracts.RawValidationResult{}, validator.err
|
||||
return contracts.ValidationResult{}, validator.err
|
||||
}
|
||||
approved := true
|
||||
if len(validator.approved) > 0 {
|
||||
@@ -1835,7 +1840,7 @@ func (validator *runnerRawValidator) ValidateRaw(ctx context.Context, req contra
|
||||
}
|
||||
approved = validator.approved[index]
|
||||
}
|
||||
return contracts.RawValidationResult{
|
||||
return contracts.ValidationResult{
|
||||
Approved: approved,
|
||||
ReasonCode: validator.reason,
|
||||
Message: validator.message,
|
||||
@@ -1847,24 +1852,29 @@ func (validator *runnerValidator) Name() string {
|
||||
return validator.name
|
||||
}
|
||||
|
||||
func (validator *runnerValidator) ExecutionClass() contracts.ExecutionClass {
|
||||
return contracts.ExecutionClassDeterministic
|
||||
}
|
||||
|
||||
func (validator *runnerValidator) Validate(ctx context.Context, req contracts.ValidationRequest) (contracts.ValidationResult, error) {
|
||||
validator.calls++
|
||||
validator.requests = append(validator.requests, req)
|
||||
if validator.order != nil {
|
||||
*validator.order = append(*validator.order, validator.name)
|
||||
}
|
||||
resultName := validator.resultName
|
||||
if resultName == "" {
|
||||
resultName = validator.name
|
||||
}
|
||||
var decisions []contracts.ValidationDecision
|
||||
if validator.decisions != nil {
|
||||
decisions = validator.decisions(req.Candidates)
|
||||
approved := true
|
||||
if len(validator.approved) > 0 {
|
||||
index := validator.calls - 1
|
||||
if index >= len(validator.approved) {
|
||||
index = len(validator.approved) - 1
|
||||
}
|
||||
approved = validator.approved[index]
|
||||
}
|
||||
return contracts.ValidationResult{
|
||||
ValidatorName: resultName,
|
||||
Decisions: decisions,
|
||||
Warnings: validator.warnings,
|
||||
Approved: approved,
|
||||
ReasonCode: validator.reason,
|
||||
Message: validator.message,
|
||||
Warnings: validator.warnings,
|
||||
}, validator.err
|
||||
}
|
||||
|
||||
@@ -2027,7 +2037,7 @@ func assertRunError(t *testing.T, err error, want string) {
|
||||
}
|
||||
}
|
||||
|
||||
func rawValidationRegistry(t *testing.T, stage ModuleStage, module string, validators ...contracts.RawValidator) *RawValidationRegistry {
|
||||
func rawValidationRegistry(t *testing.T, stage ModuleStage, module string, validators ...contracts.Validator) *RawValidationRegistry {
|
||||
t.Helper()
|
||||
|
||||
registry := NewRawValidationRegistry()
|
||||
|
||||
@@ -77,6 +77,11 @@ func (r *ValidatorRegistry) Build(key string) (contracts.Validator, error) {
|
||||
if validator.Name() != normalizedKey {
|
||||
return nil, fmt.Errorf("validator %q returned name %q", normalizedKey, validator.Name())
|
||||
}
|
||||
switch validator.ExecutionClass() {
|
||||
case contracts.ExecutionClassDeterministic, contracts.ExecutionClassLLMBacked:
|
||||
default:
|
||||
return nil, fmt.Errorf("validator %q returned unsupported execution class %q", normalizedKey, validator.ExecutionClass())
|
||||
}
|
||||
|
||||
return validator, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package pipeline
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
|
||||
@@ -56,3 +57,33 @@ func TestValidatorRegistryBehavior(t *testing.T) {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestValidatorRegistryRejectsUnsupportedExecutionClass(t *testing.T) {
|
||||
registry := NewValidatorRegistry()
|
||||
if err := registry.Register("invalid-validator", func() (contracts.Validator, error) {
|
||||
return invalidExecutionClassValidator{name: "invalid-validator"}, nil
|
||||
}); err != nil {
|
||||
t.Fatalf("Register() error = %v, want nil", err)
|
||||
}
|
||||
|
||||
_, err := registry.Build("invalid-validator")
|
||||
if err == nil {
|
||||
t.Fatal("Build() error = nil, want unsupported execution class error")
|
||||
}
|
||||
}
|
||||
|
||||
type invalidExecutionClassValidator struct {
|
||||
name string
|
||||
}
|
||||
|
||||
func (validator invalidExecutionClassValidator) Name() string {
|
||||
return validator.name
|
||||
}
|
||||
|
||||
func (validator invalidExecutionClassValidator) ExecutionClass() contracts.ExecutionClass {
|
||||
return contracts.ExecutionClass("unsupported")
|
||||
}
|
||||
|
||||
func (validator invalidExecutionClassValidator) Validate(ctx context.Context, req contracts.ValidationRequest) (contracts.ValidationResult, error) {
|
||||
return contracts.ValidationResult{Approved: true}, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user