From fb1bf4ab85dbc9412947560c6dd99ef4614d4bd2 Mon Sep 17 00:00:00 2001 From: Codex Bot Date: Sun, 8 Nov 2026 04:36:44 +0800 Subject: [PATCH] test(canvas): verify compacted logical coverage and lifecycle records --- .../platform/canvas_model_integration_test.go | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/internal/platform/canvas_model_integration_test.go b/internal/platform/canvas_model_integration_test.go index b549603..02d2d9d 100644 --- a/internal/platform/canvas_model_integration_test.go +++ b/internal/platform/canvas_model_integration_test.go @@ -344,4 +344,30 @@ func TestCanonicalModelMigrationAndIncrementalLifecycle(t *testing.T) { t.Fatal("a rejected atomic prefix consumed a logical operation ID") } + // A compacted wire projection retains prefix IDs with conditional no-ops, including in a child scope. + projectedKey, guardLogical, effectLogical := modelTestID(1019), modelTestID(22005), modelTestID(22006) + projectedGhost := modelTestID(5200) + finalGhost := modelTestNode(projectedGhost, innerCanvas) + finalGhost["data"].(map[string]any)["text"] = "composed final value" + parentVersion := model.Versions[root] + projection := modelBatch{ProtocolVersion: 2, RequestID: projectedKey, Expected: map[string]int64{innerCanvas: model.Versions[innerCanvas]}, Operations: []modelOperation{ + {ID: guardLogical, Changes: []modelChange{{Kind: "field", Target: modelTarget{ID: memberID, Incarnation: 1}, Field: "data.title", Before: modelJSON("batched"), After: modelJSON("batched")}}}, + {ID: effectLogical, Changes: []modelChange{ + {Kind: "field", Target: modelTarget{ID: memberID, Incarnation: 1}, Field: "data.title", Before: modelJSON("batched"), After: modelJSON("projected final")}, + {Kind: "element", ID: projectedGhost, Before: modelJSON(nil), After: modelJSON(finalGhost)}, + {Kind: "element", ID: projectedGhost, Before: modelJSON(finalGhost), After: modelJSON(nil)}, + }}, + }} + projectedReceipt := call("POST", base+"/model/operations", projection, projectedKey, 200) + model = read() + if !modelEqual(projectedReceipt["operation_ids"], []string{guardLogical, effectLogical}) || model.Versions[innerCanvas] != batchVersion+2 || model.Versions[root] != parentVersion { + t.Fatal("projected prefix lost its logical coverage or widened the child writer scope") + } + if modelString(model.Elements[memberID]["data"].(map[string]any)["title"]) != "projected final" || model.Tombstones[projectedGhost] != 1 || !modelEqual(model.DeadRecords[projectedGhost], finalGhost) { + t.Fatal("projected effect lost final data, tombstone or archived lifecycle record") + } + if !modelEqual(call("GET", base+"/model/operations/"+projectedKey, nil, "", 200), projectedReceipt) { + t.Fatal("compacted projection receipt was not recoverable by its original key") + } + }