package validators import ( "math" "gitea.maximumdirect.net/eric/audita/v3/internal/core/schema" "gitea.maximumdirect.net/eric/audita/v3/internal/framework/proposals" ) // SectionLookup indexes the immutable source section shared by validation // and revalidation. Application checks its own, changing transcript. type SectionLookup struct { segments []schema.Segment positions map[int]int } func NewSectionLookup(transcript *schema.Transcript) *SectionLookup { section := &SectionLookup{} if transcript != nil { section.segments = transcript.Segments section.positions = make(map[int]int, len(section.segments)) for i, segment := range section.segments { section.positions[segment.ID] = i } } return section } func (s *SectionLookup) Position(id int) (int, bool) { position, ok := s.positions[id] return position, ok } func (r Request) sectionLookup() *SectionLookup { if r.Section != nil { return r.Section } return NewSectionLookup(r.WorkingTranscript) } // Preview reuses the replacement preview for this proposal index within one // validation pass. A revision starts a new pass with its own preview map. func (r Request) Preview(candidate proposals.EnrichedCorrectionProposal) proposals.SegmentPreviewResult { if preview, ok := r.Previews[candidate.ProposalIndex]; ok { return preview } section := r.sectionLookup() var segment *schema.Segment if position, ok := section.Position(candidate.TargetSegmentID); ok { segment = §ion.segments[position] } correction := candidate.CorrectionProposal if r.IndependentEvidence && (math.IsNaN(correction.Confidence) || correction.Confidence < 0 || correction.Confidence > 1) { correction.Confidence = 0.5 } preview := proposals.PreviewProposalForSegment(segment, correction, r.ReplacementPolicy) if r.Previews != nil { r.Previews[candidate.ProposalIndex] = preview } return preview }