Fix D&D extraction issues and retire the completed audit

This commit is contained in:
2026-07-25 12:30:42 +00:00
parent 84a2854b5e
commit e4471fc300
15 changed files with 295 additions and 1782 deletions

View File

@@ -17,7 +17,7 @@ import (
const (
Key = "dnd/spells"
normalizationPolicy = "dnd.spells.normalize.v1"
normalizationPolicy = "dnd.spells.normalize.v2"
NormalizationPolicy = normalizationPolicy
)
@@ -157,20 +157,15 @@ func cloneSpellCast(input dnd.SpellCast) dnd.SpellCast {
}
func canonicalizeSourceRefs(order shared.SourceRefOrder, input []source.SourceRef) ([]source.SourceRef, bool, int) {
canonical := order.Canonicalize(input)
return canonical, !sourceRefsEqual(input, canonical), len(input) - len(canonical)
}
func sourceRefsEqual(left, right []source.SourceRef) bool {
if (left == nil) != (right == nil) || len(left) != len(right) {
return false
}
for index := range left {
if left[index] != right[index] {
return false
orderChanged := false
for index := 1; index < len(input); index++ {
if order.Less(input[index], input[index-1]) {
orderChanged = true
break
}
}
return true
canonical := order.Canonicalize(input)
return canonical, orderChanged, len(input) - len(canonical)
}
type duplicateGroup struct {

View File

@@ -104,6 +104,9 @@ func TestIdentityAndMetadataAreDefensive(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if NormalizationPolicy != "dnd.spells.normalize.v2" {
t.Fatalf("NormalizationPolicy = %q, want v2 policy", NormalizationPolicy)
}
fingerprints := normalizer.CheckpointFingerprints()
if len(fingerprints) != 2 || fingerprints[0].Name != "effective_catalog" || fingerprints[0].Value != normalizer.effectiveCatalog.Digest() || fingerprints[1] != (pipeline.CheckpointFingerprint{Name: "normalization_policy", Value: normalizationPolicy}) {
@@ -116,7 +119,7 @@ func TestIdentityAndMetadataAreDefensive(t *testing.T) {
}
metadata := normalizer.ManifestMetadata()
if metadata["catalog_base_id"] != spellcatalog.SRD5E2014ID || metadata["catalog_digest"] != normalizer.effectiveCatalog.Digest() {
if metadata["catalog_base_id"] != spellcatalog.SRD5E2014ID || metadata["catalog_digest"] != normalizer.effectiveCatalog.Digest() || metadata["normalization_policy"] != normalizationPolicy {
t.Fatalf("metadata = %#v, want catalog identity", metadata)
}
metadata["catalog_overlay_ids"].([]string)[0] = "changed"
@@ -205,11 +208,32 @@ func TestNormalizeSortsAndDeduplicatesExactSourceReferences(t *testing.T) {
if !reflect.DeepEqual(result.Value.SpellCasts[0].SourceRefs, wantRefs) {
t.Fatalf("source refs = %#v, want %#v", result.Value.SpellCasts[0].SourceRefs, wantRefs)
}
if len(result.Warnings) != 1 || result.Warnings[0].ReasonCode != ReasonCodeSourceReferencesNormalized || !strings.Contains(result.Warnings[0].Message, "original count 6") || !strings.Contains(result.Warnings[0].Message, "final count 5") || !strings.Contains(result.Warnings[0].Message, "duplicates removed 1") {
if len(result.Warnings) != 1 || result.Warnings[0].ReasonCode != ReasonCodeSourceReferencesNormalized || !strings.Contains(result.Warnings[0].Message, "original count 6") || !strings.Contains(result.Warnings[0].Message, "final count 5") || !strings.Contains(result.Warnings[0].Message, "order changed true") || !strings.Contains(result.Warnings[0].Message, "duplicates removed 1") {
t.Fatalf("warnings = %#v, want source normalization warning", result.Warnings)
}
}
func TestNormalizeReportsDuplicateRemovalWithoutOrderChange(t *testing.T) {
ref1 := source.SourceRef{SourceID: "source", StartUnitID: 1, EndUnitID: 1}
ref2 := source.SourceRef{SourceID: "source", StartUnitID: 2, EndUnitID: 2}
input := dnd.SpellList{SpellCasts: []dnd.SpellCast{{
Spell: "Cure Wounds",
SourceRefs: []source.SourceRef{ref1, ref1, ref2},
}}}
result, err := newNormalizer(t).Normalize(context.Background(), normalizeRequest(input))
if err != nil {
t.Fatalf("Normalize() error = %v, want nil", err)
}
if len(result.Warnings) != 1 || result.Warnings[0].ReasonCode != ReasonCodeSourceReferencesNormalized {
t.Fatalf("warnings = %#v, want one source normalization warning", result.Warnings)
}
message := result.Warnings[0].Message
if !strings.Contains(message, "order changed false") || !strings.Contains(message, "duplicates removed 1") {
t.Fatalf("warning = %q, want duplicate-only repair without order change", message)
}
}
func TestNormalizeOrdersReferencesBySourceDocumentPosition(t *testing.T) {
doc := &source.SourceDocument{ID: "source", Units: []source.SourceUnit{{ID: 30}, {ID: 10}}}
input := dnd.SpellList{SpellCasts: []dnd.SpellCast{{