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

@@ -84,14 +84,14 @@ func (r *Runner) runChunkPlan(ctx context.Context, input RunInput, doc *source.S
}
var producerWarnings []contracts.Warning
accepted, rejection, err := runWithRetry(ctx, input.pipeline.Chunk.Retries, func(attempt int) (bool, *contracts.RejectedOutput, error) {
retryResult, err := runWithRetry(ctx, input.pipeline.Chunk.Retries, func(attempt int) (retryAttemptResult, error) {
attemptStarted := time.Now().UTC()
attemptPath := path.Join("chunk", fmt.Sprintf("attempt-%02d", attempt))
attemptCtx, llmScope := withDebugLLMScope(ctx, attemptPath)
terminal := newAttemptTerminalRecorder(input.Debug, attemptPath, "chunk", llmScope, debugTimedEnvelope{Stage: string(StageChunk), ModuleKey: chunker.Key(), Attempt: attempt, StartedAt: attemptStarted})
requestMetadata, metadataErr := cloneMetadata(input.Metadata)
if metadataErr != nil {
return false, nil, terminal.record(nil, fmt.Errorf("clone chunk request metadata: %w", metadataErr))
return retryAttemptResult{}, terminal.record(nil, fmt.Errorf("clone chunk request metadata: %w", metadataErr))
}
chunkResult, callErr := chunker.Plan(attemptCtx, contracts.ChunkRequest{
Source: doc, SourceInput: sourceInput.Clone(), SessionID: sessionID,
@@ -99,21 +99,21 @@ func (r *Runner) runChunkPlan(ctx context.Context, input RunInput, doc *source.S
LLMProfile: input.pipeline.Chunk.LLMProfile, Metadata: requestMetadata,
})
if callErr != nil {
return false, nil, terminal.record(nil, fmt.Errorf("chunk source with chunker %q: %w", chunker.Key(), callErr))
return retryAttemptResult{}, terminal.record(nil, fmt.Errorf("chunk source with chunker %q: %w", chunker.Key(), callErr))
}
plan, chunks, validationErr := validateAndMaterializeChunkPlan(doc, chunkResult.Plan)
if validationErr != nil {
attemptErr := fmt.Errorf("validate chunk plan from chunker %q: %w", chunker.Key(), validationErr)
payload := map[string]any{"plan": debugChunkPlanEnvelope(chunkResult.Plan), "warnings": debugWarningEnvelopes(chunkResult.Warnings)}
return false, nil, terminal.record(payload, attemptErr)
return retryAttemptResult{}, terminal.record(payload, attemptErr)
}
planDigest, digestErr := source.DigestChunkPlan(plan)
if digestErr != nil {
return false, nil, terminal.record(nil, fmt.Errorf("digest generated chunk plan: %w", digestErr))
return retryAttemptResult{}, terminal.record(nil, fmt.Errorf("digest generated chunk plan: %w", digestErr))
}
producerMetadata, _, metadataErr := moduleManifestMetadata(chunker)
if metadataErr != nil {
return false, nil, terminal.record(nil, fmt.Errorf("clone chunker manifest metadata: %w", metadataErr))
return retryAttemptResult{}, terminal.record(nil, fmt.Errorf("clone chunker manifest metadata: %w", metadataErr))
}
profile := ""
if input.pipeline.ChunkExecutionClass == contracts.ExecutionClassLLMBacked {
@@ -137,7 +137,7 @@ func (r *Runner) runChunkPlan(ctx context.Context, input RunInput, doc *source.S
action = "bypassed"
}
if candidateErr := result.setCandidate(candidate, action); candidateErr != nil {
return false, nil, terminal.record(nil, fmt.Errorf("clone generated chunk plan record: %w", candidateErr))
return retryAttemptResult{}, terminal.record(nil, fmt.Errorf("clone generated chunk plan record: %w", candidateErr))
}
validationWarnings, rejected, validationErr := r.validateChunks(attemptCtx, doc, chunker.Key(), chunks, sourceInput, sessionID, input.pipeline.ChunkReferences.ReferenceSet, input.Metadata, input.Prepared.chunkValidators, attempt, input.Debug)
attemptWarnings := append(cloneWarnings(chunkResult.Warnings), validationWarnings...)
@@ -145,9 +145,16 @@ func (r *Runner) runChunkPlan(ctx context.Context, input RunInput, doc *source.S
"plan": debugChunkPlanEnvelope(plan), "materialized_chunks": debugSourceChunkEnvelopes(chunks),
"warnings": debugWarningEnvelopes(attemptWarnings), "rejection": debugRejectedOutputPtr(rejected),
}
if validationErr != nil || rejected != nil {
if validationErr != nil {
result.setValidation(validationWarnings, rejected, validationErr)
return false, rejected, terminal.record(payload, validationErr)
return retryAttemptResult{}, terminal.record(payload, validationErr)
}
if rejected != nil {
result.setValidation(validationWarnings, rejected, nil)
if debugErr := terminal.record(payload, nil); debugErr != nil {
return retryAttemptResult{}, debugErr
}
return retryAttemptResult{rejection: rejected, warnings: attemptWarnings}, nil
}
result.chunks = chunks
result.plan = &plan
@@ -155,9 +162,9 @@ func (r *Runner) runChunkPlan(ctx context.Context, input RunInput, doc *source.S
producerWarnings = cloneWarnings(chunkResult.Warnings)
result.setValidation(validationWarnings, nil, nil)
if debugErr := terminal.record(payload, nil); debugErr != nil {
return false, nil, debugErr
return retryAttemptResult{}, debugErr
}
return true, nil, nil
return retryAttemptResult{accepted: true}, nil
})
if err != nil {
if result.summary.ValidationStatus == "not_run" {
@@ -165,9 +172,10 @@ func (r *Runner) runChunkPlan(ctx context.Context, input RunInput, doc *source.S
}
return result, err
}
result.accepted = accepted
result.rejection = rejection
if !accepted {
result.accepted = retryResult.accepted
result.rejection = retryResult.rejection
if !retryResult.accepted {
result.warnings = cloneWarnings(retryResult.warnings)
return result, nil
}