Report moved history at final record paths
This commit is contained in:
@@ -74,7 +74,13 @@ enumeration or new public addressing mechanism.
|
||||
|
||||
## Finding 2 — Deep descendant history reports the old record's operation path
|
||||
|
||||
**Priority:** P2. **Status:** Open.
|
||||
**Priority:** P2. **Status:** Complete.
|
||||
|
||||
Completion: pre-resolution operation paths now use the matched record-prefix
|
||||
translation, preserving ancestor scope and suffixes. Resolution records already
|
||||
in final coordinates are left unchanged. A regression covers deep inherited
|
||||
fields, record/container queries, original source coordinates, and overlapping
|
||||
final-position records. Focused history checks and `./scripts/check.sh` passed.
|
||||
|
||||
**Code:** [shared history selection](../../internal/engine/history_select.go),
|
||||
`selectHistory`, especially the reported-path translation at lines 116–120.
|
||||
|
||||
@@ -113,11 +113,10 @@ func (model *historyModel) selectHistory(path Path) []historySelection {
|
||||
} else if !historyObservationMatchesQuery(query, observation.path) {
|
||||
continue
|
||||
}
|
||||
if query.String() != path.String() && pathContains(query, reportedPath) {
|
||||
suffix := reportedPath.segments[len(query.segments):]
|
||||
reportedPath = Path{segments: append(clonePathSegments(path.segments, len(suffix)), suffix...)}
|
||||
} else if query.String() != path.String() && pathContains(reportedPath, query) && len(reportedPath.segments) >= len(query.segments)-1 {
|
||||
reportedPath = path.clone()
|
||||
if observation.phase != historyPhaseResolution && query.String() != path.String() {
|
||||
if translated, matched := model.resolutionPayload.correspondence.finalPath(reportedPath); matched {
|
||||
reportedPath = translated
|
||||
}
|
||||
}
|
||||
selectionIndex, found := selectionByPayload[observation.payload]
|
||||
if !found {
|
||||
|
||||
@@ -40,3 +40,57 @@ func TestMovedRemovedFieldHasConsistentHistory(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMovedInheritedHistoryUsesFinalRecordPrefix(t *testing.T) {
|
||||
type config struct {
|
||||
Items []map[string]any `yaml:"items"`
|
||||
}
|
||||
field := Keys("items").Index(0).Key("nested").Key("more").Key("value")
|
||||
definition := DefinitionWithSequenceIdentityRegistrations(Definition[config]{
|
||||
Resolve: func(value *config, r *Resolution) error {
|
||||
value.Items[0], value.Items[1] = value.Items[1], value.Items[0]
|
||||
r.RecordNormalization(Keys("items"), "reorder")
|
||||
r.RecordNormalization(field, "retain inherited field")
|
||||
return nil
|
||||
},
|
||||
}, []SequenceIdentityRegistrationInput{{ExactPath: pathPointer(Keys("items")), IdentityFields: []string{"id"}}})
|
||||
result, err := testLoad(Bytes("records", []byte("items:\n - id: parent\n nested: {more: {value: old}}\n - id: child\n extends: {id: parent}\n")), Options[config]{Definition: definition})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
physical := result.Metadata().History(Keys("items"))
|
||||
sourceID := result.Inspection.Sources()[0].ID
|
||||
for _, query := range []Path{field, Keys("items").Index(0)} {
|
||||
inherited, recorded := false, false
|
||||
for _, change := range result.Metadata().History(query) {
|
||||
if change.Origin.Operation == ChangeInheritance {
|
||||
inherited = true
|
||||
if !pathContains(Keys("items").Index(0), change.Path) {
|
||||
t.Errorf("inheritance path for %s = %s", query.String(), change.Path.String())
|
||||
}
|
||||
if query.String() == field.String() && change.Path.String() != "/items/0" {
|
||||
t.Errorf("container operation replaced by leaf path: %s", change.Path.String())
|
||||
}
|
||||
for _, location := range change.Origin.Locations {
|
||||
if location.SourceID != sourceID || (query.String() == field.String() && location.Line != 3) {
|
||||
t.Errorf("source coordinates changed: %#v", location)
|
||||
}
|
||||
}
|
||||
}
|
||||
if change.Origin.Layer == LayerResolution && len(change.Reasons) == 1 && change.Reasons[0] == "retain inherited field" {
|
||||
recorded = true
|
||||
if change.Path.String() != field.String() {
|
||||
t.Errorf("final resolution path translated twice: %s", change.Path.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
if !inherited || !recorded {
|
||||
t.Errorf("missing inherited or recorded evidence for %s", query.String())
|
||||
}
|
||||
}
|
||||
for _, change := range physical {
|
||||
if change.Origin.Operation == ChangeInheritance && !pathContains(Keys("items").Index(1), change.Path) {
|
||||
t.Errorf("collection history lost physical coordinates: %s", change.Path.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user