Strengthen validation retries and checkpoint safety

This commit is contained in:
2026-08-27 11:50:37 +00:00
parent b2e83bd6e7
commit e6b2ae88d2
73 changed files with 934 additions and 1560 deletions

View File

@@ -17,7 +17,7 @@ func TestExecuteValidationChainSettlesEveryValidatorInOrder(t *testing.T) {
invoke validationInvoker
want []validationOutcome
wantCalls []string
wantGuidance string
wantGuidance []string
wantWarnings []string
}{
{
@@ -41,7 +41,7 @@ func TestExecuteValidationChainSettlesEveryValidatorInOrder(t *testing.T) {
}),
want: []validationOutcome{validationRejected, validationRejected, validationRejected},
wantCalls: []string{"shape:1", "refs:1", "coverage:1"},
wantGuidance: "repair shape\nrepair references",
wantGuidance: []string{"repair shape", "repair references"},
},
{
name: "rejection and failure both settle",
@@ -52,7 +52,7 @@ func TestExecuteValidationChainSettlesEveryValidatorInOrder(t *testing.T) {
}),
want: []validationOutcome{validationRejected, validationFailed},
wantCalls: []string{"shape:1", "remote:1"},
wantGuidance: "repair shape",
wantGuidance: []string{"repair shape"},
},
{
name: "failure only has no correction guidance",
@@ -103,8 +103,19 @@ func TestExecuteValidationChainSettlesEveryValidatorInOrder(t *testing.T) {
if !reflect.DeepEqual(outcomes, test.want) || !reflect.DeepEqual(calls, test.wantCalls) {
t.Fatalf("outcomes = %#v calls = %#v, want %#v %#v", outcomes, calls, test.want, test.wantCalls)
}
if guidance := report.CorrectionGuidance(); guidance != test.wantGuidance {
t.Fatalf("CorrectionGuidance() = %q, want %q", guidance, test.wantGuidance)
if len(test.wantGuidance) > 0 {
guidance, err := report.CorrectionRequest()
if err != nil {
t.Fatalf("CorrectionRequest() error = %v", err)
}
if !strings.Contains(guidance, "complete corrected replacement") {
t.Fatalf("CorrectionRequest() = %q, want complete replacement instruction", guidance)
}
for _, item := range test.wantGuidance {
if strings.Count(guidance, item) != 1 {
t.Fatalf("CorrectionRequest() = %q, want one occurrence of %q", guidance, item)
}
}
}
warnings := report.Warnings()
var warningCodes []string
@@ -139,7 +150,7 @@ func TestExecuteValidationChainKeepsInvocationInputsImmutable(t *testing.T) {
}
}
func TestValidationReportBoundsGuidanceAndOwnsRecords(t *testing.T) {
func TestValidationReportRejectsOversizedGuidanceAndOwnsRecords(t *testing.T) {
guidance := strings.Repeat("x", contracts.MaxValidationCorrectionGuidanceBytes)
report := validationReport{records: make([]validationRecord, 17)}
for index := range report.records {
@@ -148,8 +159,8 @@ func TestValidationReportBoundsGuidanceAndOwnsRecords(t *testing.T) {
report.records[index] = validationRecord{validatorName: "validator", outcome: validationRejected, correctionGuidance: string(unique)}
}
report.records[0].warnings = []contracts.Warning{{ReasonCode: "warning"}}
if got := report.CorrectionGuidance(); len(got) > contracts.MaxCorrectionGuidanceBytes || !strings.Contains(got, string([]byte{byte('a')})) || strings.Contains(got, string([]byte{byte('q')})) {
t.Fatalf("CorrectionGuidance() length = %d, want bounded ordered guidance", len(got))
if _, err := report.CorrectionRequest(); err == nil {
t.Fatal("CorrectionRequest() error = nil, want aggregate overflow error")
}
records := report.Records()
records[0].warnings[0].ReasonCode = "changed"