diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index 0ac6b3a..420e0f0 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -978,6 +978,14 @@ record replacement/removal, modes, origin locations, and sensitivity for both precedence and inheritance. Focused check: `go test ./internal/engine -run 'Sequence|Collection|Inheritance|History|Explain|Sensitivity'`. +Status: **complete** (E03). Prior completed commits include `8832449`, +`549fca2`, `3a1b6ff`, and `d172a5e`. Validation passed: +`env GOTOOLCHAIN=local GOPROXY=off GOTELEMETRY=off go test ./internal/engine -run 'Sequence|Collection|Inheritance|History|Explain|Sensitivity' -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 30 — Index Original Tier-History Values Lazily Finding: **E04**. diff --git a/internal/engine/history.go b/internal/engine/history.go index e736a72..bf30599 100644 --- a/internal/engine/history.go +++ b/internal/engine/history.go @@ -413,6 +413,27 @@ func applySequenceHistory(target **document.Node, incoming *document.Node, contr } } +func sequenceHistoryContributionForCombination( + destination Path, + operation sequenceMode, + incoming *document.Node, + combined sequenceCombinationResult, +) sequenceHistoryContribution { + contribution := sequenceHistoryContribution{ + path: destination.clone(), mode: sequenceHistoryMapped, + } + if operation == sequenceModeReplace { + contribution.mode = sequenceHistoryReplace + if incoming != nil && incoming.Kind == document.Sequence { + contribution.length = len(incoming.Sequence) + } + return contribution + } + contribution.items = append([]sequenceItemProjection(nil), combined.higherItems...) + contribution.replacements = append([]sequenceItemReplacement(nil), combined.replacements...) + return contribution +} + func cloneSequenceHistoryContributions(values []sequenceHistoryContribution) []sequenceHistoryContribution { if values == nil { return nil diff --git a/internal/engine/history_sequence_test.go b/internal/engine/history_sequence_test.go index c06d61f..cb32b8e 100644 --- a/internal/engine/history_sequence_test.go +++ b/internal/engine/history_sequence_test.go @@ -469,21 +469,18 @@ func TestSequenceHistoryReplaysCombinationEvidence(t *testing.T) { t.Fatalf("combine diagnostics = %#v", diagnostics) } - mode := sequenceHistoryMapped - if test.operation == sequenceModeReplace { - mode = sequenceHistoryReplace - } - length := 0 - if mode == sequenceHistoryReplace { - length = len(combined.higherItems) - } application := historyApplication{ layer: LayerOverlay, value: higherRoot, - sequences: []sequenceHistoryContribution{{ - path: Keys("records"), mode: mode, length: length, - items: combined.higherItems, replacements: combined.replacements, - }}, + sequences: []sequenceHistoryContribution{ + sequenceHistoryContributionForCombination(Keys("records"), test.operation, higher, combined), + }, + } + if len(combined.higherItems) != 0 { + combined.higherItems[0].outputIndex++ + } + if len(combined.replacements) != 0 { + combined.replacements[0].outputIndex++ } application.sequencesByPath = indexSequenceHistoryContributions(application.sequences) replayed := document.Clone(lowerRoot) diff --git a/internal/engine/inheritance_combine.go b/internal/engine/inheritance_combine.go index ce2d33d..6c65d5b 100644 --- a/internal/engine/inheritance_combine.go +++ b/internal/engine/inheritance_combine.go @@ -85,17 +85,9 @@ func combineInheritanceTemplate( result.replacements = append(result.replacements, applyInheritanceSequenceOrigins( mergedOrigins, child.origins, childPath, lowerValue, incoming, combined, resolution.operation, )...) - history := sequenceHistoryContribution{path: childPath.clone(), mode: sequenceHistoryMapped} - if resolution.operation == sequenceModeReplace { - history.mode = sequenceHistoryReplace - if incoming != nil && incoming.Kind == document.Sequence { - history.length = len(incoming.Sequence) - } - } else { - history.items = append([]sequenceItemProjection(nil), combined.higherItems...) - history.replacements = append([]sequenceItemReplacement(nil), combined.replacements...) - } - sequenceContributions = append(sequenceContributions, history) + sequenceContributions = append(sequenceContributions, sequenceHistoryContributionForCombination( + childPath, resolution.operation, incoming, combined, + )) return combined.value, true }, }) diff --git a/internal/engine/overlay.go b/internal/engine/overlay.go index 22bf4bf..e16020b 100644 --- a/internal/engine/overlay.go +++ b/internal/engine/overlay.go @@ -274,17 +274,9 @@ func (operation *overlayMergeOperation) merge(path Path, existing, incoming *doc operation.incomingOrigins, operation.incomingPolicies, operation.layer, ) operation.valueDestinations[path.String()] = true - history := sequenceHistoryContribution{path: path.clone(), mode: sequenceHistoryMapped} - if resolution.operation == sequenceModeReplace { - history.mode = sequenceHistoryReplace - if incoming != nil && incoming.Kind == document.Sequence { - history.length = len(incoming.Sequence) - } - } else { - history.items = append([]sequenceItemProjection(nil), combined.higherItems...) - history.replacements = append([]sequenceItemReplacement(nil), combined.replacements...) - } - operation.sequenceApplications[path.String()] = history + operation.sequenceApplications[path.String()] = sequenceHistoryContributionForCombination( + path, resolution.operation, incoming, combined, + ) return combined.value, true }