Identify the protected alias affected by a proposed edit
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
**Updated:** 2026-11-11
|
||||
|
||||
**Status:** 8 of nine findings resolved. Findings refer to implementation revision
|
||||
**Status:** All nine findings resolved. Findings refer to implementation revision
|
||||
`aa8073c`. See the [implementation plan](implementation.md).
|
||||
|
||||
## Review Result
|
||||
@@ -295,6 +295,8 @@ of identity loss over capitalization and the existing rejection rules.
|
||||
|
||||
### R9 — Name the Affected Protected Alias (P3)
|
||||
|
||||
**Completed.** Protection feedback identifies a spelling whose occurrence count fell. The alias regression and existing spoken-word protection tests pass.
|
||||
|
||||
**Affected plan:** Stage 5, item 4.
|
||||
|
||||
**Evidence:** When an identity loses a mention, the
|
||||
@@ -352,6 +354,6 @@ the unchanged spelling.
|
||||
- Fresh tests passed for runner, validators, process reporting, LLM adapter,
|
||||
preflight, response schemas, proposal generation, configuration, and prompts
|
||||
during the algorithmic audit.
|
||||
|
||||
Resolve the findings with focused checks at their owning boundaries. Retain the
|
||||
current architecture and accepted operator choices.
|
||||
- After remediation, the fresh full test suite, targeted race checks for the
|
||||
runner, validators, process reporting, LLM adapter, and CLI, and the CLI build
|
||||
passed.
|
||||
|
||||
@@ -99,8 +99,23 @@ func validateIdentityPreservation(beforeByID, afterByID map[glossary.Identity][]
|
||||
var selected string
|
||||
found := false
|
||||
for identity, beforeItems := range beforeByID {
|
||||
if len(afterByID[identity]) < len(beforeItems) && len(beforeItems) > 0 {
|
||||
if spelling := beforeItems[0].canonical; !found || spelling < selected {
|
||||
afterItems := afterByID[identity]
|
||||
if len(afterItems) >= len(beforeItems) {
|
||||
continue
|
||||
}
|
||||
// Protect identity counts. Within an identity that lost a mention,
|
||||
// use spelling counts to identify which alias was affected.
|
||||
remaining := make(map[string]int)
|
||||
for _, item := range afterItems {
|
||||
remaining[item.canonical]++
|
||||
}
|
||||
for _, item := range beforeItems {
|
||||
spelling := item.canonical
|
||||
if remaining[spelling] > 0 {
|
||||
remaining[spelling]--
|
||||
continue
|
||||
}
|
||||
if !found || spelling < selected {
|
||||
selected, found = spelling, true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package validators
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
domain "gitea.maximumdirect.net/eric/audita/v3/internal/core/glossary"
|
||||
@@ -107,3 +108,28 @@ func TestProtectedNameRepetitionRequiresSurvivingIdentityAndSpokenWordScope(t *t
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProtectedNameFindingIdentifiesRemovedAlias(t *testing.T) {
|
||||
req := Request{
|
||||
ModuleKey: "glossary",
|
||||
IndependentEvidence: true,
|
||||
ReplacementPolicy: proposals.ReplacementPolicyReplaceAll,
|
||||
WorkingTranscript: &schema.Transcript{Segments: []schema.Segment{
|
||||
{ID: 1, Text: "Mira spoke to Captain Mira"},
|
||||
}},
|
||||
ProtectedTerms: domain.Vocabulary([]domain.Entry{{ID: "mira", Name: "Mira", Aliases: []string{"Captain Mira"}}}, nil),
|
||||
CandidateProposal: []proposals.EnrichedCorrectionProposal{{
|
||||
CorrectionProposal: proposals.CorrectionProposal{
|
||||
TargetSegmentID: 1, OriginalText: "Captain Mira", CorrectedText: "the captain", Confidence: 0.9,
|
||||
},
|
||||
}},
|
||||
}
|
||||
result, err := ValidateProtectedTerms(req)
|
||||
if err != nil || len(result.Decisions) != 1 {
|
||||
t.Fatalf("result=%+v err=%v", result, err)
|
||||
}
|
||||
decision := result.Decisions[0]
|
||||
if decision.Approved || decision.ReasonCode != ReasonProtectedGlossaryTerm || !strings.Contains(decision.Message, `"Captain Mira"`) {
|
||||
t.Fatalf("finding did not identify the removed alias: %+v", decision)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user