Reconcile retained history accounting

This commit is contained in:
2026-10-26 17:46:31 +00:00
parent 12fd0a7191
commit 6a1447c327
8 changed files with 62 additions and 58 deletions

View File

@@ -23,7 +23,7 @@ type historyBudgetLayeredConfig struct {
func retainedInspectionNodeCountForTest(inspection *Inspection) int {
seen := make(map[*document.Node]struct{})
model := inspection.history
stack := []*document.Node{model.baseline, model.final}
stack := []*document.Node{model.baseline, model.final, inspection.final}
for _, payload := range model.sourcePayloads {
if payload.kind == historySourceApplicationPayload {
stack = append(stack, payload.application.value)
@@ -115,6 +115,25 @@ func TestLoadHistoryBudgetUsesExactRetainedNodeCount(t *testing.T) {
}
}
func TestHistoryNodeBudgetIncludesFinalInspectionProjection(t *testing.T) {
final := &document.Node{Kind: document.Mapping, Mapping: []document.Entry{{
Key: "value", Value: &document.Node{Kind: document.String, Text: "final"},
}}}
builder := newHistoryBuilder()
model := builder.freeze()
inspection := &Inspection{history: model, metadata: Metadata{historyModel: model}, final: final}
counter := newRetainedNodeCounter(2)
admitted := addInspectionHistory(counter, inspection)
if !admitted || counter.count != 2 {
t.Fatalf("final inspection projection was not counted exactly: admitted=%t count=%d", admitted, counter.count)
}
counter = newRetainedNodeCounter(1)
if addInspectionHistory(counter, inspection) {
t.Fatal("final inspection projection did not consume the node budget")
}
}
func TestLayeredHistoryBudgetRejectsBeforeSecretsAndValidation(t *testing.T) {
type callbackCounts struct {
lookups int
@@ -131,6 +150,7 @@ func TestLayeredHistoryBudgetRejectsBeforeSecretsAndValidation(t *testing.T) {
Resolve: func(configuration *historyBudgetLayeredConfig, resolution *Resolution) error {
configuration.Child.Value += "-resolved"
resolution.Record(Keys("child", "value"), ChangeNormalization, "normalize child")
resolution.Record(Keys("child"), ChangeDerivedDefault, "record enclosing child state")
return nil
},
Validate: func(*historyBudgetLayeredConfig, *Validation) { counts.validations++ },
@@ -159,6 +179,25 @@ func TestLayeredHistoryBudgetRejectsBeforeSecretsAndValidation(t *testing.T) {
if baseline.Inspection.history == nil || baseline.Inspection.metadata.historyModel != baseline.Inspection.history || len(baseline.Inspection.history.inheritancePayloads) == 0 {
t.Fatal("layered load did not publish its shared inheritance evidence owner")
}
resolution := baseline.Inspection.history.resolutionPayload
if resolution == nil || len(resolution.snapshots) != 2 || len(resolution.replayGroups) == 0 {
t.Fatalf("layered load did not retain overlapping original resolution evidence: %#v", resolution)
}
resolutionPaths := make(map[string]bool, len(resolution.snapshots))
for _, snapshot := range resolution.snapshots {
resolutionPaths[snapshot.change.Path.String()] = true
}
if !resolutionPaths["/child"] || !resolutionPaths["/child/value"] {
t.Fatalf("layered load resolution snapshots have paths %v, want /child and /child/value", resolutionPaths)
}
group := resolution.replayGroups[0]
groupRecords := make(map[int]bool, len(group.originalRecordIDs))
for _, id := range group.originalRecordIDs {
groupRecords[id] = true
}
if len(groupRecords) != 2 || !groupRecords[0] || !groupRecords[1] || group.change.Path.String() != "/child" {
t.Fatalf("layered load did not group both overlapping original records: %#v", group)
}
exactCounts := &callbackCounts{}
loaded, err := loadGroupedWithSecretLookupLimit(makeRequest(exactCounts), testSecretBinding(), lookup(exactCounts), want)
if err != nil || loaded == nil {