Preserve terminal rejection warnings

This commit is contained in:
2026-08-09 01:19:55 +00:00
parent 14bfae216d
commit 8e669a1f14
7 changed files with 254 additions and 76 deletions

View File

@@ -240,9 +240,7 @@ func (r *Runner) Run(ctx context.Context, input RunInput) (output RunOutput, err
if chunkResult.rejection != nil {
output.Rejected = append(output.Rejected, *chunkResult.rejection)
}
if chunkResult.accepted || chunkResult.lookup.Status == ChunkPlanHit {
output.Warnings = append(output.Warnings, chunkResult.warnings...)
}
output.Warnings = append(output.Warnings, chunkResult.warnings...)
chunkDebugPayload := map[string]any{
"cache_mode": chunkMode,
"lookup": chunkResult.lookup,
@@ -422,45 +420,52 @@ func (r *Runner) runPreparedSteps(ctx context.Context, input RunInput, checkpoin
return nil
}
func runWithRetry(ctx context.Context, retries int, run func(attempt int) (bool, *contracts.RejectedOutput, error)) (bool, *contracts.RejectedOutput, error) {
type retryAttemptResult struct {
accepted bool
rejection *contracts.RejectedOutput
warnings []contracts.Warning
}
func runWithRetry(ctx context.Context, retries int, run func(attempt int) (retryAttemptResult, error)) (retryAttemptResult, error) {
attempts := retries + 1
var last *contracts.RejectedOutput
var last retryAttemptResult
for attempt := 1; attempt <= attempts; attempt++ {
if err := ctx.Err(); err != nil {
return false, nil, err
return retryAttemptResult{}, err
}
accepted, rejection, err := run(attempt)
result, err := run(attempt)
if err != nil {
var debugErr *attemptDebugPersistenceError
if errors.As(err, &debugErr) {
return false, nil, fmt.Errorf("failed after %d attempt(s): %w", attempt, err)
return retryAttemptResult{}, fmt.Errorf("failed after %d attempt(s): %w", attempt, err)
}
if attempt == attempts {
return false, nil, fmt.Errorf("failed after %d attempt(s): %w", attempt, err)
return retryAttemptResult{}, fmt.Errorf("failed after %d attempt(s): %w", attempt, err)
}
if ctxErr := ctx.Err(); ctxErr != nil {
return false, nil, ctxErr
return retryAttemptResult{}, ctxErr
}
continue
}
if accepted {
return true, nil, nil
if result.accepted {
return result, nil
}
if rejection != nil {
if result.rejection != nil {
rejection := *result.rejection
rejection.AttemptCount = attempt
last = rejection
last = retryAttemptResult{rejection: &rejection, warnings: cloneWarnings(result.warnings)}
}
if ctxErr := ctx.Err(); ctxErr != nil {
return false, nil, ctxErr
return retryAttemptResult{}, ctxErr
}
if attempt == attempts {
if last == nil {
last = &contracts.RejectedOutput{ReasonCode: "output_rejected", Message: "output rejected", AttemptCount: attempt}
if last.rejection == nil {
last.rejection = &contracts.RejectedOutput{ReasonCode: "output_rejected", Message: "output rejected", AttemptCount: attempt}
}
return false, last, nil
return last, nil
}
}
return false, last, nil
return last, nil
}
func (r *Runner) validateChunks(ctx context.Context, doc *source.SourceDocument, moduleKey string, chunks []source.Chunk, sourceInput contracts.LLMInputMaterial, sessionID string, references contracts.ReferenceSet, metadata map[string]any, prepared preparedValidatorChain, attempt int, debug DebugRecorder) ([]contracts.Warning, *contracts.RejectedOutput, error) {