Classify registry normalization diagnostics

This commit is contained in:
2026-08-27 15:57:29 +00:00
parent ccba2ce3f9
commit 6a1fd7bdb6
12 changed files with 247 additions and 206 deletions

View File

@@ -31,7 +31,7 @@ func reconciliationInputs(records []normalizedRecord) ([]semanticreconcile.Candi
return candidates, envelopes, nil
}
func applyReconciliationPlan(plan semanticreconcile.Plan, records []normalizedRecord, envelopes []semanticreconcile.Record[dnd.Item], order shared.SourceRefOrder) ([]normalizedRecord, []contracts.Warning, int, error) {
func applyReconciliationPlan(plan semanticreconcile.Plan, records []normalizedRecord, envelopes []semanticreconcile.Record[dnd.Item], order shared.SourceRefOrder) ([]normalizedRecord, []contracts.Warning, []contracts.Warning, int, error) {
application, err := semanticreconcile.ApplyPlan(plan, envelopes, semanticreconcile.ApplicationPolicy[dnd.Item]{
CloneValue: cloneItem,
RejectGroup: func(members []dnd.Item, _ dnd.Item) semanticreconcile.RejectionCategory {
@@ -52,7 +52,7 @@ func applyReconciliationPlan(plan semanticreconcile.Plan, records []normalizedRe
},
})
if err != nil {
return nil, nil, 0, err
return nil, nil, nil, 0, err
}
applied := application.Records()
@@ -64,35 +64,41 @@ func applyReconciliationPlan(plan semanticreconcile.Plan, records []normalizedRe
earliest: record.EarliestInputPosition(),
}
}
type orderedWarning struct {
type orderedFinding struct {
position int
warning contracts.Warning
finding contracts.Warning
}
orderedWarnings := make([]orderedWarning, 0, len(application.AppliedGroups())+len(application.RejectedGroups()))
observations := make([]orderedFinding, 0, len(application.AppliedGroups()))
advisories := make([]orderedFinding, 0, len(application.RejectedGroups()))
for _, event := range application.AppliedGroups() {
provenance := event.Provenance()
orderedWarnings = append(orderedWarnings, orderedWarning{
observations = append(observations, orderedFinding{
position: provenance.EarliestInputPosition(),
warning: semanticDuplicateWarning(provenance, records[provenance.CanonicalPosition()]),
finding: semanticDuplicateFinding(provenance, records[provenance.CanonicalPosition()]),
})
}
for _, event := range application.RejectedGroups() {
provenance := event.Provenance()
orderedWarnings = append(orderedWarnings, orderedWarning{
advisories = append(advisories, orderedFinding{
position: provenance.EarliestInputPosition(),
warning: contracts.Warning{
finding: contracts.Warning{
Scope: itemScope(provenance.EarliestInputPosition()),
ReasonCode: ReasonCodeItemSemanticProposalInvalid,
Message: "proposal group preserved because currency may only be consolidated with aliases of one denomination",
},
})
}
sort.SliceStable(orderedWarnings, func(left, right int) bool { return orderedWarnings[left].position < orderedWarnings[right].position })
warnings := make([]contracts.Warning, len(orderedWarnings))
for index, entry := range orderedWarnings {
warnings[index] = entry.warning
sort.SliceStable(observations, func(left, right int) bool { return observations[left].position < observations[right].position })
sort.SliceStable(advisories, func(left, right int) bool { return advisories[left].position < advisories[right].position })
observationFindings := make([]contracts.Warning, len(observations))
for index, entry := range observations {
observationFindings[index] = entry.finding
}
return output, warnings, len(application.RejectedGroups()), nil
advisoryFindings := make([]contracts.Warning, len(advisories))
for index, entry := range advisories {
advisoryFindings[index] = entry.finding
}
return output, observationFindings, advisoryFindings, len(application.RejectedGroups()), nil
}
func canConsolidate(items []dnd.Item) bool {
@@ -133,7 +139,7 @@ func currencyDenomination(name string) string {
}
}
func semanticDuplicateWarning(provenance semanticreconcile.GroupProvenance, canonical normalizedRecord) contracts.Warning {
func semanticDuplicateFinding(provenance semanticreconcile.GroupProvenance, canonical normalizedRecord) contracts.Warning {
inputIndexes := provenance.OriginalInputIndexes()
details := make([]string, 0, len(inputIndexes)+1)
for _, inputIndex := range inputIndexes {