Reuse prepared glossary data across stage sections

This commit is contained in:
2026-11-10 20:42:28 +00:00
parent 8ad27e8368
commit c16d61e091
21 changed files with 174 additions and 142 deletions

View File

@@ -1,15 +1,43 @@
package validators
import (
"slices"
"gitea.maximumdirect.net/eric/audita/v3/internal/core/chunking"
"gitea.maximumdirect.net/eric/audita/v3/internal/core/glossary"
"gitea.maximumdirect.net/eric/audita/v3/internal/core/schema"
)
// GlossaryView holds the read-only matching data shared by a stage's validators
// and apply-time checks.
type GlossaryView struct {
Protection ProtectedVocabulary
context glossaryContext
}
func PrepareGlossaryView(entries []glossary.Entry, protected []glossary.Term) *GlossaryView {
return &GlossaryView{Protection: NewProtectedVocabulary(protected), context: prepareGlossaryContext(entries)}
}
type glossaryContext struct {
entries []glossary.Entry
positions map[glossary.Identity][]int
vocabulary ProtectedVocabulary
}
func prepareGlossaryContext(entries []glossary.Entry) glossaryContext {
positions := make(map[glossary.Identity][]int, len(entries))
for i, entry := range entries {
identity := glossary.Identity{Collection: entry.Collection, ID: entry.ID}
positions[identity] = append(positions[identity], i)
}
return glossaryContext{entries: entries, positions: positions, vocabulary: NewProtectedVocabulary(glossary.Vocabulary(entries, nil))}
}
// validationContext supplies adjacent source segments within the current chunk
// and glossary definitions mentioned in the candidate or that local context.
// These fields travel in each item so batching accounts for their size.
func validationContext(segments []schema.Segment, position int, selected []glossary.Entry, vocabulary ProtectedVocabulary, corrected string) ([]NeighboringSegment, []glossary.Entry) {
func (view glossaryContext) validationContext(segments []schema.Segment, position int, corrected string) ([]NeighboringSegment, []glossary.Entry) {
var neighbors []NeighboringSegment
source := segments[position].Text
if position > 0 {
@@ -23,19 +51,20 @@ func validationContext(segments []schema.Segment, position int, selected []gloss
for _, neighbor := range neighbors {
texts = append(texts, neighbor.Text)
}
mentioned := make(map[glossary.Identity]struct{})
for _, text := range texts {
for _, occurrence := range view.vocabulary.occurrences(text) {
mentioned[occurrence.identity] = struct{}{}
}
}
var matched []int
for identity := range mentioned {
matched = append(matched, view.positions[identity]...)
}
slices.Sort(matched)
var entries []glossary.Entry
if selected != nil {
mentioned := make(map[glossary.Identity]bool)
for _, text := range texts {
for identity := range vocabulary.occurrencesByIdentity(text) {
mentioned[identity] = true
}
}
for _, entry := range selected {
if mentioned[glossary.Identity{Collection: entry.Collection, ID: entry.ID}] {
entries = append(entries, entry)
}
}
for _, index := range matched {
entries = append(entries, view.entries[index])
}
return neighbors, entries
}