Index inherited compound identity restoration

This commit is contained in:
2026-10-25 23:17:59 +00:00
parent 75e209eb3b
commit f132cd6468
3 changed files with 102 additions and 11 deletions

View File

@@ -1030,6 +1030,14 @@ templates remain correct. Source review establishes O(K + C + M) lookup work plu
required copied values for K identity fields and C/M mapping entries.
Focused check: `go test ./internal/engine -run 'Identified|Identity|Inheritance'`.
Status: **complete** (E05). Prior completed commits include `549fca2`,
`3a1b6ff`, `d172a5e`, `1dd94a3`, and `75e209e`. Validation passed:
`env GOTOOLCHAIN=local GOPROXY=off GOTELEMETRY=off go test ./internal/engine -run 'Identified|Identity|Inheritance' -count=1`,
`env GOTOOLCHAIN=local GOPROXY=off GOTELEMETRY=off go test ./internal/engine -count=1`,
`env GOTOOLCHAIN=local GOPROXY=off GOTELEMETRY=off go test ./... -count=1`,
`env GOTOOLCHAIN=local GOPROXY=off GOTELEMETRY=off go test -race ./...`,
and `git diff --check`.
## Stage 32 — Index Secret Failure Locations Only When Needed
Finding: **F08**.

View File

@@ -24,6 +24,83 @@ func parseIdentifiedInheritanceSequence(t *testing.T, sourceID, input string) *d
return sequence
}
func TestPreserveInheritanceIdentityIndexesCompoundFields(t *testing.T) {
t.Parallel()
mergedEntries := []document.Entry{
{Key: "before", Value: &document.Node{Kind: document.String, Text: "keep"}},
{Key: "id", KeyLocation: document.Location{SourceID: "parent", Line: 2}, ValueLocation: document.Location{SourceID: "parent", Line: 2}, Value: &document.Node{Kind: document.String, Text: "parent-id"}},
}
for index := 0; index < 64; index++ {
key := "setting-" + string(rune('a'+index))
mergedEntries = append(mergedEntries, document.Entry{Key: key, Value: &document.Node{Kind: document.String, Text: key}})
}
mergedEntries = append(mergedEntries,
document.Entry{Key: "a/b~c", KeyLocation: document.Location{SourceID: "parent", Line: 70}, ValueLocation: document.Location{SourceID: "parent", Line: 70}, Value: &document.Node{Kind: document.String, Text: "parent-literal"}},
document.Entry{Key: "missing", Value: &document.Node{Kind: document.String, Text: "retained"}},
document.Entry{Key: "after", Value: &document.Node{Kind: document.String, Text: "keep"}},
)
merged := &document.Node{Kind: document.Mapping, Mapping: mergedEntries}
child := &document.Node{Kind: document.Mapping, Mapping: []document.Entry{
{Key: "a/b~c", KeyLocation: document.Location{SourceID: "child", Line: 9, Column: 3}, ValueLocation: document.Location{SourceID: "child", Line: 9, Column: 10}, Value: &document.Node{Kind: document.String, Text: "child-literal", Location: document.Location{SourceID: "child", Line: 9, Column: 10}}},
{Key: "id", KeyLocation: document.Location{SourceID: "child", Line: 3, Column: 3}, ValueLocation: document.Location{SourceID: "child", Line: 3, Column: 7}, Value: &document.Node{Kind: document.String, Text: "child-id", Location: document.Location{SourceID: "child", Line: 3, Column: 7}}},
}}
beforeKeys := make([]string, len(merged.Mapping))
for index, entry := range merged.Mapping {
beforeKeys[index] = entry.Key
}
untouched := merged.Mapping[2].Value
preserveInheritanceIdentityFields(merged, child, []string{"id", "a/b~c", "missing"})
for index, entry := range merged.Mapping {
if entry.Key != beforeKeys[index] {
t.Fatalf("mapping order changed at %d: %q, want %q", index, entry.Key, beforeKeys[index])
}
}
for _, want := range []struct {
key string
text string
keyLine int
keyColumn int
valueLine int
valueColumn int
}{
{key: "id", text: "child-id", keyLine: 3, keyColumn: 3, valueLine: 3, valueColumn: 7},
{key: "a/b~c", text: "child-literal", keyLine: 9, keyColumn: 3, valueLine: 9, valueColumn: 10},
} {
var got document.Entry
for _, entry := range merged.Mapping {
if entry.Key == want.key {
got = entry
break
}
}
if got.Value == nil || got.Value.Text != want.text || got.KeyLocation.SourceID != "child" || got.KeyLocation.Line != want.keyLine || got.KeyLocation.Column != want.keyColumn ||
got.ValueLocation.SourceID != "child" || got.ValueLocation.Line != want.valueLine || got.ValueLocation.Column != want.valueColumn ||
got.Value.Location.SourceID != "child" || got.Value.Location.Line != want.valueLine || got.Value.Location.Column != want.valueColumn {
t.Fatalf("restored identity %q = %#v", want.key, got)
}
if got.Value == child.Mapping[0].Value || (want.key == "id" && got.Value == child.Mapping[1].Value) {
t.Fatalf("restored identity %q borrows its child value", want.key)
}
}
if merged.Mapping[2].Value != untouched {
t.Fatal("nonidentity sibling was replaced")
}
for _, entry := range merged.Mapping {
if entry.Key == "missing" && entry.Value.Text != "retained" {
t.Fatalf("identity absent from child was changed: %#v", entry)
}
}
child.Mapping[0].Value.Text = "mutated"
for _, entry := range merged.Mapping {
if entry.Key == "a/b~c" && entry.Value.Text != "child-literal" {
t.Fatal("restored identity value aliases the child template")
}
}
}
func TestIdentifiedInheritanceGraphSchedulesForwardReferencesInPlace(t *testing.T) {
sequence := parseIdentifiedInheritanceSequence(t, "identified-graph", `- id: 2
tenant: acme

View File

@@ -144,18 +144,24 @@ func preserveInheritanceIdentityFields(merged, child *document.Node, fields []st
if len(fields) == 0 || merged == nil || merged.Kind != document.Mapping || child == nil || child.Kind != document.Mapping {
return
}
identityFields := make(map[string]struct{}, len(fields))
for _, field := range fields {
identityFields[field] = struct{}{}
}
positions := make(map[string]int, len(merged.Mapping))
for index, entry := range merged.Mapping {
if _, exists := positions[entry.Key]; !exists {
positions[entry.Key] = index
}
}
for _, entry := range child.Mapping {
if entry.Key != field {
if _, identity := identityFields[entry.Key]; !identity {
continue
}
for index := range merged.Mapping {
if merged.Mapping[index].Key == field {
merged.Mapping[index] = document.Entry{Key: field, Value: document.Clone(entry.Value)}
break
}
}
break
delete(identityFields, entry.Key)
if index, exists := positions[entry.Key]; exists {
entry.Value = document.Clone(entry.Value)
merged.Mapping[index] = entry
}
}
}